STM32标准库——控制驱动LED灯、蜂鸣器(四)

Output输出 Input输入 Set置位 Reset复位 / 清零 port:端口 data:数据 register:寄存器 Read:读取

一、库函数

RCC

STM32 的外设默认是关闭时钟的,必须通过该函数手动开启对应外设的时钟,否则外设无法工作。

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

RCC_APB2Periph``uint32_t

要配置的 APB2 外设预定义宏,如RCC_APB2Periph_GPIOA(GPIOA 时钟)、RCC_APB2Periph_USART1(USART1 时钟)、RCC_APB2Periph_SPI1(SPI1 时钟)

NewState``FunctionalState

时钟状态枚举类型,仅两个取值:- ENABLE:使能外设时钟- DISABLE:失能外设时钟

GPIO
GPIO 初始化函数

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

根据初始化结构体的配置,初始化指定 GPIO 端口的指定引脚(模式、速度、上下拉等)

  • 第一个参数 GPIOx:指定要初始化的 GPIO 端口(比如 GPIOA、GPIOB、GPIOC 等);
  • 第二个参数 GPIO_InitStruct:指向 GPIO 配置结构体的指针,包含了具体的初始化参数。
GPIO 读取函数

读取指定 GPIO 端口的单个引脚输入状态

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

读取指定 GPIO 端口所有 16 个引脚的输入状态

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

读取指定 GPIO 端口的单个引脚输出寄存器状态

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

GPIO_ReadOutputData读取指定 GPIO 端口所有引脚的输出寄存器状态

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

GPIO 写入函数

将指定 GPIO 端口的单个 / 多个引脚置高

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

将指定 GPIO 端口的单个 / 多个引脚置低

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

给指定 GPIO 引脚写入自定义值(SET/RESET)

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);

GPIO_Write给指定 GPIO 端口所有 16 个引脚写入状态

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

二、LED

1、流水灯

将前面建立的工程模板复制重命名,在新的工程文件夹中建立System文件夹,将STM32入门教程资料\程序源码\STM32Project-有注释版\1-3 Delay函数模块中的延时函数复制到System文件夹中,并在工程中添加分组、文件、文件地址。再在工程文件中建立Hardware文件夹用来装硬件驱动函数。

建立LED.c\.h文件

点击右下角的'...',找到当前工程文件中的Hardware文件夹选中

.h文件的固定形式,1检查__LED_H这个宏是否未被定义 2如果未定义,就定义这个宏,防止头文件被重复包含 4结束条件编译

LED初始化

void LED_Init(void)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

  1. 时钟使能:外设工作的前提
  • STM32 的所有外设默认都是时钟关闭状态,这是为了降低功耗。

  • 必须先开启对应 GPIO 端口的时钟,否则后续的配置都不会生效。

  • 这里我们开启的是 APB2 总线上的 GPIOA 时钟,因为 GPIOA 挂载在 APB2 总线上。

  1. 配置结构体:参数化设计的优势
  • 模式选择:GPIO_Mode_Out_PP 代表推挽输出模式,这是驱动 LED 的最佳选择,因为它可以输出强高低电平,带负载能力更强。

  • 引脚批量配置:GPIO_Pin_All,配置GPIOA所有16个引脚

  • 速度配置:GPIO_Speed_50MHz 表示引脚电平切换的最大速率,对于 LED 这类低速设备,50MHz 是完全够用的,也可以根据实际需求选择 2MHz 或 10MHz。

  1. 应用配置:写入硬件寄存器
  • 这一步会把结构体里的配置参数写入到 GPIOA 的硬件寄存器中,完成硬件层面的初始化。

  • 标准库通过封装底层寄存器操作,让我们不用直接操作寄存器,提高了代码的可移植性和可读性。

模式

模拟输入模式:GPIO_Mode_AIN = 0x0,

浮空输入模式 GPIO_Mode_IN_FLOATING = 0x04,

下拉输入模式GPIO_Mode_IPD = 0x28,

上拉输入模式 GPIO_Mode_IPU = 0x48,

开漏输出模式GPIO_Mode_Out_OD = 0x14,

推挽输出模式GPIO_Mode_Out_PP = 0x10,

复用开漏模式GPIO_Mode_AF_OD = 0x1C,

复用推挽模式GPIO_Mode_AF_PP = 0x18

声明

在.h中声明,并在main中调用LED.h

使用GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)

GPIO_Write(GPIOA, ~0x001);//0000 0000 0000 0001

Delay_ms(500);

GPIO_Write(GPIOA, ~0x002);//0000 0000 0000 0010

Delay_ms(500);

GPIO_Write(GPIOA, ~0x004);//0000 0000 0000 0100

Delay_ms(500);

GPIO_Write(GPIOA, ~0x008);//0000 0000 0000 1000

Delay_ms(500);

GPIO_Write(GPIOA, ~0x010);//0000 0000 0001 0000

Delay_ms(500);

  • 第一个参数GPIOx:指定操作的 GPIO 端口(如 GPIOA、GPIOB);
  • 第二个参数PortVal:16 位无符号整数,每一位对应 GPIO 的一个引脚(bit0 对应 Pin0,bit1 对应 Pin1...bit15 对应 Pin15);
  • 电平规则:PortVal的某一位为1 → 对应引脚输出高电平;为0 → 对应引脚输出低电平。

因为采用的低电平驱动,所以取反。

2、按键控制LED

使用A1、A2、B1、B11口

LED

封装LED驱动

void LED1_Turn(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

{

if(GPIO_ReadOutputDataBit(GPIOx, GPIO_Pin) == 0)

{

GPIO_SetBits(GPIOx, GPIO_Pin);

}

else

{

GPIO_ResetBits(GPIOx, GPIO_Pin);

}

}

封装后能大幅提升代码的可读性、可维护性和复用性。

使用GPIO_ReadOutputDataBit读取输出端口的电平,根据当前端口的电平来决定下一输出电平。

如:当前A1口是高电平,下一输出电平就是低电平,这样就可以实现按键控制灯的亮灭

在.h中声明,并且在.h中

#define LED1 GPIO_Pin_1

#define LED2 GPIO_Pin_2

这样可以更明了。

按键

建立Key.c/.h,放在Hardware中。

初始化

采用低电平触发,选择上拉输入。

读取端口电平

uint8_t Key_GetNum(void)

{

uint8_t KeyNum = 0;

if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)== 0)

{

Delay_ms(20);

while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)== 0);

Delay_ms(20);

KeyNum = 1;

}

if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)== 0)

{

Delay_ms(20);

while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)== 0);

Delay_ms(20);

KeyNum = 2;

}

return KeyNum;

}

使用GPIO_ReadInputDataBit函数读取输入端口电平,使用延时函数消抖,判断哪个按键按下然后赋值相应的值,并返回出去。函数在.h中声明。

调用

在main文件中调用相关.h文件,定义一个全局变量uint8_t KeyNum = 0用来装按键的状态,在main中调用按键和LED的启动函数。

int main(void)

{

LED_Init();

Key_Init();

while(1)

{

KeyNum = Key_GetNum();

if(KeyNum == 1)

{

LED1_Turn(GPIOA, LED1);

}

if(KeyNum == 2)

{

LED1_Turn(GPIOA, LED2);

}

}

}

三、蜂鸣器

用光敏传感器控制蜂鸣器,当光照弱时蜂鸣器就响。

蜂鸣器

建立Buzzer.c/.h,放在Hardware中。

初始化

电平翻转

蜂鸣器和LED的代码差不多,直接复制过来改个名字。

void Buzzer_Turn(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

{

if(GPIO_ReadOutputDataBit(GPIOx, GPIO_Pin) == 0)

{

GPIO_SetBits(GPIOx, GPIO_Pin);

}

else

{

GPIO_ResetBits(GPIOx, GPIO_Pin);

}

}

光敏传感器

建立LightSensor.c/.h,放在Hardware中。

初始化

返回端口的输入电平

uint8_t LightSensor_Get(void)

{

return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);

}

调用

int main(void)

{

Buzzer_Init();

LightSensor_Init();

while(1)

{

if(LightSensor_Get() == 1)

{

Buzzer_Reset(GPIOB, GPIO_Pin_12);

}

else

{

Buzzer_Set(GPIOB, GPIO_Pin_12);

}

}

}

相关推荐
小龙报2 小时前
【SOLIDWORKS 练习题】草图专题:1.带座轴承
人工智能·嵌入式硬件·物联网·硬件架构·3d建模·硬件工程·精益工程
A-code2 小时前
嵌入式UI刷新:观察者模式实战
stm32·单片机·mcu·物联网·51单片机
纳祥科技3 小时前
NX6802,4路音频DAC芯片,具备90dB 动态范围 -90 dB THD+N
单片机·音视频
安庆平.Я3 小时前
STM32——DMA
stm32·单片机·嵌入式硬件
梁下轻语的秋缘3 小时前
初学者避坑指南:Mac 虚拟机搭建 Keil5 STM32 环境 + 解决 ST-Link USB Command Error 报错
windows·stm32·macos
DLGXY3 小时前
STM32——OLED显示屏(五)
stm32·单片机·嵌入式硬件
CQ_YM3 小时前
ARM之uart
c语言·arm开发·单片机·嵌入式硬件
S火星人S3 小时前
软件调试基础(四【断点和单步执行】4.4【实模式调试器例析】)
stm32·单片机·嵌入式硬件
猫猫的小茶馆7 小时前
【Linux 驱动开发】七. 中断下半部
linux·arm开发·驱动开发·stm32·嵌入式硬件·mcu