简单介绍过STC32G12K128中核PWM有关的PWM处理寄存器,本次我照着例程学习。
/************* 功能说明 ************** 本例程基于STC32G转STC89系列转接板(降龙棍)进行编写测试。 高级PWM定时器 PWM5,PWM6,PWM7,PWM8 每个通道都可独立实现PWM输出. 4个通道PWM设置对应P20~P23输出口. 通过P2口上连接的LED灯,利用PWM实现呼吸灯效果. PWM周期和占空比可以自定义设置,最高可达65535. 下载时, 选择时钟 24MHZ (用户可自行修改频率). ******************************************/ #include "../../comm/STC32G.h" //包含此头文件后,不需要再包含"reg51.h"头文件 #define MAIN_Fosc 24000000L //定义主时钟 typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; /****************************** 用户定义宏 ***********************************/ #define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率, 1000次/秒 /*****************************************************************************/ #define PWM5_1 0x00//P2.0 #define PWM5_2 0x01//P1.7 #define PWM5_3 0x02//P0.0 #define PWM5_4 0x03//P7.4 #define PWM6_1 0x00//P2.1 #define PWM6_2 0x04//P5.4 #define PWM6_3 0x08//P0.1 #define PWM6_4 0x0C//P7.5 #define PWM7_1 0x00//P2.2 #define PWM7_2 0x10//P3.3 #define PWM7_3 0x20//P0.2 #define PWM7_4 0x30//P7.6 #define PWM8_1 0x00//P2.3 #define PWM8_2 0x40//P3.4 #define PWM8_3 0x80//P0.3 #define PWM8_4 0xC0//P7.7 #define ENO5P 0x01 #define ENO6P 0x04 #define ENO7P 0x10 #define ENO8P 0x40 #define PWM_PERIOD 1023 //设置周期值 /***************************** 本地变量声明 **********************************/ bit B_1ms; //1ms标志 u16 PWM5_Duty; u16 PWM6_Duty; u16 PWM7_Duty; u16 PWM8_Duty; bit PWM5_Flag; bit PWM6_Flag; bit PWM7_Flag; bit PWM8_Flag; void UpdatePwm(void); /******************************** 主函数 ************************************/ void main(void) { WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快 EAXFR = 1; //扩展寄存器(XFR)访问使能 CKCON = 0; //提高访问XRAM速度 P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口 P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口 P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口 P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口 P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口 P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口 P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口 P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口 PWM5_Flag = 0; PWM6_Flag = 0; PWM7_Flag = 0; PWM8_Flag = 0; PWM5_Duty = 0; PWM6_Duty = 256; PWM7_Duty = 512; PWM8_Duty = 1024; // Timer0初始化 AUXR = 0x80; //Timer0 set as 1T, 16 bits timer auto-reload, TH0 = (u8)(Timer0_Reload / 256); TL0 = (u8)(Timer0_Reload % 256); ET0 = 1; //Timer0 interrupt enable TR0 = 1; //Tiner0 run PWMB_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCxE 关闭通道 PWMB_CCER2 = 0x00; PWMB_CCMR1 = 0x60; //通道模式配置 PWMB_CCMR2 = 0x60; PWMB_CCMR3 = 0x60; PWMB_CCMR4 = 0x60; PWMB_CCER1 = 0x33; //配置通道输出使能和极性 PWMB_CCER2 = 0x33; PWMB_ARRH = (u8)(PWM_PERIOD >> 8); //设置周期时间 PWMB_ARRL = (u8)PWM_PERIOD; PWMB_ENO = 0x00; PWMB_ENO |= ENO5P; //使能输出 PWMB_ENO |= ENO6P; //使能输出 PWMB_ENO |= ENO7P; //使能输出 PWMB_ENO |= ENO8P; //使能输出 PWMB_PS = 0x00; //高级 PWM 通道输出脚选择位 PWMB_PS |= PWM5_1; //选择 PWM5_1 通道 PWMB_PS |= PWM6_1; //选择 PWM6_1 通道 PWMB_PS |= PWM7_1; //选择 PWM7_1 通道 PWMB_PS |= PWM8_1; //选择 PWM8_1 通道 PWMB_BKR = 0x80; //使能主输出 PWMB_CR1 |= 0x01; //开始计时 EA = 1; //打开总中断 while (1) { } } /********************** Timer0 1ms中断函数 ************************/ void timer0(void) interrupt 1 { if(!PWM5_Flag) { PWM5_Duty++; if(PWM5_Duty > PWM_PERIOD) PWM5_Flag = 1; } else { PWM5_Duty--; if(PWM5_Duty <= 0) PWM5_Flag = 0; } if(!PWM6_Flag) { PWM6_Duty++; if(PWM6_Duty > PWM_PERIOD) PWM6_Flag = 1; } else { PWM6_Duty--; if(PWM6_Duty <= 0) PWM6_Flag = 0; } if(!PWM7_Flag) { PWM7_Duty++; if(PWM7_Duty > PWM_PERIOD) PWM7_Flag = 1; } else { PWM7_Duty--; if(PWM7_Duty <= 0) PWM7_Flag = 0; } if(!PWM8_Flag) { PWM8_Duty++; if(PWM8_Duty > PWM_PERIOD) PWM8_Flag = 1; } else { PWM8_Duty--; if(PWM8_Duty <= 0) PWM8_Flag = 0; } UpdatePwm(); } //======================================================================== // 函数: UpdatePwm(void) // 描述: 更新PWM占空比. // 参数: none. // 返回: none. //======================================================================== void UpdatePwm(void) { PWMB_CCR5H = (u8)(PWM5_Duty >> 8); //设置占空比时间 PWMB_CCR5L = (u8)(PWM5_Duty); PWMB_CCR6H = (u8)(PWM6_Duty >> 8); //设置占空比时间 PWMB_CCR6L = (u8)(PWM6_Duty); PWMB_CCR7H = (u8)(PWM7_Duty >> 8); //设置占空比时间 PWMB_CCR7L = (u8)(PWM7_Duty); PWMB_CCR8H = (u8)(PWM8_Duty >> 8); //设置占空比时间 PWMB_CCR8L = (u8)(PWM8_Duty); }
程序中,使用了PWMB_CCER1、PWMB_CCER2、PWMB_CCMR1、PWMB_CCMR2、PWMB_CCMR3、PWMB_CCMR4、PWMB_ARRH、PWMB_ARRL、PWMB_ENO、PWMB_PS、PWMB_BKR、PWMB_CR1、PWMB_CCR5H 、PWMB_CCR5L 、PWMB_CCR6H、PWMB_CCR6L、PWMB_CCR7H、PWMB_CCR7L、PWMB_CCR8H、PWMB_CCR8L 这几个和PWM处理有关的寄存器。汇总下这几个寄存器的说明,以方便理解PWM生成的程序逻辑:
1、PWMx_CCER1(x:A/B)
捕获/比较使能寄存器,在输出模式下,配置通道输出使能和极性
在输出状态下,结尾为P的,表示控制输出极性;结尾为E的,表示使能输出。
2、PWMx_CCMR(x:A/B)
捕获/比较模式寄存器,输出模式下,通道配置为比较输出模式
3、PWMx_ARRH、PWMx_ARRL(x:A/B)
自动重装寄存器高、低字节。ARR 包含了将要装载入实际的自动重装载寄存器的值。当自动重装载的值为 0 时,计数器不工作。
4、PWMx_ENO(x:A/B)
输出使能,1有效。
5、PWMx_PS
功能脚切换,选择PWM的输出引脚
6、PWMx_BRK(x:A/B)
刹车寄存器
7、PWMx_CR1(x:A/B)
控制寄存器 1。控制计数方向等。
8、PWMx_CCRnH(x:A/B, n:1/2/3/4/5/6/7/8)
比较寄存器。改变比较值,就相当于改变PWM的占空比。
说实话,涉及到的寄存器还是挺多的。利用高级PWM寄存器,要做很多设置。这些设置,等于一定程度上,代替了程序的处理。