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的基本步骤:

  1. 使能GPIO时钟:首先需要使能相关GPIO端口的时钟。

  2. 配置GPIO模式:设置引脚为输入或输出模式。

  3. 配置GPIO速度:设置引脚的输出速度。

  4. 配置GPIO输出类型:设置引脚为推挽或开漏输出。

  5. 配置内部上拉/下拉电阻:设置引脚的内部上拉或下拉电阻。

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的基本步骤:

  1. 使能I2C时钟:首先需要使能相关I2C外设的时钟。

  2. 配置I2C引脚:设置SDA和SCL引脚为复用开漏输出模式,并启用内部上拉电阻。

  3. 配置I2C参数:设置I2C的通信模式、数据位、时钟频率等。

  4. 使能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

物联沃分享整理
物联沃-IOTWORD物联网 » STMicroelectronics 系列:STM32WLE 系列_(7).STM32WLE系列外设接口介绍

发表回复