STM32基础教程——定时器
前言
TIM定时器(Timer):STM32的TIM定时器是一种功能强大的外设模块,通过时基单元(包含预分频器、计数器和自动重载寄存器)实现精准定时和计数功能。其核心原理是:内部时钟(CK_INT)或外部时钟经预分频器分频后驱动计数器,当计数器达到自动重载寄存器(ARR)设定的值时触发更新事件,可产生中断或DMA请求,并自动重置计数器重新开始计数。定时器分为高级定时器(TIM1/TIM8)、通用定时器(TIM2-5)和基本定时器(TIM6/TIM7),功能逐级递减:高级定时器支持PWM生成、死区控制、刹车保护等复杂功能;通用定时器支持输入捕获、输出比较及编码器接口;基本定时器仅提供基础定时中断。通过配置预分频值(PSC)和自动重载值(ARR),可灵活设置定时周期(T = (PSC+1)*(ARR+1)/时钟频率),并支持APB总线时钟级联扩展超长定时。此外,TIM还支持主从模式、外部时钟输入及硬件触发DAC等高级应用,广泛用于PWM控制、信号测量、定时任务调度等场景。
技术实现
原理图
无
接线图
定时器定时中断
代码实现
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h" //延时函数
#include "OLED.h"
#include "Timer.h"uint16_t Num = 0;int main(void)
{/*OLED初始化*/OLED_Init();/*定时器初始化*/Timer_Init();/*OLED显示*/OLED_ShowString(1,1,"Num:"); //在第一行第一列开始显示字符串OLED_ShowString(2,1,"Counter:"); //在第二行第一列开始显示字符串while(1){OLED_ShowNum(1,5,Num,5); //显示中断计数变量NumOLED_ShowNum(2,9,TIM_GetCounter(TIM2),5); //显示定时器当前计数器的值}
}
Timer.h
#ifndef __TIMER_H__
#define __TIMER_H__#include "stm32f10x.h" // Device headervoid Timer_Init(void);#endif
Timer.c
#include "Timer.h"extern uint16_t Num;
/**@brief 初始化通用定时器2*@param none *@retval none
**/
void Timer_Init(void)
{/*开启高速总线APB1时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);/*选择时钟模式为内部时钟,定时器时钟频率为72MHz*/TIM_InternalClockConfig(TIM2); //系统默认时钟模式为内部时钟模式,不调用该函数并不会影响时钟模式配置为内部时钟模式/*配置时基单元*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //选择分频模式为不分频TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //选择计数模式为向上计数/*预分频值与自动重装值计算计数器溢出频率(计数器每秒记多少个数):CK_CNT_OV = 72MHz/(PSC + 1)/(ARR + 1)*/TIM_TimeBaseInitStruct.TIM_Period = 10000-1; //自动重装值(当计数器到达该预设值会将重装寄存器重新加载到计数寄存器中))TIM_TimeBaseInitStruct.TIM_Prescaler = 7200-1; //预分频值TIM_TimeBaseInitStruct.TIM_RepetitionCounter= 0; //重复计数器,只有高级定时器才有,通用定时器用不到,直接赋值为0TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);/***@note:该程序在复位后计数变量的值为1,说明复位后中断函数在初始化后就立刻进入一次。* 原因是:因为预分频器有个缓冲寄存器,我们写的值只有在更新事件时才会起作用,* 为了使我们写的值立刻起作用,在TIM_TimeBaseInt()函数末尾手动生成了一个更新事件,* 使预分频器的值有效。但会使更新事件和更新中断同时发生,更新中断会置更新中断标志位。* //Generate an update event to reload the Prescaler and the Repetition counter* //values immediately * TIMx->EGR = TIM_PSCReloadMode_Immediate; * TIM2_EGR寄存器中的UG位置一,重新初始化计数器,产生一个更新事件,然后会进入中断
**//*清除更新中断标志位*/TIM_ClearFlag(TIM2,TIM_FLAG_Update); //将更新标志位取反,取消更新事件/*使能中断输出控制*/TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*配置NVIC*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC优先级分组选择分组2/*NVIC初始化*/NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; //中断通道选择TIM2全局中断NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //启用NVIC通道NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);/*启动定时器*/TIM_Cmd(TIM2,ENABLE);
}/**@brief 通用定时器2中断*@param none *@retval none
**/
void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET) //获取TIM中断标志位{Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位}
}
OLED.h
#ifndef __OLED_H
#define __OLED_Hvoid OLED_Init(void);
void OLED_Clear(void);
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);#endif
OLED.c
#include "stm32f10x.h"
#include "OLED_Font.h"/*引脚配置*/
#define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x)) //可更改引脚配置
#define OLED_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x)) //更改引脚时,改变参数GPIOx,GPIO_Pin_x/*引脚初始化*/
void OLED_I2C_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //将引脚的输出模式设置为开漏输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//更改引脚时,改变参数GPIOx,GPIO_Pin_xGPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_Init(GPIOB, &GPIO_InitStructure);//更改引脚时,改变参数GPIOx,GPIO_Pin_xGPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_Init(GPIOB, &GPIO_InitStructure);OLED_W_SCL(1);OLED_W_SDA(1);
}/*** @brief I2C开始* @param 无* @retval 无*/
void OLED_I2C_Start(void)
{OLED_W_SDA(1);OLED_W_SCL(1);OLED_W_SDA(0);OLED_W_SCL(0);
}/*** @brief I2C停止* @param 无* @retval 无*/
void OLED_I2C_Stop(void)
{OLED_W_SDA(0);OLED_W_SCL(1);OLED_W_SDA(1);
}/*** @brief I2C发送一个字节* @param Byte 要发送的一个字节* @retval 无*/
void OLED_I2C_SendByte(uint8_t Byte)
{uint8_t i;for (i = 0; i < 8; i++){OLED_W_SDA(!!(Byte & (0x80 >> i)));OLED_W_SCL(1);OLED_W_SCL(0);}OLED_W_SCL(1); //额外的一个时钟,不处理应答信号OLED_W_SCL(0);
}/*** @brief OLED写命令* @param Command 要写入的命令* @retval 无*/
void OLED_WriteCommand(uint8_t Command)
{OLED_I2C_Start();OLED_I2C_SendByte(0x78); //从机地址OLED_I2C_SendByte(0x00); //写命令OLED_I2C_SendByte(Command); OLED_I2C_Stop();
}/*** @brief OLED写数据* @param Data 要写入的数据* @retval 无*/
void OLED_WriteData(uint8_t Data)
{OLED_I2C_Start();OLED_I2C_SendByte(0x78); //从机地址OLED_I2C_SendByte(0x40); //写数据OLED_I2C_SendByte(Data);OLED_I2C_Stop();
}/*** @brief OLED设置光标位置* @param Y 以左上角为原点,向下方向的坐标,范围:0~7* @param X 以左上角为原点,向右方向的坐标,范围:0~127* @retval 无*/
void OLED_SetCursor(uint8_t Y, uint8_t X)
{OLED_WriteCommand(0xB0 | Y); //设置Y位置OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位OLED_WriteCommand(0x00 | (X & 0x0F)); //设置X位置低4位
}/*** @brief OLED清屏* @param 无* @retval 无*/
void OLED_Clear(void)
{ uint8_t i, j;for (j = 0; j < 8; j++){OLED_SetCursor(j, 0);for(i = 0; i < 128; i++){OLED_WriteData(0x00);}}
}/*** @brief OLED显示一个字符* @param Line 行位置,范围:1~4* @param Column 列位置,范围:1~16* @param Char 要显示的一个字符,范围:ASCII可见字符* @retval 无*/
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{ uint8_t i;OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分for (i = 0; i < 8; i++){OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容}OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分for (i = 0; i < 8; i++){OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容}
}/*** @brief OLED显示字符串* @param Line 起始行位置,范围:1~4* @param Column 起始列位置,范围:1~16* @param String 要显示的字符串,范围:ASCII可见字符* @retval 无*/
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{uint8_t i;for (i = 0; String[i] != '\0'; i++){OLED_ShowChar(Line, Column + i, String[i]);}
}/*** @brief OLED次方函数* @retval 返回值等于X的Y次方*/
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{uint32_t Result = 1;while (Y--){Result *= X;}return Result;
}/*** @brief OLED显示数字(十进制,正数)* @param Line 起始行位置,范围:1~4* @param Column 起始列位置,范围:1~16* @param Number 要显示的数字,范围:0~4294967295* @param Length 要显示数字的长度,范围:1~10* @retval 无*/
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i++) {OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');}
}/*** @brief OLED显示数字(十进制,带符号数)* @param Line 起始行位置,范围:1~4* @param Column 起始列位置,范围:1~16* @param Number 要显示的数字,范围:-2147483648~2147483647* @param Length 要显示数字的长度,范围:1~10* @retval 无*/
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{uint8_t i;uint32_t Number1;if (Number >= 0){OLED_ShowChar(Line, Column, '+');Number1 = Number;}else{OLED_ShowChar(Line, Column, '-');Number1 = -Number;}for (i = 0; i < Length; i++) {OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');}
}/*** @brief OLED显示数字(十六进制,正数)* @param Line 起始行位置,范围:1~4* @param Column 起始列位置,范围:1~16* @param Number 要显示的数字,范围:0~0xFFFFFFFF* @param Length 要显示数字的长度,范围:1~8* @retval 无*/
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{uint8_t i, SingleNumber;for (i = 0; i < Length; i++) {SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;if (SingleNumber < 10){OLED_ShowChar(Line, Column + i, SingleNumber + '0');}else{OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');}}
}/*** @brief OLED显示数字(二进制,正数)* @param Line 起始行位置,范围:1~4* @param Column 起始列位置,范围:1~16* @param Number 要显示的数字,范围:0~1111 1111 1111 1111* @param Length 要显示数字的长度,范围:1~16* @retval 无*/
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{uint8_t i;for (i = 0; i < Length; i++) {OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');}
}/*** @brief OLED初始化* @param 无* @retval 无*/
void OLED_Init(void)
{uint32_t i, j;for (i = 0; i < 1000; i++) //上电延时{for (j = 0; j < 1000; j++);}OLED_I2C_Init(); //端口初始化OLED_WriteCommand(0xAE); //关闭显示OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率OLED_WriteCommand(0x80);OLED_WriteCommand(0xA8); //设置多路复用率OLED_WriteCommand(0x3F);OLED_WriteCommand(0xD3); //设置显示偏移OLED_WriteCommand(0x00);OLED_WriteCommand(0x40); //设置显示开始行OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置OLED_WriteCommand(0xDA); //设置COM引脚硬件配置OLED_WriteCommand(0x12);OLED_WriteCommand(0x81); //设置对比度控制OLED_WriteCommand(0xCF);OLED_WriteCommand(0xD9); //设置预充电周期OLED_WriteCommand(0xF1);OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别OLED_WriteCommand(0x30);OLED_WriteCommand(0xA4); //设置整个显示打开/关闭OLED_WriteCommand(0xA6); //设置正常/倒转显示OLED_WriteCommand(0x8D); //设置充电泵OLED_WriteCommand(0x14);OLED_WriteCommand(0xAF); //开启显示OLED_Clear(); //OLED清屏
}
OLED_Front.h
#ifndef __OLED_FONT_H
#define __OLED_FONT_H/*OLED字模库,宽8像素,高16像素*/
const uint8_t OLED_F8x16[][16]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 00x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 10x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 20x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 30x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 40xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 50x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 60x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 70x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 80x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 90x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 100x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 110x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 120x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 130x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 140x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 150x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 160x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 170x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 180x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 190x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 200x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 210x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 220x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 230x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 240x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 250x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 260x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 270x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 280x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 290x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 300x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 310xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 320x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 330x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 340xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 350x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 360x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 370x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 380xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 390x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 400x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 410x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 420x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 430x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 440x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 450x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 460xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 470x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 480xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 490x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 500x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 510x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 520x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 530x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 540xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 550x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 560x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 570x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 580x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 590x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 600x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 610x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 620x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 630x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 640x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 650x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 660x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 670x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 680x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 690x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 700x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 710x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 720x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 730x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 740x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 750x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 760x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 770x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 780x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 790x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 800x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 810x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 820x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 830x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 840x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 850x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 860x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 870x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 880x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 890x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 900x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 910x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 920x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 930x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};#endif
内容要点
TIMx
通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成,适用于多场合,包括测量输入信号的脉冲长度(输入捕获)或产生输出波形(输出比较和PWM).每个定时器完全独立,没有互相共享任何资源,它们可以一起同步操作。
TIMx 主要功能
通用TIMx(TIM2,TIM3,TIM4和TIM5)定时器功能包括:
- 16位向上,向下,向上/向下自动装载计数器
- 16位可编程(可实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值
- 4个独立通道:
--输入捕获
--输出比较
--PWM生成(边沿或中间对齐模式)
--单脉冲模式输出
- 使用外部信号控制定时器和定时器互连的同步电路
- 如下事件发生时产生中断/DMA
--更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或内部/外部触发计数)
--触发事件(计数器启动,停止,初始化或者由内部/外部触发计数)
--输入捕获
--输出比较
- 支持针对定位的增量(正交)编码器和霍尔传感器电路
- 触发输入作为外部时钟或按中期的电流管理
定时器初始化
1.时钟设置
/*开启高速总线APB1时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM2属于APB1外围设备,应调用函数RCC_APB1PeriphClockCmd()这只APB1时钟。
2.选择计数器时钟
计数器时钟可由下列时钟源提供:
● 内部时钟(CK_INT)
● 外部时钟模式1:外部输入脚(TIx)
● 外部时钟模式2:外部触发输入(ETR)
● 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时
器Timer1而作为另一个定时器Timer2的预分频器
/*选择时钟模式为内部时钟,定时器时钟频率为72MHz*/TIM_InternalClockConfig(TIM2); //系统默认时钟模式为内部时钟模式,不调用该函数并不会影响时钟模式配置为内部时钟模式
调用TIM_InternalClockConfig()函数将TIM2定时器的时钟配置为内部时钟,此时时钟频率为72MHz
3.设置时基单元
时基单元
可编程通用定时器的主要部分是一个16位计数器和与其相关的自动装载寄存器,这个计数器可以向上计数,向下计数或者向上向下双向计数。此计数器时钟由预分频器分频得到。
时基单元包含:
- 计数器寄存器(TIMx_CNT)
- 预分频器寄存器(TIMx_PSC)
- 自动装载寄存器(TIMx_ARR)
/*配置时基单元*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //选择分频模式为不分频TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //选择计数模式为向上计数/*预分频值与自动重装值计算计数器溢出频率(计数器每秒记多少个数):CK_CNT_OV = 72MHz/(PSC + 1)/(ARR + 1)*/TIM_TimeBaseInitStruct.TIM_Period = 10000-1; //自动重装值(当计数器到达该预设值会将重装寄存器重新加载到计数寄存器中))TIM_TimeBaseInitStruct.TIM_Prescaler = 7200-1; //预分频值TIM_TimeBaseInitStruct.TIM_RepetitionCounter= 0; //重复计数器,只有高级定时器才有,通用定时器用不到,直接赋值为0TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
将分频模式配置为不分频模式,计数器的计数模式设置为向上计数。然后进行预分频值和自动重装值的的计算。计数器溢出频率(定时器每秒触发中断的次数):CK_CNT_OV = 72MHz/(PSC + 1)/(ARR + 1),这是要求每秒计1个数(每秒触发一次中断),CK_CNT_OV值为1Hz,PSC(预分频器的值)和ARR(自动重装值)分别设置为7200和10000,即记一个数需要100us,计数值到达10000时说明定时器定时到达1S。
(51单片机是一个机器周期(12个时钟周期)计一个数,而STM32是一个时钟周期记一个数) ,通用计数器用不到重复计数器,只有高级计数器才会用到,此处直接赋值为0.
1. 51单片机的计数机制
(1) 机器周期与指令周期
- 时钟周期:51单片机的晶振频率(如12MHz)决定了时钟周期(1/12 μs)。
- 机器周期:
- 51单片机采用冯诺依曼架构,每条指令的执行需要 12个时钟周期(即1个机器周期)。
- 例如:若晶振为12MHz,则1个机器周期 = 1 μs(12个时钟周期)。
- 定时器计数:
- 定时器(如Timer0)默认以机器周期为计数单位,即每过1个机器周期(1 μs)计数一次。
- 例如:设置定时器溢出值为1000时,溢出时间为 1000 × 1 μs = 1秒。
2. STM32的计数机制
(1) 指令周期与定时器时钟
- 时钟周期:STM32采用哈佛架构,每个指令执行仅需 1个时钟周期(相比51的12周期效率更高)。
- 定时器计数时钟(CK_CNT):
- 定时器的计数时钟由**预分频器(PSC)**分频而来,分频公式为:
CK_CNT=系统时钟(如72MHz)/PSC+1
- 每个CK_CNT周期,计数器递增1次(无需等待指令周期)。
- 例如:若PSC=71,则CK_CNT = 72 MHz72=1 MHz7272MHz=1MHz,即每 1 μs 计数一次。
(2) 计数灵活性
- 直接基于时钟分频:
STM32的计数器直接由CK_CNT驱动,无需绑定到指令周期,因此可以实现任意分频比(通过PSC和ARR的灵活配置)。- 高精度计数:
例如:若系统时钟为72MHz,PSC=0(不分频),则CK_CNT=72MHz,计数器每 13.89 ns 递增一次,精度远高于51单片机。
3. 关键对比
特性 51单片机 STM32 架构 冯诺依曼架构(程序与数据共享总线) 哈佛架构(程序与数据独立总线) 指令周期 每条指令需12个时钟周期(1机器周期) 每条指令仅需1个时钟周期 定时器计数单位 机器周期(12时钟周期) 可配置的时钟分频(CK_CNT) 计数灵活性 固定为机器周期的分频(如12分频) 可通过PSC和ARR实现任意分频比 典型定时精度 1 μs(12MHz晶振时) 13.89 ns(72MHz系统时钟,不分频时)
4. 实际应用中的差异
(1) 定时1秒的配置
- 51单片机(12MHz晶振):
- 定时器溢出值 = 1秒 / 1 μs = 1000(无需分频,直接使用机器周期)。
- STM32(72MHz系统时钟):
- 需配置PSC和ARR:
- PSC = 71999 → 分频系数=72000 → CK_CNT = 72 MHz72000=1 kHz7200072MHz=1kHz
- ARR = 999 → 总计数周期 = 1000 → 1秒。
(2) PWM输出
- 51单片机:
- PWM频率受限于机器周期,难以实现高频信号。
- STM32:
- 可通过PSC和ARR灵活配置PWM频率,例如:
- PSC=0(CK_CNT=72MHz) → 高频PWM(如1MHz)。
5. 总结
- 51单片机:定时器基于固定机器周期(12时钟周期),计数灵活性较低,适合简单定时任务。
- STM32:定时器直接基于可编程的时钟分频(CK_CNT),每个时钟周期可计数一次,提供极高的灵活性和精度,适合复杂实时控制场景。
/*清除更新中断标志位*/TIM_ClearFlag(TIM2,TIM_FLAG_Update); //将更新标志位取反,取消更新事件
清除中断更新中断标志位,防止上电复位后立即进入中断。
该程序在复位后计数变量的值为1,说明复位后中断函数在初始化后就立刻进入一次。
原因是:因为预分频器有个缓冲寄存器,我们写的值只有在更新事件时才会起作用,
为了使我们写的值立刻起作用,在TIM_TimeBaseInt()函数末尾手动生成了一个更新事件,
使预分频器的值有效。但会使更新事件和更新中断同时发生,更新中断会置更新中断标志位。
* //Generate an update event to reload the Prescaler and the Repetition counter
* //values immediately
* TIMx->EGR = TIM_PSCReloadMode_Immediate;
TIM2_EGR寄存器中的UG位置一,重新初始化计数器,产生一个更新事件,然后会进入中断
4.输出中断控制
/*使能中断输出控制*/TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
选择TIM2外设,启用TIM更新中断源。
5.配置NVIC
/*配置NVIC*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC优先级分组选择分组2/*NVIC初始化*/NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; //中断通道选择TIM2全局中断NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //启用NVIC通道NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);
选择NVIC优先级分组为NVIC_PriorityGroup_2,将TIM2全局中断设置为中断通道,抢占优先级设置为2,响应优先级设置为1(在合法范围内灵活设置即可)
6.启用定时器
/*启动定时器*/TIM_Cmd(TIM2,ENABLE);
调用TIM_Cmd()函数启用指定的TIMx外设。
定时器中断
**@brief 通用定时器2中断*@param none *@retval none
**/
void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET) //获取TIM中断标志位{Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位}
}
TIM2定时器中断函数名在启动文件中的定义为TIM2_IRQHandler,此处应严格按照启动文件中的定义。TIM2 1s发生一次中断,进入中断函数后检测TIM2中断标志位,若中断标志位被置1则执行中断任务,计数变量加1,然后清除中断标志位,避免ISR无限循环。
中断发生需要满足两个条件:
- 中断使能:对应中断的使能位(如USART_CR1中的RXNEIE)被置1。
- 中断标志位置位:硬件事件发生后,对应的中断标志位(如USART_SR中的RXNE或ORE)被自动置1。
即使中断使能已打开,只有当标志位被置位时,才会触发中断。因此,进入ISR后必须通过检测标志位来确认具体是哪个事件触发了中断。
数据显示
OLED_ShowString(1,1,"Num:"); //在第一行第一列开始显示字符串OLED_ShowString(2,1,"Counter:"); //在第二行第一列开始显示字符串while(1){OLED_ShowNum(1,5,Num,5); //显示中断计数变量NumOLED_ShowNum(2,9,TIM_GetCounter(TIM2),5); //显示定时器当前计数器的值}
在OLED第一行显示计数变量Num的值,即x秒。第二行显示计数器寄存器中的值即x*10us,该数据使用TIM_GetCounter函数获取。
实验结果
相关文章:
STM32基础教程——定时器
前言 TIM定时器(Timer):STM32的TIM定时器是一种功能强大的外设模块,通过时基单元(包含预分频器、计数器和自动重载寄存器)实现精准定时和计数功能。其核心原理是:内部时钟(CK_INT)或…...
How to share files with Windows via samba in Linux mint 22
概述 Windows是大家日常使用最多的操作系统,在Windows主机之间,可以共享文件,那么如何在Windows主机与Linux主机之间共享文件呢? 要在Windows主机与Linux主机之间共享文件,我们可以借助Samba协议完成。借助Samba协议…...
[AI速读]如何构建高效的AMBA协议检查器(Checker IP)
在芯片验证过程中,检查器(Checker)是确保设计符合协议规范的关键工具。本文基于一篇技术论文,分享如何为AMBA协议(如AXI、AHB)构建可重用的检查器IP(Checker IP,简称CIP),并简化其核心思路,帮助工程师快速上手。 一、什么是Checker IP? Checker IP是一组用SystemVe…...
VBA-Excel
VBA 一、数据类型与变量 常用数据类型: Byte:字节型,0~255。Integer:整数型,用于存储整数值,范围 -32768 到 32767。Long:长整型,可存储更大范围的整数,范围 -214748364…...
网络华为HCIA+HCIP IPv6
目录 IPv4现状 IPv6基本报头 IPv6扩展报头 IPv6地址 IPv6地址缩写规范 编辑 IPv6地址分配 IPv6单播地址分配 IPv6单播地址接口标识 IPv6常见单播地址 - GUA (2 / 3 开头) IPv6常见单播地址 - ULA IPv6常见单播地址 - LLA IPv6组播地…...
LeetCode 每日一题 2025/3/17-2025/3/23
记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步 目录 3/17 1963. 使字符串平衡的最小交换次数3/18 2614. 对角线上的质数3/19 2610. 转换二维数组3/20 2612. 最少翻转操作数3/21 2680. 最大或值3/22 2643. 一最多的行3/23 2116…...
git tag以及git
git tag 以及git 一、先说收获吧 1. git bash 在windows上 类似于linux的bash提供的shell命令行窗口,可以执行很多linux命令,cd pwd ls vim cat touch mkdir,还可以用正则匹配查看标签。相当于在windows上装了一个小的linux。git init myproj…...
Android 自定义变形 MD5 算法
版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ MD5是一种哈希函数,用于将任意长度的数据映射为一个固定长度的哈希值。它由 Ron Rivest 在 1991 年设计,是继 MD4 之后的改进版本。 M…...
【SpringBoot】MorningBox小程序的完整后端接口文档
以下是「晨光宅配」小程序的完整接口文档,涵盖了所有12个表的接口。 每个接口包括请求方法、URL、请求参数、响应格式和示例 接口文档 1. 用户模块 1.1 获取用户信息 URL: /user/{userId}方法: GET请求参数: userId (路径参数): 用户ID响应格式:{"userId": 1,&qu…...
2025年01月03日微创网络(杭州银行外包)前端面试
目录 html 块级元素和行内元素有哪些阴影的几个属性垂直水平居中的实现方式定位的几种方式盒子模型的方式js的数组方法有哪些vue2 vue3 区别vuex哈希路由和浏览器路由的区别浏览器缓存的几个方式react hooks的优势react 组件传值vue 组件传值如何进行性能优化前端监控get post…...
工单分类总结
微调BERT-base模型,构建层次化分类器,Top-3准确率达97.2%,并自动识别出问题的关键类别 1. 具体微调的BERT-base模型是什么模型? BERT-base模型是一个预训练的Transformer模型,包含12个Transformer块、12个自注意头和隐藏大小为768。该模型在大规模文本数据上进行了预训练…...
2025年了,5G还有三个新变化
最近舆论开始讨论5G为什么不火了?5G是不是停滞发展了。 实际上,5G不仅在发展,还迎来了它的升级版5G-A。 在今年西班牙举行的世界移动通信大会上,5G-A就是焦点之一。 被誉为全球通信领域风向标的MWC,汇聚了华为、中兴通…...
区块链交易所平台开发全解析
在数字化飞速发展的今天,区块链技术已成为金融领域的核心驱动力之一。作为数字货币交易的关键平台,区块链交易所的开发不仅涉及复杂的技术环节,还需要兼顾用户体验、安全性、合规性等多个方面。本文将深入探讨区块链交易所平台的开发流程、关…...
hexo+butterfly博客功能完善和美化(四)---博客上传
hexobutterfly博客功能完善和美化(四)—博客上传 这是最后一期讲美化和功能完善了,笔者会陆续把csdn上面的博客转移到我的博客网站上面,大家可以来访问 Darlingの妙妙屋 文章目录 hexobutterfly博客功能完善和美化(…...
源码分析之Leaflet中dom模块DomEvent.DoubleTap的实现原理
概述 DomEvent.DoubleTap模块是Leaflet中用于模拟双击(dbclick)事件的模块,主要解决移动端浏览器对双击事件支持不完善或延迟的问题,同时避免与标签(<label>)关联的表单元素误触发。 源码分析 源码实现如下 DomEvent.DoubleTap的源码实现如下&…...
记录一次,rabbitmq开启stomp插件之后,还是连不上15674端口的问题
原因是装在docker 里面的rabbitmq 没有映射15674端口,需重新删除容器之后重新运行 docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -p 15674:15674 -p 1883:1883 -p 15675:15675 rabbitmq:版本号 进入docker容器开启插件 docker exec -it rabbitm…...
git clone项目报错fatal: fetch-pack: invalid index-pack output问题
前情回顾:git项目放在公司服务器上面,克隆等操作需要连接VPN才能操作。由于项目比较大,网速比较慢,克隆项目经常出现fetch-pack: invalid index-pack output。在网上查找各种解决方法。也就这一种有点效果。仅供参考,不…...
【access开发】导入excel 并生成表
hi,大家好呀! 最近天气越来越暖了,在这个春暖花开的季节了,每天心情应该都是美美的,正所谓一年之计在于春,在这个美好的季节,大家一起努力学习学习吧!那我们来看看今天学点啥呢&…...
利用knn算法实现手写数字分类
利用knn算法实现手写数字分类 1.作者介绍2.KNN算法2.1KNN(K-Nearest Neighbors)算法核心思想2.2KNN算法的工作流程2.3优缺点2.4 KNN算法图示介绍 3.实验过程3.1安装所需库3.2 MNIST数据集3.3 导入手写数字图像进行分类3.4 完整代码3.5 实验结果 1.作者介…...
从零开始实现 C++ TinyWebServer 处理请求 HttpRequest类详解
文章目录 HTTP 请求报文HttpRequest 类实现 Init() 函数实现 ParseRequestLine() 函数实现 ParseHeader() 函数实现 ParsePath() 函数实现 ParseBody() 函数实现 ParsePost() 函数实现 ParseFromUrlEncoded() 函数实现 UserVerify() 函数实现 Parse() 函数HttpRequest 代码Http…...
Android开发layer-list
Android开发layer-list 它的用处可以在drawable上进行多图拼接,比如启动页,不想图片被拉伸就这么做。还有做某些线突出来。 示例代码: <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android&q…...
如何提升库存系统的高并发和稳定性:算法与设计模式
库存系统是企业运营的核心模块,尤其是在电商、零售和供应链管理中,系统的高并发和稳定性直接影响订单处理的准确性和效率。面对海量订单、复杂的库存管理需求,如何在高并发环境下确保库存数据的准确性和系统的稳定性?本文将从架构…...
关于CNN,RNN,GAN,GNN,DQN,Transformer,LSTM,DBN你了解多少
以下是神经网络中常见的几种模型的简要介绍: 1. CNN (Convolutional Neural Network, 卷积神经网络) 用途: 主要用于图像处理和计算机视觉任务。特点: 通过卷积核提取局部特征,具有平移不变性,能够有效处理高维数据(如图像…...
设计模式之装饰器模式
装饰器模式(Decorator)依然是我们设计模式中的结构型模式,其中的构造思想仍然是对多个类进行组合使用,以达成系统调用实现指定功能的设计模式。装饰器模式不论在我们日常开发过程中还是在我们提升技术阅读源码过程中都是比较常见的,但是整体学…...
Mistral AI发布开源多模态模型Mistral Small 3.1:240亿参数实现超越GPT-4o Mini的性能
法国人工智能初创公司Mistral AI于2025年3月正式推出新一代开源模型Mistral Small 3.1 ,该模型凭借240亿参数的轻量级设计,在多项基准测试中表现优异,甚至超越了Google的Gemma 3和OpenAI的GPT-4o Mini等主流专有模型。 1、核心特性与优势 多…...
SpringBoot3实战(SpringBoot3+Vue3基本增删改查、前后端通信交互、配置后端跨域请求、数据批量删除(超详细))(3)
目录 一、从0快速搭建SpringBoot3工程、SpringBoot3集成MyBatis、PageHelper分页查询的详细教程。(博客链接) 二、实现前端与后端通信对接数据。(axios工具) (1)安装axios。(vue工程目录) (2)封装请求工具类。(request.js) <1&…...
LabVIEW发电平台数据采集系统
本文详细介绍了基于LabVIEW的摇臂式波浪发电平台数据采集系统的设计与实现。通过整合LabVIEW软件与多种传感器技术,本系统能够有效提升数据采集的准确性和效率,为波浪能的利用和发电设备的优化提供科学依据。 项目背景 随着全球能源需求增长和环境保…...
人工智能(AI)系统化学习路线
一、为什么需要系统化学习AI? 人工智能技术正在重塑各行各业,但许多初学者容易陷入误区: ❌ 盲目跟风:直接学习TensorFlow/PyTorch,忽视数学与算法基础。 ❌ 纸上谈兵:只看理论不写代码,无法解…...
oracle事务的组成
1)数据库事务由以下的部分组成: 一个或多个DML 语句 ; 一个 DDL(Data Definition Language – 数据定义语言) 语句; 一个 DCL(Data Control Language – 数据控制语言)语句; 2)事务的执行开始: 以第一个 DML 语句的执行作为开始 ,…...
第二十八篇 数据获取与数据分析:数仓体系下的专业化分工与协同
声明:文章内容仅供参考,需仔细甄别。文中技术名称属相关方商标,仅作技术描述;代码示例为交流学习用途,部分参考开源文档(Apache 2.0/GPLv3);案例数据已脱敏,技术推荐保持…...
SpringSecurity——前后端分离登录认证
SpringSecurity——前后端分离登录认证的整个过程 前端: 使用Axios向后端发送请求 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>登录</title><script src"https://cdn…...
【AI】Orin Nano+ubuntu22.04上移植YoloV11,并使用DeepStream测试成功
1、准备工作 使用 sdk-manager 烧写 OrinNano, JetPack版本为6.0 DP,对应操作系统为:Ubuntu22.04 参见博客:【NVIDIA】Jetson Orin Nano系列:烧写Ubuntu22.04 2、安装 PyTorch 2.1 下载依赖 1)安装onnx pip install onnx -i https://pypi.tuna.tsinghua.edu.cn/sim…...
RHCE 使用nginx搭建网站
一。准备工作 Windows dns映射 创建目录网页 vim 编辑内容 添加如下 重启nginx服务,在Windows浏览器进行测试...
arm linux下的读写信号量rw_semphore的实现
本文基于arm linux 5.10来介绍内核中使用的读写信号量rw remphore的实现代码。 内核中信号量结构体struct rw_semaphore的定义在include/linux/rwsem.h 32位architectures下,结构体struct rw_semaphore中的count的使用如下: 先来看信号量的定义和初始化…...
搭建主从DNS、nfs、nginx
任务需求: 客户端通过访问 www.nihao.com 后,能够通过 dns 域名解析,访问到 nginx 服务中由 nfs 共享的首页文件,内容为:Very good, you have successfully set up the system. 各个主机能够实现时间同步,…...
Qt6+QML实现Windows屏幕录制
前言 Qt6提供了更丰富的多媒体支持类,使用Qt6 QMediaCaptureSession、QScreenCapture、QMediaRecorder,来实现一个屏幕录制的demo,其中QScreenCapture 最低版本 Qt6.5。支持录制的清晰度设置,选择视频保存位置,UI使用…...
python二级每日十题(1)
\ 第一题,在Python中,变量名的命名规则:以字母或下划线开头,后面跟字母、下划线和数字;不能以数字开头.故选c项,博主正确 缩进:在逻辑行首的空白(空格和制表符)用来决定逻辑行的缩进层次&…...
记录一次truncate导致MySQL夯住的故障
目录 环境信息: 故障描述: 处理过程: 原理分析: show processlist结果中的system lock含义: truncate原理: 1. TRUNCATE 的执行流程 2、TRUNCATE 表导致数据库夯住的原因 3、 TRUNCATE 表导致…...
Java Web应用程序实现用户登录、学生信息管理和验证码验证以及页面跳转等基本功能(IDEA)含(Ajax、JSTL)
一、具体框架以及代码功能的展示: 1. 文件结构 web03: 项目根目录。 src: 包含Java源代码。 cn.lvb: 主包。 bean: 包含实体类,如 Book 和 Student。 controller: 包含处理HTTP请求的Servlet类,如 DoLogin, Index, StuList1, VerifyCode。 …...
【Mybatis-plus】在mybatis-plus中 if test标签如何判断 list不为空
博主介绍:✌全网粉丝22W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
MySQL 事务(Transaction)详解
MySQL 事务(Transaction)详解 1. 什么是事务? 事务(Transaction)是一组要么全部执行,要么全部回滚的 SQL 语句,用于保证数据一致性。事务一般用于银行转账、订单支付等操作,确保多个…...
Redis 知识点梳理
第一章 NoSQL数据库发展历史简介 1、 Web的历史发展历程 web1.0时代简介 web 1.0是以编辑为特征,网站提供给用户的内容是网站编辑进行编辑处理后提供的,用户阅读网站提供的内容这个过程是网站到用户的单向行为web1.0时代的代表站点为新浪,…...
github上传操作简单说明
前期准备 0.下载git(如果已经有了就不用了) 1.在GitHub上新建一个存储库 2.先在本地创建一个目录作为本地库目录,在目录里打开git bash进行上传 上传过程 echo "# Garbled_repair" >> README.md 作用:创建一个…...
在 ASP .NET Core 9.0 中使用 Scalar 创建漂亮的 API 文档
示例代码:https://download.csdn.net/download/hefeng_aspnet/90407900 Scalar 是一款可帮助我们为 API 创建精美文档的工具。与感觉有些过时的默认 Swagger 文档不同,Scalar 为 API 文档提供了全新而现代的 UI。其简洁的设计让开发人员可以轻松找到测试…...
针对 pdf.mjs 文件因 MIME 类型错误导致的 Failed to load module script 问题解决方案
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of “application/octet-stream”. Strict MIME type checking is enforced for module scripts per HTML spec. pdf.mjs 这种问题该如何处理 nginx 针对 pdf.…...
Flink介绍与安装
Apache Flink是一个在有界数据流和无界数据流上进行有状态计算分布式处理引擎和框架。Flink 设计旨在所有常见的集群环境中运行,以任意规模和内存级速度执行计算。 一、主要特点和功能 1. 实时流处理: 低延迟: Flink 能够以亚秒级的延迟处理数据流,非常…...
《双指针算法指南:LeetCode 经典题解(C++实现)》
《双指针算法指南:LeetCode 经典题解(C实现)》 —— 从快慢指针到对撞指针,刷题效率提升 200%! 常⻅的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。 对撞指针: ⼀般⽤于顺…...
kaggle上经典泰坦尼克项目数据分析探索
之前了解在kaggle上这个项目很火,最近想要加强一下python数据分析,所以在kaggle上找到这个项目进行学习探索,下面是将一些学习资料以及过程整理出来。 一、首先我们了解一下项目背景以及如何找到这个项目。 kaggle项目地址: https://www.k…...
【深度学习】多目标融合算法(五):定制门控网络CGC(Customized Gate Control)
目录 一、引言 二、CGC(Customized Gate Control,定制门控网络) 2.1 技术原理 2.2 技术优缺点 2.3 业务代码实践 2.3.1 业务场景与建模 2.3.2 模型代码实现 2.3.3 模型训练与推理测试 2.3.4 打印模型结构 三、总结 一、引言 上一…...
Ubuntu上查看GPU使用情况并释放内存
先用nvidia-smi查看GPU当前使用情况 再用fuser 命令查找对应显卡上占用 GPU 的进程 最后查到了用kill -9强制杀掉进程(PID)即可...