通过STM32F407的串口输出运行状态信息

调试的时候,通过IDE查看状态是最常用的手段,但如果不断地把运行过程信息通过串口输出来,也会是一种好办法。所以创建新项目后,可以先将调试信息输出功能写好,再慢慢做写其他代码,正所谓工欲善其事必先利其器嘛。
功能的实现非常简单,就是通过串口的TX把信息print出来,使用DMA传输可以降低MCU负担,为了简化,甚至把初始化也放在print函数中,在需要输出的地方直接调用DrvDebugInfoPrint(),例如在LED任务里调用:DrvDebugInfoPrint(“LED Start to flash!”);
头文件:
/* DrvUartTool, V1.0, 2018-7-4, Yangwb ****************************************/
/* Use USART1_TX:PA9, DMA2_Stream7, DMA_Channel_4 *****************************/
/* 
set USE_DEBUG_INFO_AT_UART = 1 to use this module; 0 to disable, then the
function DrvDebugInfoPrint() define as null.
module need'n init, DrvDebugInfoPrint() auto call init function.
Example: when LED task start, DrvDebugInfoPrint("LED start to flash!").
*/

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DrvDebug_H
#define __DrvDebug_H
/* Private functional switch -------------------------------------------------*/
#define USE_DEBUG_INFO_AT_UART 1
#if USE_DEBUG_INFO_AT_UART == 1
/* Private define ------------------------------------------------------------*/
#define DEBUG_INFO_UART_BAUDRATE 115200
#define DEBUG_INFO_UART_BUFF_SIZE 50
#define DEBUG_INFO_UART_TX_STATUS_NOT_INIT 0
#define DEBUG_INFO_UART_TX_STATUS_READY 12
#define DEBUG_INFO_UART_TX_STATUS_BUSY 123
/* Includes ------------------------------------------------------------------*/
#include "Common.h"
#include "stm32f4xx.h"
#include <stdio.h>
#include <string.h>
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
extern volatile INT8U g_u8DebugTxDmaStatus;
extern volatile INT8U g_au8DebugTxDmaBuff[DEBUG_INFO_UART_BUFF_SIZE];
#endif // end of USE_DEBUG_INFO_AT_UART
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#if USE_DEBUG_INFO_AT_UART == 1
void DrvDebugInfoAtUartInit(void);
#define DrvDebugInfoPrint(String)                                             \
  do                                                                          \
  {                                                                           \
    if (g_u8DebugTxDmaStatus == DEBUG_INFO_UART_TX_STATUS_NOT_INIT)           \
    {                                                                         \
      DrvDebugInfoAtUartInit();                                               \
      g_u8DebugTxDmaStatus = DEBUG_INFO_UART_TX_STATUS_READY;                 \
    }                                                                         \
    while (g_u8DebugTxDmaStatus != DEBUG_INFO_UART_TX_STATUS_READY)           \
    {                                                                         \
    }                                                                         \
    g_u8DebugTxDmaStatus = DEBUG_INFO_UART_TX_STATUS_BUSY;                    \
    if (strlen(String) <= DEBUG_INFO_UART_BUFF_SIZE)                          \
    {                                                                         \
      strncpy((char *)g_au8DebugTxDmaBuff, String, strlen(String));           \
    }                                                                         \
    else                                                                      \
    {                                                                         \
      strncpy((char *)g_au8DebugTxDmaBuff, "Too long!", strlen("Too long!")); \
    }                                                                         \
    DMA2_Stream7->CR &= ~0x1ul;                                               \
    DMA2_Stream7->M0AR = (INT32U)g_au8DebugTxDmaBuff;                         \
    DMA2_Stream7->NDTR = (INT32U)strlen(String);                              \
    DMA2_Stream7->CR |= 0x1ul;                                                \
  } while (0)
#else
#define DrvDebugInfoPrint(String)
#endif

#endif /* __DrvDebug_H */

C文件:
/* Attention, read head file at first. ****************************************/
/* Includes ------------------------------------------------------------------*/
#include "DrvDebug.h"
#if USE_DEBUG_INFO_AT_UART == 1
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
volatile INT8U g_u8DebugTxDmaStatus = DEBUG_INFO_UART_TX_STATUS_NOT_INIT;
volatile INT8U g_au8DebugTxDmaBuff[DEBUG_INFO_UART_BUFF_SIZE] = {"Hello!"};
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
  * @brief  config dma buff
  * @param  None
  * @retval None
  */
void DrvDebugInfoAtUartInit(void)
{
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
    if (g_u8DebugTxDmaStatus != DEBUG_INFO_UART_TX_STATUS_NOT_INIT)
    {
        return;
    }

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);

    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);

    /* uart DMA send irq */
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* uart irq */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* DMA2_Stream7 config as uart1 dma send */
    /* Reset DMA Stream registers (for debug purpose) */
    DMA_DeInit(DMA2_Stream7);

    /* Check if the DMA Stream is disabled before enabling it.
     Note that this step is useful when the same Stream is used multiple times:
     enabled, then disabled then re-enabled... In this case, the DMA Stream disable
     will be effective only at the end of the ongoing data transfer and it will
     not be possible to re-configure it before making sure that the Enable bit
     has been cleared by hardware. If the Stream is used only once, this step might
     be bypassed. */
    while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE)
    {
    }

    /* Configure DMA Stream */
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (INT32U)(&(USART1->DR));
    DMA_InitStructure.DMA_Memory0BaseAddr = (INT32U)(g_au8DebugTxDmaBuff);
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize = (INT32U)DEBUG_INFO_UART_BUFF_SIZE;
    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_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream7, &DMA_InitStructure);
    /* Enable DMA Stream Transfer Complete interrupt */
    DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA2_Stream7, DISABLE);

    /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/
    USART_InitStructure.USART_BaudRate = DEBUG_INFO_UART_BAUDRATE;
    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_Tx;
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE); /* Enable USART */
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); /* use dma send*/

    g_u8DebugTxDmaStatus = DEBUG_INFO_UART_TX_STATUS_READY;
}

/**
* @brief  This function handles DMA Stream interrupt request.
*/
void DMA2_Stream7_IRQHandler(void)
{
    if (DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7))
    {
        /* Clear DMA Stream Transfer Complete interrupt pending bit */
        DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);
        g_u8DebugTxDmaStatus = DEBUG_INFO_UART_TX_STATUS_READY;
    }
}
#endif // end of USE_DEBUG_INFO_AT_UART

猜你喜欢

转载自blog.csdn.net/b260123292/article/details/81205975