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

news2024/11/25 19:47:31

目录

一、引言

二、硬件准备

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1669135.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决 Content type ‘application/json;charset=UTF-8‘ not supported

文章目录 问题描述原因分析解决方案参考资料 问题描述 我项目前端采用vue-elementUi-admin框架进行开发&#xff0c;后端使用SpringBoot&#xff0c;但在前后端登录接口交互时&#xff0c;前端报了如下错误 完整报错信息如下 前端登录接口JS代码如下 export function login(…

Busybox 在 Docker 中的部署和启动

可以使用 docker pull 指令下载 busybox:latest 镜像&#xff1a; PS C:\Users\yhu> docker pull busybox:latest latest: Pulling from library/busybox ec562eabd705: Pull complete Digest: sha256:5eef5ed34e1e1ff0a4ae850395cbf665c4de6b4b83a32a0bc7bcb998e24e7bbb St…

网安面经之文件包含漏洞

一、文件包含漏洞 1、文件包含漏洞原理&#xff1f;危害&#xff1f;修复&#xff1f; 原理&#xff1a;开发⼈员⼀般希望代码更灵活&#xff0c;所以将被包含的⽂件设置为变量&#xff0c;⽤来进⾏动态调⽤&#xff0c;但是由于⽂件包含函数加载的参数没有经过过滤或者严格的…

Selenium 自动化 —— 一篇文章彻底搞懂XPath

更多关于Selenium的知识请访问“兰亭序咖啡”的专栏&#xff1a;专栏《Selenium 从入门到精通》 文章目录 前言 一、什么是xpath&#xff1f; 二、XPath 节点 三. 节点的关系 1. 父&#xff08;Parent&#xff09; 2. 子&#xff08;Children&#xff09; 3. 同胞&#xff08;S…

LLM量化

Efficient Finetuning prefix tuning 针对每种任务&#xff0c;学习prefix vector 启发于prompting&#xff0c;调整上下文内容让模型去输出自己想要的内容 核心就是找到一个上下文去引导模型解决NLP生成任务 传统情况下&#xff0c;我们为了得到想要的结果&#xff0c;会…

1.9. 离散时间鞅-组合方法分析随机游动(不用鞅方法)

组合方法分析随机游动-不用鞅方法 组合方法分析随机游动(不用鞅方法)1. 反射原理 → \rightarrow →首击时分布2. 反正弦定律(末击时分布)组合方法分析随机游动(不用鞅方法) 本节将不使用鞅更深入地研究简单随机游动的属性,有益于过渡到马氏链的研究. 1. 反射原理

20240512,函数对象,常用算法:遍历,查找

函数对象 函数对象基本使用 重载 函数调用操作符 的类&#xff0c;其对象被称为函数对象&#xff1b;函数对象使用重载的&#xff08;&#xff09;时&#xff0c;行为类似函数调用&#xff0c;也叫仿函数 函数对象&#xff08;仿函数&#xff09;本质是一个类&#xff0c;不是…

【GlobalMapper精品教程】080:WGS84转UTM投影

参考阅读:ArcGIS实验教程——实验十:矢量数据投影变换 文章目录 一、加载实验数据二、设置输出坐标系三、数据导出一、加载实验数据 打开配套案例数据包中的data080.rar中的矢量数据,如下所示: 查看源坐标系:双击图层的,图层投影选项卡,数据的已有坐标系为WGS84地理坐标…

opencompass实践

参考教程 https://github.com/InternLM/Tutorial/blob/camp2/opencompass/readme.md 下载opencompass&#xff0c;配置必要的环境之后&#xff0c;解压下载的数据集 cp /share/temp/datasets/OpenCompassData-core-20231110.zip /root/opencompass/ unzip OpenCompassData-co…

Smurf 攻击是不是真的那么难以防护

Smurf攻击是一种网络攻击方式&#xff0c;属于分布式拒绝服务&#xff08;DDoS&#xff09;攻击的变种。以 1990 年代流行的名为 Smurf 的漏洞利用工具命名。该工具创建的 ICMP 数据包很小&#xff0c;但可以击落大目标。 它利用ICMP协议中的回声请求&#xff08;ping&#x…

第七次--大模型测评

在该章节中更多是体验与尝试 一、理论学习 类型&#xff1a;语言大模型和多模态大模型这两种是主要的类型。 挑战&#xff1a;要想办法建立一个全面的评价体系&#xff0c;还要能处理大规模的数据&#xff0c;并且要保证评测的准确性和可重复性&#xff0c;真不是一件容易的事…

Unity生命周期函数详解

Unity生命周期函数详解 Unity生命周期函数是Unity引擎中用于控制游戏对象行为的一系列方法。它们在游戏的不同阶段被自动调用&#xff0c;允许开发者在适当的时机执行特定的代码。了解和正确使用生命周期函数对于创建流畅和高效的游戏至关重要。 生命周期函数概述 Unity生命…

变量的解构赋值

变量的解构赋值 数组的解构赋值对象解构赋值 对象的解构与数组有一个重要的不同。嵌套结构的对象 字符串的解构赋值数值和布尔值的解构赋值函数参数的解构赋值 变量的解构赋值用途 交换变量的值从函数返回多个值函数参数的定义提取JSON数据设置默认值遍历Map和Set不完全解构输入…

TM1650 并联在I2C 信号线的处理方法

目的是可以并联多个TM1650 在标准I2C 总线上&#xff0c;并且不影响其他标准I2C 器件。思路就是拿个额外的开关控制每一片TM1650 的使能&#xff0c;就像SPI 的CS 信号那样。 协议 TM1650 的通信协议虽说不是标准I2C&#xff0c;但也算是比较兼容的&#xff0c;比方说&#x…

azkaban-tools 项目介绍

本文背景 应一个用户的好心和好奇心&#xff0c;在最近水深火热的百忙之中抽时间写完了一个简短的项目介绍&#xff0c;其实就是几个azkaban的批量操作脚本&#xff0c;但在大数据集群的“运维生涯”中&#xff0c;还是帮了自己不少忙&#xff0c;也算是为了它做一个简单的回顾…

SpringBoot集成jxls2实现复杂(多表格)excel导出

核心依赖 需求 导出多个表格&#xff0c;包含图片&#xff0c;类似商品标签 1.配置模板 创建一个xlsx的模板文件&#xff0c;配置如下 该模板进行遍历了两次&#xff0c;因为我想要导出的数据分为两列展示&#xff0c;左右布局&#xff0c;一个循环实现不了&#xff0c;所以采…

重学JavaScript高阶知识点(三)—— 详解Js中的内存管理

详解Js中的内存管理 1. 简介2. 内存生命周期3. JavaScript 的内存分配4. 垃圾回收 1. 简介 很多底层语言一般都有底层的内存管理接口&#xff0c;比如 C语言&#xff0c;可以调用对应的API去创建和释放内存空间。意思是需要手动去创建和释放内存空间&#xff0c;很明显&#x…

TCP服务器实现将客服端发送的信息广播发送(使用内核链表管理客户端信息)

目录 1.服务器端实现思路 2.服务器端代码 3.客户端代码 4.内核链表代码 5.运行格式 一、服务器端 二、客户端 6.效果 1.服务器端实现思路 Tcp广播服务初始化 等待客户端连接 广播发送 2.服务器端代码 #include "list.h" #include <signal.h> #def…

如何解决IntelliJ IDEA中pom.xml依赖项引发的安全漏洞黄线警告问题

背景 在开发过程中&#xff0c;当我们在pom.xml文件中添加依赖项时&#xff0c;经常会发现IntelliJ IDEA报出黄色警告线条&#xff0c;提示存在潜在的安全漏洞。警告的具体展现形式如下&#xff1a; 解决方案 首先&#xff0c;打开设置菜单界面&#xff0c;接着选择编辑器选…

神经网络复习--神经网络算法模型及BP算法

文章目录 神经网络模型的构成BP神经网络 神经网络模型的构成 三种表示方式&#xff1a; 神经网络的三要素&#xff1a; 具有突触或连接&#xff0c;用权重表示神经元的连接强度具有时空整合功能的输入信号累加器激励函数用于限制神经网络的输出 感知神经网络 BP神经网络 …