你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

如何点亮流水灯基于STM32单片机

[复制链接]
攻城狮Melo 发布时间:2023-3-29 19:15
STM32单片机GPIO口点亮流水灯
任何一个单片机,最简单的外设莫过于 IO 口的高低电平控制了,本文将通过一个经典的流水灯程序,了解 STM32F1 的 IO 口作为输出LED:DS0 和 DS1 交替闪烁,实现类似流水灯的效果。

STM32IO口简介
本文将要实现的是控制ALIENTEK 精英 STM32开发板上的两个LED实现一个类似流水灯的效果,该实验的关键在于如何控制 STM32 的 IO 口输出。了解了 STM32 的 IO 口如何输出的,就可以实现流水灯了。
STM32上有众多IO口,每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。每个 IO 口可以自由编程,但 IO 口寄存器必须要按 32 位字被访问。STM32 的很多 IO 口都是 5V 兼容的,这些 IO 口在与 5V 电平的外设连接的时候很有优势,具体哪些 IO 口是 5V 兼容的,可以从该芯片的数据手册管脚描述章节查到(I/O Level 标 FT 的就是 5V 电平兼容的)。

20210519200849428.png

STM32 的 IO 口相比 51 而言要复杂得多,所以使用起来也困难很多。首先 STM32 的 IO 口
可以由软件配置成如下 8 种模式:
1、输入浮空
2、输入上拉
3、输入下拉
4、模拟输入
5、开漏输出
6、推挽输出
7、推挽式复用功能
8、开漏复用功能

20210519201425354.png

STM32 的 CRL 控制着每组 IO 端口(A~G)的低 8 位的模式。每个 IO 端口的位占用 CRL 的 4 个位,高两位为 CNF,低两位为 MODE。这里我们可以记住几个常用的配置,比如 0X0 表示模拟输入模式(ADC 用)、0X3 表示推挽输出模式(做输出口用,50M 速率)、0X8 表示上/下拉输入模式(做输入口用)、0XB 表示复用输出(使用 IO 口的第二
功能,50M 速率)。CRH 的作用和 CRL 完全一样,只是 CRL 控制的是低 8 位输出口,而 CRH 控制的是高 8位输出口。
这里我们点亮流水灯是使用库函数进行配置GPIO口的相关参数。


基于固件库函数配置GPIO口
GPIO 相关的函数和定义分布在固件库文件 stm32f10x_gpio.c 和头文件 stm32f10x_gpio.h 文件中。
在固件库开发中,操作寄存器 CRH 和 CRL 来配置 IO 口的模式和速度是通过 GPIO 初始化函数完成:
  1. void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
复制代码

这个函数有两个参数:
第一个参数是用来指定 GPIO,取值范围为 GPIOA~GPIOG。
第二个参数为初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef。结构体的具体定义如下。
  1. typedef struct
  2. {
  3.         int16_t GPIO_Pin;
  4.         GPIOSpeed_TypeDef GPIO_Speed;
  5.         GPIOMode_TypeDef GPIO_Mode;
  6. }GPIO_InitTypeDef;
复制代码

那么如何具体配置一个IO口呢?
初始化结构体初始化 GPIO 的常用格式是:
  1. GPIO_InitTypeDef GPIO_InitStructure;
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
  3. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
  4. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度 50MHz
  5. GPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数配置 GPIO
复制代码

上面代码的意思是设置 GPIOB 的第 5 个端口为推挽输出模式,同时速度为 50M。从上面初始化代码可以看出,结构体 GPIO_InitStructure 的第一个成员变量 GPIO_Pin 用来设置是要初始化哪个或者哪些 IO 口;第二个成员变量 GPIO_Mode 是用来设置对应 IO 端口的输出输入模式,第三个参数是 IO 口速度设置,有三个可选值。GPIO_Mode和GPIO_Speed均是由枚举类型定义。具体定义分别为

GPIO_Mode:
  1. typedef enum
  2. {
  3.         GPIO_Mode_AIN = 0x0, //模拟输入
  4.         GPIO_Mode_IN_FLOATING = 0x04, //浮空输入
  5.         GPIO_Mode_IPD = 0x28, //下拉输入
  6.         GPIO_Mode_IPU = 0x48, //上拉输入
  7.         GPIO_Mode_Out_OD = 0x14, //开漏输出
  8.         GPIO_Mode_Out_PP = 0x10, //通用推挽输出
  9.         GPIO_Mode_AF_OD = 0x1C, //复用开漏输出
  10.         GPIO_Mode_AF_PP = 0x18 //复用推挽
  11. }GPIOMode_TypeDef;
复制代码

GPIO_Speed:
  1. typedef enum
  2. {
  3. GPIO_Speed_10MHz = 1,
  4. GPIO_Speed_2MHz,
  5. GPIO_Speed_50MHz
  6. }GPIOSpeed_TypeDef;
复制代码

这样我们就可以初始化好一个GPIO口。


实现流水灯的基本代码
想要实现流水灯,要先了解控制GPIO口输出高低电平的函数。


输出高电平
  1. GPIO_SetBits(GPIOB, GPIO_Pin_5);//PB.5输出高电平
复制代码

输出低电平
  1. GPIO_ResetBits(GPIOB, GPIO_Pin_5);//PB.5输出低电平
复制代码

使用IO口的基本操作为
1) 使能 IO 口时钟。调用函数为 RCC_APB2PeriphClockCmd()。 2) 初始化 IO 参数。调用函数 GPIO_Init();
3) 操作 IO。


实操一波
先建立led.c和led.h文件
  1. #include "led.h"
  2. //初始化 PB5 和 PE5 为输出口.并使能这两个口的时钟
  3. //LED IO 初始化
  4. void LED_Init(void)
  5. {
  6.         GPIO_InitTypeDef GPIO_InitStructure;
  7.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|
  8.         RCC_APB2Periph_GPIOE, ENABLE); //使能 PB,PE 端口时钟
  9.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 推挽输出
  10.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
  11.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  13.         GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
  14.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 推挽输出
  15.         GPIO_Init(GPIOE, &GPIO_InitStructure);
  16.         GPIO_SetBits(GPIOE,GPIO_Pin_5); /PE.5 输出高
  17. }
复制代码

在led.h文件里,可以使用如下宏定义
  1. #ifndef __LED_H
  2. #define __LED_H
  3. #include "sys.h"
  4. //LED 端口定义
  5. #define LED0 PBout(5)// DS0
  6. #define LED1 PEout(5)// DS1
  7. void LED_Init(void);//初始化
  8. #endif
复制代码

这样就可以实现位带操作来实现操作某个 IO 口的 1 个位

我们在main.c里写下主函数
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. //ALIENTEK 精英 STM32 开发板实验 1
  5. //跑马灯实验
  6. int main(void)
  7. {
  8.         delay_init(); //延时函数初始化
  9.         LED_Init(); //初始化与 LED 连接的硬件接口
  10.         while(1)
  11.         {
  12.                 LED0=0;
  13.                 LED1=1;
  14.                 delay_ms(300); //延时 300ms
  15.                 LED0=1;
  16.                 LED1=0;
  17.                 delay_ms(300); //延时 300ms
  18.         }
  19. }
复制代码

如果没有使用宏定义,也可以使用输出电平函数进行设计
  1. GPIO_SetBits(GPIOB, GPIO_Pin_5); //设置 GPIOB.5 输出 1,等同 LED0=1;
  2. GPIO_ResetBits(GPIOB, GPIO_Pin_5); //设置 GPIOB.5 输出 0,等同 LED0=0;
复制代码

注:
由于stm32精英板的led灯只有两个,如果点亮外设的led灯,最好注意一下IO口的选择,许多IO口有多种功能,在选择IO口上可以考虑那些,未接任何外设,完全独立的IO口。
————————————————
版权声明:Pessimist~
如有侵权请联系删除



收藏 评论0 发布时间:2023-3-29 19:15

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版