前言
上一篇文章相信大家已经成为了点灯高手了,那么进阶就是成为点灯大师 实现PWM呼吸灯
接下来就是直接的代码讲解了,不再讲PWM原理的
这里部分内容参考了另一个博主的文章
合泰杯——合泰单片机工程7之PWM输出
如果有小伙伴不理解引脚设置和delay函数生成或者环境配置的可以浏览上一章内容
合泰杯开发板HT66F2390入门教程(点亮LED灯)——获得成就:点灯大师
本文中会讲解代码为什么要这样配置寄存器和引脚才可以制作呼吸灯(内容可能不完整,持续更新)
代码
#include "HT66F2390.h"
const int Period = 4095; // 定义PWM周期为4095
void setLED_PWM(unsigned long Duty);
void delay(unsigned long count); // 声明延时函数
void PWM_Init(void);
void main()
{
_wdtc=0b10101011; //关闭看门狗
int i=0;
PWM_Init();
while(1)
{
for(i=0;i<Period;i++)
{
delay(50);
setLED_PWM(i);
}
for(i=Period;i>0;i--)
{
delay(50);
setLED_PWM(i);
}
}
}
void delay(unsigned long count) //延时10us级别
{
volatile unsigned long i;
for(i=0;i<count;i++)
asm("nop");
}
void setLED_PWM(unsigned long Duty)
{
_ptm3ah =Duty/256; //占空比设置
_ptm3al =Duty%256;
}
void PWM_Init(void){
_ptm3c0=0b00001000; //时钟选择为8MHz/4
_ptm3c1=0b10101000; //功能选择寄存器,选择PWM输出且低有效
_ptm3rph=Period/256; //周期设置,写入CCRP的两个寄存器之中这个是把16位的数据划分成高8位和低8位
_ptm3rpl=Period%256;
_pds1=0b00000010; //PTP3引脚选择,接的是D4
_emi=1; //开启总中断
}
代码讲解
学过PWM的同学都能理解呼吸灯的原理,同样,本文中的呼吸灯原理就是通过配置HT66F2390中周期型TM寄存器实现PWM控制,这里就不对PWM原理进行讲解了
可以打开该芯片的数据手册
合泰官方HT66F2390数据手册
我们要使用PWM的话,想一想肯定和定时器有关,那么我们能就翻开数据手册找到定时器有关的内容
在旁边的目录就能找到
如图,我们发现了PWM的身影,那么就接着往下看看
这里我们看到了PTM的输出引脚,其中的数字代表的不同引脚类型,后面有说(本文章使用的PTM,如果你要使用STM也是差不多的思路)那这个时候我们就又要跳到PTM相关的内容了
这个时候我们发现上面的数字PTPn很有可能就是代表下面的n,然后又可以发现n=0~1是10-bit,n=2和3是16-bit的,我们选择16位所以选择n为2或者3
接着往下看这些寄存器代表什么意思
那我们就可以发现这些寄存器是配置计数器,周期和占空比之类的
最重要的是下面这两个寄存器
PTMnC0和PTMnC1,n的数值代表多少位的计数器
那么看到这里,我想用n = 3(16位计数器),PWM输出高有效,那么是不是就把这两个寄存器配置为,如果是你要10位n=1的话就是_ptm1c0 = 0bxxxxxxxx;
_ptm3c0=0b00001000; //时钟选择为8MHz/4
_ptm3c1=0b10101000; //功能选择寄存器,选择PWM输出且高有效
然后周期和占空比也知道怎么配置了,也是同理配置寄存器
_ptm3rph=Period/256; //周期设置,写入CCRP的两个寄存器之中这个是把16位的数据划分成高8位和低8位
_ptm3rpl=Period%256;
_ptm3ah =Duty/256; //占空比设置
_ptm3al =Duty%256;
然后我配置了寄存器但是我要知道怎如何使用他,他是哪个引脚呢,那么就需要回到前面这个图了
我们选择的n = 3,那么就是输出引脚为PTP3,我们接下来看看这个HT66F2390芯片的引脚图
我们发现他有两个引脚的复用都是PTP3,那么说明这两个引脚都可以使用PWM功能,接下来就是需要知道怎么配置复用功能引脚了
例如我要用PD4就去设置复用功能
这里如果你想用PB2也是一样的意思,找到PBS1或这PBS0看看
最终我们的初始化PWM代码就可以有下面的部分,我这里是n=3,PD4引脚
void PWM_Init(void){
_ptm3c0=0b00001000; //时钟选择为8MHz/4
_ptm3c1=0b10101000; //功能选择寄存器,选择PWM输出且低有效
_ptm3rph=Period/256; //周期设置,写入CCRP的两个寄存器之中这个是把16位的数据划分成高8位和低8位
_ptm3rpl=Period%256;
_pds1=0b00000010; //PTP3引脚选择,接的是D4
_emi=1; //开启总中断
}
设置占空比
void setLED_PWM(unsigned long Duty)
{
_ptm3ah =Duty/256; //占空比设置
_ptm3al =Duty%256;
}
最后一个也是关键的内容
这里就可以说明为什么我们的代码是这样的了,这里的delay参数是10us
const int Period = 4095; // 定义PWM周期为4095
while(1)
{
for(i=0;i<Period;i++)
{
delay(50);
setLED_PWM(i);
}
for(i=Period;i>0;i--)
{
delay(50);
setLED_PWM(i);
}
}
结果演示
PWM呼吸灯演示视频
总结
这个也是最近学习的内容,网上的详细教程也比较少,最后也是自己看着别人的例程对着数据手册写出来的,所以打算自己写一个完整的阅读数据手册配置寄存器完成指定目的的思路,这也大大提升了我阅读数据手册的能力,加下来学习其他的功能我也会继续更新我自己的学习的内容和教程
如果有错误的地方或者需要改进的地方欢迎大家指出!