STC8增强型单片机开发【LED呼吸灯(PWM)⭐⭐】

目录

一、引言

二、硬件准备

三、PWM技术概述

四、电路设计

五、代码编写

 EAXSFR:

六、编译与下载

七、测试与调试

八、总结


一、引言

在嵌入式系统开发中,LED呼吸灯是一种常见的示例项目,它不仅能够展示PWM(脉冲宽度调制)技术的应用,还能为系统增添一丝动感和美感。STC8系列增强型单片机凭借其高性能和丰富的功能,非常适合用于LED呼吸灯的开发。本文将详细介绍如何使用STC8增强型单片机实现LED呼吸灯效果。

二、硬件准备

  1. STC8增强型单片机开发板
  2. LED灯珠
  3. 限流电阻
  4. 杜邦线若干

三、PWM技术概述

PWM技术是一种通过调整方波的占空比来模拟输出电压的模拟技术。在LED呼吸灯项目中,我们可以利用PWM技术调整LED的亮度,实现呼吸效果。

四、电路设计

将LED灯珠的正极通过限流电阻连接到STC8单片机的PWM输出引脚,LED的负极连接到单片机的GND引脚。注意选择合适的限流电阻,以免损坏LED或单片机。

五、代码编写

以下是一个基于STC8增强型单片机的LED呼吸灯代码示例:

#include "STC8G_H_GPIO.h"
#include "STC8G_H_UART.h"
#include "STC8G_H_NVIC.h"
#include "STC8H_PWM.h"
#include "Config.h"
#include "STC8G_H_Delay.h"
#include "STC8G_H_Switch.h"

#define LED_SW	P45
#define LED1		P27
#define LED2		P26
#define LED3		P15
#define FREQ		1000

#define PERIOD 	MAIN_Fosc / 1000ul// 周期
/*
 Period = 24000000L / 1000ul
        = 24000

	所以现在Period的结果为24000
*/

// 配置GPIO
void GPIO_config(void) {
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    // LED_SW
    GPIO_InitStructure.Pin  = GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_PullUp;	//指定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 | GPIO_Pin_3 | GPIO_Pin_2 | GPIO_Pin_1 | GPIO_Pin_0;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P2, &GPIO_InitStructure);//初始化
    // P1
    GPIO_InitStructure.Pin  = GPIO_Pin_4 | GPIO_Pin_5;		//指定要初始化的IO,
    GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
    GPIO_Inilize(GPIO_P1, &GPIO_InitStructure);//初始化
}

// 配置UART
void UART_config(void) {
    // >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<
    COMx_InitDefine		COMx_InitStructure;					//结构定义
    COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;	//模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
    COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4

    NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    UART1_SW(UART1_SW_P30_P31);		// 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}

// 配置PWM
void	PWM_config(void)
{

    // 配置三个部分:PWMA,PWM通道,选择引脚
    PWMx_InitDefine		PWMx_InitStructure;
    /*
    CCMRn_PWM_MODE1:默认全部输出低电平,当占空比大于0时,高电平的占比会随着占空比逐渐增大
    CCMRn_PWM_MODE2:默认全部输出高电平,当占空比大于0时,低电平的占比会随着占空比逐渐增大
    */

    // 配置PWM4
    PWMx_InitStructure.PWM_Mode    =	CCMRn_PWM_MODE1;	//模式,		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;	//输出通道选择,	ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P

    // 配置PWM通道
    PWM_Configuration(PWM4, &PWMx_InitStructure);  	// 配置PWM4通道
    PWM_Configuration(PWM3, &PWMx_InitStructure);	 	//  配置PWM3通道
    PWM_Configuration(PWM2, &PWMx_InitStructure);		//  配置PWM2通道
    PWM_Configuration(PWM1, &PWMx_InitStructure);		//  配置PWM1通道

    PWM4_SW(PWM4_SW_P26_P27);	 // 配置PWM4的引脚
    PWM3_SW(PWM3_SW_P14_P15);	 // 配置PWM3的引脚
    PWM2_SW(PWM2_SW_P22_P23);	 // 配置PWM2的引脚
    PWM1_SW(PWM1_SW_P20_P21);	 // 配置PWM1的引脚
    // 配置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

    // 需要中断吗?PWMA是有中断的,但是我们不用。
}

int main() {
    int precent_duty = 0; // 表示占位比的百分比  0~100 / 100 = 0~1 * 24000 = 占空比
    int direction = 1; // 方向   用于表示PWM占空比的增加或减少方向(1表示增加,-1表示减少)。
    PWMx_Duty duty;    // 结构体 在STC8H_PWM.h的第713到723行,用于存储PWM设置信息


    // 打开中断总开关
    EA = 1;

    // 打开PWM使用的扩展RAM寄存器,不打开PWM不能工作,必须配置!
    EAXSFR();

    // 1. 设置工作模式
    GPIO_config();
    UART_config();
    // 2. 配置PWM的工作参数
    PWM_config();
    // 3. 打开LED_SW总开关
    LED_SW = 0;
    // 4. 开启呼吸灯
    while(1) {
        // 呼吸灯效果实现
        precent_duty = precent_duty + direction; // 0~100  // 根据direction的值增加或减少percent_duty
        // 确保precent_duty的值在0至100之间【限制】
        if(precent_duty >= 100) {		// 如果percent_duty的值大于等于100
            precent_duty = 100;			// 给percent_duty设置为100
            direction = -1;					//  给direction设置为-1
            // 表示减少占位比
        } else if(precent_duty <= 0) {		// 如果percent_duty的值小于等于0
            precent_duty = 0;
            direction = 1;
            // 表示增加占位比
        }
        // 个人理解【占位比越高马达越强,占位比越低马达越弱,根据while循环一直执行这处代码】
        // percent_duty为100时  direction为-1 占位比开始减少,占位比越低,马达得到的平均电压越低,马达动力开始降低
        // percent_duty为0时    direction为1  占位比开始增加,占位比越高,马达得到的平均电压越高,马达动力开始增加

        duty.PWM4_Duty = precent_duty / 100.0f * PERIOD;
        duty.PWM3_Duty = precent_duty / 100.0f * PERIOD;
        duty.PWM2_Duty = precent_duty / 100.0f * PERIOD;
        duty.PWM1_Duty = precent_duty / 100.0f * PERIOD;
        //作用:【设置PWM(脉宽调制)的占空比】 用这个公式得到实际的PWM占空比。这个值被赋给duty.PWM4_Duty\PWM3_Duty\PWM2_Duty\PWM1_Duty
        /*
        		percent_duty 为100时
        				100 / 100.0f * 24000 = 24000.0
        					100 / 100.0f = 1.0
        					1.0 * 24000 = 24000.0
						percent_duty 为0时
								0 / 100.0f * 24000 = 0.0
									0 / 100.0f = 0.0
									0.0 * 24000 = 0.0

						当 duty.PWM4_Duty 等于 24000.0 时, 这通常表示100%的占空比,将提供最大的功率或亮度。
						当 duty.PWM4_Duty 等于 0.0 时,这通常表示0%的占空比,将不提供任何功率或亮度。
        */
        // 更新PWMA  PWMA中包含 PWM1\PWM2\PWM3\PWM4
        UpdatePwm(PWMA,&duty); 

        delay_ms(20); // 延迟

    }

}
// 马达也可以用

上列代码所以库函数文件:

 

注意:上述代码仅为示例,具体实现时需要根据STC8增强型单片机的型号和开发板的数据手册进行相应的修改和配置。 

 EAXSFR:

 在STC8H.H文件中第1044行代码。

 STC8H.H不需要导入STC8默认导入

这里的宏定义做了以下事情:

  1. P_SW2 是一个外设端口切换寄存器(可能是一个特定的硬件寄存器,用于控制或配置微控制器的某些外设或功能)。
  2. 0x80 是一个十六进制数,其二进制表示为 10000000
  3. |= 是一个位或赋值操作符,它将 P_SW2 寄存器的当前值与 0x80 进行位或操作,并将结果存回 P_SW2 寄存器。这实际上是将 P_SW2 寄存器的第7位(从右边开始数,最低位为第0位)设置为1,而不改变其他位。

关于注释中提到的 /* MOVX A,@DPTR/MOVX @DPTR,A指令的操作对象为扩展SFR(XSFR) */,这部分是描述某个指令(可能是MOVX指令,用于数据指针(DPTR)和累加器(A)之间的数据交换)的操作对象是扩展的特殊功能寄存器(SFR,Special Function Register)。但是,这与 EAXSFR() 宏本身的具体操作没有直接关系,只是提供了上下文或背景信息。

总结来说,EAXSFR() 在这个上下文中是一个宏,用于设置 P_SW2 寄存器的第7位为1,可能用于控制或启用与扩展SFR相关的某些功能或外设。

六、编译与下载

  1. 在Keil C51中编译程序代码,确保没有错误和警告。
  2. 将编译生成的hex文件通过编程器下载到STC8增强型单片机开发板中。

七、测试与调试

  1. 给开发板上电,观察LED灯珠的亮度变化,检查是否实现了呼吸灯效果。
  2. 如果效果不理想,可以通过调整PWM参数、延时时间等参数进行优化。

八、总结

通过本文的介绍,我们了解了如何使用STC8增强型单片机开发LED呼吸灯项目。在项目实践中,我们不仅掌握了PWM技术的应用,还提高了嵌入式系统开发的能力。希望本文能对大家有所帮助,激发大家对嵌入式系统开发的兴趣和热情。

<think>好的,用户想了解STC8A8K64D4单片机PWM配置和使用方法,需要教程和示例代码。首先,我需要回忆一下之前提供的引用内容,里面有关于寄存器配置、PWM通道设置以及示例应用的信息。引用[1]提到PWMSET和ENPWM寄存器,可能涉及到使能PWM模块。引用[2]详细说明了每个PWM通道的独立配置寄存器,比如PWMnCR,需要配置初始电平和中断。引用[3]和[5]提到了PCA_PWM增强型PWM的设置,特别是周期和占空比的计算方法,比如T1和T2的设置。引用[4]则涉及GPIO和存储资源,可能需要配置引脚功能。接下来,用户需要具体的配置步骤和示例代码。首先应该确定使用的是增强型PWM还是传统的PCA_PWM。根据引用[5],增强型PWM可能更常用,因为它有更详细的周期设置。然后,配置步骤可能包括:时钟选择、周期设置、占空比调整、引脚映射、使能PWM输出。需要检查每个寄存器的位设置,比如PWMCKS用于时钟源选择,PWMCAR设置周期,PWMnT1和PWMnT2设置占空比。同时,根据引用[2],每个通道的PWMnCR需要配置初始电平,比如BIT6和BIT5位。 示例代码部分,可能需要初始化PWM相关的寄存器,设置周期和占空比,并启动PWM。用户可能需要一个简单的例子,比如输出固定频率和占空比的PWM信号,或者更复杂的如呼吸效果,这需要动态调整占空比。 还要注意引脚配置,比如将PWM通道映射到特定的GPIO,这涉及到P_SW2寄存器来切换引脚功能,如引用[5]提到的P_SW2的BIT0和BIT1位。最后,确保代码正确,比如时钟源的设置是否正确,预分频是否影响频率计算,以及中断配置是否需要。用户可能还需要了解如何通过库函数简化配置,但根据引用[3],用户可能更倾向于直接操作寄存器,所以示例代码应基于寄存器配置。总结一下,回答的结构应该是先介绍配置步骤,分点说明每个寄存器的设置,然后提供示例代码,并解释关键部分。最后生成相关问题,帮助用户深入理解。</think>### STC8A8K64D4单片机PWM配置教程 STC8A8K64D4的PWM功能通过**增强型PWM模块**和**PCA_PWM模块**实现,以下是核心配置步骤及代码示例: --- #### 一、PWM模块配置要点 1. **时钟源选择** - 通过`PWMCKS`寄存器选择内部时钟或外部输入,默认使用系统时钟分频(如$f_{sys}/1$)[^5]。 - 计算公式: $$ PWM频率 = \frac{时钟源频率}{(PWMCAR + 1)} $$ 2. **周期与占空比设置** - **周期寄存器**:`PWMCAR`定义PWM总周期值。 - **占空比寄存器**:`PWMnT1`(高电平时间)和`PWMnT2`(低电平时间),占空比为$\frac{PWMnT1}{PWMCAR}$[^5]。 3. **引脚映射与使能** - 使用`P_SW2`寄存器切换PWM通道到指定引脚(如P2.0映射为PWM0)[^3]。 - 在`PWMnCR`寄存器中使能通道输出(设置`ENPWM`位)[^2]。 --- #### 二、示例代码(输出1kHz方波,占空比50%) ```c #include "STC8A8K64D4.h" void PWM_Init() { // 1. 配置PWM0通道引脚(P2.0) P2M1 &= ~0x01; // 设置为推挽输出 P2M0 |= 0x01; P_SW2 |= 0x80; // 允许访问XFR寄存器 // 2. 设置时钟源(假设系统时钟24MHz) PWMCKS = 0x00; // 使用系统时钟/1 PWMCAR = 23999; // 周期值:24MHz/(24000) = 1kHz // 3. 配置PWM0占空比(50%) PWM0T1 = 11999; // 高电平时间 PWM0T2 = PWM0T1 + 1; // 低电平时间 // 4. 使能PWM0通道 PWM0CR = 0x80; // ENPWM=1,初始高电平 PWMFDCR = 0x00; // 关闭故障检测 // 5. 启动PWM模块 PWMCR = 0x80; // 全局使能 } void main() { PWM_Init(); while(1); } ``` --- #### 三、关键寄存器说明 1. **PWMCKS (B7H)** - BIT0~3:时钟预分频系数(0~15)[^5]。 2. **PWMnCR (通道配置寄存器)** - BIT7:`ENPWM`(通道使能) - BIT6:`RST`(计数器复位) - BIT5:`SET`(初始电平控制)[^2]。 --- #### 四、应用场景 1. 电机调速(通过占空比调节转速)[^1]。 2. LED调光(呼吸效果)[^4]。 3. 音频信号生成(需高频PWM调制)[^3]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值