Arduino CH552 PWM的使用
Arduino CH552 PWM的使用
- 🌿相关篇《Arduino CH552 定时器的使用》
📑CH552 PWM简介
CH552 提供了 2 路 8 位 PWM,PWM 可以选择默认的输出极性为低电平或者高电平,可以动态修改PWM 的输出占空比,通过简单 RC 电阻电容进行积分低通滤波后,即可获得各种输出电压,相当于低速数模转换器 DAC。PWM1 输出占空比= PWM_DATA1 / 256,支持范围 0%到 99.6%。PWM2 输出占空比= PWM_DATA2 / 256,支持范围 0%到 99.6%。
实际应用中,建议允许 PWM 引脚输出并且设置 PWM 输出引脚为推挽输出模式。
📘PWM1 和 PWM2 相关寄存器
- PWM2 数据寄存器(PWM_DATA2):
- PWM1 数据寄存器(PWM_DATA1):
- PWM 控制寄存器(PWM_CTRL):
-
- PWM 时钟分频设置寄存器(PWM_CK_SE):
- PWM 时钟分频设置寄存器(PWM_CK_SE):
📝测试代码
开启PWM中断,需要在固件:
C:\Users\Administrator\AppData\Local\Arduino15\packages\CH55xDuino\hardware\mcs51\0.0.23\cores\ch55xduino\main.c
文件中,将PWM中断函数添加进去:void PWMInterrupt( void ) __interrupt(INT_NO_PWMX);
/*PWM_F = Fsys/256/分频系数PWM默认输出通道:PWM1:P15 PWM2: P34开启备用输出通道:PWM1PINAlter( )和PWM2PINAlter( )之后PWM输出引脚PWM1 使用 P3.0PWM2 使用 P3.1同时开启2个通道,PWM1通道输出会有杂波
*/
#include <Arduino.h>#define LED_BUILTIN 11
#define LED_PIN 17volatile uint16_t count = 0; // 中断计数器
const uint16_t target = 500; // 500次中断(每次1ms)
static bool LED_FLAG = 0;
static bool LED2_FLAG = 0;#define PWM_INTERRUPT 1#define SetPWMClk(CK_SE) (PWM_CK_SE = CK_SE) //分频,默认时钟Fsys 0 ~ 255 #define SetPWM1Dat(dat) (PWM_DATA1 = dat) //设置PWM输出占空比
#define SetPWM2Dat(dat) (PWM_DATA2 = dat)#define PWM1PINAlter( ) {PIN_FUNC |= bPWM1_PIN_X;} //PWM映射脚P30
#define PWM2PINAlter( ) {PIN_FUNC |= bPWM2_PIN_X;} //PWM映射脚P31#define ForceClearPWMFIFO( ) {PWM_CTRL |= bPWM_CLR_ALL;} //强制清除PWM FIFO和COUNT
#define CancleClearPWMFIFO( ) {PWM_CTRL &= ~bPWM_CLR_ALL;} //取消清除PWM FIFO和COUNT#define PWM1OutEnable() (PWM_CTRL |= bPWM1_OUT_EN) //允许PWM1输出
#define PWM2OutEnable() (PWM_CTRL |= bPWM2_OUT_EN) //允许PWM2输出
#define DsiablePWM1Out() (PWM_CTRL &= ~bPWM1_OUT_EN) //关闭PWM1输出
#define DisablePWM2Out() (PWM_CTRL &= ~bPWM2_OUT_EN) //关闭PWM2输出 #define PWM1OutPolarHighAct()(PWM_CTRL &= ~bPWM1_POLAR) //PWM1输出默认低,高有效
#define PWM2OutPolarHighAct()(PWM_CTRL &= ~bPWM2_POLAR) //PWM2输出默认低,高有效
#define PWM1OutPolarLowAct() (PWM_CTRL |= bPWM1_POLAR) //PWM1输出默认高,低有效
#define PWM2OutPolarLowAct() (PWM_CTRL |= bPWM2_POLAR) //PWM2输出默认高,低有效 /*******************************************************************************
* Function Name : PWMInterruptEnable()
* Description : PWM中断使能
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void PWMInterruptEnable()
{PWM_CTRL |= bPWM_IF_END | bPWM_IE_END; //清除PWM中断,使能PWM中断IE_PWMX = 1;
}void PWM_Init()
{P1_MOD_OC &= ~(bPWM1 | bPWM2); //设置PWM引脚为推挽输出P1_DIR_PU |= bPWM1 | bPWM2; SetPWMClk(94); //PWM时钟配置 ,Fsys/256/94分频=24000,000/256/94=992HzForceClearPWMFIFO( ); //强制清除PWM FIFO和COUNTCancleClearPWMFIFO( ); //取消清除PWM FIFO和COUNTPWM1OutEnable( ); //允许PWM1输出 PWM2OutEnable( ); //允许PWM2输出 PWM1OutPolarHighAct( ); //PWM1输出默认低,高有效 PWM2OutPolarLowAct( ); //PWM2输出默认高,低有效
#if PWM_INTERRUPTPWMInterruptEnable(); EA = 1;SetPWM1Dat(64); //占空比25%SetPWM2Dat(0x7f);
#else SetPWM1Dat(0x10); //占空比0x10/256 SetPWM2Dat(0x40); while(1){if(PWM_CTRL&bPWM_IF_END){PWM_CTRL |= bPWM_IF_END; //清除PWM中断 SetPWM1Dat(64);SetPWM2Dat(0x7f); // printf("PWM_CYC_END %02X\n",(UINT16)PWM_CTRL);USBSerial_printf("PWM_CYC_END %02X\n",(uint16_t)PWM_CTRL);// wait for a secondUSBSerial_flush();//等待串口数据发送结束(串口数据发送必不可少)}}
#endif }/*******************************************************************************
* Function Name : PWMInterrupt(void)
* Description : PWM中断服务程序
*******************************************************************************/
void PWMInterrupt( void ) __interrupt(INT_NO_PWMX) __using(1) //PWM1&2中断服务程序,使用寄存器组1
{PWM_CTRL |= bPWM_IF_END; //清除PWM中断SetPWM1Dat(64);// SetPWM2Dat(0x7f); // LED2_FLAG = !LED2_FLAG;// digitalWrite(LED_PIN, LED_FLAG); // 翻转LED}// 定时器2中断服务函数
void Timer2Interrupt(void) __interrupt(INT_NO_TMR2) __using(3)
{if (TF2) {TF2 = 0; // 清除定时器2溢出标志count++;if (count >= target) {count = 0;LED_FLAG = !LED_FLAG;// 执行500ms任务digitalWrite(LED_BUILTIN, LED_FLAG); // 翻转LED}}}void Timer2_init()
{// 配置定时器2T2CON = 0x00; // 清除T2CON,设置为16位自动重载模式T2MOD = 0x00; // 时钟=Fsys(24MHz)// 计算定时器初值(24MHz时钟,1ms中断)uint16_t timerValue = 65536 - 1000;//1msRCAP2L = timerValue & 0xFF; // 低8位RCAP2H = (timerValue >> 8); // 高8位// 装载初值TL2 = RCAP2L;TH2 = RCAP2H;// 使能定时器2中断ET2 = 1; // 使能定时器2中断EA = 1; // 使能全局中断// 启动定时器2TR2 = 1;
}// the setup function runs once when you press reset or power the board
void setup() {// initialize digital pin LED_BUILTIN as an output.pinMode(LED_BUILTIN, OUTPUT);digitalWrite(LED_BUILTIN, LOW);pinMode(LED_PIN, OUTPUT);digitalWrite(LED_PIN, LOW); // 初始化为低电平(LED熄灭)PWM_Init();Timer2_init();
}// the loop function runs over and over again forever
void loop() {// USBSerial_println("Hello World123!");// USBSerial_flush();// delay(1000); // wait for a second// USBSerial_println("perseverance51");// wait for a second// USBSerial_flush();//等待串口数据发送结束(串口数据发送必不可少)
}
- 同时输出双路PWM输出,在PWM中断中重新装载计数值,PWM1输出波形中偶尔会出现杂波。只启用单路输出没有。两路PWM共用一个中断,只有PWM1有溢出标志位。