STMicroelectronics 系列:STM32WLE 系列_(7).STM32WLE系列外设接口介绍
STM32WLE系列外设接口介绍
在这一节中,我们将详细介绍STM32WLE系列单片机的外设接口。这些接口是单片机与外部世界进行通信和数据交换的重要手段,了解它们的原理和使用方法对于开发高效、可靠的嵌入式系统至关重要。
1. GPIO(General Purpose Input/Output)
1.1 原理
GPIO(通用输入输出)端口允许单片机直接与外部设备进行数字信号的交互。每个GPIO端口可以配置为输入或输出模式,支持多种功能,如推挽输出、开漏输出、上拉/下拉输入等。STM32WLE系列单片机通常拥有多个GPIO端口,每个端口包含多个引脚。
1.2 内容
1.2.1 配置GPIO
配置GPIO端口包括设置模式(输入或输出)、速度、输出类型和内部上拉/下拉电阻。以下是配置GPIO的基本步骤:
-
使能GPIO时钟:首先需要使能相关GPIO端口的时钟。
-
配置GPIO模式:设置引脚为输入或输出模式。
-
配置GPIO速度:设置引脚的输出速度。
-
配置GPIO输出类型:设置引脚为推挽或开漏输出。
-
配置内部上拉/下拉电阻:设置引脚的内部上拉或下拉电阻。
1.2.2 代码示例
以下是一个使用STM32 HAL库配置GPIO的例子:
#include "stm32wlexx_hal.h"
// 指定GPIO端口和引脚
#define LED_PIN GPIO_PIN_5
#define LED_PORT GPIOA
void GPIO_Init(void) {
// 1. 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 2. 配置GPIO
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 设置引脚为输出模式
GPIO_InitStruct.Pin = LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStruct.Pull = GPIO_NOPULL; // 不使用内部上拉/下拉电阻
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速输出
// 初始化GPIO
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
}
int main(void) {
// 初始化HAL库
HAL_Init();
// 初始化GPIO
GPIO_Init();
// 主循环
while (1) {
// 点亮LED
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
HAL_Delay(500); // 延时500ms
// 熄灭LED
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
HAL_Delay(500); // 延时500ms
}
}
1.3 描述
上述代码示例中,我们首先使能GPIOA的时钟,然后配置PA5引脚为推挽输出模式,不使用内部上拉/下拉电阻,并设置为低速输出。在主循环中,通过HAL_GPIO_WritePin
函数控制LED的点亮和熄灭,每次操作后延时500毫秒,实现LED的闪烁效果。
2. UART(Universal Asynchronous Receiver/Transmitter)
2.1 原理
UART是一种用于异步串行通信的接口,广泛应用于单片机与外部设备(如传感器、显示器、其他单片机等)之间的数据传输。STM32WLE系列单片机通常包含多个UART接口,支持可配置的波特率、数据位、停止位和校验位。
2.2 内容
2.2.1 配置UART
配置UART包括使能UART时钟、选择USART外设、配置USART参数(如波特率、数据位、停止位、校验位等)和使能UART中断。
2.2.2 代码示例
以下是一个使用STM32 HAL库配置UART并实现简单通信的例子:
#include "stm32wlexx_hal.h"
// 指定USART2的TX和RX引脚
#define USART2_TX_PIN GPIO_PIN_2
#define USART2_RX_PIN GPIO_PIN_3
#define USART2_TX_PORT GPIOA
#define USART2_RX_PORT GPIOA
// 指定USART2的中断
#define USART2_IRQn USART2_IRQn
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
void SystemClock_Config(void) {
// 配置系统时钟
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 配置HSE
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
HAL_RCC_OscInit(&RCC_OscInitStruct);
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
}
static void MX_GPIO_Init(void) {
// 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置USART2的TX和RX引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = USART2_TX_PIN | USART2_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
GPIO_InitStruct.Pull = GPIO_NOPULL; // 不使用内部上拉/下拉电阻
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速输出
GPIO_InitStruct.Alternate = GPIO_AF1_USART2; // 选择USART2复用功能
HAL_GPIO_Init(USART2_TX_PORT, &GPIO_InitStruct);
}
static void MX_USART2_UART_Init(void) {
// 使能USART2时钟
__HAL_RCC_USART2_CLK_ENABLE();
// 配置USART2
UART_HandleTypeDef huart2;
huart2.Instance = USART2;
huart2.Init.BaudRate = 9600;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowControl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
// 初始化USART2
if (HAL_UART_Init(&huart2) != HAL_OK) {
// 初始化错误处理
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* huart) {
if (huart->Instance == USART2) {
// 重置USART2
__HAL_RCC_USART2_FORCE_RESET();
__HAL_RCC_USART2_RELEASE_RESET();
// 配置USART2的中断
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
}
}
void USART2_IRQHandler(void) {
HAL_UART_IRQHandler(&huart2);
}
void Error_Handler(void) {
// 错误处理函数
while (1) {
// 无限循环
}
}
int main(void) {
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化GPIO
MX_GPIO_Init();
// 初始化USART2
MX_USART2_UART_Init();
// 主循环
while (1) {
// 发送数据
char tx_data[] = "Hello, STM32WLE!\r\n";
HAL_UART_Transmit(&huart2, (uint8_t*)tx_data, sizeof(tx_data), HAL_MAX_DELAY);
// 延时1秒
HAL_Delay(1000);
}
}
2.3 描述
上述代码示例中,我们配置了USART2的TX和RX引脚,使能了USART2的时钟,并设置了UART的参数(如波特率、数据位、停止位、校验位等)。通过HAL_UART_Init
函数初始化USART2,使其能够进行串行通信。在主循环中,使用HAL_UART_Transmit
函数发送字符串“Hello, STM32WLE!”,每次发送后延时1秒。
3. SPI(Serial Peripheral Interface)
3.1 原理
SPI是一种同步串行通信接口,用于单片机与外部设备(如传感器、存储器、显示器等)之间的高速通信。SPI通信涉及四个信号线:MISO(主设备输入从设备输出)、MOSI(主设备输出从设备输入)、SCLK(时钟信号)和NSS(片选信号)。STM32WLE系列单片机通常包含多个SPI接口,支持多种工作模式和数据传输速率。
3.2 内容
3.2.1 配置SPI
配置SPI包括使能SPI时钟、选择SPI外设、配置SPI参数(如模式、数据位、时钟极性和时钟相位等)和使能SPI中断。
3.2.2 代码示例
以下是一个使用STM32 HAL库配置SPI并实现简单通信的例子:
#include "stm32wlexx_hal.h"
// 指定SPI1的引脚
#define SPI1_SCK_PIN GPIO_PIN_5
#define SPI1_MISO_PIN GPIO_PIN_6
#define SPI1_MOSI_PIN GPIO_PIN_7
#define SPI1_PORT GPIOA
// 指定SPI1的中断
#define SPI1_IRQn SPI1_IRQn
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
void SystemClock_Config(void) {
// 配置系统时钟
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 配置HSE
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
HAL_RCC_OscInit(&RCC_OscInitStruct);
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
}
static void MX_GPIO_Init(void) {
// 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置SPI1的引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = SPI1_SCK_PIN | SPI1_MISO_PIN | SPI1_MOSI_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出
GPIO_InitStruct.Pull = GPIO_NOPULL; // 不使用内部上拉/下拉电阻
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速输出
GPIO_InitStruct.Alternate = GPIO_AF0_SPI1; // 选择SPI1复用功能
HAL_GPIO_Init(SPI1_PORT, &GPIO_InitStruct);
}
static void MX_SPI1_Init(void) {
// 使能SPI1时钟
__HAL_RCC_SPI1_CLK_ENABLE();
// 配置SPI1
SPI_HandleTypeDef hspi1;
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER; // 主模式
hspi1.Init.Direction = SPI_DIRECTION_2LINES; // 双线模式
hspi1.Init.DataSize = SPI_DATASIZE_8BIT; // 8位数据
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // 时钟极性低
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // 时钟相位1
hspi1.Init.NSS = SPI_NSS_SOFT; // 软件片选
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // 波特率预分频器
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; // 最高位先发送
hspi1.Init.TIMode = SPI_TIMODE_DISABLE; // 禁用TI模式
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // 禁用CRC计算
hspi1.Init.CRCPolynomial = 7; // CRC多项式
// 初始化SPI1
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
// 初始化错误处理
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) {
if (hspi->Instance == SPI1) {
// 重置SPI1
__HAL_RCC_SPI1_FORCE_RESET();
__HAL_RCC_SPI1_RELEASE_RESET();
// 配置SPI1的中断
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
}
void SPI1_IRQHandler(void) {
HAL_SPI_IRQHandler(&hspi1);
}
void Error_Handler(void) {
// 错误处理函数
while (1) {
// 无限循环
}
}
int main(void) {
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化GPIO
MX_GPIO_Init();
// 初始化SPI1
MX_SPI1_Init();
// 主循环
while (1) {
// 发送数据
uint8_t tx_data = 0x55;
HAL_SPI_Transmit(&hspi1, &tx_data, 1, HAL_MAX_DELAY);
// 延时1秒
HAL_Delay(1000);
}
}
3.3 描述
上述代码示例中,我们配置了SPI1的SCK、MISO和MOSI引脚,使能了SPI1的时钟,并设置了SPI1的参数(如工作模式、数据位、时钟极性和时钟相位等)。通过HAL_SPI_Init
函数初始化SPI1,使其能够进行同步通信。在主循环中,使用HAL_SPI_Transmit
函数发送一个字节的数据0x55,每次发送后延时1秒。
4. I2C(Inter-Integrated Circuit)
4.1 原理
I2C(Inter-Integrated Circuit)是一种用于单片机与外部设备(如传感器、存储器等)之间的半双工同步串行通信接口。I2C通信涉及两条信号线:SDA(数据线)和SCL(时钟线)。这种接口设计简单,占用的引脚较少,适合在多设备之间进行通信。STM32WLE系列单片机通常包含多个I2C接口,支持多种通信模式和数据传输速率。
4.2 内容
4.2.1 配置I2C
配置I2C包括使能I2C时钟、选择I2C外设、配置I2C参数(如模式、数据位、时钟频率等)和使能I2C中断。以下是配置I2C的基本步骤:
-
使能I2C时钟:首先需要使能相关I2C外设的时钟。
-
配置I2C引脚:设置SDA和SCL引脚为复用开漏输出模式,并启用内部上拉电阻。
-
配置I2C参数:设置I2C的通信模式、数据位、时钟频率等。
-
使能I2C中断:如果需要使用中断,需要配置中断优先级并使能中断。
4.2.2 代码示例
以下是一个使用STM32 HAL库配置I2C并实现简单通信的例子:
#include "stm32wlexx_hal.h"
// 指定I2C1的引脚
#define I2C1_SCL_PIN GPIO_PIN_6
#define I2C1_SDA_PIN GPIO_PIN_7
#define I2C1_PORT GPIOB
// 指定I2C1的中断
#define I2C1_IRQn I2C1_IRQn
// I2C设备地址
#define I2C_DEVICE_ADDRESS 0x50
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
void SystemClock_Config(void) {
// 配置系统时钟
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 配置HSE
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
HAL_RCC_OscInit(&RCC_OscInitStruct);
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
}
static void MX_GPIO_Init(void) {
// 使能GPIO时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
// 配置I2C1的引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = I2C1_SCL_PIN | I2C1_SDA_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 复用开漏输出
GPIO_InitStruct.Pull = GPIO_PULLUP; // 内部上拉电阻
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速输出
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; // 选择I2C1复用功能
HAL_GPIO_Init(I2C1_PORT, &GPIO_InitStruct);
}
static void MX_I2C1_Init(void) {
// 使能I2C1时钟
__HAL_RCC_I2C1_CLK_ENABLE();
// 配置I2C1
I2C_HandleTypeDef hi2c1;
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000; // 100kHz
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // 2:1占空比
hi2c1.Init.OwnAddress1 = 0x00; // 不使用自己的地址
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7位地址模式
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 禁用双地址模式
hi2c1.Init.OwnAddress2 = 0x00; // 不使用第二个地址
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 禁用通用呼叫模式
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 禁用时钟拉伸
// 初始化I2C1
if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
// 初始化错误处理
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) {
if (hi2c->Instance == I2C1) {
// 重置I2C1
__HAL_RCC_I2C1_FORCE_RESET();
__HAL_RCC_I2C1_RELEASE_RESET();
// 配置I2C1的中断
HAL_NVIC_SetPriority(I2C1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_IRQn);
}
}
void I2C1_IRQHandler(void) {
HAL_I2C_IRQHandler(&hi2c1);
}
void Error_Handler(void) {
// 错误处理函数
while (1) {
// 无限循环
}
}
int main(void) {
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化GPIO
MX_GPIO_Init();
// 初始化I2C1
MX_I2C1_Init();
// 主循环
while (1) {
// 发送数据
uint8_t tx_data = 0x55;
HAL_I2C_Master_Transmit(&hi2c1, I2C_DEVICE_ADDRESS << 1, &tx_data, 1, HAL_MAX_DELAY);
// 延时1秒
HAL_Delay(1000);
// 接收数据
uint8_t rx_data;
HAL_I2C_Master_Receive(&hi2c1, I2C_DEVICE_ADDRESS << 1, &rx_data, 1, HAL_MAX_DELAY);
// 延时1秒
HAL_Delay(1000);
}
}
4.3 描述
上述代码示例中,我们配置了I2C1的SCL和SDA引脚,使能了I2C1的时钟,并设置了I2C1的参数(如通信模式、数据位、时钟频率等)。通过HAL_I2C_Init
函数初始化I2C1,使其能够进行同步通信。在主循环中,使用HAL_I2C_Master_Transmit
函数发送一个字节的数据0x55,使用HAL_I2C_Master_Receive
函数接收一个字节的数据,每次操作后延时1秒。
5. ADC(Analog-to-Digital Converter)
5.1 原理
ADC(模数转换器)是一种将模拟信号转换为数字信号的接口,广泛应用于单片机与模拟传感器(如温度传感器、压力传感器等)之间的数据采集。STM32WLE系列单片机通常包含多个ADC通道,支持多种转换模式(如单次转换、连续转换等)和分辨率(如12位、16位等)。
5.2 内容
5.2.1 配置ADC
配置ADC包括使能ADC时钟、选择ADC外设、配置ADC参数(如分辨率、采样时间、通道等)和使能ADC中断。
5.2.2 代码示例
以下是一个使用STM32 HAL库配置ADC并实现简单数据采集的例子:
#include "stm32wlexx_hal.h"
// 指定ADC的引脚
#define ADC_PIN GPIO_PIN_0
#define ADC_PORT GPIOA
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC_Init(void);
void SystemClock_Config(void) {
// 配置系统时钟
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 配置HSE
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
HAL_RCC_OscInit(&RCC_OscInitStruct);
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
}
static void MX_GPIO_Init(void) {
// 使能GPIO时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置ADC的引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = ADC_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // 模拟输入模式
HAL_GPIO_Init(ADC_PORT, &GPIO_InitStruct);
}
static void MX_ADC_Init(void) {
// 使能ADC时钟
__HAL_RCC_ADC_CLK_ENABLE();
// 配置ADC
ADC_HandleTypeDef hadc;
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; // 时钟预分频器
hadc.Init.Resolution = ADC_RESOLUTION_12B; // 12位分辨率
hadc.Init.ScanConvMode = DISABLE; // 禁用扫描模式
hadc.Init.ContinuousConvMode = DISABLE; // 禁用连续转换模式
hadc.Init.DiscontinuousConvMode = DISABLE; // 禁用不连续转换模式
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 右对齐
hadc.Init.NbrOfConversion = 1; // 1个转换
hadc.Init.DMAContinuousRequests = DISABLE; // 禁用DMA连续请求
// 初始化ADC
if (HAL_ADC_Init(&hadc) != HAL_OK) {
// 初始化错误处理
Error_Handler();
}
// 配置ADC通道
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_0; // 通道0
sConfig.Rank = ADC_REGULAR_RANK_1; // 排名1
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; // 采样时间
// 配置ADC通道
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) {
// 配置通道错误处理
Error_Handler();
}
}
void Error_Handler(void) {
// 错误处理函数
while (1) {
// 无限循环
}
}
int main(void) {
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化GPIO
MX_GPIO_Init();
// 初始化ADC
MX_ADC_Init();
// 主循环
while (1) {
// 启动ADC转换
if (HAL_ADC_Start(&hadc) != HAL_OK) {
// 启动转换错误处理
Error_Handler();
}
// 等待转换完成
if (HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY) != HAL_OK) {
// 转换完成错误处理
Error_Handler();
}
// 读取转换结果
uint32_t adc_value = HAL_ADC_GetValue(&hadc);
// 延时1秒
HAL_Delay(1000);
// 处理ADC值
// 例如,可以将ADC值通过UART发送出去
// char tx_data[20];
// sprintf(tx_data, "ADC Value: %lu\r\n", adc_value);
// HAL_UART_Transmit(&huart2, (uint8_t*)tx_data, strlen(tx_data), HAL_MAX_DELAY);
}
}
5.3 描述
上述代码示例中,我们配置了ADC1的引脚,使能了ADC1的时钟,并设置了ADC1的参数(如分辨率、采样时间、通道等)。通过HAL_ADC_Init
函数初始化ADC1,并配置ADC通道0。在主循环中,使用HAL_ADC_Start
函数启动ADC转换,等待转换完成,然后使用HAL_ADC_GetValue
函数读取转换结果。每次读取后延时1秒,可以进一步处理ADC值,例如通过UART发送出去。
6. 总结
在这一节中,我们详细介绍了STM32WLE系列单片机的几个重要外设接口:GPIO、UART、SPI和I2C。这些接口是单片机与外部世界进行通信和数据交换的重要手段。通过配置这些接口,我们可以实现各种功能,如控制LED、串行通信、高速数据传输和模拟信号采集。了解它们的原理和使用方法对于开发高效、可靠的嵌入式系统至关重要。希望这些示例代码能够帮助你更好地理解和应用这些外设接口。
作者:kkchenkx