简单介绍过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寄存器,要做很多设置。这些设置,等于一定程度上,代替了程序的处理。
我要赚赏金
