STM32 定时器TIM
定时器基础知识
定时器就是用来定时的机器,是存在于STM32单片机中的一个外设。STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个基本定时器(TIM6、TIM7),如下图所示:
STM32F10X系列总共最多有八个定时器
三种STM32定时器的区别:
向上是指1234逐个递增计数,向下是指逐个递减计数,向上/向下是指中央对齐模式(基本定时器只能向上,上图写错了) ,捕获指的是输入捕获,比较指的是输出比较
基本定时器
1. 时钟源 2. 控制器 3. 时基单元
时钟源
时钟源来自RCC的TIMx_CLK(属于内部的CK_INIT)
外设挂载在总线下的APB1对应的是时钟2~时钟7(所以我们的基本定时器TIM6 TIM7在APB1下的)
根据时钟树
因为AHB 72M,(AHB默认分频是2)所以APB1是 36M,(APB1默认分频是2)所以根据(如果APB1预分频系数=1则频率不变,否则频率x2.)可知定时器的频率 = 72M
时基(定时器的心脏)
定时器最重要的就是时基部分:包括预分频器、计数器、自动重装载寄存器
预分频器:1-16位预分频器PSC对内部时钟CK_PSC进行分频之后,得到计数器时钟CK_INT=CK_PSC/(PSC+1)
CNT在计数器时钟的驱动下开始计数,计数一次的时间为1/CK_INT
计数器、重装在寄存器:定时器使能(CEN置1)后,计数器CNT在CK_CNT驱动 下计数,当CNT值与ARR的设定值相等时就自动生成事件并CNT自动清零,然后 自动重新开始计数,如此重复以上过程。
影子寄存器
1.PSC和ARR都有影子寄存器,功能框图上有个影子
2.影子寄存器的存在起到一个缓冲的作用,用户值->寄存器->影子寄存器->起作用, 如果不使用影子寄存器则用户值在写到寄存器之后则里面起作用,ARR影子, TIMx_CR1:APRE位控制。
定时时间的计算
定时器时间=(PSC+1)*(ARR+1)/72M
因为我们的计数器是从0开始计数的,所以要加1
基本定时器的功能
1.计数器16bit,只能向上计数,只有TIM6和TIM7
2.没有外部的GPIO,是内部资源,只能用来定时
3.时钟来自PCKL1,为72M,可实现1~65536分频
通用定时器
STM32 的通用定时器功能:
位于低速的APB1总线上(APB1)
16 位/32 位(仅 TIM2 和 TIM5)向上、向下、向上/向下自动装载计数器 (TIMx_CNT),注意:TIM9~TIM14 只支持向上(递增)计数方式
16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~ 65535 之间的任意数值
4 个独立通道(TIMx_CH1~4,TIM9~TIM14 最多 2 个通道),这些通道可以用来作为:
输入捕获
输出比较
PWM 生成(边缘或中间对齐模式) ,注意:TIM9~TIM14 不支持中间对齐模式
单脉冲模式输出
可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外 一个定时器)的同步电路。
如下事件发生时产生中断/DMA(TIM9~TIM14 不支持 DMA):
更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
输入捕获
输出比较
支持针对定位的增量(正交)编码器和霍尔传感器电路(TIM9~TIM14 不支持)
触发输入作为外部时钟或者按周期的电流管理(TIM9~TIM14 不支持)
STM32的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等
使用定时器分频器和RCC时钟控制分频器,脉冲长度和波型周期可以在几个微妙到几个毫秒间调整,STM32的每个通用定时器都是完全独立的,没有互相共享的任何资源
计数器模式
向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且 产生一个计数器溢出事件
向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装 入的值重新开始,并产生一个计数器向下溢出事件
中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个 计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数
通用定时器框图
框图可以分为四个大部分,分别是:
时钟产生部分
时基单元部分
输入捕获部分
输出捕获部分
时钟产生部分
内部时钟(CKINT)
外部时钟模式:外部触发输入(ETR)
内部触发输入(TRX):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Iimer2的预分频器。
外部时钟模式:外部输入脚(TIx)
时机单元
时基单元就是定时器框图的第二部分,它包括三个寄存器,分别是:计教器寄存器(TIMXCND、预分频器寄存器(TIMXPSC)和自动装载寄存器(TIMX ARR)。对这三个寄存器的介绍如下:
计数器寄存器(TIMx_CNT)
向上计数、向下计数或者中心对齐计数;
预分频器寄存器(TIMx_PSC)
可将时钟频率按1到65535之间的任意值进行分频,可在运行时改变其设置值;
自动装载寄存器(TIMX ARR)
如果TIMx_CR1寄存器中的ARPE位为0,ARR寄存器的内容将直接写入影子寄存器;如果ARPE为1,ARR寄存器的那日同将在每次的更新时间UEV发生时,传送到影子寄存器;
输入捕获通道
1.IC1、2和IC3、4可以分别通过软件设置将其映射到T11、TI2和TI3、TI4;
2.4个16位捕捉比较寄存器可以编程用于存放检测到对应的每一次输入捕捉时计数器的值,
3.当产生一次捕捉,相应的CCxIF标志位被置1;同时如果中断或DMA请求使能,则产生中断或DMA请求。
4.如果当CCxIF标志位已经为1,当又产生一个捕捉,则捕捉溢出标志位CCxOF将被置1。
输出比较通道
PWM模式运行产生:
定时器2、3和4可以产生独立的信号:频率和占空比可以进行如下设定一个自动重载寄存器用于设定PWM的周期;每个PWM通道有一个
捕捉比较寄存器用于设定占空时间。
两种可设置PWM模式:
边沿对齐模式
中心对齐模式
常用库函数
定时器参数初始化函数(第一个参数定时器几,第二个参数结构体指针)
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
结构体内部成员
typedef struct
{uint16_t TIM_ClockDivision; //外部输入时钟分频因子,基本定时器没有uint16_t TIM_CounterMode; //计数模式,基本定时器只能向上计数uint16_t TIM_Period; //自动重装载值 //注意重装载值和分频因子的数配置不能超过65535uint16_t TIM_Prescaler; //分频因子 uint8_t TIM_RepetitionCounter; //重复计数值,基本定时器没有,高级定时器专用} TIM_TimeBaseInitTypeDef;
65535
定时器控制LED灯软件流程设计
初始化系统
初始化定时器和LED的IO时钟、初始化LED的引脚IO
使能定时器时钟、初始化定时器、开启中断配置、使能定时器、
编写定时器中断函数
定时器时间= (ARR+1)*(PSC+1)/TCLK(72M=72 000 000)
假如定时1秒 1= 72 00*10000/72M
#include "stm32f10x.h"
#include "tim.h"void Base_Tim_Init()
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);TIM_TimeBaseInitTypeDef TIM_TimeIinitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeIinitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeIinitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeIinitStruct.TIM_Period = 7200 - 1;TIM_TimeIinitStruct.TIM_Prescaler = 10000 - 1;TIM_TimeIinitStruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeIinitStruct);TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);TIM_Cmd(TIM2, ENABLE);NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_InitStruct);}
TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
第二个参数
输入捕获输出比较所用到的通道
如果我们只是想产生定时器的更新源中断用第一个参数
#include "stm32f10x.h"
#include "main.h"
#include "led.h"
#include "bear.h"
#include "key.h"
#include "relay.h"
#include "shake.h"
#include "usart.h"
#include "stdio.h"
#include "tim.h"void delay(uint16_t time) {uint16_t i = 0;while (time--) {i = 12000;while (i--);}
}int main()
{Led_Init();Base_Tim_Init();while (1){ }
}void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){GPIO_ResetBits(GPIOA, GPIO_Pin_1);delay(1000);GPIO_SetBits(GPIOA, GPIO_Pin_1);delay(1000);}TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
定时器中断应用
超声波模块
1.工作原理
首先单片机给Trig引脚,给至少10us(10微秒)的高电平信号。
模块自动发送8个40KHz的方波,自动检测是否有信号返回。
有信号返回,通过Echo引脚输出高电平,高电平持续时间就是超声波从发射到返回的时间
HC-SR04超声波测距模块提供2cm-400cm的测距功能,精度达3mm。
2.硬件接线
四根杜邦线,VCC连接单片机3.3-5V(推荐5V供电),GND接到板子的GND,Trig为外部触发信号输入,输入一个10us的高电平即可触发模块测距,Echo(接收引脚)即为 回响信号输出,测距结束时此管引脚输出一个低电平,电平宽度反映超声波往返时间之和。
3.控制超声波测距步骤
初始化定时器时钟和定时器中断
初始化超声波时钟和超声波引脚模式
编写定时器中断函数测距
先发送10us的高电平信号,发送了之后我的定时器就开始捕获Echo的高电平的时间,什么时候低电平就什么时候关闭定时器,就开始算比如说我们产生了多少次定时器的中断,比如是一次定时器中断是1秒,多少个定时器中断就是多少个秒,通过一系列公式就能知道距离是多少
1. 发送 10μs 的高电平信号(触发信号)
目的:启动一次测距操作。
这里的 “发送高电平” 通常是通过单片机的 IO 口输出一个持续 10 微秒(μs) 的高电平脉冲(如 HC-SR04 模块需要这样的触发信号)。为什么是 10μs?
这是目标设备(如超声波传感器)的协议规定,用于告知传感器 “开始发射信号”(例如超声波传感器会在接收到 10μs 高电平后,发射一束超声波)。2. 定时器开始捕获 Echo 信号的高电平时间
Echo 信号是什么?
Echo 是 “回波信号”,即目标设备接收到反射回来的信号后,输出的电信号。例如:
发送端发射超声波后,Echo 信号保持低电平;
当超声波遇到障碍物反射回来被接收端检测到,Echo 信号变为高电平;
直到信号接收完毕,Echo 信号重新变为低电平。
定时器的作用:
从触发信号发送完成的时刻起,定时器开始记录 Echo 信号 高电平的持续时间(即从 “收到回波” 到 “回波结束” 的时间)。3. 检测到低电平时关闭定时器
何时关闭定时器?
当 Echo 信号从高电平跳转为低电平时(即回波接收完毕),立即停止定时器计数。本质:
定时器记录的是 “回波信号高电平的持续时间 T”,这个时间 T 等于信号从发射到接收的 往返时间(即信号从发射端→障碍物→接收端的总时间)。4. 通过定时器中断次数计算时间 T
定时器中断机制:
定时器通常配置为按固定周期产生中断(例如每 1μs、1ms 产生一次中断),每次中断时计数器加 1。
假设定时器中断周期为 1μs(即每 1 微秒产生一次中断),中断次数为 N 次,则总时间 T = N × 1μs。
(原句中 “一次中断是 1 秒” 是简化举例,实际应用中中断周期远小于 1 秒,通常为微秒或毫秒级,否则精度不足。)
如何计算中断次数?
定时器启动后,每当 Echo 为高电平时,中断计数器持续累加,直到 Echo 变低时停止计数,此时计数器的值即为高电平期间的中断次数。5. 通过公式计算距离
核心公式(以超声波测距为例):
距离 = (信号速度 × 时间 T) / 2
除以 2 的原因:信号往返一次(发射→障碍物→接收),实际距离是单程距离。
信号速度:超声波在空气中约为 340m/s(即 0.034cm/μs),光速约为 3×10⁸m/s(用于激光测距)。
举例计算:
若 T = 1000μs(1 毫秒),则距离 = (0.034cm/μs × 1000μs) / 2 = 17cm。
超声波代码框架
只有收到回响信号的时候,我们的trigr,在信号发出的时候我的echo引脚输入给我们的单片机,然后如果我们的单片机之前是低电平,检测高电平的瞬间才开始打开定时器(怎么打开和关闭定时器呢)之前配置定时器的时候结构体配置和中断的配置TIM_Cmd(TIM2, DISABLE);函数,先关闭
当收到信号的时候再打开,怎么计算高电平时间?首先要先判断echo引脚什么时候变成高电平
用GPIO_ReadInputDataBit函数然后这里再打开定时器这时就开始我们的中断函数,中断函数去计数定时器进入的次数,因为我们用定时器的开启的时候用定时器的中断计算进入定时器的时间,注意 这里定时器的配置TIM_Initstruct.TIM_Period = 1000 -1; TIM_Initstruct.TIM_Prescaler = 72 -1;
所以定时器的定时周期的1毫秒,计数器每计1次代表1微秒 ,中断1次是1毫秒,因为我们对应的时间是高电平的时间等于中断次数加上不足一个中断的次数(不足一个中断的次数是说不到1毫秒但有多少个微秒呢)打开定时器,就会跳到定时器中断函数void TIM2_IRQHandler()让mscount++;这里需要定义一个新变量,然后关闭定时器,计算总电平时间,定义一个变量uint16_t t=0;定义一个函数专门用来封装总的高电平时间int Get_Echon_Time()(这里返回值是int)然后将总时间换算成距离以种种方式将t换算距离然后返回值length
#include "stm32f10x.h"
#include "tim.h"uint16_t mscount = 0;//定义一个变量专门用来记录中断的次数void delay_us(uint32_t us)
{us*= 8;while(us--);//延时微秒函数}
void delay_ms(uint32_t ms)
{while(ms--){delay_us(1000);} //延时毫秒函数}void Base_Tim_Init()
{TIM_TimeBaseInitTypeDef TIM_Initstruct;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_TIM_Initstruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_Initstruct.TIM_ClockDivision =TIM_CKD_DIV1;TIM_Initstruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_Initstruct.TIM_Period = 1000 -1;TIM_Initstruct.TIM_Prescaler = 72 -1;TIM_Initstruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_Initstruct);TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);TIM_Cmd(TIM2, DISABLE);NVIC_TIM_Initstruct.NVIC_IRQChannel = TIM2_IRQn;NVIC_TIM_Initstruct.NVIC_IRQChannelCmd = ENABLE;NVIC_TIM_Initstruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_TIM_Initstruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_TIM_Initstruct);}
void HC04_Iint()
{GPIO_InitTypeDef GPIO_Initstruction;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);//Tring B11GPIO_Initstruction.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Initstruction.GPIO_Pin = GPIO_Pin_11;GPIO_Initstruction.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(GPIOB, &GPIO_Initstruction);//Echo B10GPIO_Initstruction.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Initstruction.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOB, &GPIO_Initstruction);}void Open_Tim()
{TIM_SetCounter(TIM2, 0);mscount = 0;TIM_Cmd(TIM2, ENABLE);}
void Close_Tim()
{TIM_Cmd(TIM2, DISABLE);}
//获取定时器中断的次数
void TIM2_IRQHandler()
{if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){mscount++;TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}}//获取总的高电平时间
int Get_Echon_Time()
{uint16_t t = 0;t = mscount * 1000;t = t +TIM_GetCounter(TIM2);delay_ms(50);TIM_SetCounter(TIM2, 0);return t;}float Get_Length()
{float sum = 0;uint16_t t=0;float length = 0;int i = 0;while(i != 5){//1.hc04开始工作 Tring引脚输出高电平20usGPIO_SetBits(GPIOB, GPIO_Pin_11)delay_us(20);//延时20微秒GPIO_ResetBits(GPIOB, GPIO_Pin_11);//然后关闭//2.定时器计算高电平时间while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10) == 0);//当GPIO 10引脚高电平时 会卡在这Open_Tim();//打开定时器while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10) == 1);//当高电平跳成低电平时Close_Tim();//关闭定时器t = Get_Echon_Time();//3.将时间换算成距离length = ((float)t/58.0);sum = sum+length;}length = sum/5.0;return length;}
int main()
{float length = 0;my_usart_init();Ch04_Init();Led_Init();Base_Tim_Init();while (1){length = Get_Length();printf("%f\r\n",length);}
}
通用定时输出PWM
第一步内部时钟的选择,第二步是预分频器,计数器,去配置输出 捕获和比较
定时器3的通道2
以TIM3为例,STM32的通用定时器氛围TIM2,TIM3,TIM4,TIM5,每个定时器都有独立的四个通道可以用来作为: 输入捕获,输出比较,PWM输出,单脉冲模式输出等。
STM32的定时器除了TIM6和TIM7(基本定时器)之外,其他的定时器都可以产生PWM波输出,高级定时器TIM1,TIM8可以同时产生7路PWM输出,而通用定时器可以同时产生4路PWM输出,这样STM32可以最多同时输出30路PWM输出。
PWM的工作原理
以向上计数为例,讲述PWM原理:
①在PWM输出模式下除了CNT(计数器当前值),ARR(自动重装载值),CCRx(捕获/比较寄存器值)。
②当CNT小于CCRx时,TIMx_CHx通道输出低电平
③当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平
假设ARR设置是100CRRX是80,在0加到80过程中都属于低电平,在80加到100都属于高电平,这就是一个周期,所以占空比为百分之二十,
所谓脉宽调制信号(PWM波),就是一个TIMx_ARR自动重装载寄存器确定频率=周期的导数(由它决定PWM周期),TIM_CCRx寄存器确定占空比信号。
占空比=高电平占低电平的时间
PWM的内部运作机制
CCR1:设置捕获比较寄存器,设置比较值。
CCMR1寄存区:设置PWM模式1 或者PWM模式2。
CCER: P位:输出/捕获 :设置极性: 0 高电平有效,1 低电平有效
E位:输出/捕获 : 使能端口
PWM的模式
模式一 边沿对齐模式
向上计数时: 当TIMx_CNT<TIMx_CCRx时通道1为有效电平,否则为无效电平;(计数值小于有效值是有效电平)
向下计数时: 一旦TIMx_CNT>TIMx_CCRx,CCR1通道1为无效电平,否则为有效电平。(计数值大于比较值为无效电平)
但是这里的有效电平是高电平还是低电平有极性( 0 高电平有效,1 低电平有效)去选择
模式二 中央对齐模式
向上计数时: 当TIMx_CNT<TIMx_CCRx时通道1为无效电平,否则为无效电平;
向下计数时: 一旦TIMx_CNT>TIMx_CCRx,CCR1通道1为有效电平,否则为无效电平。
和模式一相反
但是这里的有效电平是高电平还是低电平有极性( 0 高电平有效,1 低电平有效)去选择
自动加载的预加载寄存器
简单的说:
APER =1 ,ARR立即生效
APER =0,ARR下个周期生效
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
定时器输出PWM 结构体
typedef struct
{uint16_t TIM_OCMode; //配置PWM模式1还是模式2uint16_t TIM_OutputState; //配置输出使能/ OR失能uint16_t TIM_OutputNState; uint16_t TIM_Pulse; //配置比较值,CCRxuint16_t TIM_OCPolarity; //比较输出极性uint16_t TIM_OCNPolarity; uint16_t TIM_OCIdleState; uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;
定时器输出PWM 库函数
void TIM_OCxInit //结构体初始化
(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_SetCompare1 //设置比较值函数
(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_OC1PreloadConfig //使能输入比较预装载
(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_Cmd //开启定时器(TIM_TypeDef* TIMx, FunctionalState NewState)
void TIM_ARRPreloadConfig //使能自动重装载的预装载寄存器允许位
(TIM_TypeDef* TIMx, FunctionalState NewState);
void TIM_OC1PolarityConfig //配置修改极性
(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
定时器输出PWM 库函数
TIM3 PWM输出 驱动SG90电机 配置过程:
1.GPIO结构体
2.配置通用定时器结构体
3.配置定时去输出PWM结构体
4.打开时钟 ---> GPIO时钟,TIM定时器时钟,部分重映射时钟
5.配置PWM比较值
void motor_config(void)
{GPIO_InitTypeDef GPIO_MotorInitStruct;TIM_TimeBaseInitTypeDef TIM_MotorInit;TIM_OCInitTypeDef TIMPWM_MotorInit;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);//部分重映射配置GPIO_MotorInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_MotorInitStruct.GPIO_Pin = GPIO_Pin_5;GPIO_MotorInitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_MotorInitStruct);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);TIM_MotorInit.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割TIM_MotorInit.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数模式TIM_MotorInit.TIM_Period = 200-1;//设置下一个更新事件装入活动的自动重装载值TIM_MotorInit.TIM_Prescaler = 7200 -1; //分频周期TIM_TimeBaseInit(TIM3, &TIM_MotorInit);TIMPWM_MotorInit.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式1TIMPWM_MotorInit.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能TIMPWM_MotorInit.TIM_OCNPolarity = TIM_OCPolarity_Low;//选择有效输出极性TIM_OC2Init(TIM3, &TIMPWM_MotorInit);//因为选择的是定时器3的通道2 所以选OC2TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);TIM_Cmd(TIM3, ENABLE);}
int main()
{uint16_t pwmval = 155;motor_config();while(1){for(pwmval = 195;pwmval >= 175;pwmval-=5){TIM_SetCompare2(TIM2, pwmval);delay(500);}}}
垃圾桶项目
int main()
{int pwmval =195;float Length =0;Ch04_Init(); my_usart_init();motor_config();while(1){pwmval =155;Length= Get_Length();printf("%.3f\r\n",Length);if(Length<5){for(pwmval=195;pwmval>=155;pwmval-=15){TIM_SetCompare2(TIM3, pwmval);delay(500); }}else if(Length>5){TIM_SetCompare2(TIM3, pwmval-20);}}}
相关文章:
STM32 定时器TIM
定时器基础知识 定时器就是用来定时的机器,是存在于STM32单片机中的一个外设。STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个基本定时器(TIM6、TIM7),如下图所示: STM32F1…...
基于大模型的急性化脓性阑尾炎全程诊疗预测与方案研究
目录 一、引言 1.1 研究背景与意义 1.2 国内外研究现状 1.3 研究目标与方法 二、大模型技术原理与应用基础 2.1 大模型概述 2.2 相关技术原理 2.3 数据收集与预处理 三、术前风险预测与准备 3.1 病情评估指标分析 3.2 大模型预测方法与结果 3.3 术前准备方案 四、…...
第一个 servlet请求
文章目录 前端后端前后端 产生 联系 前端 后端 package com.yanyu;import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;import java.io.I…...
XLSX.utils.sheet_to_json设置了blankrows:true,但无法获取到开头的空白行
在用sheetJs的XLSX库做导入,遇到一个bug。如果开头行是空白行的话,调用sheet_to_json转数组获得的数据也是没有包含空白行的。这样会导致在设置对应的起始行时,解析数据不生效。 目前是直接跳过了开头的两行空白行 正确应该获得一下数据 问…...
python一款简单的数据库同步dts小实现
一、实现说明 在数据开发与运维场景中,数据库同步是一项基础且高频的需求。无论是开发环境与生产环境的数据镜像,还是多数据库之间的数据分发,都需要可靠的同步工具。本文将基于 Python 和pymysql库,实现一个轻量级数据库同步工具…...
误触网络重置,笔记本电脑wifi连接不上解决方法(Win10,Win11通用)
笔记本电脑连接不上网,有人说网络重置按钮可以解决,结果把wifi图标都给搞没了,只剩飞行模式,解决方法(错误码39),罪魁祸首就是这个网络重置,一下连网络都检测不到了 那么没有网络怎…...
markdown-it-katex 安装和配置指南
markdown-it-katex 是一个用于 Markdown-it 的插件,旨在通过 KaTeX 库在 Markdown 文档中添加数学公式支持。KaTeX 是一个快速渲染数学公式的库,相比于 MathJax,它在性能上有显著优势。 步骤 1: 安装 Markdown-it 首先,你需要安装…...
开源财务软件:企业财务数字化转型的有力工具
在当今数字化时代,企业财务数字化转型已成为必然趋势。随着业务的不断拓展和复杂化,企业对财务软件的需求也在日益增长。然而,传统商业财务软件往往伴随着高昂的授权费用和有限的定制化能力,这让许多企业,尤其是中小企…...
大模型——Suna集成浏览器操作与数据分析的智能代理
大模型——Suna集成浏览器操作与数据分析的智能代理 Suna 是 Kortix AI 开发的一个开源通用 AI 代理,托管在 GitHub 上,基于 Apache 2.0 许可证,允许用户免费下载、修改和自托管。它通过自然语言对话帮助用户完成复杂任务,如网页浏览、文件管理、数据抓取和网站部署。Suna…...
QT中的事件及其属性
Qt中的事件是对操作系统提供的事件机制进行封装,Qt中的信号槽就是对事件机制的进一步封装 但是特殊情况下,如对于没有提供信号的用户操作,就需要通过重写事件处理的形式,来手动处理事件的响应逻辑 常见的Qt事件: 常见事…...
flutter 选择图片 用九宫格显示图片,右上角X删除选择图片,点击查看图片放大缩小,在多张图片可以左右滑动查看图片
flutter 选择图片 用九宫格显示图片,右上角X删除选择图片,点击查看图片放大缩小,在多张图片可以左右滑动查看图片 ************ 暂无压缩图片功能 ********* 显示图片 — import dart:io;import package:flutter/material.dart; import pa…...
机器学习day2-seaborn绘图练习
1.使用tips数据集,创建一个展示不同时间段(午餐/晚餐)账单总额分布的箱线图 import seaborn as sns import matplotlib.pyplot as plt import pandas as pd import numpy as np# 设置主题 sns.set_theme(style"darkgrid")# 设置中文 plt.rcParams[font.s…...
如何优雅地解决AI生成内容粘贴到Word排版混乱的问题?
随着AI工具的广泛应用,越来越多人开始使用AI辅助撰写论文、报告或博客。然而,当我们直接将AI生成的文本复制到Word文档中时,常常会遇到排版混乱、格式异常的问题。这是因为大部分AI输出时默认使用了Markdown格式,而Word对Markdown…...
设计一个食品种类表
需求:设计一个食品种类表,注意食品种类有多层,比如面食下面,面条、方便面,面条下有干面、湿面等 一、食品种类表结构设计(food_category) CREATE TABLE food_category (category_id INT IDENT…...
Haply MinVerse触觉3D 鼠标—沉浸式数字操作,助力 3D 设计与仿真
在2025年CES展上,Haply MinVerse触觉3D鼠标凭借创新交互方式引发关注。这款设备为用户与数字环境的互动带来新维度,操作虚拟物体时能感受真实触觉反馈。 三维交互与触觉反馈 MinVerse 突破传统鼠标二维限制,增加第三运动轴,实现真…...
神经网络预测评估机制:损失函数详解
文章目录 一、引言二、损失函数的引入三、回顾预测算法四、损失函数的形式五、成本函数六、损失函数的定义与作用七、损失函数的重要性注释思维导图 一、引言 在上一篇文章中,我们了解到神经网络可通过逻辑回归等算法对输入进行预测。而判断预测结果是否准确至关重要…...
PHP实现 Apple ID 登录的服务端验证指南
在 iOS 应用中启用 “通过 Apple 登录”(Sign In with Apple)后,客户端会获取一个 身份令牌(identity token)。该令牌是一个JWT(JSON Web Token),需要由服务端验证其真实性和完整性&…...
一、linux系统启动过程操作记录
一、linux系统启动过程 经历: 上电–>uboot–>加载内核–>挂载根文件系统–>执行应用程序 uboot等效bootloader,启动过程进行了 跳转到固定的位置执行相应的代码 初始化硬件设备,如:cpu初始化 ,看门狗&a…...
【首款Armv9开源芯片“星睿“O6测评】SVE2指令集介绍与测试
SVE2指令集介绍与测试 一、什么是SVE2 在Neon架构扩展(其指令集向量长度固定为128位)的基础上,Arm设计了可伸缩向量扩展(Scalable vector extension, SVE)。SVE是一种新的单指令多数据(SIMD&am…...
获取电脑mac地址
Windows 系统 方法1:通过命令提示符 1. 按下 `Win + R`,输入 `cmd` 后按回车,打开命令提示符。 2. 输入以下命令并按回车:...
AI核心技术与应用场景的深度解析
AI核心技术与应用场景的深度解析 在互联网大厂Java求职者的面试中,经常会被问到关于AI核心技术与应用场景的问题。本文通过一个故事场景来展示这些问题的实际解决方案。 第一轮提问 面试官:马架构,欢迎来到我们公司的面试现场。请问您对AI…...
练习普通话,声音细柔和
《繁星》 我爱月夜,但我也爱星天。从前在家乡七八月 的夜晚,在庭院里纳凉的时候,我最爱看天上密密 麻麻的繁星。望着星天,我就会忘记一切,仿佛回 到了母亲的怀里似的。 三年前在南京我住的地方,有…...
Linux进程详细解析
1.操作系统 概念 任何计算机系统都包含⼀个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括: • 内核(进程管理,内存管理,文件管理,驱动管理) • 其他程序(…...
Linux执行脚本报错
执行脚本报错:./startup.sh -bash: ./startup.sh: /bin/bash^M: bad interpreter: No such file or directory ./startup.sh -bash: ./startup.sh: /bin/bash^M: bad interpreter: No such file or directory可能的原因: 文件开头格式问题:…...
C++学习:六个月从基础到就业——模板编程:类模板
C学习:六个月从基础到就业——模板编程:类模板 本文是我C学习之旅系列的第三十三篇技术文章,也是第二阶段"C进阶特性"的第十一篇,主要介绍C中的类模板编程。查看完整系列目录了解更多内容。 目录 引言类模板的基本语法…...
Conda 虚拟环境复用
文章目录 一、导出环境配置二、克隆环境配置三、区别小结 一、导出环境配置 导出:将当前虚拟环境导出成一个yml配置文件。conda activate your_env conda env export > your_env.yml导入:基于yml文件创建新环境,会自动按照yml里的配置&am…...
Nacos简介—4.Nacos架构和原理三
大纲 1.Nacos的定位和优势 2.Nacos的整体架构 3.Nacos的配置模型 4.Nacos内核设计之一致性协议 5.Nacos内核设计之自研Distro协议 6.Nacos内核设计之通信通道 7.Nacos内核设计之寻址机制 8.服务注册发现模块的注册中心的设计原理 9.服务注册发现模块的注册中心的服务数…...
4月27日日记
现在想来,可以想到什么就记录下来,这也是网上写日记的一个好处,然后 今天英语课上看到一个有关迷信的视频,就是老师课件里的,感觉画风很不错,但是我贫瘠的语言形容不出来,就想到是不是世界上的…...
CentOS7.9安装OpenSSL 1.1.1t和OpenSSH9.9p1
一、临时开启telnet登录方式,避免升级失败无法登录系统 (注意telnet登录方式存在安全隐患,升级openssh相关服务后要记得关闭) 1.安装telnet服务 yum -y install xinetd telnet* 2.允许root用户通过telnet登陆,编辑…...
单例模式:全局唯一性在软件设计中的艺术实践
引言 在软件架构设计中,单例模式(Singleton Pattern)以其独特的实例控制能力,成为解决资源复用与全局访问矛盾的经典方案。该模式通过私有化构造方法、静态实例存储与全局访问接口三大核心机制,确保系统中特定类仅存在…...
Spring 与 ActiveMQ 的深度集成实践(三)
五、实战案例分析 5.1 案例背景与需求 假设我们正在开发一个电商系统,其中订单模块和库存模块是两个独立的子系统 。当用户下单后,订单模块需要通知库存模块进行库存扣减操作 。在传统的同步调用方式下,订单模块需要等待库存模块完成扣减操…...
30-算法打卡-字符串-重复的子字符串-leetcode(459)-第三十天
1 题目地址 459. 重复的子字符串 - 力扣(LeetCode)459. 重复的子字符串 - 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。 示例 1:输入: s "abab"输出: true解释: 可由子串 "ab" 重复两次构成…...
rocketmq一些异常记录
rocketmq一些异常记录 Product 设置不重复发送 发送 一次失败,不会在被发送到mq消息队列中,相当于消息丢失。 2、 Consumer 消费失败 重试三次消费 都失败 则消息消费失败,失败后 会放入 死信队列,可以手动处理在mq面板 处理死信队…...
SQLMesh 测试自动化:提升数据工程效率
在现代数据工程中,确保数据模型的准确性和可靠性至关重要。SQLMesh 提供了一套强大的测试工具,用于验证数据模型的输出是否符合预期。本文将深入探讨 SQLMesh 的测试功能,包括如何创建测试、支持的数据格式以及如何运行和调试测试。 SQLMesh …...
WPF使用SQLite与JSON文本文件结合存储体侧平衡数据的设计与实现
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
关系型数据库PostgreSQL vs MySQL 深度对比:专业术语+白话解析+实战案例
PostgreSQL 与 MySQL 的详细对比 PostgreSQL 和 MySQL 是两种最流行的开源关系型数据库,它们在设计理念、功能特性和适用场景上有显著差异。以下是它们的详细对比: 一、基本架构与设计理念 PostgreSQL:多进程架构,使用共享内存通…...
利用 SSRF 和 Redis 渗透
环境搭建 在本次实验中,我们使用 Docker 环境进行测试。 解压实验包,搭建 docker 环境。 docker环境 web的dockerfile 主要利用代码 : redis服务器 通过 docker-compose up -d 启动相关容器,初次启动失败。 发现 docker 版本问…...
脏读、幻读、可重复读
脏读 定义:一个事务读取了另一个事务尚未提交的数据 。比如事务 A 修改了某条数据但还没提交,此时事务 B 读取了这条被修改但未提交的数据。若事务 A 后续回滚,事务 B 读到的数据就是无效的,相当于读到了 “脏数据”。危害&#…...
第1讲、#PyTorch教学环境搭建与Tensor基础操作详解
引言 PyTorch是当前深度学习领域最流行的框架之一,因其动态计算图和直观的API而备受开发者青睐。本文将从零开始介绍PyTorch的环境搭建与基础操作,适合各种平台的用户和深度学习初学者。 1. 安装和环境搭建 macOS (Apple Silicon) 对于Mac M1/M2/M3用…...
【创新实训个人博客】数据库搭建
1.原因 为了降低模型使用以前训练的数据或者幻觉知识,我们在对话时需要提供相关内容的数据,同时由于需要最新的广告实时数据,实时爬取和版权问题。数据由团队在网上爬取,为了广告内容的有效性,如果长期使用࿰…...
《代码整洁之道》第6章 对象和数据结构 - 笔记
数据抽象 (Data Abstraction) 这个小节主要讲的是**面向对象编程(OOP)**的一种核心思想:对象应该隐藏它的内部数据,只暴露可以操作这些数据的“行为”(也就是方法/函数)。 大白话: 你创建一个…...
Python判断字符串中是否包含特殊字符
在 Python 中,判断一个字符串是否包含特殊字符可以通过多种方法实现。常见的特殊字符包括空格、感叹号、单引号、括号、星号、加号、逗号、斜杠、冒号、分号、等号、问号、 符号、方括号、花括号和 & 符号等。 为了判断字符串中是否包含这些特殊字符࿰…...
disruptor-spring-boot-start版本优化升级
文章目录 1.前言2.升级内容3.依赖4.总结 1.前言 由于之前写了一篇《disruptor-spring-boot-start生产实践导致pod节点CPU爆表100%的问题解决说明》的文章,里面说本地启动没有啥问题,后面我启动之前写的那个测试的controller发现,本地电脑的CP…...
复杂背景下无人机影像小目标检测:MPE-YOLO抗遮挡与抗背景干扰设计
目录 一、引言 二、挑战和贡献 密集小目标和遮挡 实时性要求与精度权衡 复杂背景 三、MPE-YOLO模型细节 多级特征集成器(MFI) 感知增强卷积(PEC) 增强范围C2f模块(ES-C2f) 四、Coovally AI模型训…...
项目实战 -- 状态管理
redux基础 还记得好久好久之前就想要实现的一个功能吗? 收起侧边栏折叠菜单,没错,现在才实现 因为不是父子通信,所以处理起来相对麻烦一点 可以使用状态树或者中间人模式 这就需要会redux了 Redux工作流: 异步就…...
基于单片机的智能药盒系统
标题:基于单片机的智能药盒系统 内容:1.摘要 本文聚焦于基于单片机的智能药盒系统。背景方面,随着人口老龄化加剧,老年人按时准确服药问题愈发凸显,同时现代快节奏生活也使人们容易遗忘服药时间。目的是设计并实现一个能帮助人们按时、按量服…...
【PyCharm- Python- ArcGIS】:安装一个和 ArcGIS 不冲突的独立 Python让PyCharm 使用 (解决全过程记录)
之前电脑上安装了anaconda3,python3和arcgis10.2.其中anaconda3带有python3,arcgis10.2自带python2.7。arcgis不能正常使用,之前为了使用arcgis,因此卸载了anaconda3和python3,PyCharm不能正常使用了 之前安装的卸载后…...
【C语言干货】回调函数
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、回调函数 前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、回调函数 在 C 语言中,当你有一个函数并希望将其作…...
Redis使用总结
NoSQL 1.1为什么要用NoSQL 面对现在用户数据的急剧上升,我们需要对这些用户数据进行挖掘,传统的关系型数据库已经不适合这些 应用了.Nosql 的发展可以很了的处理这些大的数据. 1.2什么是NoSQL Not Only Sql->NoSQL(不仅仅是SQL) 非关系型数据库.随…...
现场问题排查-postgresql某表索引损坏导致指定数据无法更新影响卷宗材料上传
问题现象 今天突然被拉进一个群,说某地区友商推送编目结果报错,在我们自己的卷宗系统上传材料也一直转圈,也删除不了案件卷宗,重置模板也没用,只有个别案件有问题。虽然这事儿不属于我负责,但还是抽时间给…...