STM32F4 STD标准库串口接收例程

STM32F4 STD标准库串口接收中断+空闲中断例程


  • 🔖工程基于STM32F446

✨用惯了STM32CubeMX傻瓜式配置,突然改用标准库写代码,初始化外设内容,总是丢三落四的。

本文将提供3种串口接收和发送模式:串口接收中断+空闲中断串口空闲中断+DMA接收串口DMA接收和发送数据+空闲中断
  • 📍DMA发送参考:https://blog.csdn.net/m0_64354650/article/details/125648186

📗串口接收中断+空闲中断模式例程

📑串口初始化配置
void uart_init(uint32_t bound)
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//使能USART1,GPIOA时钟
    /* Enable GPIO clock */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    /* Connect PXx to USARTx_Tx*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);

    /* Connect PXx to USARTx_Rx*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
    //USART1_TX   GPIOA.9
    /* Configure USART Tx as alternate function  */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure USART Rx as alternate function  */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

    //USART 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    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); //初始化串口1
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口空闲中断
    USART_Cmd(USART1, ENABLE); //使能串口1

}
📘串口中断函数
void USART1_IRQHandler(void)	//串口1中断服务程序
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        // USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清标志位
//        USART_RX_BUF[length] = USART_ReceiveData(USART1);//读取接收到的数据
         USART_RX_BUF[length] = USART1->DR & 0x0FF;
        length++;
    } else if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) != RESET) { //空闲帧中断
            USART1->SR; //先读SR.再读DR
            USART1->DR; //清空寄存器
            length = 0;
            USART_RX_STA = 1; //数据接收 标志位
    }

}
📑接收数据所需的变量和宏定义
#define USART_REC_LEN   			64  	//定义最大接收字节数 64
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收
uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
uint8_t USART_RX_STA = 0; //接收状态标记
static __IO uint16_t length = 0;//接收数据时的下标
📒处理接收数据和释放空间
 if(USART_RX_STA) {
            USART_RX_STA = 0;//清标志位
            printf("Re:%s\n", USART_RX_BUF);
            memset(USART_RX_BUF, 0x00, sizeof(USART_RX_BUF));//清空接收数组
        }
  • 🔬测试效果:
    在这里插入图片描述
📚串口接收中断+空闲中断测试工程
链接:https://pan.baidu.com/s/13UxJawYkAkpIb8SzhSnpqg?pwd=8rc0 
提取码:8rc0

📘 串口DMA接收和发送数据+空闲中断 模式

  • 🌿DMA配置
static void USART_DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    RCC_AHB1PeriphClockCmd(USART_TX_DMA_CLK | USART_RX_DMA_CLK, ENABLE);//使能DMA2时钟

    /* 配置发送 */
    DMA_InitStructure.DMA_BufferSize = 0;//随便配置,因为在接收到数据后我们会重新给这值赋值
    DMA_InitStructure.DMA_Channel = USART_TX_DMA_CHANNEL;//串口发送通道
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//DMA搬运方向:存储器到外设

    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Rec;//存储器地址
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发模式选择:单次模式
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据宽度:字节
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable ;//使能存储器地址自动递增功能
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA 传输模式选择:一次传输
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_BASE;//外设地址
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发模式选择:单次模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度:字节
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//禁止外设地址自动递增功能
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//软件设置数据流的优先级:中等
    /* FIFO不用随便配置 */
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

    DMA_Init(USART_TX_DMA_STREAM, &DMA_InitStructure);
    DMA_Cmd(USART_TX_DMA_STREAM, DISABLE);//发送先失能

    /* 配置接收 */
    DMA_InitStructure.DMA_BufferSize = RX_MAX_LEN;//接收数据的长度
    DMA_InitStructure.DMA_Channel = USART_RX_DMA_CHANNEL;//串口发送通道
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//DMA搬运方向:外设到存储器
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA 传输模式选择:循环接收

    /* 其余配置与上面一样 */
    DMA_Init(USART_RX_DMA_STREAM, &DMA_InitStructure);
    DMA_Cmd(USART_RX_DMA_STREAM, ENABLE);//接收使能
}
  • 🌿串口配置
void USART_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* 使能时钟 */
    RCC_AHB1PeriphClockCmd(USART_TX_GPIO_CLK | USART_RX_GPIO_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(USART_CLK, ENABLE);
    /* GPIO相关配置 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF ;//复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP ;//推挽输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//无上拉  无下拉
    GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed ;//高速

    GPIO_InitStructure.GPIO_Pin = USART_TX_PIN;//配置发送引脚
    GPIO_Init(USART_TX_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = USART_RX_PIN;//配置接收引脚
    GPIO_Init(USART_RX_GPIO_PORT, &GPIO_InitStructure);
    /* 将对应的IO口连接到外设,开始启动复用功能 */
    GPIO_PinAFConfig(USART_TX_GPIO_PORT, USART_TX_SOURCE, USART_TX_AF);
    GPIO_PinAFConfig(USART_RX_GPIO_PORT, USART_RX_SOURCE, USART_RX_AF);

    /* USART1的相关配置 */
    USART_InitStructure.USART_BaudRate = USART_BAUDRATE;//波特率115200
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx ;//USART模式控制:同时使能接收和发送
    USART_InitStructure.USART_Parity = USART_Parity_No;//校验位选择:不使用校验
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位:1个停止位
    USART_InitStructure.USART_WordLength = USART_WordLength_8b ;//字长(数据位+校验位):8

    USART_Init(USART, &USART_InitStructure);

    USART_NVIC_Config();//中断配置

    USART_DMA_Config();//DMA配置

    USART_ITConfig(USART, USART_IT_IDLE, ENABLE); //开启空闲中断

    USART_DMACmd(USART, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);//使能DMA接收与发送

    USART_Cmd(USART, ENABLE); //使能串口
}
  • 🌿串口中断
//串口中断服务程序
void USART_IRQHandler(void)
{
    uint16_t temp;
    if(USART_GetFlagStatus(USART, USART_FLAG_IDLE) != RESET) {
        temp = USART1->SR;
        temp = USART1->DR;//清除IDLE中断

        temp = DMA_GetCurrDataCounter(USART_RX_DMA_STREAM);//获取剩余的接收数据的量

        DMA_Cmd(USART_RX_DMA_STREAM, DISABLE);

        DMA_SetCurrDataCounter(USART_RX_DMA_STREAM, RX_MAX_LEN);//设置需要接收的量

        DMA_Cmd(USART_RX_DMA_STREAM, ENABLE);


        DMA_Cmd(USART_TX_DMA_STREAM, DISABLE);

        DMA_SetCurrDataCounter(USART_TX_DMA_STREAM, RX_MAX_LEN - temp);//设置需要发送的量

        DMA_Cmd(USART_TX_DMA_STREAM, ENABLE);

        while(USART_GetFlagStatus(USART, USART_FLAG_TC) == RESET); //必须等待,否则最后一位数据错误

        DMA_ClearFlag(USART_TX_DMA_STREAM, DMA_FLAG_TCIF7); //清除DMA传输完成标志

        USART_ClearFlag(USART, USART_FLAG_TC); //清除传输完成标志
    }
}
📚串口DMA接收和发送数据+空闲中断 模式测试代码
链接:https://pan.baidu.com/s/1aAVqOlT7nBd-ZwNN4ZN09g?pwd=3ci8 
提取码:3ci8

📙串口空闲中断+DMA接收模式

  • 🌿DMA配置
static void USART_DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    RCC_AHB1PeriphClockCmd(USART_RX_DMA_CLK, ENABLE);//使能DMA2时钟

    /* 配置发送 */
//    DMA_InitStructure.DMA_BufferSize = 0;//随便配置,因为在接收到数据后我们会重新给这值赋值
//    DMA_InitStructure.DMA_Channel = USART_TX_DMA_CHANNEL;//串口发送通道
//    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//DMA搬运方向:存储器到外设

    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART_RX_BUF;//存储器地址
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发模式选择:单次模式
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据宽度:字节
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable ;//使能存储器地址自动递增功能
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA 传输模式选择:一次传输
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_BASE;//外设地址
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发模式选择:单次模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度:字节
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//禁止外设地址自动递增功能
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//软件设置数据流的优先级:中等
    /* FIFO不用随便配置 */
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

//    DMA_Init(USART_TX_DMA_STREAM, &DMA_InitStructure);
//    DMA_Cmd(USART_TX_DMA_STREAM, DISABLE);//发送先失能

    /* 配置接收 */
    DMA_InitStructure.DMA_BufferSize = RX_MAX_LEN;//接收数据的长度
    DMA_InitStructure.DMA_Channel = USART_RX_DMA_CHANNEL;//串口发送通道
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//DMA搬运方向:外设到存储器
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA 传输模式选择:循环接收

    /* 其余配置与上面一样 */
    DMA_Init(USART_RX_DMA_STREAM, &DMA_InitStructure);
    DMA_Cmd(USART_RX_DMA_STREAM, ENABLE);//接收使能
}


  • 🌿串口配置
void USART_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* 使能时钟 */
    RCC_AHB1PeriphClockCmd(USART_TX_GPIO_CLK | USART_RX_GPIO_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(USART_CLK, ENABLE);
    /* GPIO相关配置 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF ;//复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP ;//推挽输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//无上拉  无下拉
    GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed ;//高速

    GPIO_InitStructure.GPIO_Pin = USART_TX_PIN;//配置发送引脚
    GPIO_Init(USART_TX_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = USART_RX_PIN;//配置接收引脚
    GPIO_Init(USART_RX_GPIO_PORT, &GPIO_InitStructure);
    /* 将对应的IO口连接到外设,开始启动复用功能 */
    GPIO_PinAFConfig(USART_TX_GPIO_PORT, USART_TX_SOURCE, USART_TX_AF);
    GPIO_PinAFConfig(USART_RX_GPIO_PORT, USART_RX_SOURCE, USART_RX_AF);

    /* USART1的相关配置 */
    USART_InitStructure.USART_BaudRate = USART_BAUDRATE;//波特率115200
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx ;//USART模式控制:同时使能接收和发送
    USART_InitStructure.USART_Parity = USART_Parity_No;//校验位选择:不使用校验
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位:1个停止位
    USART_InitStructure.USART_WordLength = USART_WordLength_8b ;//字长(数据位+校验位):8

    USART_Init(USART, &USART_InitStructure);

    USART_NVIC_Config();//中断配置

    USART_DMA_Config();//DMA配置

    USART_ITConfig(USART, USART_IT_IDLE, ENABLE); //开启空闲中断

    USART_DMACmd(USART, USART_DMAReq_Rx, ENABLE);//使能DMA接收

    USART_Cmd(USART, ENABLE); //使能串口
}




-🌿 中断配置

//串口中断服务程序
void USART_IRQHandler(void)
{
    uint16_t temp;
    if(USART_GetFlagStatus(USART, USART_FLAG_IDLE) != RESET) {
        temp = USART1->SR;
        temp = USART1->DR;//清除IDLE中断
			
				USART_RX_STA = 1; //数据接收 标志位
			
        temp = DMA_GetCurrDataCounter(USART_RX_DMA_STREAM);//获取剩余的接收数据的量

        DMA_Cmd(USART_RX_DMA_STREAM, DISABLE);

        DMA_SetCurrDataCounter(USART_RX_DMA_STREAM, RX_MAX_LEN);//设置需要接收的量

        DMA_Cmd(USART_RX_DMA_STREAM, ENABLE);

    }
}
📚串口空闲中断+DMA接收模式例程代码
链接:https://pan.baidu.com/s/1R8F0R4KzjVTCR8zd2V-lVA?pwd=j595 
提取码:j595
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的使用STM32HAL库的串口接收中断例程: 首先,需要在STM32CubeMX工具中配置串口参数,例如波特率、数据位、停止位等。然后生成和打开工程。 在工程的主文件中加入头文件 "stm32f1xx_hal.h" 和 "stdbool.h"。 接下来,在main函数中初始化串口和使能接收中断,例如: ```c uint8_t rxData[10]; bool isRxComplete = false; UART_HandleTypeDef huart; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 接收完成中断回调函数 isRxComplete = true; HAL_UART_Receive_IT(&huart, rxData, sizeof(rxData)); } int main(void) { HAL_Init(); SystemClock_Config(); // 串口初始化 huart.Instance = USART1; huart.Init.BaudRate = 9600; huart.Init.WordLength = UART_WORDLENGTH_8B; huart.Init.StopBits = UART_STOPBITS_1; huart.Init.Parity = UART_PARITY_NONE; huart.Init.Mode = UART_MODE_RX; huart.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart) != HAL_OK) { Error_Handler(); } // 使能UART接收中断 HAL_UART_Receive_IT(&huart, rxData, sizeof(rxData)); // 主循环 while (1) { if (isRxComplete) { // 处理接收到的数据 // ... // 重置接收完成标志 isRxComplete = false; } } } ``` 在上述代码中,我们首先定义了一个大小为10的数组`rxData`用于接收数据,并定义了一个标志位`isRxComplete`用于表示接收是否完成。 然后,在主函数中,我们初始化了串口并使能了接收中断。在接收完成的中断回调函数中,我们将接收完成标志位设置为true,并重新启动接收中断。 在主循环中,如果接收完成标志位为true,则处理接收到的数据,并重置接收完成标志位。 这样就实现了基于STM32HAL库的串口接收中断例程

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值