完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
近期在学习和培训时重新熟悉了一下这方面的内容,一方面自己也是整理了一下,一方面也和新人小白们分享一下经验,大神轻喷。
话不多说,直接进入正题。首先知道正常的PWM波是用一个定时器输出的,配置好以后就开始源源不断地输出波形。那么如何控制波形脉冲的个数呢?这里我提出三种设计思路:
用定时器的主从模式来做 这里先上代码,再做解释 pwm.c文件: #include "pwm.h"void TIM1_PWM_Init(u16 arr,u16 psc)//主定时器{ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//TIM1时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //GPIO外设时钟使能 //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = arr/2-1; //设置待装入捕获比较寄存器的脉冲值,即占空比50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);//主从模式 TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);//TIM1更新产生触发,把TIM1的CR2的MMS位置为010 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能 TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器 }void TIM2_PWM_Init(u16 PulseNum)//从定时器{ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Period = PulseNum-1;//设置输出的波形数量 TIM_TimeBaseStructure.TIM_Prescaler =0; TIM_TimeBaseStructure.TIM_ClockDivision=0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0);//设置SMCR寄存器的TS位,进行触发选择 TIM2->SMCR|=0x07; //设置SMCR寄存器的SMS位,选择外部时钟源模式1 TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE); //定时器2更新先失能 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }//进入TIM2中断意味着脉冲数量够了,之后停止输出void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); TIM_CtrlPWMOutputs(TIM1,DISABLE); TIM_Cmd(TIM1, DISABLE); TIM_Cmd(TIM2, DISABLE); TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); }}void Pulse_output(u16 arr,u16 psc,u16 PulseNum){ TIM2_PWM_Init(PulseNum); TIM_Cmd(TIM2, ENABLE); TIM_ClearITPendingBit(TIM2,TIM_IT_Update); TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); TIM1_PWM_Init(arr,psc); TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能 TIM_Cmd(TIM1, ENABLE);//先使能TIM2再使能TIM1,保证每个脉冲都被检测到。}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778文件里面包括了4个函数,TIM1_PWM_Init(u16 arr,u16 psc)和 TIM2_PWM_Init(u16 PulseNum)都是配置的函数,Pulse_output(u16 arr,u16 psc,u16 PulseNum)是入口函数,它调用了两个配置函数并先后使能,它也在主函数里被调用。 要注意的一点是,由于TIM1是高级定时器,所以一定需要一个主输出使能以后才会真正有输出。pwm.h文件是在声明这几个函数,就没什么好说的了。 主函数main.c #include "delay.h"#include "sys.h"#include "pwm.h"int main(void) { delay_init(); //延时函数初始化 while(1) {Pulse_output(899,0,100); delay_ms(10); } }123456789主函数就十分简单了,我这里设置波形的周期是12.5mu sμs ,每次输出100个(用了1.25msms),然后每10msms重复一次。 通过波形仿真可以看到效果 再放大一点看,一次是100个脉冲 用高级定时器的重复计数功能来做 首先要注意的是对于STM32F103系列的来说只有TIM1和TIM8有重复计数功能。 利用这个功能来做的时候就只用一个定时器就好了。重复计数的本质就是设置定时器溢出多少次再产生一个更新中断。RCR的基本知识参考手册里也有 这里也直接贴上代码 pwm.c: void TIM1_PWM_Init(u16 arr,u16 psc){ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能 //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseStructure.TIM_RepetitionCounter = 10; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = arr/2-1; //设置待装入捕获比较寄存器的脉冲值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx TIM_ClearITPendingBit(TIM1, TIM_IT_Update); TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能 TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器 TIM_Cmd(TIM1, ENABLE); //使能TIM1 }123456789101112131415161718192021222324252627282930313233343536373839404142主函数直接调用这个函数就OK了。改变数量就是改变TIM_TimeBaseStructure.TIM_RepetitionCounter的值,但由于RCR只有8位,所以它最大255 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1800 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1629 浏览 1 评论
1096 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
735 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1684 浏览 2 评论
1943浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
744浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
578浏览 3评论
601浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
563浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 23:15 , Processed in 0.652528 second(s), Total 48, Slave 42 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号