| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> STM32 高级定时器 COM事件 -> 正文阅读 |
|
[嵌入式]STM32 高级定时器 COM事件 |
STM32高级定时器COM事件-软件方式产生 STM32的COM事件只针对高级定时器TIM1和TIM8有效,主要是用来BLDC方波(6步梯形波)控制中更新3路PWM占空比,达到3相同时换相(即同时更新占空比),如果采用普通的更新占空比,则会造成3个通道先后延迟;这里BLDC控制采用H_PWM-L_ON(即上MOS用PWM,下MOS用高低(开关)电平,实际采用PWM占比100%), 设计思路是:换相更新3路占空比,然后在另一处产生COM事件使得前面设置的占空比生效 COM事件产生有2中方式:通过函数TIM_SelectCOM()来选择
硬件TRGI又由什么条件产生呢:看下图 红色方框是TRGI的输入源,选择器前面的都是TRGI的来源,我们追踪可以看到相关的寄存器TIMx_SMCR 关于硬件方式产生COM事件请看另一篇文章,这里不做过多说明 1.涉及到的寄存器有: TIMx_CR2 说明一下:CCPUS位:更新方式选择,一般选择CCUS=1,软件和硬件都能更新 2.使用常见的换向方式见下表格,这里采用有感HALL换相触发 换相表:546231 5:导通相Q3、Q6 4:导通相Q3、Q2 6:导通相Q5、Q2 2:导通相Q5、Q4 3:导通相Q1、Q4 1:导通相Q1、Q6 设计步骤
TIM_CCPreloadControl(TIM8,ENABLE);//使能捕获比较预装载控制 TIM8->CCER&=0x0000;//关闭6路PWM输出或者其他库函数TIM_CCxCmd()等实现关闭功能 //COM中断配置(不必须的) ?????? NVIC_InitStre.NVIC_IRQChannel=TIM8_TRG_COM_TIM14_IRQn; ?????? NVIC_InitStre.NVIC_IRQChannelPreemptionPriority=0x02; ?????? NVIC_InitStre.NVIC_IRQChannelSubPriority=0x01; ?????? NVIC_InitStre.NVIC_IRQChannelCmd=ENABLE; ?????? NVIC_Init(&NVIC_InitStre);//初始化 ?????? TIM_ITConfig(TIM8,TIM_IT_COM,ENABLE);//使能TIM1/8的COM触发中断 2.6路IO口初始化,配置高级定时器 3.HALL定时器和IO初始化 4.HALL的输入捕获中断服务函数编写 5.COM事件触发的中断服务函数编写(可不要) 这里只说明设计思路和算法过程,详细的关于BLDC的算法设计请参见其他资料 HALL的输入捕获中断服务函数,完成功能: ?????? 根据hall读取值判断换相顺序,在对应的换相中,更新3路占空比(这时候还没有生效) Switch(ReadHallVal) { Case 5:更新3路占空比;TIM8->CCER=SetVal_DISABLE_ENABLE; break; Case 4:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break; Case 3:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break; Case 2:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break; Case 6:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break; Case 1:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break; } 更新占空比值可用TIMx_CCRx=Num;或函数TIM_SetCompare1()等 SetVal_DISABLE_ENABLE值是换相对应的选择通道,具体如何设定参见TIM8->CCER寄存器,就是配置相关的通道使能或失能 TIM_GenerateEvent(TIM8,TIM_EventSource_COM);//完成COM事件的产生,设定的占空比真正生效,当然生效还可以由硬件自动产生(TRGI) 这个时候就会触发TIM8的COM事件中断(如果配置中断的话),中断可要可不要,如果没有对应需要处理的任务,可以不加 //TIM8 COM事件触发实验,中断服务函数 void TIM8_TRG_COM_TIM14_IRQHandler(void) { //LED电平翻转,用来对照 } 演示代码:我们用软件方式产生COM事件来更新占空比 3.对互补通道PWM输出,定时器TIM8 #define CH1_ON_CH23_OFF (0x0444|(0x001<<0)) //CH1开 CH2关 CH3关 #define CH2_ON_CH13_OFF (0x0444|(0x001<<4)) //CH1关 CH2开 CH3关 #define CH3_ON_CH12_OFF (0x0444|(0x001<<8)) //CH1关 CH2关 CH3开 //IO口初始化 ?????? GPIO_InitTypeDef GPIO_InitStre; ?????? ?????? RCC_AHB1PeriphClockLPModeCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC, ENABLE); ?????? ?????? GPIO_InitStre.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8; ?????? GPIO_InitStre.GPIO_Mode=GPIO_Mode_AF; ?????? GPIO_InitStre.GPIO_OType=GPIO_OType_PP; ?????? GPIO_InitStre.GPIO_PuPd=GPIO_PuPd_DOWN; ?????? GPIO_InitStre.GPIO_Speed=GPIO_Speed_2MHz; ?????? GPIO_Init(GPIOC, &GPIO_InitStre); ?????? ?????? GPIO_InitStre.GPIO_Pin=GPIO_Pin_14|GPIO_Pin_15; ?????? GPIO_InitStre.GPIO_Mode=GPIO_Mode_AF; ?????? GPIO_InitStre.GPIO_OType=GPIO_OType_PP; ?????? GPIO_InitStre.GPIO_PuPd=GPIO_PuPd_NOPULL; ?????? GPIO_InitStre.GPIO_Speed=GPIO_Speed_2MHz; ?????? GPIO_Init(GPIOB, &GPIO_InitStre); ?????? ?????? GPIO_InitStre.GPIO_Pin=GPIO_Pin_7; ?????? GPIO_InitStre.GPIO_Mode=GPIO_Mode_AF; ?????? GPIO_InitStre.GPIO_OType=GPIO_OType_PP; ?????? GPIO_InitStre.GPIO_PuPd=GPIO_PuPd_NOPULL; ?????? GPIO_InitStre.GPIO_Speed=GPIO_Speed_2MHz; ?????? GPIO_Init(GPIOA, &GPIO_InitStre); ?????? ?????? ? /* Connect TIM3 pins to AF2 */? ?????? GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM8); ?????? GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM8); ?????? GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM8); ?????? ?????? GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM8); ?????? GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_TIM8); ?????? GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_TIM8); ?????? TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStre; ?????? TIM_OCInitTypeDef TIM_OCInitStre; ?????? TIM_BDTRInitTypeDef???? TIM_BDTRInitStructure; ?????? //定时器初始化 ?????? RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); ?????? PV_PEEP_IO_Init();//IO口初始化 ?????? ?????? //计数频率20kHz=168/(TIM_Prescaler+1)/(TIM_Period+1) ?????? TIM_TimeBaseInitStre.TIM_Prescaler=100-1;//定时器频率168M/(0+1) ?????? TIM_TimeBaseInitStre.TIM_Period=11200-1;//周期计数值 15k-11200? 一个计数值 改成20kHz-8400 ?????? TIM_TimeBaseInitStre.TIM_ClockDivision=0x00;//不分频 ?????? TIM_TimeBaseInitStre.TIM_CounterMode=TIM_CounterMode_CenterAligned1 ; ?????? TIM_TimeBaseInitStre.TIM_RepetitionCounter=0x00; ?????? TIM_TimeBaseInit(TIM8, &TIM_TimeBaseInitStre); ?????? ?????? TIM_OCInitStre.TIM_OCMode=TIM_OCMode_PWM1; ?????? TIM_OCInitStre.TIM_OCPolarity=TIM_OCPolarity_High ; ?????? TIM_OCInitStre.TIM_OCIdleState=TIM_OCIdleState_Reset ; ?????? TIM_OCInitStre.TIM_OutputState=TIM_OutputState_Enable; ?????? ?????? TIM_OCInitStre.TIM_OCNPolarity=TIM_OCPolarity_High; ?????? TIM_OCInitStre.TIM_OCNIdleState=TIM_OCIdleState_Reset; ?????? TIM_OCInitStre.TIM_OutputNState=TIM_OutputState_Enable ; ????????????? ?????? TIM_OCInitStre.TIM_Pulse=0;//占空比0% ?????? TIM_OC1Init(TIM8, &TIM_OCInitStre);//消音圈 ?????? ?????? TIM_OCInitStre.TIM_Pulse=0;//占空比0% ?????? TIM_OC2Init(TIM8, &TIM_OCInitStre);//消音圈 ?????? ?????? TIM_OCInitStre.TIM_Pulse=0;//占空比0% ?????? TIM_OC3Init(TIM8, &TIM_OCInitStre);//消音圈 ?????? ?????? TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; ? TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; ? TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; ? TIM_BDTRInitStructure.TIM_DeadTime = 132;// ?????? TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; ? TIM_BDTRConfig(TIM8, &TIM_BDTRInitStructure); ?????? ?????? TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable); ?????? TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable); ?????? TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable); ?????? TIM_CtrlPWMOutputs(TIM8, ENABLE);//高级定时器要加这个使能 ?????? TIM_Cmd(TIM8, ENABLE);//使能时钟 ?????? TIM_GenerateEvent(TIM8, TIM_EventSource_Update); ?????? TIM8->CCER = 0x0444;//失能3对通道输出PWM 这里使用串口中断接收数据,来模拟6步换相 void USART1_IRQHandler( void )//串口1中断 { ?????? u8 CHannel = 0; ?????? ?????? //接收 ?????? if( USART_GetITStatus( USART1, USART_IT_RXNE ) != RESET ) ?????? {???????????? ????????????????CHannel = USART_ReceiveData( USART1 ); ?????? } switch(CHannel) { Case1:TIM8->CCR1=5000;TIM8->CCR2=0;TIM8->CCR3=0;TIM8->CCER=CH2_ON_CH13_OFF;?TIM_GenerateEvent(TIM8, TIM_EventSource_Update);break;//TIM8->CCER=0x0445 case2:TIM8->CCR1=0;TIM8->CCR2=5000;TIM8->CCR3=0;TIM8->CCER=CH2_ON_CH13_OFF;?TIM_GenerateEvent(TIM8, TIM_EventSource_Update);break; case3:TIM8->CCR1=0;TIM8->CCR2=0;TIM8->CCR3=5000;TIM8->CCER=CH3_ON_CH12_OFF;?TIM_GenerateEvent(TIM8, TIM_EventSource_Update);break; default:;break; } TIM_GenerateEvent(TIM8,TIM_EventSource_COM);//产生COM事件 } 为什么要加TIM_GenerateEvent(TIM8, TIM_EventSource_Update);是为了让计数器清0,即TIM8->CNT=0 实验现象: PWM输出通道开始占空比=0,外部串口产生事件触发对应通道占空比更新,计数;占空比=设定值,示波器波形如下 图1是硬件自动更新占空比比较值,可以看到通道切换间由很明显的延迟 图1 图2是软件产生的COM事件来更新占空比比较值,通道切换几乎没有延迟 ? 图2 |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 9:40:12- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |