在使用STM8单片机的PWM功能时,一直没出现过问题。但是在一个项目中需要在PWM波输出的过程中变频,这时候问题来了。在PWM输出过程中,输出的波形是不是的就会有一大段空白的地方,好像波形输出被关闭了一样。
输出波形如下图所示:

放大后查看

  可以看到波形输出的过程中突然就消失了,而且还不是偶尔的出现一次。是频繁的出现。这就奇怪了?难道是单片机坏了?换了几个单片机测试都是这样的,那么肯定就是软件代码出问题了。那么到底是什么地方有问题了,于是开启找BUG模式,一行一行代码分析。

  代码分析了半天也没找不到哪行代码有问题,输出单一频率的PWM波一直很稳定,只是改变频率的时候就会出现波形断开情况,频率改变的越多,出现断开的这种情况就会越多,那么肯定就是在变频设置的这块有问题,网上找了半天也没找见有用的方法,看来还是得靠自己解决问题。
  于是开始看芯片手册,关于定时器相关的章节,一个字一个字往过分析。终于发现了一点端倪。

  在定时器时基单元介绍的时候提到了一个自动预装载的功能,并且还有一个影子寄存器。当我们设置寄存器的装载值时,其实不是直接设置的寄存器,而是值传递给通过ARR寄存器传递给影子寄存器,然后由影子寄存器去设置定时器的装载值。

  继续往下看,会讲到影子寄存器的作用。

  在向上计数模式中说到了使能和不使能ARPE的区别,从图上大概可以看出来,不使能预装载功能时,自动重装载寄存器和它的影子寄存器是同步的,相当于计数器溢出时,影子寄存器会被立即跟新。而使能了预装载功能后,计数器溢出时,影子寄存器不会立即更新,而是要等一段时间更新。

  这里说的是向上计数模式,而代码中使用的是PWM模式,下面继续看PWM模式介绍中有没有说这个预装载功能。

  在PWM模式中也提到了预装载寄存器,同时也说了要使能TIM1_CR1寄存器的ARPE位,那么是不是这个预装载寄存器没有开启导致的?

  于是在定时器初始化代码中开启预装载寄存器。

   开启TIM1_CR1寄存器中的APRE位,允许自动预装载寄存器。开启TIM1_CCMR1寄存器中OC1PE位,使能TIM1_CCR1寄存器的预装载功能。

设置好之后继续测试测试

这时发现输出的波形竟然好了,中间没有断开的地方了。看来就是这个预装载寄存器导致的。

  现在仔细分析一下这个预装载功能,为什么在最开始没有开启这个功能呢?可能是被资料上的一句话误导了。

  当禁止预装载功能时,写入的数据会立即起作用。想的是如果PWM要变频,肯定是数据要随时变化,需要改变频率后,立即输出就要发生改变。所以禁止了预装载功能。

  通过上面的资料分析和实验现象来看,对于这句话的理解可能出现了问题。立即生效也就是意味着发出PWM波的过程中,如果一个周期的波没有完全发出去,此时如果改变了频率,那么发送的上一个周期的波就会立即停止,重新开始发送新的周期波。这样的话,发出的波形就会出现不完整,如果代码中改变频率的速度非常快,那么有可能第一个周期的波还没有发出,频率改变了,又开始发第二个波,第二个波还没发出,频率又改变了。于是导致输出的波形有问题。

  而希望输出的波形是,每一个频率至少要输出一个完整的波形,然后在下一个周期再改变频率。所以这里必须要使能预装载寄存器,使能预装载寄存器后,设置的值不会立即生效,而是存入影子寄存器中,影子寄存器会在寄存器重新加载ARR值的时候,将改变后的值写入ARR寄存器,这样在波形输出的过程中,就不会发生一个周期的波形未输出完成时,ARR的值就被改变了。

  由此可见,这个预装载寄存器和影子寄存器主要是用来保证输出波形完整性的,它会自动的在一个波形输出完成后才设置下一次需要改变的值,而不会中断正在输出的波形。所以在使用PWM变频时,必须要开机预装载寄存器和自动重装载功能。

完整的PWM变频代码如下:

#include "pwm.h"unsigned int tim1fre  = 290;
unsigned int ch1_dc = 50;
unsigned int ch2_dc = 50;void pwm_gpio_init( void )
{PC_DDR |= ( 1 << 6 );               //PC6 推挽输出PC_CR1 |= ( 1 << 6 );PC_DDR |= ( 1 << 7 );               //PC7 推挽输出PC_CR1 |= ( 1 << 7 );PC_ODR &= ~( 1 << 6 );PC_ODR |= ( 1 << 7 );
}
//定时器1初始化
void tim1_init( void )
{pwm_gpio_init();TIM1_CCMR1 = 0x60;                  //TIM1 CH1 输出模式 PWM1TIM1_CCMR1 |= ( 1 << 3 );           //开启预装载功能TIM1_CCER1 |= 0x01;                 //CC1为输出TIM1_CCMR2 = 0x60;                  //TIM1 CH2 输出模式 PWM1TIM1_CCER1 |= 0x10;                 //CC2为输出TIM1_PSCRH = 0x00;                  //预分频 0TIM1_PSCRL = 0x00;                  //16MTIM1_ARRH = tim1fre >> 8;               //设定自动重装载值高8位TIM1_ARRL = ( unsigned char )tim1fre;   //设置自动重装载值低8位TIM1_BKR |= ( 1 << 7 );                 //主输出使能  关闭刹车输TIM1_CR1 |= ( 1 << 7 );                 //使能预装载寄存器TIM1_CR1 |= ( 1 << 0 );                 //使能计数器
}
//TIM1 CH1  PC6
void tim1_ch1_dc( unsigned int ch1_dc )
{static unsigned int dc = 0;dc = tim1fre * ch1_dc / 100;TIM1_CCR1H = dc >> 8;               //捕获比较寄存器高8位TIM1_CCR1L = dc;                    //捕获比较寄存器低8位 占空比值
}
//TIM1 CH2  PC7
void tim1_ch2_dc( unsigned int ch2_dc )
{static unsigned int dc = 0;dc = tim1fre * ch2_dc / 100;TIM1_CCR2H = dc >> 8;TIM1_CCR2L = dc;
}void tim1_fre( unsigned int freq )
{tim1fre = freq;TIM1_ARRH = freq >> 8;                     //设置频率TIM1_ARRL = freq;
}

STM8输出PWM变频时波形断开解决方法相关推荐

  1. C# .net中cookie值为中文时的乱码解决方法

    C# .net中cookie值为中文时的乱码解决方法 一.cookie的名称或子cookie的名称不能为中文,否则无法获得cookie 这个好办,名称不用中文即可 二.cookie的值为中文时候,取c ...

  2. 安装VM虚拟机提示 尝试创建目录 C:\Public\documents\SharedVirtual Machines 时发生错误解决方法

    安装VM虚拟机提示 尝试创建目录 C:\Public\documents\SharedVirtual Machines 时发生错误解决方法 参考文章: (1)安装VM虚拟机提示 尝试创建目录 C:\P ...

  3. python使用退格键时出现^H解决方法

    python使用退格键时出现^H解决方法 参考文章: (1)python使用退格键时出现^H解决方法 (2)https://www.cnblogs.com/effortsing/p/9982040.h ...

  4. ”dpkg: 处理归档 /var/cache/apt/archives/XXXXXX(--unpack)时出错“的解决方法

    "dpkg: 处理归档 /var/cache/apt/archives/XXXXXX(--unpack)时出错"的解决方法 参考文章: (1)"dpkg: 处理归档 /v ...

  5. mysql编写中文时变成问号解决方法

    mysql编写中文时变成问号解决方法 参考文章: (1)mysql编写中文时变成问号解决方法 (2)https://www.cnblogs.com/yangzhixue/p/11449525.html ...

  6. PLSQL 查询结果只显示年月日不显示时分秒的解决方法

    PLSQL 14查询结果只显示年月日不显示时分秒的解决方法 如果plsql里面日期显示出现混乱,并且按照一般的调整首选项里日期格式调整不了,可以修改环境变量,新建环境变量,变量名:nls_date_f ...

  7. ajax get 不会缓存,ajax的get请求时缓存处理解决方法

    ajax的get请求时缓存处理解决方法 本文实例讲述了ajax的get请求时缓存处理解决方法.分享给大家供大家参考.具体分析如下: 很多时候在Ajax的get方法调用的时候由于缓存的原因无法及时获取正 ...

  8. centos下MySQL Workbench连接时崩溃的解决方法

    centos下MySQL Workbench连接时崩溃的解决方法 参考文章: (1)centos下MySQL Workbench连接时崩溃的解决方法 (2)https://www.cnblogs.co ...

  9. [转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法

    [转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法 参考文章: (1)[转] linux下shell ...

最新文章

  1. [ActiveMQ]初识ActiveMQ
  2. 对c语言课程的心得体会,C语言课程设计心得体会
  3. java 中map_Java Map集合详解
  4. python读取postgresql数据库并发送相关提醒邮件
  5. 在Hyper-v中创建并安装虚拟机
  6. Qt文档阅读笔记-QGraphicsBlurEffect官方解析与实例
  7. Kendo UI grid 表格数据更新
  8. B站项目资源过于敏感,稍后删,抓紧保存!!!
  9. 推荐两个非常不错的公众号
  10. win10 android fastboot usb驱动
  11. unity android录制视频教程,Unity3d 录屏功能教程指南 | Cross Platform Replay Kit
  12. 基于单片机的自行车码表设计
  13. 一步步教你装超强插件~油猴插件管理器Tampermonkey
  14. RANSAC与其改进
  15. 有10名学生,每个学生的数据要求包括学号、姓名。3门课的成成绩,从键盘输入10个学生数据,要求打印出3门课总平均成绩以及最高分学生的数据(包括学号、姓名、三门课成绩、平均分数)。C++。
  16. 聚合广告SDK API
  17. 淘宝API:item_get_app - 获得淘宝app商品详情原数据
  18. linux操作系统基础复习
  19. 何洋开讲丨“云”将如何在中国制造2025中起到颠覆作用?
  20. 服务器里搭建游戏玩家访问卡是什么原因

热门文章

  1. ADO.NET远程访问Access数据库的连接字符串
  2. 估值指标方法20190805
  3. 如何成为优秀的科学家
  4. PHP编码规范 代码样式风格规范
  5. ylb:SQL 视图(View)基础
  6. 【原创】ABAP根据文件路径获取文件所在目录
  7. Windows一些操作
  8. 【测试】软件测试分类体系系统学习
  9. Java实现数组逆置
  10. python基础之元组定义进阶操作、字典定义进阶操作