【STM32】编写程序控制开发板的RGB LED灯

目录

    • 1、原理图
    • 2、文件结构
    • 3、使用寄存器模式点亮
      • 3.1、什么是寄存器
      • 3.2、寄存器开发的本质
      • 3.3、寄存器开发步骤
      • 3.4、主要源码
        • 3.4.1、main.c
        • 3.4.2、drv_gpio.h
        • 3.4.3、drv_gpio.c
        • 3.4.4、使用BSRR和BRR影子寄存器优化`drv_gpio.c`
        • 3.4.5、效果演示
    • 4、使用标准库模式点亮
      • 4.1、使用标准库模式的好处
      • 4.2、主要源码
        • 4.2.1、main.c
        • 4.2.2、drv_gpio.h
        • 4.2.3、drv_gpio.c
        • 4.2.4、效果演示多了白灯

1、原理图

在这里插入图片描述
如图知,拉低为点亮

  • LED

    引脚状态
    D3红PB5输出, 拉低为亮
    D3绿PB0输出, 拉低为亮
    D3蓝PB1输出, 拉低为亮

2、文件结构

在这里插入图片描述

3、使用寄存器模式点亮

3.1、什么是寄存器

寄存器是微控制器(MCU)内部的一种特殊存储器,用于存储配置参数、状态信息或控制信号。每个寄存器通常有固定的地址,并且每一位或一组位对应特定的功能。

3.2、寄存器开发的本质

寄存器开发的本质是直接与硬件交互,绕过高级库(如 HAL 库或标准库)的封装,直接操作底层硬件。
STM32 的寄存器开发是通过直接读写寄存器来实现对外设的控制。

3.3、寄存器开发步骤

(1) 查找寄存器地址

  • 根据 STM32 的参考手册(Reference Manual),找到目标外设的寄存器地址。
  • 每个外设(如 GPIO、TIMER、USART 等)都有一组寄存器,用于配置和控制其行为。

(2) 配置寄存器

  • 通过指针操作或直接访问寄存器地址,向寄存器写入特定的值,以配置外设的工作模式、中断、时钟等。

(3) 读取寄存器

  • 通过读取寄存器的值,获取外设的状态信息(如标志位、数据等)。

3.4、主要源码

3.4.1、main.c
#include "drv_gpio.h"// SysTick 初始化
void SysTick_Init(void)
{SysTick->LOAD = 72000000 / 1000 - 1; // 1ms 延时SysTick->VAL = 0;					 // 清空当前值SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
}// 精确延时函数(单位:ms)
void Delay_ms(uint32_t ms)
{for (uint32_t i = 0; i < ms; i++){while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));}
}int main()
{// 初始化 SysTickSysTick_Init();// 初始化 RGB LEDRGB_Init();while (1){RGB_RedOn();Delay_ms(500);  // 延时 500msRGB_RedOff();RGB_GreenOn();Delay_ms(500);  // 延时 500msRGB_GreenOff();RGB_BlueOn();Delay_ms(500);  // 延时 500msRGB_BlueOff();}
}
3.4.2、drv_gpio.h
#ifndef _DRV_GPIO_H_
#define _DRV_GPIO_H_//ARM提供的,有所有外设寄存器的信息
#include "stm32f10x.h"void RGB_Init(void);void RGB_RedOn(void);void RGB_RedOff(void);void RGB_GreenOn(void);void RGB_GreenOff(void);void RGB_BlueOn(void);void RGB_BlueOff(void);#endif
3.4.3、drv_gpio.c
#include "drv_gpio.h"void RGB_Init(void)
{// 1.配置RCCRCC->APB2ENR |= (1 << 3);// 2.配置PB5的功能// bit 20~23 全部置为0//  bit 20 置为1//pb5GPIOB->CRL &= (uint32_t)(~(0xF << 20));GPIOB->CRL |= (uint32_t)(1 << 20);  //配置为通用推挽输出模式(0b0001)//pb0GPIOB->CRL &= (uint32_t)(~(0xF));GPIOB->CRL |= (uint32_t)(1);//pb1GPIOB->CRL &= (uint32_t)(~(0xF << 4));GPIOB->CRL |= (uint32_t)(1 << 4);  // 3.将pb5、pb0、pb1的初始值改为1,防止配置完就亮灯GPIOB->ODR |= (1 << 5);GPIOB->ODR |= 1;GPIOB->ODR |= (1 << 1);}void RGB_RedOn(void)
{// 3.拉低PB5对应的ODR寄存器地址GPIOB->ODR &= ~(1 << 5);
}void RGB_RedOff(void)
{GPIOB->ODR |= (1 << 5);
}void RGB_GreenOn(void)
{GPIOB->ODR &= ~(1);
}void RGB_GreenOff(void)
{GPIOB->ODR |= 1;
}void RGB_BlueOn(void)
{GPIOB->ODR &= ~(1 << 1);
}void RGB_BlueOff(void)
{GPIOB->ODR |= (1 << 1);
}
3.4.4、使用BSRR和BRR影子寄存器优化drv_gpio.c

由于对ODR直接操作, 可能有意无意修改到其他引脚的状态

#include "drv_gpio.h"void RGB_Init(void)
{// 1.配置RCCRCC->APB2ENR |= (1 << 3);// 2.配置PB5的功能// bit 20~23 全部置为0//  bit 20 置为1//pb5GPIOB->CRL &= (uint32_t)(~(0xF << 20));GPIOB->CRL |= (uint32_t)(1 << 20);  //配置为通用推挽输出模式(0b0001)//pb0GPIOB->CRL &= (uint32_t)(~(0xF));GPIOB->CRL |= (uint32_t)(1);//pb1GPIOB->CRL &= (uint32_t)(~(0xF << 4));GPIOB->CRL |= (uint32_t)(1 << 4);  // 3.将pb5、pb0、pb1的初始值改为1,防止配置完就亮灯GPIOB->ODR |= (1 << 5);GPIOB->ODR |= 1;GPIOB->ODR |= (1 << 1);}void RGB_RedOn(void)
{// 3.拉低PB5对应的ODR寄存器地址//GPIOB->ODR &= ~(1 << 5); GPIOB->BRR &= (1 << 5);// 直接将PB5拉低,同时不影响其他位
}void RGB_RedOff(void)
{//GPIOB->ODR |= (1 << 5);GPIOB->BSRR |= (1 << 5); //直接拉高,并不影响
}void RGB_GreenOn(void)
{//GPIOB->ODR &= ~(1);GPIOB->BRR &= (1);
}void RGB_GreenOff(void)
{//GPIOB->ODR |= 1;GPIOB->BSRR |= (1);
}void RGB_BlueOn(void)
{//GPIOB->ODR &= ~(1 << 1);GPIOB->BRR &= (1 << 1);
}void RGB_BlueOff(void)
{//GPIOB->ODR |= (1 << 1);GPIOB->BSRR |= (1 << 1);
}
3.4.5、效果演示

在这里插入图片描述

4、使用标准库模式点亮

4.1、使用标准库模式的好处

标准库封装了底层寄存器的操作,提供了易于理解的API函数,开发者无需直接读写寄存器。

4.2、主要源码

4.2.1、main.c
#include "drv_gpio.h"// SysTick 初始化
void SysTick_Init(void)
{SysTick->LOAD = 72000000 / 1000 - 1; // 1ms 延时SysTick->VAL = 0;					 // 清空当前值SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
}// 精确延时函数(单位:ms)
void Delay_ms(uint32_t ms)
{for (uint32_t i = 0; i < ms; i++){while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));}
}int main()
{// 初始化 SysTickSysTick_Init();// 初始化 RGB LEDRGB_Init();while (1){RGB_RedOn();Delay_ms(500);  // 延时 500msRGB_RedOff();RGB_GreenOn();Delay_ms(500);  // 延时 500msRGB_GreenOff();RGB_BlueOn();Delay_ms(500);  // 延时 500msRGB_BlueOff();RGB_WriteOn();Delay_ms(500);  // 延时 500msRGB_WriteOff();}
}
4.2.2、drv_gpio.h
#ifndef _DRV_GPIO_H_
#define _DRV_GPIO_H_//使用gpio标准库
#include "stm32f10x_gpio.h"#define RGB_Port GPIOB
#define RGB_Pin_R GPIO_Pin_5
#define RGB_Pin_G GPIO_Pin_0
#define RGB_Pin_B GPIO_Pin_1void RGB_Init(void);void RGB_RedOn(void);void RGB_RedOff(void);void RGB_GreenOn(void);void RGB_GreenOff(void);void RGB_BlueOn(void);void RGB_BlueOff(void);void RGB_WriteOn(void);void RGB_WriteOff(void);#endif
4.2.3、drv_gpio.c
#include "drv_gpio.h"void RGB_Init(void)
{// 1.RCC配置RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 2、配置红、绿、蓝灯输出GPIO_InitTypeDef gpio_initStruct = {0};gpio_initStruct.GPIO_Pin = RGB_Pin_R | RGB_Pin_G | RGB_Pin_B;gpio_initStruct.GPIO_Speed = GPIO_Speed_50MHz;gpio_initStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(RGB_Port, &gpio_initStruct);GPIO_SetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}void RGB_RedOn(void)
{// 3.拉低PB5对应的ODR寄存器地址GPIO_ResetBits(RGB_Port, RGB_Pin_R);
}void RGB_RedOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_R);
}void RGB_GreenOn(void)
{GPIO_ResetBits(RGB_Port, RGB_Pin_G);
}void RGB_GreenOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_G);
}void RGB_BlueOn(void)
{GPIO_ResetBits(RGB_Port, RGB_Pin_B);
}void RGB_BlueOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_B);
}void RGB_WriteOn(void)
{GPIO_ResetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}void RGB_WriteOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}
4.2.4、效果演示多了白灯

在这里插入图片描述

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

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

相关文章

MyBatis-Plus 的加载及初始化

在 Spring Boot 启动过程中&#xff0c;MyBatis-Plus 的加载和初始化涉及多个阶段的工作。这些工作包括 MyBatis-Plus 自身的配置解析、Mapper 接口的扫描与注册、SQL 语句的动态注入以及底层 MyBatis 的初始化等。以下是对整个过程的详细分析&#xff1a; 1. Spring Boot 启动…

SpringBoot中安全的设置阿里云日志SLS的accessKey

众所周知,阿里云的服务都是基于accesskeyId和accesskeySecret来进行身份鉴权的,但唯独日志因为需要写入到.xml文件里对于accesskeyId和accesskeySecret需要进行一定程度的改进,尤其是使用了jasypt进行加密的参数传递进去logback.xml更是会遇到需要对参数进行解密的问题,而官网只…

关于解决Ubuntu终端及系统字体大小的问题

在Ubuntu中调整终端和系统字体大小可以通过以下方法&#xff08;可能不仅仅只是这几种&#xff09;实现&#xff1a; 1. 调整系统字体大小 打开终端并输入以下命令&#xff0c;安装GNOME Tweaks&#xff0c;等待安装完成&#xff1a; sudo apt install gnome-tweaks 接着进行…

Rust vs. Go: 性能测试(2025)

本内容是对知名性能评测博主 Anton Putra Rust vs. Go (Golang): Performance 2025 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。 再次对比 Rust 和 Go&#xff0c;但这次我们使用的是最具性能优势的 HTTP 服务器库---Hyper&#xff0c;它基于 Tokio 异步运…

【NLP 48、大语言模型的神秘力量 —— ICL:in context learning】

目录 一、ICL的优势 1.传统做法 2.ICL做法 二、ICL的发展 三、ICL成因的两种看法 1.meta learning 2.Bayesian Inference 四、ICL要点 ① 语言模型的规模 ② 提示词prompt中提供的examples数量和顺序 ③ 提示词prompt的形式&#xff08;format&#xff09; 五、fine-tune VS I…

两数之和解题记录

开始打算用一个数组保存差值&#xff0c;arr[target-nums[i]] i, 只要arr[nums[i]]有内容就能满足target&#xff0c;返回arr[nums[i]]和i。但是会出现复数的情况&#xff0c;所以换成map。 换成map就只用一边遍历&#xff0c;一遍检查和存入对应key就行了&#xff0c;value就…

P1722 矩阵Ⅱ - 洛谷

题源&#xff1a;P1722 矩阵 II - 洛谷 看了题目之后&#xff0c;需要注意的是&#xff1a; ①在1 ~ i 个格子中红色数量 > 黑色数量 ②最后&#xff0c;在2 * n 个格子中&#xff0c;红色数量 黑色数量 根据这两个约束条件&#xff0c;可以知道&#xff0c;第一个格…

数据库——MySQL基础操作

一、表结构与初始数据 假设存在以下两张表&#xff1a; 1. student 表 字段名数据类型描述idINT学生唯一标识符nameVARCHAR(100)学生姓名ageINT学生年龄sexVARCHAR(10)学生性别 初始数据&#xff1a; idnameagesex1张三20男2李四22女3王五21男 2. course 表 字段名数据类…

行业白皮书2025 | 益企研究院:AI时代的存储基石

在当今科技飞速发展的时代&#xff0c;AI技术已成为推动各行业变革的关键力量。日前&#xff0c;益企研究院重磅发布《AI时代的存储基石》白皮书。 下载方式&#xff1a;关注“渡江客涂鸦板”&#xff0c;回复st250326获取免费下载地址 数据需求与技术挑战&#xff1a; AI技术…

音视频新人如何快速上手nginx-rtmp-module

一、整体设计架构 nginx-rtmp-module 是 Nginx 的一个扩展模块&#xff0c;专门为 Nginx 添加了对 RTMP 协议的支持。其核心功能包括&#xff1a; RTMP推流&#xff08;publish&#xff09; RTMP拉流&#xff08;play&#xff09; 流转发&#xff08;relay&#xff09; 流录…

vue 封装 Axios菜鸟教程

1、Axios依赖下载 $ npm install axios 2、以下链接为Axios 的api Axios 实例 | Axios中文文档 | Axios中文网 3、 项目新建request.js&#xff0c;文件名称按照驼峰命名法就可以 4、封装request.js代码如下 import axios from "axios"//创建axios实例&#xff0…

[项目]基于FreeRTOS的STM32四轴飞行器: 十一.MPU6050配置与读取

基于FreeRTOS的STM32四轴飞行器: 十一.MPU6050 一.芯片介绍二.配置I2C三.编写驱动四.读取任务的测试五.MPU6050六轴数据的校准 一.芯片介绍 芯片应该放置在PCB中间&#xff0c;X Y轴原点&#xff0c;敏感度131表示范围越小越灵敏。理想状态放置在地面上X&#xff0c;Y&#xf…

iOS常见网络框架

URLSession、Alamofire 和 Moya 1. URLSession 1.1 核心概念 URLSession 是 Apple 官方提供的网络请求 API&#xff0c;封装在 Foundation 框架中。它支持 HTTP、HTTPS、FTP 等协议&#xff0c;可用于&#xff1a; ​ • 普通网络请求&#xff08;GET/POST&#xff09; ​ …

AOA(到达角度)与TOA(到达时间)两个技术的混合定位,MATLAB例程,自适应基站数量,三维空间下的运动轨迹,滤波使用UKF(无迹卡尔曼滤波)

本文介绍一个MATLAB代码,实现了三维动态目标非线性定位与滤波系统,通过融合 到达角(AOA) 和 到达时间(TOA) 的混合定位方法,结合 无迹卡尔曼滤波(UKF) 处理非线性观测模型,优化轨迹精度。代码支持自适应基站数量配置,适用于复杂非线性场景的定位研究。 文章目录 运行…

Ubuntu 重置密码方法

目录 修改过 root 密码&#xff0c;重置密码的方法没改过 root 密码‌&#xff0c;重置密码的方法 修改过 root 密码&#xff0c;重置密码的方法 Ubuntu 默认禁用root用户&#xff0c;意思就是安装好Ubuntu系统后&#xff0c;root用户默认是没有密码的&#xff0c;普通用户通过…

Leetcode 路径总和 III

java 解法一&#xff1a;双递归 class Solution {public int pathSum(TreeNode root, long targetSum) { //外层递归,把每个节点都当作路径起点if(root null) return 0;int ret rootSum(root, targetSum);ret pathSum(root.left, targetSum);ret pathSum(root.right, targ…

WEB安全--SQL注入--利用log写入webshell

一、原理&#xff1a; 这也是对之前文章的补充&#xff1a;WEB安全--SQL注入--INTO OUTFILE-CSDN博客 我们可以通过修改MySQL的log文件&#xff0c;用select关键字写入木马文件放在服务器物理地址中&#xff0c;通过访问物理地址getshell。 二、条件&#xff1a; 用户有写入权限…

C++11中引入的比较常用的新特性讲解(上)

目录 1、C11简介 2、统一的列表初始化 2.1、&#xff5b;&#xff5d;初始化 2.2、std::initializer_list 3、变量类型推导 3.1、auto 3.2、decltype 3.3、nullptr 4、范围for循环 5、STL中一些变化 6、右值引用和移动语义 6.1、左值引用和右值引用 6.2、右值引用…

hugo+github pages 部署实验室网站

&#xff01;&#xff01;太爽了&#xff0c;看了很久教程&#xff0c;自己试了好久&#xff0c;终于搞懂怎么把hugo和public单独进行部署了&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 目的是什么&#xff1f;目的当然是为了修改这天杀的hugo的模板。现在…

两头文件互引问题解决(前置声明)

问题&#xff1a; 想必正在基础阶段学习的朋友们都遇见过以下问题吧 widget.h otherwidget.h 如上问题是&#xff0c;我在widget.h中引用了otherwidget.h ,在ohterwidget中又引用了widget.h&#xff0c;两个头文件互相引用产生了报错 解决办法&#xff1a; 那么我们该如何解…