STC8增强型单片机进阶开发教程:LED呼吸灯(PWM)

知不足而奋进 望远山而前行

文章目录

  • 目录

    文章目录

    前言

    目标

    内容

    PWM基础概念

    STC8H芯片

    PWMA应用

    PWM配置详解

    周期

    占空比

    模式

    使能PWM

    引脚配置

    EAXSFR扩展寄存器

    总结



  • 前言

    学习PWM(脉宽调制)是探索数字信号转模拟信号的重要一步,尤其在控制电路输出方面具有广泛的应用。本次学习将聚焦于了解PWM的基础概念、掌握在STC8H芯片上配置PWMA的方法以及应用实践。通过深入学习PWM技术,您将能够控制各种设备的亮度、速度等参数,从而在工程和电子领域中做出更多创新。


    目标

    1. 了解PWM基础概念和工作原理
    2. 学习如何在STC8H上配置PWMA
    3. 掌握PWMA的各个配置
    4. 学习如何使用PWMA控制LED亮度
    5. 掌握调试PWM的方法

    内容

    PWM基础概念

    PWM全称是脉宽调制(Pulse Width Modulation),是一种通过改变信号的脉冲宽度来控制电路输出的技术。PWM技术在工业自动化、电机控制、LED调光等领域广泛应用。

    PWM是一种将数字信号转换为模拟信号的技术,它通过改变信号的占空比来控制输出的电平。在STC8H中,PWM输出的频率占空比可以由程序控制,因此可以用来控制各种电机、灯光和其他设备的亮度、速度等参数。

    STC8H芯片

    STC8H 系列的单片机内部集成了8 通道 16 位高级PWM 定时器,分成两周期可不同的 PWM,分别命名为 PWMA 和PWMB ,可分别单独设置。

    第一组 PWMA 可配置成4 组互补/对称/死区控制的PWM 或捕捉外部信号。

    第二组 PWMB 可配置成4 路PWM 输出或捕捉外部信号。

    两组 PWM 的时钟频率可分别独立设置。

    PWM与引脚对应关系如下图:

    PWM

    PWM通道

    对应引脚

    PWMxP

    PWMxN

    PWMA

    PWM1P & PWM1N

    P1.0

    P1.1

    P2.0

    P2.1

    PWM2P & PWM2N

    P5.4

    P1.3

    P2.2

    P2.3

    PWM3P & PWM3N

    P1.4

    P1.5

    P2.4

    P2.5

    PWM4P & PWM4N

    P1.6

    P1.7

    P2.6

    P2.7

    P3.4

    P3.3

    PWMB

    PWM5

    P0.0

    P1.7

    P2.0

    PWM6

    P0.1

    P2.1

    P5.4

    PWM7

    P0.2

    P2.2

    P3.3

    PWM8

    P0.3

    P2.3

    P3.4

    PWMA应用

    控制引脚P2.7实现LED灯1的呼吸效果。

    1. 拷贝所需库文件(其他必备库请自行准备)
      1. STC8H_PWM.cSTC8H_PWM.h
      2. NVIC.cNVIC.h
      3. Switch.h
    1. 导入头文件,初始化宏及全局变量
    #include "Config.h"
    #include "GPIO.h"
    #include "Delay.h"
    #include "NVIC.h"
    #include "Switch.h"
    #include "STC8H_PWM.h"
    
    #define LED_SW	P45
    
    #define LED1		P27
    #define LED2		P26
    #define LED3		P15
    
    #define FREQ		1000
    
    #define PERIOD 	((MAIN_Fosc / FREQ) - 1)	// 周期
    
    PWMx_Duty dutyA;
    1. 配置GPIO
    void GPIO_config(void) {
        GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
        // LED_SW
        GPIO_InitStructure.Pin  = GPIO_Pin_5;		//指定要初始化的IO,
        GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P4, &GPIO_InitStructure);//初始化
        // P2
        GPIO_InitStructure.Pin  = GPIO_Pin_6 | GPIO_Pin_7;		//指定要初始化的IO,
        GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//初始化
    }
    1. 配置PWM
    void	PWM_config(void)
    {
        PWMx_InitDefine		PWMx_InitStructure;
    		
    	// 配置PWM4
        PWMx_InitStructure.PWM_Mode    =	CCMRn_PWM_MODE2;	//模式,		CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
        PWMx_InitStructure.PWM_Duty    =  0;								//PWM占空比时间, 0~Period
        PWMx_InitStructure.PWM_EnoSelect  = ENO4P | ENO4N;	//输出通道选择,	ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
        PWM_Configuration(PWM4, &PWMx_InitStructure);
    
    	// 配置PWMA
        PWMx_InitStructure.PWM_Period   = PERIOD;					//周期时间,   0~65535
        PWMx_InitStructure.PWM_DeadTime = 0;					//死区发生器设置, 0~255
        PWMx_InitStructure.PWM_MainOutEnable= ENABLE;			//主输出使能, ENABLE,DISABLE
        PWMx_InitStructure.PWM_CEN_Enable   = ENABLE;			//使能计数器, ENABLE,DISABLE
        PWM_Configuration(PWMA, &PWMx_InitStructure);			//初始化PWM通用寄存器,  PWMA,PWMB
    
    	// 切换PWM4选择PWM4_SW_P26_P27
        PWM4_SW(PWM4_SW_P26_P27);			//PWM4_SW_P16_P17,PWM4_SW_P26_P27,PWM4_SW_P66_P67,PWM4_SW_P34_P33
    
    	// 初始化PWMA的中断
        NVIC_PWM_Init(PWMA,DISABLE,Priority_0);
    }
    1. 编写Main函数
    
    void main() {
        char direction = 1;
        u8 duty_percent = 0;// 0 -> 100
    
        EAXSFR();		/* 扩展寄存器访问使能, 必写! */
        GPIO_config();
        PWM_config();
        EA = 1;
    
        // 总开关
        LED_SW = 0;
        LED1 = 0; // P2.7 PWM4
        LED2 = 0;
        LED3 = 0;
    
        // 循环之前,设置一次pwm(可选)
        dutyA.PWM4_Duty = PERIOD * duty_percent / 100;
        UpdatePwm(PWM4, &dutyA);
        // 0 -> 100
        while(1) {
            duty_percent += direction;
            // 让duty_percent一直在0-100来回往返
            if(duty_percent >= 100) {
                duty_percent = 100;
                direction = -1;
            } else if(duty_percent <= 0) {
                duty_percent = 0;
                direction = 1;
            }
            // 修改PWM4的duty
            dutyA.PWM4_Duty = PERIOD * duty_percent / 100;
            UpdatePwm(PWM4, &dutyA);
    				
            delay_ms(10);
        }
    }

    PWM配置详解

    周期

    系统主频:1秒钟计数多少次。

    代码中的PWM周期(PWM Period),指的是按N等份切分1秒钟,每个等份的计数值。

    例如上图,我们按照8等份切分1秒钟的总计数值MAIN_Fosc(主频),每个PWM周期的计数值为:

    PWM_Period = MAIN_Fosc / 8 = 24M / 8 = 3M = 3 000 000 单位为次。

    即如果将这个3M作为Period参数,可以得到PWM方波每个周期的时长为:

    1 / 8 = 0.125s

    代码中的配置:

    #define PERIOD 	(MAIN_Fosc / FREQ)	// 周期
    PWMx_InitStructure.PWM_Period   		= PERIOD - 1;

    配置的是周期中的计数值。

    我们的理解策略:通常我们不关心计数值,关心的是1秒钟执行多少次(即频率Hz),也就是一秒钟多少个周期。

    因此在代码MAIN_Fosc / 1000中的1000表示的是1秒钟多少个周期(即频率Hz)。

    MAIN_Fosc / 1000表示的是每个周期的计数值。那为什么要-1呢?因为计数器是从0开始计数的。

    占空比

    在一个PWM的周期计数中,高电平的计数时长百分比。

    模式
  • 冻结: CCMRn_FREEZE
  • 匹配时设置通道 n 的输出为有效电平: CCMRn_MATCH_VALID
  • 匹配时设置通道 n 的输出为无效电平: CCMRn_MATCH_INVALID
  • 翻转: CCMRn_ROLLOVER
  • 强制为无效电平: CCMRn_FORCE_INVALID
  • 强制为有效电平: CCMRn_FORCE_VALID
  • PWM 模式 1: CCMRn_PWM_MODE1
  • PWM 模式 2: CCMRn_PWM_MODE2
  • 常用的为PWM 模式 1PWM 模式 2

    PWM 模式 1和PWM 模式 2是反向的,一个占空比越大越亮,一个是越小越亮。

    使能PWM
    PWMx_InitStructure.PWM_MainOutEnable= ENABLE;			//主输出使能, ENABLE,DISABLE
    PWMx_InitStructure.PWM_CEN_Enable   = ENABLE;			//使能计数器, ENABLE,DISABLE
    PWM_Configuration(PWMA, &PWMx_InitStructure);			//初始化PWM通用寄存器,  PWMA,PWMB
    引脚配置
    PWM4_SW(PWM4_SW_P26_P27);

    使能配置成功后,pwm才能工作。

    如果运行中pwm想停止掉,也可以通过配置使能来停止。

    EAXSFR扩展寄存器

    由于PWM的配置相关特殊功能寄存器位于扩展RAM区域,访问这些寄存器,需先将P_SW2的BIT7设置为1,才可正常读写。

    EAXSFR();		/* 扩展寄存器访问使能 */

    详细可参见STC8手册:

  • 3.1.2 《外设端口切换控制寄存器 2(P_SW2)》
  • 9.2.8 《扩展 SFR 使能寄存器 EAXFR 的使用说明》

  • 总结

    通过本次学习,您已经了解了PWM的基本概念和工作原理,掌握了在STC8H上配置PWMA的步骤以及PWM的各种配置参数。此外,您还学会了如何利用PWM控制LED的亮度,并掌握了调试PWM的方法

    作者:薛慕昭

    物联沃分享整理
    物联沃-IOTWORD物联网 » STC8增强型单片机进阶开发教程:LED呼吸灯(PWM)

    发表回复