前言
基于PMS150G操控PWM调节占空比做到呼吸灯,调节灯光亮度的作用
直接看代码吧,都有注释
代码1
呼吸灯
#include "extern.h"
void TM2_Init(void);
void LED_light(void);
void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/16 // SYSCLK=IHRC/4
clkmd.En_WatchDog = 0; // WatchDog Enable 看门狗
// Insert Initial Code
TM2_Init();
while (1)
{
LED_light();
// ...
// wdreset; 看门狗复位
}
}
void TM2_Init(void)//设置频率
{
// $ TM2C SYSCLK,PB2,PWM; //选择时钟源,输出脚,PWM模式,是否反极性输出(写Inverse为启用,不写则为停用)
//根据要求时钟可选择SYSCLK, EOSC, IHRC, ILRC等,输出脚可以选择Disable(不选择), PB2, PB4, PA3
//注:时钟源与输出脚位的选择请参考对应芯片的datasheet,个别芯片有些不同
$ TM2S 8bit,/1,/1; //选择分辨率,预分频,分频
//分辨率可选择8bit,6bit,预分频可选择/1, /4, /16, /64,分频可选择/1 ~ /32(对应TM2S[4:0]的00000 ~ 11111)
TM2B = 0; //1/256的亮度
// PWM模式的频率和占空比计算
//频率=时钟源/(分辨率*预分频*分频)=1M / (2^8 * 1 * 1) = 3906.25Hz
//占空比=(TM2B+1)/分辨率*100%=(0 + 1) / 2^8 *100% = 1/256*100% = 0.38%
$ TM2C Stop; //关闭PWM,即0%的亮度
}
bit Add_Sign; //空占比增加标志位
byte PWM_Num; //调节空占比变量
void LED_light(void)
{
$ TM2C SYSCLK,PA3,PWM;//打开PWM
if(Add_Sign == 1) //标志位为增加
{
PWM_Num++;
TM2B = PWM_Num; //将变量传入TM2B改变占空比
if(PWM_Num == 255)
{
Add_Sign = 0; //加满标志位置0
}
.delay 10000;//延时10ms,控制渐变时长
}
else //标志位置0时开始减少
{
PWM_Num--;
TM2B = PWM_Num;
if(PWM_Num == 0)
{
$ TM2C Stop; //关闭PWM达到0亮度
Add_Sign = 1; //标志位置1
}
.delay 10000;//延时10ms,控制渐变时长
}
}
void Interrupt (void)
{
pushaf;
if (Intrq.T16)
{ // T16 Trig
// User can add code
Intrq.T16 = 0;
//...
}
popaf;
}
代码2
调节亮度 3档亮度 占空比 100%,50%,10%
//********************************************************************************//
// 功能名称: TM2/TM3产生任意频率的PWM
// 功能编号: 020101
// 适应芯片: 只有TM2的芯片:
// PMC系列:PMC234
// PMS系列:PMS234 PMS150C PMS150G PMS152 PMS15A
// TM2和TM3都有的芯片:
// PFC系列:PFC151 PFC154 PFC232 PFC161
// PFS系列:PFS154 PFS172 PFS173 PFS122 PFS123
// PMC系列:PMC131 PMC232
// PMS系列:PMS130 PMS131 PMS232 PMS164 PMS154C PMS171B PMS132B PMS133 PMS134
//--------------------------------------------------------------------------------//
//程序说明:
// 设置TM2从PB2脚产生3906.25Hz的频率50%的占空比
// 设置TM3从PB5脚产生3906.25Hz的频率50%的占空比
// 占空比可以修改TM2B/TM3B进行调整
//注意事项:
// 1.案例为PMS154C,其他芯片时钟源和输出IO脚可能存在不同,其他原理都相同
//********************************************************************************//
#include "extern.h"
byte m=255; //调整占空比
byte time_10ms;
word reload_T16;
byte high1=0; //模式标志位
byte high2=0;
byte high3=0;
byte low=0; //电平标志位
byte count=1; //下个模式标志位
void GPIO_init(void);
void mode1(void);
void mode2(void);
void mode3(void);
void TM2_PWM(void);
void Timer_init(void);
/******************************/
/*主函数*/
/******************************/
void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/4,VDD=5V;
GPIO_init();
Timer_init();
while (1)
{
mode1();
mode2();
mode3();
}
}
/******************************/
/*GPIO初始化*/
/******************************/
void GPIO_init(void)
{
pac = 0b1001_1111;
}
/******************************/
/*模式3 空占比:100%*/
/******************************/
void mode1(void)
{
if(high1==0&&count==1&&low==0) //high1可拉高 已经低电平 如果是模式1
{
if(pa.5 == 1) //如果高电平
{
m=255; //100%空占比
TM2_PWM();
high1=1; //high1拉高
low=1; //电平已经在高位
count=2; //下个模式为模式2
}
}
if((high1!=1)&&low==1) //high1排除
{
if(pa.5 == 0) //如果是低电平 关灯
{
$ TM2C STOP; //pwm输出停止
low=0;
high2=0; //拉低后 模式2,3清零 可拉高
high3=0;
}
}
}
/******************************/
/*模式3 空占比:50%*/
/******************************/
void mode2(void)
{
if(high2==0&&count==2&&low==0)
{
if(pa.5 == 1)
{
m=127;
TM2_PWM();
high2=1;
low=1;
count=3;
}
}
if((high2!=1)&&low==1)
{
if(pa.5 == 0)
{
$ TM2C STOP;
low=0;
high1=0;
high3=0;
}
}
}
/******************************/
/*模式3 空占比:10%*/
/******************************/
void mode3(void)
{
if(high3==0&&count==3&&low==0)
{
if(pa.5 == 1)
{
m=25;
TM2_PWM();
high3=1;
low=1;
count=1;
}
}
if((high3!=1)&&low==1)
{
if(pa.5 == 0)
{
$ TM2C STOP;
low=0;
high1=0;
high2=0;
}
}
}
/******************************/
/*PWM初始化*/
/******************************/
void TM2_PWM(void)
{
TM2CT = 1; //计数寄存器
TM2B = m; //上限寄存器
$ TM2C SYSCLK,PA3,PWM; //选择时钟源,输出脚,PWM模式,是否反极性输出(写Inverse为启用,不写则为停用)
//根据要求时钟可选择SYSCLK, EOSC, IHRC, ILRC等,输出脚可以选择Disable(不选择), PB2, PB4, PA3
//注:时钟源与输出脚位的选择请参考对应芯片的datasheet,个别芯片有些不同
// $ TM2C STOP; //关掉时钟,即TM2停止工作
$ TM2S 8BIT,/1,/1; //选择分辨率,预分频,分频
//分辨率可选择8bit,6bit,预分频可选择/1, /4, /16, /64,分频可选择/1 ~ /32(对应TM2S[4:0]的00000 ~ 11111)
// PWM模式的频率和占空比计算
//频率=时钟源/(分辨率*预分频*分频)=1M / (2^8 * 1 * 1) = 3906.25Hz
//占空比=(TM2B+1)/分辨率*100%=(127 + 1) / 2^8 *100% = 50%
}
/******************************/
/*定时器中断初始化*/
/******************************/
void Timer_init(void)
{
$ T16M SYSCLK,/16,bit10; //T16的时钟源选择,内部的时钟分频器,中断源选择(当选择位由低到高或者由高到低时,发生中断事件);
//时钟源选择可以选择STOP, SYSCLK, PA4_F, IHRC, ILRC, PA0_F;分频器可选择/1, /4, /16, /64
//中断源可选择BIT8, BIT9, BIT10, BIT11, BIT12, BIT13, BIT14, BIT15
reload_T16 = 1024 - 625; //每次进中断为10ms;
//计算公式为 [1/(时钟源/分频器)]*(中断源-reload_T16)=[1/(1M/16)]*(2^10-(1024-625))=0.01s
stt16 reload_T16; //设定计数器初始值reload_T16,当计数器累加超过设定中断源时产生中断;
$ INTRQ T16; //中断请求寄存器,此位是由硬件置位并由软件清零;1:请求,0:不请求。
//注:INTEN,INTRQ没有初始值,所以要使用中断前,一定要根据需要设定数据。即使INTEN为0,INTRQ还是会被中断发生源触发。
$ INTEGS BIT_R; //T16中断边缘选择,上升缘请求中断为BIT_R,下降缘请求中断为BIT_F;默认为上升缘请求。
// 设定INTEN、INTRQ的初始值
INTEN.T16 = 1; //中断允许寄存器,启用从T16的溢出中断;1:启用,0:停用。
// INTEN.T16 = 0; //关T16中断
INTRQ.T16 = 0; //清零INTRQ寄存器。
ENGINT; //打开全局中断
time_10ms = 0;
}
void Interrupt (void)
{
pushaf;
if (Intrq.T16)
{ // T16 Trig
// User can add code
stt16 reload_T16; //设定计数器初始值reload_T16
time_10ms++;
if(time_10ms > 20) //定时两秒
{
time_10ms = 0;
}
Intrq.T16 = 0;
INTEN.T16 = 1;
}
popaf;
}