【中移芯昇】3. uart读写

1 前言

本章介绍下如何使用uart的rx和tx功能,其中tx利用dma更为方便。

2 基础

参考文章:STM32单片机串口空闲中断+DMA接收不定长数据

uart一次只能收发一字节数据,所以发送相对简单点,直接用函数USART_SendData(),发送多个数据。
但是rx接收时需要等uart状态rx结束,读取到USART_FLAG_RXDNE状态可以收数据。
不过使用dma更为方便,使用usart目录下的DMA_polling示例。

简单介绍下dma:在内存中开辟一段数组空间,uart收到数据后将存入dma中,指针向后移动,直到填满后产生dma中断。
dma中断中可以配置清空等操作。

3 引脚介绍

整理了一下开发板的uart端口。
其中usart有三个,分别为usart1-3,uart有四个,分别为uart4-7。
usart相对uart多了时钟信号,用于同步。

其中uart4一般作为和电脑的串口通信,用于打印信息。printf函数显示log就通过uart4传输出来。

在这里插入图片描述

4 硬件

usart3和uart5-7,分别为PC10/11,PB13/14,PB0/1,PC4/5。

在这里插入图片描述
uart4根据电路图来看是接到了PA2/3。推测PA2/3和PA13/12有关联,因为PA13/12是microusb数据线。
在这里插入图片描述
在这里插入图片描述

5 代码

主要参考两个示例,usart/printf是用于打印log,usart/dma_polling是用于dma接收数据。

printf示例:https://gitee.com/CMIOT-XinShengTech/CMIOT.CM32M4xxR_Library/tree/main/Projects/CM32M433R-START/Examples/USART/Printf

示例源码路径:https://gitee.com/CMIOT-XinShengTech/CMIOT.CM32M4xxR_Library/tree/main/Projects/CM32M433R-START/Examples/USART/DMA_Polling

打印log使用的uart4,用到的io为PD0/1。
uart收发使用的uart5,用到io为PB13/14。

5.1 main.h

头文件定义uart引脚和dma信息。

/*******************************************************************************
*
* COPYRIGHT(c) 2020, China Mobile IOT
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*	1. Redistributions of source code must retain the above copyright notice,
*	   this list of conditions and the following disclaimer.
*	2. Redistributions in binary form must reproduce the above copyright notice,
*	   this list of conditions and the following disclaimer in the documentation
*	   and/or other materials provided with the distribution.
*	3. Neither the name of China Mobile IOT nor the names of its contributors
*	   may be used to endorse or promote products derived from this software
*	   without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/

/**
 * @file main.h
 * @author CMIOT Firmware Team
 * @version v1.0.0
 *
 * @copyright Copyright (c) 2020, CMIOT. All rights reserved.
 */

#ifndef __MAIN_H__
#define __MAIN_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "nuclei_sdk_soc.h"

/* USARTx configuration */
#define _USART4_COM_

#ifdef _USART4_COM_
#define USARTx          	UART4
#define USARTx_GPIO     	GPIOD
#define USARTx_CLK      	RCC_APB1_PERIPH_UART4
#define USARTx_GPIO_CLK		RCC_APB2_PERIPH_GPIOD
#define USARTx_RxPin    	GPIO_PIN_1
#define USARTx_TxPin    	GPIO_PIN_0

#define GPIO_APBxClkCmd		RCC_EnableAPB2PeriphClk
#define USART_APBxClkCmd	RCC_EnableAPB1PeriphClk
#endif

#define _USART5_USART6_

#ifdef _USART5_USART6_
#define USARTy                      UART5
#define USARTy_GPIO                 GPIOB
#define USARTy_CLK                  RCC_APB1_PERIPH_UART5
#define USARTy_GPIO_CLK             RCC_APB2_PERIPH_GPIOB
#define USARTy_TxPin                GPIO_PIN_13
#define USARTy_RxPin                GPIO_PIN_14
#define USARTy_APBxClkCmd           RCC_EnableAPB1PeriphClk
#define USARTy_DMAx                 DMA1
#define USARTy_DMAx_CLK             RCC_AHB_PERIPH_DMA1
#define USARTy_DR_Base              (UART5_BASE + 0x04)
#define USARTy_Tx_DMA_Channel       DMA1_CH1
#define USARTy_Tx_DMA_FLAG          DMA1_FLAG_TC1
#define USARTy_Rx_DMA_Channel       DMA1_CH8
#define USARTy_Rx_DMA_FLAG          DMA1_FLAG_TC8
#define USARTy_Tx_DMA_IRQn          DMA1_Channel1_IRQn
#define USARTy_Tx_DMA_IRQHandler    DMA1_Channel1_IRQHandler
#define USARTy_Tx_DMA_INT           DMA1_INT_TXC1

#define USARTz                      UART6
#define USARTz_GPIO                 GPIOB
#define USARTz_CLK                  RCC_APB2_PERIPH_UART6
#define USARTz_GPIO_CLK             RCC_APB2_PERIPH_GPIOB
#define USARTz_TxPin                GPIO_PIN_0
#define USARTz_RxPin                GPIO_PIN_1
#define USARTz_APBxClkCmd           RCC_EnableAPB2PeriphClk
#define USARTz_DMAx                 DMA2
#define USARTz_DMAx_CLK             RCC_AHB_PERIPH_DMA2
#define USARTz_DR_Base              (UART6_BASE + 0x04)
#define USARTz_Tx_DMA_Channel       DMA2_CH2
#define USARTz_Tx_DMA_FLAG          DMA2_FLAG_TC2
#define USARTz_Rx_DMA_Channel       DMA2_CH1
#define USARTz_Rx_DMA_FLAG          DMA2_FLAG_TC1
#define USARTz_Rx_DMA_IRQn          DMA2_Channel1_IRQn
#define USARTz_Rx_DMA_IRQHandler    DMA2_Channel1_IRQHandler
#define USARTz_Rx_DMA_INT           DMA2_INT_TXC1
#define USARTz_IRQn           	    UART6_IRQn
#endif

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H__ */

5.2 main.c

实现uart测试功能。

测试1:dma的tx传输
测试2:uart传输字符串
测试3:dma的rx接收

/*******************************************************************************
*
* COPYRIGHT(c) 2020, China Mobile IOT
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*    1. Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*    2. Redistributions in binary form must reproduce the above copyright notice,
*       this list of conditions and the following disclaimer in the documentation
*       and/or other materials provided with the distribution.
*    3. Neither the name of China Mobile IOT nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/

/**
 * @file main.c
 * @author CMIOT Firmware Team
 * @version v1.0.0
 *
 * @copyright Copyright (c) 2020, CMIOT. All rights reserved.
 */

#include <stdio.h>
#include "main.h"

/** @addtogroup CM32M4xxR_StdPeriph_Examples
 * @{
 */

/** @addtogroup USART_DMA_Polling
 * @{
 */

typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} TestStatus;

#define TxBufferSize1 (countof(TxBuffer1) - 1)
#define TxBufferSize2 (countof(TxBuffer2) - 1)

#define countof(a) (sizeof(a) / sizeof(*(a)))

USART_InitType USART_InitStructure;
uint8_t TxBuffer1[] = "USART DMA Polling: USARTy -> USARTz using DMA";
uint8_t TxBuffer2[] = "USART DMA Polling: USARTz -> USARTy using DMA";
uint8_t RxBuffer1[TxBufferSize2];
uint8_t RxBuffer2[TxBufferSize1];
volatile TestStatus TransferStatus1 = FAILED;
volatile TestStatus TransferStatus2 = FAILED;

void RCC_Configuration(void);
void GPIO_Configuration(void);
void DMA_Configuration(void);

// youkai add
void func_init_uart4();
void print_dma();

bool status_wait_uart = false;
#define UART_STATUS_RX true
#define UART_STATUS_TX false

void print_uart_wait();
void print_uart_wait_end();

void reset_dma_rx();
void reset_dma_tx();
void myUart_rx(uint8_t uart_id,bool rx_tx);
void myUart_tx(uint8_t uart_id,uint8_t * data,uint8_t len_send);
void myUart_senddata(uint8_t uart_id, uint8_t * data,uint8_t len_send);

void myDMA_tx(uint8_t uart_id);

void delay(vu32 nCount);

/**
 * @brief  Main program
 */
int main(void)
{
    func_init_uart4();

    printf("start init\r\n");

    printf("-------test1: dma tx---------\r\n");

    /* System Clocks Configuration */
    RCC_Configuration();

    /* Configure the GPIO ports */
    GPIO_Configuration();

    /* Configure the DMA */
    DMA_Configuration();

    /* USARTy and USARTz configuration ------------------------------------------------------*/
    USART_InitStructure.BaudRate            = 115200;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

    /* Configure USARTy and USARTz */
    USART_Init(USARTy, &USART_InitStructure);
    USART_Init(USARTz, &USART_InitStructure);

//    strcpy(TxBuffer1,"hihihihihihihihihihihihihihihihihihihihihihih");
//    printf("TxBuffer1 = [%s]\r\n",(char*)TxBuffer1);

    /* Enable USARTy DMA Rx and TX request */
    USART_EnableDMA(USARTy, USART_DMAREQ_RX | USART_DMAREQ_TX, ENABLE);

    /* Enable USARTz DMA Rx and TX request */
    USART_EnableDMA(USARTz, USART_DMAREQ_RX | USART_DMAREQ_TX, ENABLE);

    /* Enable USARTy TX DMA1 Channel */
   DMA_EnableChannel(USARTy_Tx_DMA_Channel, ENABLE);

    /* Enable USARTy RX DMA1 Channel */
    DMA_EnableChannel(USARTy_Rx_DMA_Channel, ENABLE);

    /* Enable USARTz TX DMA1 Channel */
    DMA_EnableChannel(USARTz_Tx_DMA_Channel, ENABLE);

    /* Enable USARTz RX DMA1 Channel */
    DMA_EnableChannel(USARTz_Rx_DMA_Channel, ENABLE);

    /* Enable the USARTy and USARTz */
    USART_Enable(USARTy, ENABLE);
    USART_Enable(USARTz, ENABLE);

    // wait until dma send data ok.
    while(DMA_GetFlagStatus(DMA1_FLAG_TC1,USARTy_DMAx)==RESET)
    {
    }

    printf("\r\n-------test2: uart tx---------\r\n");
    delay(1000);

    printf("dma tx over.\r\n");

//    USART_SendData(USARTy,'\n');
//    delay();
    char temp_rx[]="hihihi";
    myUart_tx(5,temp_rx,4);
//    reset_dma_rx();

    printf("\r\n-------test3: uart rx---------\r\n");
    int count = 0;
    while (1)
    {
        printf("count = %d\r\n",count++);

        myUart_rx(5,UART_STATUS_RX);

    }
}

/**
 * @brief  Configures the different system clocks.
 */
void RCC_Configuration(void)
{
    /* DMA clock enable */
    RCC_EnableAHBPeriphClk(USARTy_DMAx_CLK, ENABLE);
    RCC_EnableAHBPeriphClk(USARTz_DMAx_CLK, ENABLE);

    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(USARTy_GPIO_CLK | USARTz_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE);

    /* Enable USARTy and USARTz Clock */
    USARTy_APBxClkCmd(USARTy_CLK, ENABLE);
    USARTz_APBxClkCmd(USARTz_CLK, ENABLE);
}

/**
 * @brief  Configures the different GPIO ports.
 */
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;
    GPIO_ConfigPinRemap(GPIO_RMP_USART1,ENABLE);

    /* Configure USARTy Rx as input floating */
    GPIO_InitStructure.Pin       = USARTy_RxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USARTy_GPIO, &GPIO_InitStructure);

    /* Configure USARTz Rx as input floating */
    GPIO_InitStructure.Pin = USARTz_RxPin;
    GPIO_Init(USARTz_GPIO, &GPIO_InitStructure);

    /* Configure USARTy Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = USARTy_TxPin;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(USARTy_GPIO, &GPIO_InitStructure);

    /* Configure USARTz Tx as alternate function push-pull */
    GPIO_InitStructure.Pin = USARTz_TxPin;
    GPIO_Init(USARTz_GPIO, &GPIO_InitStructure);

    GPIO_ConfigPinRemap(GPIO_RMP1_UART5, ENABLE);
    GPIO_ConfigPinRemap(GPIO_RMP3_UART6, ENABLE);
}

/**
 * @brief  Configures the DMA.
 */
void DMA_Configuration(void)
{
    DMA_InitType DMA_InitStructure;

    /* USARTy TX DMA1 Channel (triggered by USARTy Tx event) Config */
    DMA_DeInit(USARTy_Tx_DMA_Channel);
    DMA_InitStructure.PeriphAddr     = USARTy_DR_Base;
    DMA_InitStructure.MemAddr        = (uint32_t)TxBuffer1;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;
    DMA_InitStructure.BufSize        = TxBufferSize1;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;
    DMA_InitStructure.MemDataSize    = DMA_MEMORY_DATA_SIZE_BYTE;
    DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;
    DMA_InitStructure.Priority       = DMA_PRIORITY_VERY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    DMA_Init(USARTy_Tx_DMA_Channel, &DMA_InitStructure);

    /* USARTy RX DMA1 Channel (triggered by USARTy Rx event) Config */
    DMA_DeInit(USARTy_Rx_DMA_Channel);
    DMA_InitStructure.PeriphAddr = USARTy_DR_Base;
    DMA_InitStructure.MemAddr    = (uint32_t)RxBuffer1;
    DMA_InitStructure.Direction  = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize    = TxBufferSize2;
    DMA_Init(USARTy_Rx_DMA_Channel, &DMA_InitStructure);

    /* USARTz TX DMA1 Channel (triggered by USARTz Tx event) Config */
    DMA_DeInit(USARTz_Tx_DMA_Channel);
    DMA_InitStructure.PeriphAddr = USARTz_DR_Base;
    DMA_InitStructure.MemAddr    = (uint32_t)TxBuffer2;
    DMA_InitStructure.Direction  = DMA_DIR_PERIPH_DST;
    DMA_InitStructure.BufSize    = TxBufferSize2;
    DMA_Init(USARTz_Tx_DMA_Channel, &DMA_InitStructure);

    /* USARTz RX DMA1 Channel (triggered by USARTz Rx event) Config */
    DMA_DeInit(USARTz_Rx_DMA_Channel);
    DMA_InitStructure.PeriphAddr = USARTz_DR_Base;
    DMA_InitStructure.MemAddr    = (uint32_t)RxBuffer2;
    DMA_InitStructure.Direction  = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize    = TxBufferSize1;
    DMA_Init(USARTz_Rx_DMA_Channel, &DMA_InitStructure);
}



void func_init_uart4()
{
    //RCC_Configuration
    /* Enable GPIO clock */
    GPIO_APBxClkCmd(USARTx_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE);

    /* Enable USARTy and USARTz Clock */
    USART_APBxClkCmd(USARTx_CLK, ENABLE);

    //GPIO_Configuration
    GPIO_InitType GPIO_InitStructure;
    GPIO_ConfigPinRemap(GPIO_RMP_USART1,ENABLE);

    /* Configure USARTx Tx as alternate function push-pull */
    GPIO_InitStructure.Pin        = USARTx_TxPin;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(USARTx_GPIO, &GPIO_InitStructure);

    /* Configure USARTx Rx as input floating */
    GPIO_InitStructure.Pin       = USARTx_RxPin;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(USARTx_GPIO, &GPIO_InitStructure);

    GPIO_ConfigPinRemap(GPIO_RMP3_UART4, ENABLE);

    //uart
    /* USARTy and USARTz configuration ------------------------------------------------------*/
    USART_InitStructure.BaudRate            = 115200;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

    /* Configure USARTx */
    USART_Init(USARTx, &USART_InitStructure);

    /* Enable the USARTx */
    USART_Enable(USARTx, ENABLE);

}


void print_dma()
{
//    printf("TxBuffer1 = [%s]\r\n",(char*)TxBuffer1);
//    printf("TxBuffer2 = [%s]\r\n",(char*)TxBuffer2);
    printf("RxBuffer1 = [%s]\r\n",(char*)RxBuffer1);
//    printf("RxBuffer2 = [%s]\r\n",(char*)RxBuffer2);
    printf("\r\n");
}



void print_uart_wait()
{
    if(status_wait_uart == true)
    {
        status_wait_uart = false;
        printf("uart transfer waiting......\r\n");
    }
}

void print_uart_wait_end()
{
    status_wait_uart = true;
    printf("end uart wait.\r\n");
}

void myDMA_tx(uint8_t uart_id)
{

    // choose dma
    DMA_Module* dma =  USARTy_Tx_DMA_Channel;
    uint32_t dma_flag = DMA1_FLAG_TC1;
    switch(uart_id)
    {
    case 5:
            dma =  USARTy_Tx_DMA_Channel;
            dma_flag= DMA1_FLAG_TC1;
            break;
    case 6:
            dma =  USARTz_Tx_DMA_Channel;
            dma_flag = DMA2_FLAG_TC8;
            break;
    default:
            printf("use default uart5\r\n");
            dma =  USARTy_Tx_DMA_Channel;
            dma_flag = DMA1_FLAG_TC1;
            break;
    }

    printf("send\r\n");
    // tx : send uart data to other dev
    while (DMA_GetFlagStatus(dma_flag, dma) == RESET)
    {
        print_uart_wait();
    }
    print_uart_wait_end();



}

void myUart_senddata(uint8_t uart_id,uint8_t* data, uint8_t len_send)
{
    uint8_t * temp_value = data;
    uint8_t temp_len = len_send;

    printf("len_send = %d, strvalue = [%s]\r\n",temp_len,(char * )data);

    // choose uart
    USART_Module* uart =  USARTy;
    switch(uart_id)
    {
    case 5:
            uart = USARTy;
            break;
    case 6:
            uart = USARTz;
            break;
    default:
            printf("use default uart5\r\n");
            uart = USARTy;
            break;
    }

    int i=0;
    while(temp_len > i)
    {
//        printf("i = %d, value = %02x\r\n",i,*temp_value);
        USART_SendData(uart,*temp_value);

        // wait until data has send
        while(USART_GetFlagStatus(uart,USART_FLAG_TXDE)==RESET)
        {

        }

        i++;
        temp_value++;
    }
    return;
}

void myUart_tx(uint8_t uart_id,uint8_t * data,uint8_t len_send)
{
    int len_str = strlen(data);

    bool str_data = len_send>=len_str;

    // if send overside strlen, just send strlen
    int len = str_data? len_str:len_send;
    printf("strlen = %d, send len = %d, send>strlen = %s\r\n",len_str,len_send,
            str_data?"true":"false");

    if(str_data == true)
    {
        printf("send data len overside str_len.\r\n");
    }
    else
    {
        printf("send data len = %d.\r\n",len_send);
    }

    myUart_senddata(uart_id,data,len);
}

void myUart_rx(uint8_t uart_id,bool rx_tx)
{
    USART_Module * uart = USARTy;
    DMA_Module * dma = USARTy_Rx_DMA_Channel;

    switch(uart_id)
    {
    case 5:
            uart = USARTy;
            dma = USARTy_Rx_DMA_Channel;
            break;
    case 6:
            uart = USARTz;
            dma = USARTz_Rx_DMA_Channel;
            break;
    default:
            printf("use default uart5\r\n");
            uart = USARTy;
            break;
    }

//    printf("receive\r\n");
    // rx : get uart data from other dev
    /* Wait until USARTy get idlef */
    while (USART_GetFlagStatus(uart, USART_FLAG_IDLEF) == RESET)
    {
        print_uart_wait();
    }
    print_uart_wait_end();

    printf("uart is idlef\r\n");

    int dma_last = DMA_GetCurrDataCounter(USARTy_Rx_DMA_Channel);
    printf("dma get count =%d \r\n",dma_last);

    printf("has recv data len = %d\r\n",TxBufferSize2-dma_last);

    reset_dma_rx();
}

void reset_dma_rx()
{
    print_dma();

    memset(RxBuffer1,0x00,sizeof(RxBuffer1));
    DMA_EnableChannel(USARTy_Rx_DMA_Channel, DISABLE);

    DMA_SetCurrDataCounter(USARTy_Rx_DMA_Channel,TxBufferSize1);

    DMA_EnableChannel(USARTy_Rx_DMA_Channel, ENABLE);

    // clear idlef flag
    USART_ReceiveData(USARTy);
}

void reset_dma_tx()
{
    print_dma();

    memset(TxBuffer1,0x00,sizeof(TxBuffer1));
    DMA_EnableChannel(USARTy_Rx_DMA_Channel, DISABLE);

    DMA_SetCurrDataCounter(USARTy_Rx_DMA_Channel,TxBufferSize1);

    DMA_EnableChannel(USARTy_Rx_DMA_Channel, ENABLE);

    // clear idlef flag
    USART_ReceiveData(USARTy);
}

/**
 * @brief  Delay function.
 */
void delay(vu32 nCount)
{
    vu32 index = 0;
    for (index = (34000 * nCount); index != 0; index--)
    {
    }
}

/**
 * @}
 */

/**
 * @}
 */

6 结果

请添加图片描述
可以看到,串口接收工具

  1. 收到dma传输的字符串
  2. 收到通过uart函数传输的字符串
  3. 向uart5发出不定长度的数据,log中显示出来获取的数据及长度。

7 使用函数

USART_SendData:uart传输数据tx
USART_GetFlagStatus:获取uart状态,根据传入的uart和flag,返回set表示该flag已经设置,则跳出while循环

DMA_GetCurrDataCounter:获取dma剩余空间长度,用于计算当前收到了多少数据。

DMA_EnableChannel:开关dma的channel,两个dma,每个有8channel。
DMA_SetCurrDataCounter:设置当前dma的指针。
PS:收到过一次后需要开关dma,然后重新设置当前数据数。

此外,由于判断dma收到数据状态,通过判断usart的idle,空闲中断。
当判定到uart收到空闲中断,则表示uart数据传输完成。不过该状态清空需要使用到receive函数。
USART_ReceiveData:uart接收数据rx。

8 小结

本章介绍了结合uart及dma实现数据的收发,后续再结合串口屏实现功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值