51单片机--PWM

发布时间 2023-12-13 08:53:23作者: 易安yan

芯片:STC8H1K28

目的:呼吸灯

这是一段官网下载的例程,配置了多路PWM,目前不知道具体寄存器赋值,先把能使用的代码贴上,后续再添加

#define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer 0 中断频率, 1000次/秒

#define PWMA_ENO     (*(unsigned char  volatile xdata *)  0xFEB1)
#define PWMA_PS      (*(unsigned char  volatile xdata *)  0xFEB2)
#define PWMB_ENO     (*(unsigned char  volatile xdata *)  0xFEB5)
#define PWMB_PS      (*(unsigned char  volatile xdata *)  0xFEB6)                               

#define PWMA_CR1     (*(unsigned char  volatile xdata *)  0xFEC0)
#define PWMA_CR2     (*(unsigned char  volatile xdata *)  0xFEC1)
#define PWMA_SMCR    (*(unsigned char  volatile xdata *)  0xFEC2) 
#define PWMA_ETR     (*(unsigned char  volatile xdata *)  0xFEC3) 
#define PWMA_IER     (*(unsigned char  volatile xdata *)  0xFEC4) 
#define PWMA_SR1     (*(unsigned char  volatile xdata *)  0xFEC5) 
#define PWMA_SR2     (*(unsigned char  volatile xdata *)  0xFEC6) 
#define PWMA_EGR     (*(unsigned char  volatile xdata *)  0xFEC7) 
#define PWMA_CCMR1   (*(unsigned char  volatile xdata *)  0xFEC8) 
#define PWMA_CCMR2   (*(unsigned char  volatile xdata *)  0xFEC9)
#define PWMA_CCMR3   (*(unsigned char  volatile xdata *)  0xFECA)
#define PWMA_CCMR4   (*(unsigned char  volatile xdata *)  0xFECB)
#define PWMA_CCER1   (*(unsigned char  volatile xdata *)  0xFECC)
#define PWMA_CCER2   (*(unsigned char  volatile xdata *)  0xFECD)
#define PWMA_CNTRH   (*(unsigned char  volatile xdata *)  0xFECE)
#define PWMA_CNTRL   (*(unsigned char  volatile xdata *)  0xFECF)
#define PWMA_PSCRH   (*(unsigned char  volatile xdata *)  0xFED0)
#define PWMA_PSCRL   (*(unsigned char  volatile xdata *)  0xFED1)
#define PWMA_ARRH    (*(unsigned char  volatile xdata *)  0xFED2)
#define PWMA_ARRL    (*(unsigned char  volatile xdata *)  0xFED3)
#define PWMA_RCR     (*(unsigned char  volatile xdata *)  0xFED4)
#define PWMA_CCR1H   (*(unsigned char  volatile xdata *)  0xFED5)
#define PWMA_CCR1L   (*(unsigned char  volatile xdata *)  0xFED6)
#define PWMA_CCR2H   (*(unsigned char  volatile xdata *)  0xFED7)
#define PWMA_CCR2L   (*(unsigned char  volatile xdata *)  0xFED8)
#define PWMA_CCR3H   (*(unsigned char  volatile xdata *)  0xFED9)
#define PWMA_CCR3L   (*(unsigned char  volatile xdata *)  0xFEDA)
#define PWMA_CCR4H   (*(unsigned char  volatile xdata *)  0xFEDB)
#define PWMA_CCR4L   (*(unsigned char  volatile xdata *)  0xFEDC)
#define PWMA_BKR     (*(unsigned char  volatile xdata *)  0xFEDD)
#define PWMA_DTR     (*(unsigned char  volatile xdata *)  0xFEDE)
#define PWMA_OISR    (*(unsigned char  volatile xdata *)  0xFEDF)

/*****************************************************************************/

#define PWM1_1      0x00    //P:P1.0  N:P1.1
#define PWM1_2      0x01    //P:P2.0  N:P2.1
#define PWM1_3      0x02    //P:P6.0  N:P6.1

#define PWM2_1      0x00    //P:P1.2/P5.4  N:P1.3
#define PWM2_2      0x04    //P:P2.2  N:P2.3
#define PWM2_3      0x08    //P:P6.2  N:P6.3

#define PWM3_1      0x00    //P:P1.4  N:P1.5
#define PWM3_2      0x10    //P:P2.4  N:P2.5
#define PWM3_3      0x20    //P:P6.4  N:P6.5

#define PWM4_1      0x00    //P:P1.6  N:P1.7
#define PWM4_2      0x40    //P:P2.6  N:P2.7
#define PWM4_3      0x80    //P:P6.6  N:P6.7
#define PWM4_4      0xC0    //P:P3.4  N:P3.3

#define ENO1P       0x01
#define ENO1N       0x02
#define ENO2P       0x04
#define ENO2N       0x08
#define ENO3P       0x10
#define ENO3N       0x20
#define ENO4P       0x40
#define ENO4N       0x80

/*************  本地变量声明    **************/
bit B_1ms;          //1ms标志

u16 PWM1_Duty;
u16 PWM2_Duty;
u16 PWM3_Duty;
u16 PWM4_Duty;

bit PWM1_Flag;
bit PWM2_Flag;
bit PWM3_Flag;
bit PWM4_Flag;

void UpdatePwm(void);

/******************** 主函数 **************************/
void main(void)
{
    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;   //设置为准双向口

    PWM1_Flag = 0;
    PWM2_Flag = 0;
    PWM3_Flag = 0;
    PWM4_Flag = 0;
    
        PWM1_Duty = 0;
        PWM2_Duty = 256;
        PWM3_Duty = 512;
        PWM4_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

    P_SW2 |= 0x80;
        
    PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCxE 关闭通道
    PWMA_CCER2 = 0x00;
    PWMA_CCMR1 = 0x60; //通道模式配置
    PWMA_CCMR2 = 0x60;
    PWMA_CCMR3 = 0x60;
    PWMA_CCMR4 = 0x60;
    PWMA_CCER1 = 0x55; //配置通道输出使能和极性
    PWMA_CCER2 = 0x55;

    PWMA_ARRH = 0x03; //设置周期时间
    PWMA_ARRL = 0xff;

    PWMA_ENO = 0x00;
    PWMA_ENO |= ENO1P; //使能输出
    PWMA_ENO |= ENO1N; //使能输出
    PWMA_ENO |= ENO2P; //使能输出
    PWMA_ENO |= ENO2N; //使能输出
    PWMA_ENO |= ENO3P; //使能输出
    PWMA_ENO |= ENO3N; //使能输出
    PWMA_ENO |= ENO4P; //使能输出
    PWMA_ENO |= ENO4N; //使能输出

    PWMA_PS = 0x00;  //高级 PWM 通道输出脚选择位
    PWMA_PS |= PWM1_3; //选择 PWM1_3 通道
    PWMA_PS |= PWM2_3; //选择 PWM2_3 通道
    PWMA_PS |= PWM3_3; //选择 PWM3_3 通道
    PWMA_PS |= PWM4_2; //选择 PWM4_3 通道

    PWMA_BKR = 0x80; //使能主输出
    PWMA_CR1 |= 0x01; //开始计时
    P_SW2 &= 0x7f;

    P40 = 0;        //给LED供电
    EA = 1;     //打开总中断

    while (1)
    {
        }
}


/********************** Timer0 1ms中断函数 ************************/
void timer0(void) interrupt 1
{
        if(!PWM1_Flag)
        {
                PWM1_Duty++;
                if(PWM1_Duty >= 2047) PWM1_Flag = 1;
        }
        else
        {
                PWM1_Duty--;
                if(PWM1_Duty <= 0) PWM1_Flag = 0;
        }

        if(!PWM2_Flag)
        {
                PWM2_Duty++;
                if(PWM2_Duty >= 2047) PWM2_Flag = 1;
        }
        else
        {
                PWM2_Duty--;
                if(PWM2_Duty <= 0) PWM2_Flag = 0;
        }

        if(!PWM3_Flag)
        {
                PWM3_Duty++;
                if(PWM3_Duty >= 2047) PWM3_Flag = 1;
        }
        else
        {
                PWM3_Duty--;
                if(PWM3_Duty <= 0) PWM3_Flag = 0;
        }

        if(!PWM4_Flag)
        {
                PWM4_Duty++;
                if(PWM4_Duty >= 2047) PWM4_Flag = 1;
        }
        else
        {
                PWM4_Duty--;
                if(PWM4_Duty <= 0) PWM4_Flag = 0;
        }
        
        UpdatePwm();
}


//========================================================================
// 函数: UpdatePwm(void)
// 描述: 更新PWM占空比. 
// 参数: none.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void UpdatePwm(void)
{
    P_SW2 |= 0x80;
    PWMA_CCR1H = (u8)(PWM1_Duty >> 8); //设置占空比时间
    PWMA_CCR1L = (u8)(PWM1_Duty);
    PWMA_CCR2H = (u8)(PWM2_Duty >> 8); //设置占空比时间
    PWMA_CCR2L = (u8)(PWM2_Duty);
    PWMA_CCR3H = (u8)(PWM3_Duty >> 8); //设置占空比时间
    PWMA_CCR3L = (u8)(PWM3_Duty);
    PWMA_CCR4H = (u8)(PWM4_Duty >> 8); //设置占空比时间
    PWMA_CCR4L = (u8)(PWM4_Duty);
    P_SW2 &= 0x7f;
}

 我只使用了1路PWM

代码如下:

 1 void PWMA_config(void)
 2 {
 3     PWMA_CCER1 = 0x00; //写 CCMRx 前必须先清零 CCxE 关闭通道
 4     PWMA_CCER2 = 0x00;
 5     PWMA_CCMR4 = 0x60; //设置 CC1 为 PWMA 输出模式
 6     PWMA_CCER1 = 0x55; //配置通道输出使能和极性
 7     PWMA_CCER2 = 0x55;
 8     PWMA_ARRH = 0x03; //设置周期时间
 9     PWMA_ARRL = 0xff;
10     PWMA_ENO = 0x00;
11     PWMA_ENO |= ENO4P; //使能输出
12     PWMA_PS = 0x00;  //高级 PWM 通道输出脚选择位
13     PWMA_PS |= 0x40; //选择 PWM4_3 通道
14     PWMA_BKR = 0x80; //使能主输出
15     PWMA_CR1 |= 0x01; //开始计时
16     P_SW2 &= 0x7f;
17 }
18 
19 void UpdatePwm(u16 duty)
20 {
21   P_SW2 |= 0x80;
22 
23   PWMA_CCR4H = (u8)(duty >> 8); //设置占空比时间
24   PWMA_CCR4L = (u8)(duty);
25   P_SW2 &= 0x7f;
26 }