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技术的应用,还提高了嵌入式系统开发的能力。希望本文能对大家有所帮助,激发大家对嵌入式系统开发的兴趣和热情。

  • 40
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STC8H8K64U是一款基于8051架构的单片机,它内置了多个PWM模块,可以方便地实现LED呼吸灯效果。 以下是基于STC-ISP v6.86B和Keil uVision5环境下的代码示例: ```c #include <stc12.h> //头文件 #include <intrins.h> //头文件 #define FOSC 24000000L //系统时钟频率 #define PWM_FREQ 500 //PWM信号频率 //PWM初始化函数 void PWMInit(void) { P_SW2 |= 0x80; // P1.0 引脚连接 PWM1 输出 PWMCKS = 0x04; // PWM 时钟选择,选择 Fosc/16 PWMCFG = 0x00; // PWM 配置,选择单边输出 PWMCR = 0x80; // 使能 PWM 输出 } //PWM调节函数 void PWMAdjust(unsigned int freq, unsigned char duty) { unsigned long pwmval = FOSC / 16 / freq; unsigned int highcnt = pwmval * duty / 100; unsigned int lowcnt = pwmval - highcnt; PWM1H = highcnt >> 8; PWM1L = highcnt & 0xFF; PWM1C = lowcnt >> 8; PWM1D = lowcnt & 0xFF; } //LED呼吸灯代码 void LEDBreath(void) { unsigned char i; for (i = 0; i < 100; i++) { PWMAdjust(PWM_FREQ, i); //调整PWM占空比 _nop_(); //延时 } for (i = 100; i > 0; i--) { PWMAdjust(PWM_FREQ, i); //调整PWM占空比 _nop_(); //延时 } } void main(void) { PWMInit(); //初始化PWM while (1) { LEDBreath(); //LED呼吸灯效果 } } ``` 上述代码中,PWMInit()函数用于初始化PWM模块,PWMAdjust()函数用于调节PWM的占空比,LEDBreath()函数则实现了LED呼吸灯效果。在main()函数中,我们不断地调用LEDBreath()函数,让LED呈现出不断变化的亮度。 注意:以上代码仅供参考,具体实现方式可能因硬件环境和需求而有所不同,请根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值