STM32定时器应用:实现1ms中断与10us延迟

版权申诉
0 下载量 97 浏览量 更新于2024-11-04 收藏 3KB RAR 举报
资源摘要信息:"STM32_TIM.rar_stm32 delay_stm32 tim_stm32 定时器 1ms_stm32 延迟" 在微控制器领域,STM32是STMicroelectronics(意法半导体)公司生产的一系列基于ARM Cortex-M微处理器的广泛使用的32位微控制器。STM32系列因其实时性能、丰富的外设接口和灵活的软件支持而备受欢迎。该文件“STM32_TIM.rar_stm32 delay_stm32 tim_stm32 定时器 1ms_stm32 延迟”集中讨论了STM32微控制器中定时器(TIM)的使用,特别是如何配置和使用定时器产生精确的1ms中断和10微秒(us)的延迟。 ### 定时器基础 在STM32微控制器中,定时器(TIM)是一种灵活的计时器/计数器,可用于多种功能,包括产生周期性中断(用于任务调度和时间基准)、PWM波形生成、输入捕获(测量时间间隔或频率)等。 ### 定时器的配置和使用 为了产生1ms的中断,需要配置定时器的预分频器(Prescaler)和自动重装载寄存器(Auto-reload register),这两个参数共同决定了定时器的更新事件(Update Event)的频率,进而决定中断的频率。具体步骤可能包括: 1. **选择合适的时钟源**:首先,需要选择定时器的时钟源,通常是APB总线上的时钟(APB1或APB2),取决于定时器挂载在哪个总线上。时钟频率的两倍通常作为定时器的输入时钟频率(因为APB1的最大频率通常是内核时钟的一半,而APB2的频率和内核时钟相同)。 2. **计算预分频器和自动重装载寄存器值**:通过将时钟频率除以所需中断频率得到定时器计数频率,再用定时器计数频率除以最大计数值(16位定时器的最大值为65535,32位则为***)计算出预分频器的值,然后用最大计数值减去计算出的定时器计数频率得到自动重装载寄存器的值。 3. **配置中断**:在NVIC(Nested Vectored Interrupt Controller)中配置定时器的中断优先级,使能定时器中断通道,编写中断服务函数(ISR),并在该函数中添加用户代码,用于处理中断事件。 4. **启动定时器**:通过设置定时器控制寄存器中的相应位启动定时器,开始产生中断。 ### 延迟的实现 STM32微控制器中实现精确延迟通常有软件延迟和硬件定时器延迟两种方法。软件延迟通过循环消耗时间来实现,但这种方法效率低下且不易控制。使用硬件定时器则可实现精确的延迟。 1. **软件延迟**:通过循环执行空操作(如NOP指令)来消耗时间。这种方法的缺点是占用CPU资源,且因指令执行时间的波动(可能受流水线、分支预测等因素影响)而不准确。 2. **硬件定时器延迟**:使用定时器的计数溢出功能,当计数器值达到设定值时产生中断。在中断服务函数中可以计数中断发生的次数,从而精确控制延迟时间。这种方法准确且不占用CPU资源。 ### 产生10微秒延迟的方法 要产生10微秒的延迟,可以使用定时器的快速脉冲模式,或者通过直接操作GPIO(通用输入输出)来实现。快速脉冲模式下,定时器被配置为产生非常短的脉冲。对于GPIO方法,则需要精确计算并产生一个宽度为10微秒的脉冲信号。 1. **定时器快速脉冲模式**:配置定时器产生一个很短的周期,然后在中断服务函数中计算中断发生的次数,通过次数控制延迟时间。 2. **直接GPIO操作**:通过GPIO控制一个引脚的高低电平变化,精确控制脉冲宽度。这种方法虽然简单,但需要对硬件非常熟悉,并且可能会受到GPIO操作速度的限制。 ### 总结 STM32定时器的应用非常广泛,从简单的延迟到复杂的PWM控制,都是基于定时器的精确时序控制能力。本文档中所提及的STM32定时器配置方法、产生1ms中断和10微秒延迟的技巧,对于希望深入学习STM32微控制器编程的开发者来说,是一个重要的参考资源。理解并掌握这些基础知识,可以帮助开发人员更加高效地开发出性能稳定、时序精确的嵌入式系统。

修改 #include "stm32f10x.h" void TIM4_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* 使能定时器4时钟 / RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); / 定时器基本配置 / TIM_TimeBaseStructure.TIM_Period = 20000; // 每个PWM周期为20ms TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; // 定时器预分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); / PWM模式配置 / TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; / PWM输出通道1配置 / TIM_OC1Init(TIM4, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); / PWM输出通道3配置 / TIM_OC3Init(TIM4, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); / 使能定时器4 / TIM_Cmd(TIM4, ENABLE); } void Servo_Control(uint16_t angle1, uint16_t angle2) { uint16_t ccr1 = 1000 + (angle1 * 1000 / 180); // 将角度转换为对应的PWM占空比 uint16_t ccr3 = 1000 + (angle2 * 1000 / 270); / 设置PWM输出占空比 / TIM_SetCompare1(TIM4, ccr1); TIM_SetCompare3(TIM4, ccr3); } int main(void) { / 初始化定时器4和GPIOB的相应引脚 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); TIM4_Configuration(); while(1) { Servo_Control(0, 0); // 控制舵机1和舵机2的角度 delay_ms(1000); // 延迟1秒 Servo_Control(90, 135); delay_ms(1000); Servo_Control(180, 270); delay_ms(1000); Servo_Control(90, 135); delay_ms(1000); } }

2023-05-30 上传

这段代码的含义(#include "stm32f10x.h" // Device header #include "stm32f10x_gpio.h" #define PWM_PERIOD 1000 // PWM波形周期,单位us void TIM_Configuration(void); void GPIO_Configuration(void); int main(void) { GPIO_Configuration(); TIM_Configuration(); while (1) { // 不断更新PWM占空比以控制电机转速 TIM_SetCompare2(TIM1, 500); // 设置占空比为50% delay_ms(1000); TIM_SetCompare2(TIM1, 750); // 设置占空比为75% delay_ms(1000); TIM_SetCompare2(TIM1, 250); // 设置占空比为25% delay_ms(1000); } } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); // PA8 -> TIM1_CH1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // PB13 -> TIM1_CH2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // PB14 -> TIM1_CH3 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // PB15 -> DRV8313_EN GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // PB12 -> DRV8313_FAULT GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD - 1; TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 72MHz时钟,分频为72,计数频率为1MHz TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // PWM模式1,TIM1_CH2作为PWM输出 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM1, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); // 启用死区时间,设置死区时间为1us TIM_BDTRInitStructure.TIM_DeadTime = 10; TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); // 启动TIM1 TIM_Cmd(TIM1, ENABLE); // 使能DRV8313芯片 GPIO_SetBits(GPIOB, GPIO_Pin_15); })

2023-05-19 上传
2023-07-15 上传

float speed; int main(void) { Breath_Init (); KEY_InitU(); OLED_Init(); Motor_init(); OLED_ShowString(1,1,"Rspeed:"); while (1) { Motor_derection(20); } } #include "stm32f10x.h" // Device header void Breath_Init () { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); GPIO_InitTypeDef GPIO_Initstucture; GPIO_Initstucture.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽 GPIO_Initstucture.GPIO_Pin=GPIO_Pin_0; GPIO_Initstucture.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_Initstucture); TIM_InternalClockConfig(TIM2); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitstucture; TIM_TimeBaseInitstucture.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInitstucture.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInitstucture.TIM_Period=100-1;//72M/TIM_Period为频率也是ARR TIM_TimeBaseInitstucture.TIM_Prescaler=72-1;//分频也是PSC TIM_TimeBaseInitstucture.TIM_RepetitionCounter=0;//周期数 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitstucture); TIM_OCInitTypeDef TIM_OCInitstructure; TIM_OCStructInit(&TIM_OCInitstructure); TIM_OCInitstructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitstructure.TIM_OCPolarity=TIM_OCPolarity_High; TIM_OCInitstructure.TIM_OutputState=TIM_OutputState_Enable; TIM_OCInitstructure.TIM_Pulse=0;//CCR TIM_OC1Init(TIM2,&TIM_OCInitstructure); TIM_Cmd(TIM2,ENABLE); } void TIM_Compare(uint16_t compare) { TIM_SetCompare1(TIM2,compare); } void KEY_InitD (void)//下拉 { //GPIOB初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_Initstructure; GPIO_Initstructure.GPIO_Mode =GPIO_Mode_IPD ; GPIO_Initstructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_Initstructure); } void KEY_InitU (void)//上拉 { //GPIOB初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_Initstructure; GPIO_Initstructure.GPIO_Mode =GPIO_Mode_IPU ; GPIO_Initstructure.GPIO_Pin = GPIO_Pin_1; GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_Initstructure); } uint16_t Key_GetNum () { uint8_t KeyNum = 0; if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) { Delay_ms(20); while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0); Delay_ms(20); KeyNum = 1; } } void Motor_init () { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; GPIO_Init(GPIOA, &GPIO_InitStructure); } void Motor_derection (float speed) { if(speed>0) { GPIO_SetBits(GPIOA,GPIO_Pin_4);//in1 GPIO_ResetBits(GPIOA,GPIO_Pin_5);//in2 TIM_Compare(speed); } else GPIO_ResetBits(GPIOA,GPIO_Pin_4);//in1 GPIO_SetBits(GPIOA,GPIO_Pin_5);//in2 TIM_Compare(-speed); } 为什么直流电机不转

2023-07-23 上传