OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4810|回复: 4

TIM1 PWM多通道输出不同频率,能输出1M以上吗?

[复制链接]

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-10-23 15:58:42 | 显示全部楼层 |阅读模式
29金钱


用的TIM1的PWM输出模式,问题就是标题,现在是用的103,不知道407可不可以,但是407没发软件仿真看不出来。

调试时,100KHz还能稳定输出,大于100KHz之后就有些问题了,具体在哪个数值变化没有精确测试,反正1MHz输出不出来。

是不是中断响应时间不够,导致的输出上不去呢? 以下附上代码,各位大神帮忙分析分析。。。

这是TIM1 的初始化,主要配置了4个通道输出。
  1. static void TIM1_GPIO_Config(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStructure;

  4.         /* GPIOA and GPIOB clock enable */
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  6. //        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_13 ;//| GPIO_Pin_14 | GPIO_Pin_15;
  7. //        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  8. //        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  9. //        GPIO_Init(GPIOB, &GPIO_InitStructure);
  10.        
  11.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
  12.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  13.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  14.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  15. }

  16. /*配置TIM1输出的PWM信号的模式,如周期、极性、占空比 */
  17. static void TIM1_Mode_Config(u32 arr,u32 psc)
  18. {
  19.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  20.         TIM_OCInitTypeDef  TIM_OCInitStructure;
  21.         NVIC_InitTypeDef NVIC_InitStructure;
  22.        
  23.         /* TIM1 clock enable */
  24.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  25.        
  26.         NVIC_InitStructure.NVIC_IRQChannel=TIM1_CC_IRQn;
  27.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
  28.         NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
  29.         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  30.         NVIC_Init(&NVIC_InitStructure);
  31.        
  32. /* Time base configuration */
  33.   TIM_TimeBaseStructure.TIM_Period = psc;                //2M/1000 = 1K
  34.   TIM_TimeBaseStructure.TIM_Prescaler = arr;                //72M/(35+1) = 2M
  35.   TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  36.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  37.   TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  38.   /* PWM1 Mode configuration: Channel1 */
  39.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  40.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  41.   TIM_OCInitStructure.TIM_Pulse = CCR1_Val;//(psc+1)/2;
  42.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  43.   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

  44.   TIM_OC1Init(TIM1, &TIM_OCInitStructure);
  45. //  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

  46. ///*
  47.   // PWM1 Mode configuration: Channel2
  48.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  49.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  50.   TIM_OCInitStructure.TIM_Pulse = CCR2_Val;//(psc+1)/2;
  51.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  52.   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  53.   
  54.   TIM_OC2Init(TIM1, &TIM_OCInitStructure);
  55. //  TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);       


  56.   // PWM1 Mode configuration: Channel3
  57.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  58.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  59.   TIM_OCInitStructure.TIM_Pulse = CCR3_Val;//(psc+1)/2;
  60.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  61.   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  62.   
  63.   TIM_OC3Init(TIM1, &TIM_OCInitStructure);
  64. //  TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);       

  65.         // PWM1 Mode configuration: Channel1
  66.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  67.   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  68.   TIM_OCInitStructure.TIM_Pulse = CCR4_Val;//(psc+1)/2;
  69.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  70.   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

  71.   TIM_OC4Init(TIM1, &TIM_OCInitStructure);
  72. //  TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
  73. //*/
  74.   TIM_ARRPreloadConfig(TIM1, ENABLE);

  75.   /* TIM1 enable counter */
  76.   TIM_Cmd(TIM1, ENABLE);
  77.   TIM_ITConfig(TIM1, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
  78.   TIM_CtrlPWMOutputs(TIM1, ENABLE);
  79. }
复制代码


这是中断处理,中间有一些不懂参考的网上。这个里面解答了我一些疑惑,可以参考下 https://blog.csdn.net/hes_c/article/details/88897149

  1. void TIM1_CC_IRQHandler(void)
  2. {
  3.         if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
  4.         {
  5.                 TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
  6.                 capture = TIM_GetCapture1(TIM1);
  7.                 TIM_SetCompare1(TIM1, capture + CCR1_Val);
  8.         }
  9.        
  10.         if (TIM_GetITStatus(TIM1, TIM_IT_CC2) != RESET)
  11.         {
  12.                 TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
  13.                 capture = TIM_GetCapture2(TIM1);
  14.                 TIM_SetCompare2(TIM1, capture + CCR2_Val);
  15.         }
  16.        
  17.         if (TIM_GetITStatus(TIM1, TIM_IT_CC3) != RESET)
  18.         {
  19.                 TIM_ClearITPendingBit(TIM1, TIM_IT_CC3);
  20.                 capture = TIM_GetCapture3(TIM1);
  21.                 TIM_SetCompare3(TIM1, capture + CCR3_Val);
  22.         }
  23.        
  24.         if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)
  25.         {
  26.                 TIM_ClearITPendingBit(TIM1, TIM_IT_CC4);
  27.                 capture = TIM_GetCapture4(TIM1);
  28.                 TIM_SetCompare4(TIM1, capture + CCR4_Val);
  29.         }
  30. }
复制代码

再就是主函数的调用。。。
  1. u16 capture = 0;
  2. vu16 CCR1_Val = 0;
  3. vu16 CCR2_Val = 0;
  4. vu16 CCR3_Val = 0;
  5. vu16 CCR4_Val = 0;
  6. int main(void)
  7. {
  8.         /* 定时器初始化  TIMx_PWM_Init(u32 arr,u32 psc)*/
  9.         //计算公式        系统时钟 72M/(arr+1) = 计数器时钟
  10.         //                        计数器时钟 / (psc+1) = 频率
  11.         TIM1_PWM_Init(1-1 ,65536 - 1);                //1M

  12.         CCR1_Val = 3600;        //10KHz
  13.         CCR2_Val = 360;                //100KHz
  14.         CCR3_Val = 270;
  15.         CCR4_Val = 36;                //1MHz

  16.         while(1)
  17.         {
  18.         }
  19. }
复制代码



以下是keil自带的仿真结果,CCR4_Val 输出的就不是理想的频率了。

1.png

2.png

可以看到第二张下面的时间,确定波形1 和 波形2的频率为 10KHz 和 100KHz,

到下面1MHz 就输出不了了。。。是有啥没注意的地方吗,求大神指导。。。




最佳答案

查看完整内容[请看2#楼]

换不同定时器才可以,你这种输出比较模式,不适合频率高的应用,因为MCU的中断处理是需要时间的,很难处理1Mhz以上的中断。
茵茵猪头
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2019-10-23 15:58:43 | 显示全部楼层
换不同定时器才可以,你这种输出比较模式,不适合频率高的应用,因为MCU的中断处理是需要时间的,很难处理1Mhz以上的中断。
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
 楼主| 发表于 2019-10-23 18:09:13 | 显示全部楼层
本帖最后由 htao 于 2021-2-3 10:21 编辑




茵茵猪头
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
 楼主| 发表于 2021-2-3 10:21:14 | 显示全部楼层
顶一下
贴一个软件仿真的配置图(f103)
别的配置可能导致输入引脚名字时  PORTA.6 发生无法识别



下图是打开 波形动态更新

茵茵猪头
回复

使用道具 举报

4

主题

178

帖子

0

精华

高级会员

Rank: 4

积分
672
金钱
672
注册时间
2019-7-28
在线时间
61 小时
发表于 2021-2-3 13:31:35 | 显示全部楼层
程序太大,不能相应这么快了!
首先简化程序,其次可以使用高级定时器:TIM1
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-7 22:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表