前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕
📚📗📕📘📖🕮💡📝🗂️✍️🛠️💻🚀🎉🏗️🌐🖼️🔗📊👉🔖⚠️🌟🔐⬇️·正文开始
⬇️·🎥😊🎓📩😺🌈🤝🤖📜📋🔍✅🧰❓📄📢📈 🙋0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟🆗*️⃣#️⃣
【热门主题】000052 STM32 外设应用全攻略
📚一、STM32 外设概述
STM32 微控制器的外设资源极为丰富,涵盖了通用外设、通信外设和模拟外设三大类,在众多领域都有着广泛的应用。
通用外设中,定时器 / 计数器可产生精确的定时脉冲,用于测量时间间隔或计数事件。例如,在一些需要定时触发任务的场景中,如定时采集传感器数据、定时控制设备的开关等,定时器就发挥了重要作用。STM32 的定时器具有多种工作模式,通过配置预分频器和自动重装载寄存器等参数,可以满足不同的定时需求。
看门狗定时器则为系统的稳定运行提供了保障。它通过定期复位计数器来检测系统是否正常运行,一旦发现异常,就会触发复位信号,重新启动系统。这在一些对系统稳定性要求较高的应用中,如工业自动化控制、汽车电子等领域,是非常关键的功能。
DMA 控制器可以自动在内存和外设之间传输数据,极大地减轻了 CPU 的负担。在数据量较大的应用场景中,如音频、视频数据的传输,DMA 控制器能够高效地完成数据传输任务,提高系统的整体性能。
通信外设方面,UART/USART 用于异步串行通信,可与 PC 进行调试或与外部传感器进行数据交换。它具有可配置的波特率、数据位、停止位和校验位等通信参数,能够适应不同的通信需求。
SPI 用于同步串行通信,支持多主机和多从机模式,具有占用引脚少、数据传输速率高的优点。在与 LCD 显示屏、存储器等外部设备进行快速数据交换时,SPI 接口表现出色。
I2C 用于双向串行通信,支持多主模式,可实现多个主设备与多个从设备之间的通信。在与传感器、EEPROM、RTC 等设备进行通信时,I2C 接口以其低功耗、简单可靠的特点受到广泛应用。
模拟外设中,ADC 用于将模拟信号转换为数字信号,广泛应用于传感器数据采集、电池电量检测等场景。例如,在温度传感器数据采集应用中,ADC 将温度传感器输出的模拟电压转换为数字量,以便 STM32 进行处理和分析。
DAC 用于将数字信号转换为模拟信号,在音频信号输出、模拟信号生成等场合有广泛应用。比如在一些简单的音频播放应用中,DAC 可以将数字音频数据转换为模拟音频信号,驱动小型扬声器。
📚二、常用外设详解
📘(一)GPIO
GPIO(General Purpose Input/Output)即通用输入输出端口,在 STM32 中有着广泛的应用。
GPIO 的基础功能之一是控制 LED 亮灭。通过将 GPIO 引脚设置为输出模式,并向该引脚输出高电平或低电平,可以控制连接在该引脚上的 LED 的亮灭状态。例如,当输出高电平时,LED 导通发光;当输出低电平时,LED 熄灭。
读取按键状态也是 GPIO 的常见应用。将 GPIO 引脚设置为输入模式,可以读取连接在该引脚上的按键状态。当按键未按下时,GPIO 引脚输入高电平;当按键按下时,GPIO 引脚输入低电平。
STM32 的 GPIO 具有多种输入输出模式,每种模式都有其特点。例如,推挽输出模式可以输出高、低电平,连接数字器件,驱动力比较强;开漏输出模式输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行,适合做电流型的驱动,其吸收电流的能力相对强。浮空输入模式下,IO 的电平状态是不确定的,完全由外部输入决定;上拉输入模式下,当 IO 不接外设时,上拉电阻将 IO 口的电位钳制在 VDD,呈现高电平;下拉输入模式下,当 IO 不接外设时,下拉电阻将 IO 口的电位钳制在 VSS,呈现低电平。
📘(二)ADC
ADC(Analog-to-Digital Converter)是模拟数字转换器,它将模拟信号转换为数字信号。
在温度传感器读取方面,ADC 可以将温度传感器输出的模拟电压转换为数字量,STM32 通过读取这个数字量来确定当前的温度值。例如,常见的热敏电阻温度传感器,其电阻值随温度变化而变化,通过一个分压电路将电阻值的变化转换为电压的变化,ADC 再将这个电压转换为数字量。
在电池电压监测中,ADC 可以实时监测电池的输出电压。通过连接电池的输出端到 ADC 的输入通道,STM32 可以定期读取 ADC 转换后的数字值,从而判断电池的电量状态。当电池电量过低时,可以发出警报或采取相应的节能措施。
📘(三)UART
UART(Universal Asynchronous Receiver/Transmitter)即通用异步收发器,用于串行通信。
UART 具有可配置的波特率、数据位、停止位和校验位等通信参数,能够适应不同的通信需求。在与其他设备进行数据交换的应用场景中,例如与 PC 进行调试时,可以通过 UART 将 STM32 的调试信息发送到 PC 上的串口调试助手工具,方便开发者查看程序的运行状态。在与外部传感器进行数据交换时,UART 可以接收传感器发送的测量数据,或者向传感器发送控制指令。
📘(四)I2C
I2C(Inter-Integrated Circuit)是一种常用串行通信协议。
I2C 具有多主模式功能,支持多个设备通过两条线(一个串行数据线 SDA 和一个串行时钟线 SCL)进行通信。在 OLED 显示屏驱动方面,STM32 可以通过 I2C 接口与 OLED 显示屏进行通信,发送控制指令和数据,实现图像和文字的显示。在 EEPROM 数据存储中,I2C 可以用于读写 EEPROM 芯片,将重要的数据进行存储,以便在掉电后仍能保存。
📘(五)SPI
SPI(Serial Peripheral Interface)是一种高速通信协议。
SPI 支持高速的全双工数据传输,只需少量的信号线和硬件引脚。在 LCD 显示屏驱动场合,SPI 可以快速地传输图像数据,实现流畅的显示效果。在 Flash 存储中,SPI 可以实现高速的数据读写操作,提高存储和读取数据的效率。
📘(六)TIM
TIM(Timer)定时器可以产生精确时间延迟、测量时间间隔等功能。
在 PWM 控制方面,TIM 可以产生不同占空比的脉冲宽度调制信号,用于控制电机的速度、LED 的亮度等。在计时器中断中,TIM 可以设置一定的时间间隔,当时间到达时产生中断信号,触发特定的任务执行。例如,可以设置一个定时器每隔 1 秒产生一次中断,在中断服务函数中更新系统时间或者执行其他周期性任务。
📘(七)CAN
CAN(Controller Area Network)总线协议在车辆信息传输、工业设备控制等领域有着广泛的应用。
在车辆信息传输中,CAN 总线可以连接车辆中的各个电子控制单元(ECU),实现发动机控制、制动系统控制、仪表盘显示等功能之间的高速通信。在工业设备控制中,CAN 总线可以实现多个设备之间的可靠通信,具有抗干扰能力强、传输距离远等优点。
📘(八)USB
USB(Universal Serial Bus)外设使 STM32 与计算机或其他 USB 设备通信。
在数据传输场景中,STM32 可以通过 USB 接口与计算机进行高速数据传输,例如将采集到的数据上传到计算机进行分析处理,或者从计算机下载程序到 STM32 中进行固件更新。在固件更新方面,通过 USB 接口可以方便地对 STM32 的固件进行升级,提高设备的功能和性能。
📚三、外设应用实例
📘STM32 外设应用实例(自用)
🔖1. 定时器应用
STM32 的定时器功能强大,可用于多种场景。例如,基本定时器可以实现 LED 的周期性闪烁。以下是一个使用基本定时器实现 LED 闪烁的示例代码:
#include “stm32f4xx.h”
void TIM2_Init() {
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // 使能 TIM2 时钟
TIM2->PSC = 1600 - 1; // 设置预分频值,时钟频率为 84MHz/(1600) = 52.5kHz
TIM2->ARR = 500 - 1; // 设置重装载值,定时周期为(500/52.5k) ≈ 9.5ms
TIM2->CR1 |= TIM_CR1_ARPE; // 自动重装载使能
TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器
}
void LED_Init() {
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // 使能 GPIOD 时钟
GPIOD->MODER |= GPIO_MODER_MODER12_0; // 设置 PD12 为输出模式
}
int main() {
LED_Init();
TIM2_Init();
while(1) {
if (TIM2->SR & TIM_SR_UIF) {
TIM2->SR &= ~TIM_SR_UIF; // 清除更新中断标志位
GPIOD->ODR ^= GPIO_ODR_ODR_12; // 翻转 LED 状态
}
}
}
🔖2. 串口应用
STM32 的串口可用于与外部设备进行数据交换。例如,使用串口与 PC 进行调试时,可以通过 UART 将 STM32 的调试信息发送到 PC 上的串口调试助手工具,方便开发者查看程序的运行状态。以下是一个简单的串口通信示例代码:
#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
// 初始化串口
void USART1_Init(void) {
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
int main() {
USART1_Init();
while(1) {
// 发送和接收数据的逻辑可以根据实际需求添加
}
}
🔖3. 蓝牙模块应用
下面是一个基于 STM32 的蓝牙通信示例代码,它使用了 HX-08 的蓝牙模块,并通过 UART 进行通信。
#include "main.h"
#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
void HAL_MspInit(void) {
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
}
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
// 打开蓝牙模块
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_Delay(1000);
// 设置蓝牙模块为 AT 指令模式
HAL_UART_Transmit(&huart1, (uint8_t*)"AT", 2, 100);
HAL_Delay(1000);
// 设置蓝牙模块波特率
HAL_UART_Transmit(&huart1, (uint8_t*)"AT+BAUD8", 8, 100);
HAL_Delay(1000);
// 设置蓝牙模块名称
HAL_UART_Transmit(&huart1, (uint8_t*)"AT+NAMEMyDevice", 14, 100);
HAL_Delay(1000);
while(1) {
// 接收蓝牙模块发来的数据
uint8_t buffer[1024];
HAL_UART_Receive(&huart1, buffer, sizeof(buffer), HAL_MAX_DELAY);
// 处理接收到的数据,这里简单地将收到的数据原样发送回去
HAL_UART_Transmit(&huart1, buffer, sizeof(buffer), HAL_MAX_DELAY);
}
}
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Configure the main internal regulator output voltage*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/**Initializes the CPU, AHB and APB busses clocks*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK