目录
一、引言
二、硬件准备
三、PWM技术概述
四、电路设计
五、代码编写
EAXSFR:
六、编译与下载
七、测试与调试
八、总结
一、引言
在嵌入式系统开发中,LED呼吸灯是一种常见的示例项目,它不仅能够展示PWM(脉冲宽度调制)技术的应用,还能为系统增添一丝动感和美感。STC8系列增强型单片机凭借其高性能和丰富的功能,非常适合用于LED呼吸灯的开发。本文将详细介绍如何使用STC8增强型单片机实现LED呼吸灯效果。
二、硬件准备
- STC8增强型单片机开发板
- LED灯珠
- 限流电阻
- 杜邦线若干
三、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默认导入。
这里的宏定义做了以下事情:
P_SW2
是一个外设端口切换寄存器(可能是一个特定的硬件寄存器,用于控制或配置微控制器的某些外设或功能)。0x80
是一个十六进制数,其二进制表示为10000000
。|=
是一个位或赋值操作符,它将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相关的某些功能或外设。
六、编译与下载
- 在Keil C51中编译程序代码,确保没有错误和警告。
- 将编译生成的hex文件通过编程器下载到STC8增强型单片机开发板中。
七、测试与调试
- 给开发板上电,观察LED灯珠的亮度变化,检查是否实现了呼吸灯效果。
- 如果效果不理想,可以通过调整PWM参数、延时时间等参数进行优化。
八、总结
通过本文的介绍,我们了解了如何使用STC8增强型单片机开发LED呼吸灯项目。在项目实践中,我们不仅掌握了PWM技术的应用,还提高了嵌入式系统开发的能力。希望本文能对大家有所帮助,激发大家对嵌入式系统开发的兴趣和热情。