求大神帮忙解决:用C8051F340定时器0输出一个250Hz的PWM控制电压,再用ADC0采集该电压完成闭环控制的问题

2019-07-15 13:40发布

我用C8051F340的定时器0输出了一个250Hz的PWM(没用PCA模块是因为PCA输出的PWM好像到不了这么低的频率),我要用这个PWM去调节并输出一个电压,然后再用C8051F340内部的ADC0去采集硬件输出的电压值,再用程序实现闭环控制,定时器输出PWM的程序是从网上找的,如下:
  1. void timer0(void)        interrupt 1 using 1                //Timer0,8位重装 ,时钟源500kHz,TH =(256-100)
  2. {
  3.         uint8 count;
  4. aaaa = 1;                //用于示波器测量
  5.         i_PWM++;
  6.         if(i_PWM==2)                               
  7.         {
  8.                 i_PWM = 0;
  9.                 j_PWM++;
  10.                 j_PWM = j_PWM%10;
  11.         }
  12.        
  13.         if(j_PWM>=duty)                                                //duty改变占空比
  14.         {
  15.                 pwm_out = 0;
  16.         }
  17.        
  18.         else
  19.         {
  20.                 pwm_out = 1;                                       
  21.         }
  22.         aaaa = 0;                //用于示波器测量
  23.         AD0BUSY = 1;//软件开启ADC0测量
  24. }
复制代码定时器中断程序的思路是:定时器输出完PWM之后,再打开ADC0启动转换信号,这样会输出一个5kHz的AD采样频率(定时器设置的就是5k),也就是说,在1个PWM波里面进行20次采样;ADC0的转换完成中断是允许的,即EADC0 = 1;ADC0的时钟源(SAR CLK)设置的2MHz;低功耗跟踪模式;右对齐;AD0BUSY触发模式;ADC0的中断程序如下:
  1. void ADC0_interrupt(void)        interrupt 10
  2. {
  3.         bbbb = 1;                //用于示波器测量
  4.         temp_ADC0[i_ADC0]= ADC0H*256+ADC0L;
  5.         v_value = v_value+temp_ADC0[i_ADC0-1];//20次采样求和
  6.         if(i_ADC0 == 20)
  7.         {
  8.                 i_ADC0 = 0;
  9.                 vout = v_value/20;
  10.         }
  11.        
  12.         i_ADC0++;
  13.         AD0INT = 0;
  14.         bbbb= 0;                //用于示波器测量
  15. }
复制代码上面两个程序都有配置用于示波器测量的外置引脚(变量aaaa和变量bbbb),示波器测量得到的波形如下:
QQ图片20160611001814.jpg
黄 {MOD}的为定时器中断里的aaaa信号,相位靠前;绿 {MOD}的为ADC0中断里的bbbb信号,相位靠后,其中bbbb有一段高电平较长的波段,那个是在第20次中断里面做的除法运算,所以耗时较长。
/*********************************************************************************/
问题是:在允许了ADC0的中断后,定时器0的PWM没有了,但从上图示波器的情况可以看出,定时器0中断进去了,而且里的程序跑完了(因为有aaaa的下降沿)。然后我去掉ADC0的中断后,PWM波就恢复正常了;于是我debug进行单步调试,发现timer0中断里面PWM输出的相关程序只运行了20次,即,前20次定时器中断里面,一切正常,输出了一个PWM波,之后,定时器0里面的整个一段程序就不执行了,不执行的程序如下:
  1. if(i_PWM==2)
  2. {
  3. i_PWM = 0;
  4. j_PWM++;
  5. j_PWM = j_PWM%10;
  6. }

  7. if(j_PWM>=duty) //duty改变占空比
  8. {
  9. pwm_out = 0;
  10. }

  11. else
  12. {
  13. pwm_out = 1;
  14. }
复制代码debug中看到i_PWM跑飞了(本来应该只是0、1、2三个值循环的),说明上面的程序在定时器0中断里面没在跑,这程序为啥还能跳过去了呢?求各位大神帮忙解决一下呀




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。