STM32使用标准库存在bug?还是我使用不对?
本帖最后由 单片机_电子爱好者 于 2018-8-30 13:50 编辑这几天一直在搞stm32f0的芯片,在使用stm的高级定时器tim输出pwm时,正常配置输出正常,但是如果每隔一定时间(人为控制)对TIM1的PWM输出初始化,就会有可能PWM输出不了,一旦输出不了,就再也不能输出,必须重新上电才可以,不知道什么原因造成的?麻烦又遇到的人或者高手指导下,谢谢 (上一次对TIM16初始化也造成了TIM1 pwm输出有问题,和上面情况类似,后来只对tim16初始化一次就好了,一直不知道为什么,今天又遇到了,很奇怪)
初始化函数如下(keil5的编码没有改,注释全部乱码了):
void TIM1_PWM_Config(void)
{
TIM_TimeBaseInitTypeDefTIM_Time1BaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t TimerPeriod = 0;
/* TIM1 µÄÅäÖà ---------------------------------------------------
TIM1 ÊäÈëʱÖÓ(TIM1CLK) ÉèÖÃΪ APB2 ʱÖÓ (PCLK2)
=> TIM1CLK = PCLK2 = SystemCoreClock
TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock
SystemCoreClock Ϊ48 MHz*/
TimerPeriod = (SystemCoreClock / DEF_PWMFRE);
/* TIM1 ʱÖÓʹÄÜ */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
// /* TIM1 ʹÄÜ*/
// TIM_Cmd(TIM1, DISABLE);
/* Time ¶¨Ê±»ù´¡ÉèÖÃ*/
TIM_Time1BaseStructure.TIM_Prescaler = 0;
TIM_Time1BaseStructure.TIM_CounterMode = TIM_CounterMode_Up ;/* ÉèÖÃ¶ÔÆëģʽ Time TIM_CounterMode_Up¶¨Ê±ÉèÖÃΪÉÏÉýÑØ¼ÆËãģʽ*/
TIM_Time1BaseStructure.TIM_Period = TimerPeriod;//PWM_PERIOD
TIM_Time1BaseStructure.TIM_ClockDivision = 0;
TIM_Time1BaseStructure.TIM_RepetitionCounter = 0; // ÖØ¸´¼ÆÊýÉèÖÃ
TIM_TimeBaseInit(TIM1, &TIM_Time1BaseStructure);
/* ƵµÀ1,2,3,4µÄPWM ģʽÉèÖà */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable ;//TIM_OutputState_Enable; //PWMÊä³öʹÄÜλ
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable ;//TIM_OutputNState_Enable; //»¥²¹PWMÊä³öʹÄÜλ
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//PWM 1ΪÓÐЧµçƽ ¿ÉÉèÖÃµçÆ½·´×ª TIM_OCPolarity_Low
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //PWM»¥²¹ 0ΪÎÞЧµçƽ ¿ÉÉèÖÃµçÆ½·´×ª TIM_OCPolarity_Low
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = 0; //¸³Õ¼¿Õ±ÈÖµ
TIM_OC1Init(TIM1, &TIM_OCInitStructure);//ʹÄÜÆµµÀ1ÅäÖÃ
TIM_OCInitStructure.TIM_Pulse = 0; //¸³Õ¼¿Õ±ÈÖµ
TIM_OC2Init(TIM1, &TIM_OCInitStructure);//ʹÄÜÆµµÀ2ÅäÖÃ
TIM_OCInitStructure.TIM_Pulse = 0; //¸³Õ¼¿Õ±ÈÖµ
TIM_OC3Init(TIM1, &TIM_OCInitStructure);//ʹÄÜÆµµÀ3ÅäÖÃ
//------ʹÄܱȽÏËÄͨµÀ------------------------------------
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable ;//TIM_OutputState_Enable; //
//TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable ; //ʹÓÃADC_ExternalTrigConv_T1_CC4´¥·¢ÐèÒª´ò¿ªcc4Êä³ö²ÅÄÜ´¥·¢ADC
TIM_OCInitStructure.TIM_Pulse = PWM_PERIOD_30P;
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
//TIM_ITConfig(TIM1,TIM_IT_CC4, ENABLE); //TIM1±È½ÏËÄÖжÏ
TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);//Ñ¡ÔñTRGOÊä³ö
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Disable); // ½ûÖ¹OC4Ԥװֵ
//------ÅäÖÃTIME1 BREAKPB12¹¦ÄÜ-----------------------------------
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOB , &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_2);
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 48;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;//TIM_BreakPolarity_Low
//TIM_AutomaticOutput_Enable ɲ³µºó£¬É²³µÊäÈëµçƽ±äΪÎÞЧºó£¬ÏÂÒ»¸öÂö³åÖÜÆÚ£¬×Ô¶¯»Ö¸´Âö³åÊä³ö
//TIM_AutomaticOutput_Disable ɲ³µºó£¬Âö³åÊä³öÓÀ¾Ã½ûÖ¹£¬³ý·ÇÊÖ¶¯µ÷ÓÃTIM_CtrlPWMOutputs(TIM1, ENABLE)£¬·ñÔò²»ÄÜÆô¶¯pwm
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
TIM_ITConfig(TIM1,TIM_IT_Break, ENABLE); //TIME1 COM??
//TIM_CCPreloadControl(TIM1, ENABLE);
TIM_ITConfig(TIM1,TIM_IT_Update, DISABLE); //TIME1 COM??
NVIC_InitStructure.NVIC_IRQChannel = TIM1_BRK_UP_TRG_COM_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//ËÀÇøÊ±¼äÉèÖÃ0.93us
TIM1->BDTR|=0x002D;
//--------------------------------------------------------
/* TIM1 ʹÄÜ*/
TIM_Cmd(TIM1, ENABLE);
/* TIM1 Ö÷Êä³öʹÄÜ */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}发一下中断函数:
void TIM1_CC_IRQHandler()
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET) // CC4比较中断
{
...和tim1操作没有关系代码.....
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4 );
}
}
在网上找到遇到类似问题的帖子 http://bbs.21ic.com/icview-350027-1-1.html
我的问题是多次初始化之后三路PWM中有一路输出不了,并且总是同一路,在线仿真观测改路的OC寄存器,发现和其他路设置相同,没有不一样的地方
是否bug不该过早定论。
运行中要初始化定时器,应该先关闭定时器吧?
TIM_Cmd(TIM1, DISABLE); 只有初始化代码,没有对应中断处理函数的代码,也不知道你“人为控制”怎么设置的初始化,分析起来有点难度呀
比如用到了其他中断,但是未清除,肯定有问题 在keil–edit–configuration中encoding改为chinese-GB2312 今天改了下字体再把初始函数发一下(字体没有乱码就是看着有点别扭)
void TIM1_PWM_Config(void)
{
TIM_TimeBaseInitTypeDefTIM_Time1BaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t TimerPeriod = 0;
/* TIM1 的配置 ---------------------------------------------------
TIM1 输入时钟(TIM1CLK) 设置为 APB2 时钟 (PCLK2)
=> TIM1CLK = PCLK2 = SystemCoreClock
TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock
SystemCoreClock 为48 MHz*/
TIM_DeInit(TIM1); // 初始化TIM1
//TimerPeriod = (SystemCoreClock / DEF_PWMFRE);
TimerPeriod = (48000000 / DEF_PWMFRE);
/* TIM1 时钟使能 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
/* TIM1 使能*/
TIM_Cmd(TIM1, DISABLE);
/* Time 定时基础设置*/
TIM_Time1BaseStructure.TIM_Prescaler = 0;
TIM_Time1BaseStructure.TIM_CounterMode = TIM_CounterMode_Up ;/* 设置对齐模式 Time TIM_CounterMode_Up定时设置为上升沿计算模式*/
TIM_Time1BaseStructure.TIM_Period = TimerPeriod;//PWM_PERIOD
TIM_Time1BaseStructure.TIM_ClockDivision = 0;
TIM_Time1BaseStructure.TIM_RepetitionCounter = 0; // 重复计数设置
TIM_TimeBaseInit(TIM1, &TIM_Time1BaseStructure);
/* 频道1,2,3,4的PWM 模式设置 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable ;//TIM_OutputState_Enable; //PWM输出使能位
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable ;//TIM_OutputNState_Enable; //互补PWM输出使能位
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//PWM 1为有效电平 可设置电平反转 TIM_OCPolarity_Low
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //PWM互补 0为无效电平 可设置电平反转 TIM_OCPolarity_Low
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = 0; //赋占空比值
TIM_OC1Init(TIM1, &TIM_OCInitStructure);//使能频道1配置
TIM_OCInitStructure.TIM_Pulse = 0; //赋占空比值
TIM_OC2Init(TIM1, &TIM_OCInitStructure);//使能频道2配置
TIM_OCInitStructure.TIM_Pulse = 0; //赋占空比值
TIM_OC3Init(TIM1, &TIM_OCInitStructure);//使能频道3配置
//------使能比较四通道------------------------------------
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable ;//TIM_OutputState_Enable; //
//TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable ; //使用ADC_ExternalTrigConv_T1_CC4触发需要打开cc4输出才能触发ADC
TIM_OCInitStructure.TIM_Pulse = PWM_PERIOD_30P;
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
//TIM_ITConfig(TIM1,TIM_IT_CC4, ENABLE); //TIM1比较四中断
TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);//选择TRGO输出
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Disable); // 禁止OC4预装值
//------配置TIME1 BREAKPB12功能-----------------------------------
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOB , &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_2);
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 48;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;//TIM_BreakPolarity_Low
//TIM_AutomaticOutput_Enable 刹车后,刹车输入电平变为无效后,下一个脉冲周期,自动恢复脉冲输出
//TIM_AutomaticOutput_Disable 刹车后,脉冲输出永久禁止,除非手动调用TIM_CtrlPWMOutputs(TIM1, ENABLE),否则不能启动pwm
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
TIM_ITConfig(TIM1,TIM_IT_Break, ENABLE); //TIME1 COM??
//TIM_CCPreloadControl(TIM1, ENABLE);
TIM_ITConfig(TIM1,TIM_IT_Update, DISABLE); //TIME1 COM??
NVIC_InitStructure.NVIC_IRQChannel = TIM1_BRK_UP_TRG_COM_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//死区时间设置0.93us
TIM1->BDTR|=0x002D;
//--------------------------------------------------------
/* TIM1 使能*/
TIM_Cmd(TIM1, ENABLE);
/* TIM1 主输出使能 */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
} wenyangzeng 发表于 2018-8-28 21:46
是否bug不该过早定论。
运行中要初始化定时器,应该先关闭定时器吧?
TIM_Cmd(TIM1, DISABLE); ...
我试过加TIM_Cmd(TIM1, DISABLE);一样的有问题,我加了TIM_DeInit(TIM1);都没有什么用 feixiang20 发表于 2018-8-29 02:20
在keil–edit–configuration中encoding改为chinese-GB2312
谢谢,改了字体,不乱码了,看着有点别扭,改成UTF-8比较好,就是转来转去麻烦:lol,还是KEIL4好使 中断函数也发一下
void TIM1_CC_IRQHandler()
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET) // CC4比较中断
{
....中间代码省略(没有设计到TIM1操作的代码)....
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4 );
}
}
在网上要搜到差不多类似情况的帖子
http://bbs.21ic.com/icview-350027-1-1.html
我的情况是三路PWM有一路输出不了,而且每次都是同一路,仿真时该路的OC寄存器设置都正常 发一下中断函数:
void TIM1_CC_IRQHandler()
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET) // CC4比较中断
{
...和tim1操作没有关系代码.....
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4 );
}
}
在网上找到遇到类似问题的帖子 http://bbs.21ic.com/icview-350027-1-1.html
我的问题是多次初始化之后三路PWM中有一路输出不了,并且总是同一路,在线仿真观测改路的OC寄存器,发现和其他路设置相同,没有不一样的地方
页:
[1]