[APM32F1] apm32f103c8t6PWM输出3MHZ脉冲方波为什么不稳定?

[复制链接]
 楼主| 叶萌 发表于 2022-11-16 15:31 | 显示全部楼层 |阅读模式
有没有大佬帮忙看看,为什么输出3mhz的脉冲方波,脉冲个数不稳定?代码如下,用的apm32f103c8t6,定时器1的通道1输出,帮忙看看,谢谢!
  1. void  InitTime1Config(void)
  2. {
  3.         GPIO_Config_T GPIO_ConfigStruct;
  4.     TMR_BaseConfig_T TMR_TimeBaseStruct;
  5.     TMR_OCConfig_T OCcongigStruct;
  6.    
  7.     RCM_EnableAPB2PeriphClock((RCM_APB2_PERIPH_T)(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_TMR1 ));

  8.     GPIO_ConfigStruct.pin = GPIO_PIN_8;
  9.     GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
  10.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  11.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);
  12.    
  13.     TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
  14.     TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_CENTERALIGNED2;
  15.     TMR_TimeBaseStruct.division = 4;
  16.     TMR_TimeBaseStruct.period = 2;
  17.     TMR_ConfigTimeBase(TMR1, &TMR_TimeBaseStruct);
  18.        
  19.     OCcongigStruct.idleState = TMR_OC_IDLE_STATE_RESET;
  20.     OCcongigStruct.mode = TMR_OC_MODE_PWM1;
  21.     OCcongigStruct.nIdleState = TMR_OC_NIDLE_STATE_RESET;
  22.     OCcongigStruct.nPolarity = TMR_OC_NPOLARITY_HIGH;
  23.     OCcongigStruct.outputNState = TMR_OC_NSTATE_ENABLE;
  24.     OCcongigStruct.outputState = TMR_OC_STATE_ENABLE;
  25.     OCcongigStruct.polarity = TMR_OC_POLARITY_HIGH;//Êä³ö¼«ÐÔΪHIGH
  26.     OCcongigStruct.pulse = 1;
  27.     TMR_ConfigOC1(TMR1, &OCcongigStruct);
  28.         TMR_ConfigOC1Preload(TMR1, TMR_OC_PRELOAD_ENABLE);
  29.        
  30.         TMR_EnablePWMOutputs(TMR1);
  31.        
  32.         TMR_EnableAUTOReload(TMR1);
  33.     TMR_Enable(TMR1);
  34. }   
复制代码
下面还有示波器的图片,黄色为3mhz晶振的效果,可见脉冲个数稳定在15k,蓝色是我的代码输出的wm波,可见脉冲个数不太稳定,有没有大佬指点一下,谢谢
3mhz.jpg
3mhz2.jpg
 楼主| 叶萌 发表于 2022-11-16 15:32 | 显示全部楼层
 楼主| 叶萌 发表于 2022-11-17 09:06 | 显示全部楼层
17666100887 发表于 2022-11-17 08:58
我们是极海的代理,可以加我微信,17666100887

代理能懂这个嘛
一叶倾城wwq 发表于 2022-11-17 11:03 | 显示全部楼层
什么驱动需要上兆的pwm?不稳定除了配置问题就是被其他中断打断了呗

评论

不是驱动 就是和超声波发射之类的有关系 目前除了系统时钟的中断 没有任何其他中断 pwm输出会被中断打断吗  发表于 2022-11-17 15:55
 楼主| 叶萌 发表于 2022-11-17 15:57 | 显示全部楼层
一叶倾城wwq 发表于 2022-11-17 11:03
什么驱动需要上兆的pwm?不稳定除了配置问题就是被其他中断打断了呗

我想问的就是会和芯片的精度有关系吗  比如这个mcu就是达不到3mhz的精度之类的

评论

@一叶倾城wwq :用户手册只写了那些定时器能够pwm输出,没写最高能到多少兆,唉  发表于 2022-11-22 16:59
看看芯片PWM部分的规格书嘛,看上面标注的范围是多少,计算一下,一般估计做不到上兆的pwm,我还没用过上兆的pwm呢。  发表于 2022-11-19 18:29
一个人破 发表于 2022-11-24 15:33 | 显示全部楼层
外部晶振HSE的输入范围不是4~16MHz吗
111111.png
一个人破 发表于 2022-11-24 15:36 | 显示全部楼层
觉得定时输出不准的话,不妨用MCO输出SYSCLK波形。看下定时器之前的时钟准不准
一个人破 发表于 2022-11-24 15:43 | 显示全部楼层
想知道你的时钟配置是怎样的:
时钟源是3MHz的晶振?
HSE是直接作为系统时钟吗,还是经过PLL倍频。

可以通过MCO先检查下时钟路径上的时钟是不是都是正常的,如果都是正常的,我们再排查代码问题
JunKook 发表于 2022-11-24 15:52 | 显示全部楼层
你好,请问你测出来的PWM脉冲个数不稳定是普遍现象吗?也就是说无论PWM的频率是多少,脉冲个数都不稳定是吗?
WuKaiLi 发表于 2022-11-24 16:40 | 显示全部楼层
本帖最后由 WuKaiLi 于 2022-11-24 16:49 编辑

由于MCU的定时器频率限制,建议你使用最大频率,并且不要进行分频。你的代码有一些问题:
1.计数值设置太小,为2,不利于精度;
2.翻转电平错误,计数值你设置的2,理论计数为0,1,2;你设置的翻转值为1,则电平持续时间的计数值为0,翻转电平时间持续的的计数值为1,2;所以你占空比不对;

我写了一个demo,供你参考,注意:系统频率为72M;

  1. int main(void)
  2. {
  3.     GPIO_Config_T GPIO_ConfigStruct;
  4.     TMR_BaseConfig_T TMR_TimeBaseStruct;
  5.     TMR_OCConfig_T OCcongigStruct;

  6.     RCM_EnableAPB2PeriphClock((RCM_APB2_PERIPH_T)(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_TMR1 | RCM_APB2_PERIPH_GPIOB));

  7.     GPIO_ConfigStruct.pin = GPIO_PIN_13;
  8.     GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
  9.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  10.     GPIO_Config(GPIOB, &GPIO_ConfigStruct);

  11.     GPIO_ConfigStruct.pin = GPIO_PIN_8;
  12.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);

  13.     TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
  14.     TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
  15.     TMR_TimeBaseStruct.division = 0;
  16.     TMR_TimeBaseStruct.period = 23;
  17.     TMR_ConfigTimeBase(TMR1, &TMR_TimeBaseStruct);

  18.     OCcongigStruct.idleState = TMR_OC_IDLE_STATE_RESET;
  19.     OCcongigStruct.mode = TMR_OC_MODE_PWM1;
  20.     OCcongigStruct.nIdleState = TMR_OC_NIDLE_STATE_RESET;
  21.     OCcongigStruct.nPolarity = TMR_OC_NPOLARITY_HIGH;
  22.     OCcongigStruct.outputNState = TMR_OC_NSTATE_ENABLE;
  23.     OCcongigStruct.outputState = TMR_OC_STATE_ENABLE;
  24.     OCcongigStruct.polarity = TMR_OC_POLARITY_HIGH;
  25.     OCcongigStruct.pulse = 12;
  26.     TMR_ConfigOC1(TMR1, &OCcongigStruct);

  27.     TMR_ConfigOC1Preload(TMR1, TMR_OC_PRELOAD_ENABLE);
  28.     TMR_EnableAutoReload(TMR1);
  29.     TMR_Enable(TMR1);
  30.     TMR_EnablePWMOutputs(TMR1);

  31.     while(1)
  32.     {
  33.     }
  34. }
复制代码


示波器测试截图如下,不知道是否满足你的需求: IMG_20221124_163047.jpg

 楼主| 叶萌 发表于 2022-11-25 16:34 | 显示全部楼层
一个人破 发表于 2022-11-24 15:33
外部晶振HSE的输入范围不是4~16MHz吗

我外部晶振是用的12m呀,我说的3mhz是接的外部触发脚想取代定时器触发3mhz
 楼主| 叶萌 发表于 2022-11-25 16:35 | 显示全部楼层
一个人破 发表于 2022-11-24 15:43
想知道你的时钟配置是怎样的:
时钟源是3MHz的晶振?
HSE是直接作为系统时钟吗,还是经过PLL倍频。

MCO是什么,还没接触过
 楼主| 叶萌 发表于 2022-11-25 16:37 | 显示全部楼层
JunKook 发表于 2022-11-24 15:52
你好,请问你测出来的PWM脉冲个数不稳定是普遍现象吗?也就是说无论PWM的频率是多少,脉冲个数都不稳定是吗 ...

不是噢 5k的频率就正常
 楼主| 叶萌 发表于 2022-11-25 16:42 | 显示全部楼层
WuKaiLi 发表于 2022-11-24 16:40
由于MCU的定时器频率限制,建议你使用最大频率,并且不要进行分频。你的代码有一些问题:
1.计数值设置太小 ...

你好,看了一下你的代码,和我有区别的有两个,第一个我的系统频率是60mhz,第二个我是采取的中央对齐计数法,你可以看一下我的示波器图片,我感觉频率和占空比是合格的,但是脉冲数相对外部晶振来说不太稳定
 楼主| 叶萌 发表于 2022-11-25 16:50 | 显示全部楼层
WuKaiLi 发表于 2022-11-24 16:40
由于MCU的定时器频率限制,建议你使用最大频率,并且不要进行分频。你的代码有一些问题:
1.计数值设置太小 ...

你好,我根据你的代码改了以下代码,
TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
TMR_TimeBaseStruct.division = 0;
TMR_TimeBaseStruct.period = 19;
OCcongigStruct.pulse = 10;
目前接收到的频率和占空比是和我之前的一样,然后呢脉冲个数还是有缺失的情况,可以辛苦你用你的代码再实验一次吗,把示波器调到us级别,脉冲个数1k以上,这样才能看出来脉冲个数的情况,非常谢谢
一个人破 发表于 2022-11-25 18:00 | 显示全部楼层
叶萌 发表于 2022-11-25 16:35
MCO是什么,还没接触过

Main Clock Output
通过配置可以输出时钟波形:SYSCLK、HSICLK、HSECLK、PLLCLK/2
平常对于时钟频率有怀疑的时候,用它可以很方便的排除是硬件问题还是程序问题。


33333333.png
22222.png
一个人破 发表于 2022-11-25 18:05 | 显示全部楼层
叶萌 发表于 2022-11-25 16:35
MCO是什么,还没接触过
  1. void MCO_Init(void)
  2. {
  3.   GPIO_InitTypeDef      GPIO_InitStructure;
  4.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    //使能GPIO通道时钟  
  5.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  6.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  7.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //GPIO_Speed_50MHz;
  8.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  9.   
  10.   RCC_MCOConfig(RCC_MCO_SYSCLK);//这里可以选择你想测试的时钟
  11. }
复制代码
将PA8引脚进行复用,然后选择自己想要测试的时钟就好了
一个人破 发表于 2022-11-25 18:09 | 显示全部楼层
叶萌 发表于 2022-11-25 16:35
MCO是什么,还没接触过

用示波器观察时钟波形稳不稳定的话,用触发模式比较方便。
选择波形的中间电平,看会不会有抖动的迹象

到时把波形也发出来看看吧
 楼主| 叶萌 发表于 2022-11-26 09:19 | 显示全部楼层
一个人破 发表于 2022-11-25 18:09
用示波器观察时钟波形稳不稳定的话,用触发模式比较方便。
选择波形的中间电平,看会不会有抖动的迹象

好滴,谢谢,我试试!
 楼主| 叶萌 发表于 2022-11-26 17:01 | 显示全部楼层
你好,我做了如下测试,发现这个12mhz直接MCO输出也是会有脉冲丢失的情况,代码和示波器图片如下,可以帮我看看吗
  1. void  InitMCOConfig(void)
  2. {
  3.         GPIO_Config_T GPIO_ConfigStruct;
  4.     RCM_EnableAPB2PeriphClock((RCM_APB2_PERIPH_T)(RCM_APB2_PERIPH_GPIOA));

  5.     GPIO_ConfigStruct.pin = GPIO_PIN_8;
  6.     GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
  7.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  8.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);
  9.        
  10.         RCM_ConfigMCO(RCM_MCOCLK_SYSCLK);
  11. }
复制代码


12mhz1.jpg
12mhz2.jpg
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

40

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部