这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 【STC32G12K128】使用高级定时器生成PWM波的例程

共3条 1/1 1 跳转至

【STC32G12K128】使用高级定时器生成PWM波的例程

专家
2024-12-16 22:36:43     打赏

简单介绍过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有效。

图片9.png

5、PWMx_PS

功能脚切换,选择PWM的输出引脚

图片10.png

6、PWMx_BRK(x:A/B)

刹车寄存器

图片11.png

7、PWMx_CR1(x:A/B)

控制寄存器 1。控制计数方向等。

图片12.png图片13.png

8、PWMx_CCRnH(x:A/B, n:1/2/3/4/5/6/7/8)

比较寄存器。改变比较值,就相当于改变PWM的占空比。

图片14.png

说实话,涉及到的寄存器还是挺多的。利用高级PWM寄存器,要做很多设置。这些设置,等于一定程度上,代替了程序的处理。





关键词: 菜鸟学单片机    

专家
2024-12-17 00:51:06     打赏
2楼

感谢分享


专家
2024-12-17 07:01:11     打赏
3楼

看看


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]