STM32F1 USART2 DMA查询方式收发数据

    xiaoxiao2023-11-04  144

    现有一个小需求,使用STM32F1系列单片机做串口2的收发数据的功能,通过PC上的串口调试助手给单片机发一串数据,单片机收到数据后再给PC的串口调试助手发回去。

    本次使用的是串口DMA方式接收数据,和DMA方式发送数据。

    STM32使用USART2,对应单片机的PA1控制方向,PA2发送,PA3接收。

    代码如下:

    main.c

    #include "stm32f10x.h" #include <string.h> #define LEN_DMA_RECV_BUF 256 u16 len_dma_recv; u8 dma_recv_buf[LEN_DMA_RECV_BUF]; u8 usart2_cache[LEN_DMA_RECV_BUF]; u8 dma_send_buf[LEN_DMA_RECV_BUF]; void init_hardware_usart2_dma(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = bound; 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(USART2, &USART_InitStructure); DMA_DeInit(DMA1_Channel6); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)dma_recv_buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = LEN_DMA_RECV_BUF; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel6, &DMA_InitStructure); DMA_Cmd(DMA1_Channel6, ENABLE); DMA_DeInit(DMA1_Channel7); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)dma_send_buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 0; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel7, &DMA_InitStructure); DMA_Cmd(DMA1_Channel7, DISABLE); DMA_ClearFlag(DMA1_FLAG_GL7); GPIO_ResetBits(GPIOA, GPIO_Pin_1); USART_Cmd(USART2, ENABLE); USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE); USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE); } void func_usart2_dma_send_bytes(u8 *bytes, u8 bytes_len) { GPIO_SetBits(GPIOA, GPIO_Pin_1); DMA_Cmd(DMA1_Channel7, DISABLE); memcpy(dma_send_buf, bytes, bytes_len); DMA_SetCurrDataCounter(DMA1_Channel7, bytes_len); DMA_Cmd(DMA1_Channel7, ENABLE); while(DMA_GetCurrDataCounter(DMA1_Channel7)); while(USART_GetFlagStatus(USART2, USART_FLAG_TC) != SET); GPIO_ResetBits(GPIOA, GPIO_Pin_1); } int main() { init_hardware_usart2_dma(9600); while(1) { if(USART_GetFlagStatus(USART2, USART_FLAG_IDLE) != RESET) { USART_ReceiveData(USART2); DMA_Cmd(DMA1_Channel6, DISABLE); len_dma_recv = LEN_DMA_RECV_BUF - DMA_GetCurrDataCounter(DMA1_Channel6); memcpy(usart2_cache, dma_recv_buf, len_dma_recv); memset(dma_recv_buf, 0, len_dma_recv); DMA_SetCurrDataCounter(DMA1_Channel6, LEN_DMA_RECV_BUF); USART_ClearFlag(USART2, USART_FLAG_IDLE); DMA_Cmd(DMA1_Channel6, ENABLE); func_usart2_dma_send_bytes(usart2_cache, len_dma_recv); } } }

    需要注意的问题1:

    在DMA方式接收数据时,需要将USART_FLAG_IDLE清除,清除的方式为

    USART_GetFlagStatus(USART2, USART_FLAG_IDLE)方法查看源代码,有读SR寄存器。USART_ReceiveData(USART2)方法查看源码有读DR寄存器。

    需要注意的问题2:

    DMA方式发送数据时,需要判断是否发送完成了。

    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) != SET);

    通过该方法判断发送是否完成,如果未发送完成,继续等待,直到发送完成。

    代码执行后,效果如下:

    STM32接收了串口调试助手发送的5万多条数据,并成功发送给串口调试助手。

    测试代码,仅供参考。

    最新回复(0)