EFM32片内外设--USART UART TX+DMA

来源:互联网 发布:江苏昆山华道数据 编辑:程序博客网 时间:2024/05/29 14:00

硬件准备:TG STK , 将20pin 扩展口的4脚与6脚相连接。第4脚为PD0,Tx, 第6脚为PD1,Rx。

软件流程:UART配置完毕之后,在主函数中不停的触发TX的DMA传输,总共传输12个字节的数据,0~9, '\n' , '\r'。 Rx采用普通中断来做。

 

#include <stdint.h>
#include <stdbool.h>
#include "efm32.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"
#include "em_dma.h"

#define DMA_CHANNEL_UART_TX    0  //定义DMA传输的通道,0代表是通道0

#define SPITXSAMPLES          (12)  //定义了传输的字节个数,最大为1024字节


//定义DMA控制器的全局变量,请不要动
/* DMA init structure */
DMA_Init_TypeDef dmaInit;
/* DMA callback structure */
DMA_CB_TypeDef cb[DMA_CHAN_COUNT];//DMA_CHAN_COUN通道总数

/** DMA control block, requires proper alignment. */
#if defined (__ICCARM__)
#pragma data_alignment=256
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2];
#elif defined (__CC_ARM)
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2] __attribute__ ((aligned(256)));
#elif defined (__GNUC__)
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMA_CHAN_COUNT * 2] __attribute__ ((aligned(256)));
#else
#error Undefined toolkit, need to define alignment
#endif

 

unsigned char ucUARTTxBuffer[SPITXSAMPLES]; //定义一个1K字节的缓冲区,作为Tx的传输测试


unsigned char ucComplete = 0;

//USART1的接收中断函数
void USART1_RX_IRQHandler(void)
{
    USART_Rx(USART1);// 接收中断标志位在读取Rx数据之后,自动清零
}

void UART_Initial(void)
{
    CMU_ClockEnable(cmuClock_HFPER, true);
    CMU_ClockEnable(cmuClock_GPIO, true);
    CMU_ClockEnable(cmuClock_USART1, true);
   
    USART_InitAsync_TypeDef UART_init = USART_INITASYNC_DEFAULT;

    //设置USART1的波特率为9600
    UART_init.baudrate = 9600;
   
    //初始化USART1
    USART_InitAsync(USART1, &UART_init);
   
    //先清除Rx中断标志位,然后使能Rx中断允许
    USART1->IFC = _USART_IFC_MASK;
    NVIC_ClearPendingIRQ(USART1_RX_IRQn);
    NVIC_EnableIRQ(USART1_RX_IRQn);
    USART1->IEN = USART_IEN_RXDATAV;
   
    //USART1 GPIO口设置
    GPIO_PinModeSet(gpioPortD,0,gpioModePushPull,1); //tx
    GPIO_PinModeSet(gpioPortD,1,gpioModeInput,1);    //rx
   
    USART1->ROUTE |=  USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC1;

}

void UARTTxTransferComplete(unsigned int channel, bool primary, void *user)
{
    ucComplete = 1;
}

void DMA_for_UART_Tx(void)
{
    DMA_CfgChannel_TypeDef  chnlCfg;
    DMA_CfgDescr_TypeDef    descrCfg;
   
    /* Setting up call-back function */ 
    cb[DMA_CHANNEL_UART_TX].cbFunc = UARTTxTransferComplete; //设置DMA完成之后,是否调用回调函数。如果没有回调函数,则设置为NULL
    cb[DMA_CHANNEL_UART_TX].userPtr = NULL;
   
    /* Setting up channel */
    chnlCfg.highPri = false;
    chnlCfg.enableInt = true;
    //设置DMA发送下一字节的条件,此处为:当Tx发送完毕之后,DMA再开始取下一字节进行发送
    chnlCfg.select = DMAREQ_USART1_TXEMPTY;
   
    //初始化DMA寄存器中的回调部分的功能
    chnlCfg.cb = &(cb[DMA_CHANNEL_UART_TX]);
    DMA_CfgChannel(DMA_CHANNEL_UART_TX, &chnlCfg);
   
    //定义DMA逻辑部分的寄存器
    /* Setting up channel descriptor */
    descrCfg.dstInc = dmaDataIncNone;   //意思目标地址不变
    descrCfg.srcInc = dmaDataInc1;      //意思是源地址每次加1字节
    descrCfg.size = dmaDataSize1;       //每次发送的字节单位
    descrCfg.arbRate = dmaArbitrate1;   //DMA仲裁,每发送1字节,仲裁一次
    descrCfg.hprot = 0;
    DMA_CfgDescr(DMA_CHANNEL_UART_TX, true, &descrCfg);
   
    //激活一次DMA发送
    DMA_ActivateBasic(DMA_CHANNEL_UART_TX,
                      true,
                      false,
                      (void *)&(USART1->TXDATA),
                      (void *)&ucUARTTxBuffer,
                      SPITXSAMPLES - 1);
}

//DMA初始化,无需改动
void DMAInit(void)

    CMU_ClockEnable(cmuClock_DMA, true);
  /* Initializing the DMA */
  dmaInit.hprot = 0;
  dmaInit.controlBlock = dmaControlBlock;
  DMA_Init(&dmaInit);
}

//Demo演示使用,初始化发送缓冲区
void Uart_Tx_Data_Init(void)
{
    unsigned char ucData = '0';
    unsigned long ucCount = 0;
    for(ucCount = 0; ucCount < SPITXSAMPLES-2; ucCount++)
    {
        ucUARTTxBuffer[ucCount] = ucData;
        if(ucData < '9')ucData++;
        else ucData = '0';
    }
   
    ucUARTTxBuffer[ucCount] = '\n';
    ucCount++;
    ucUARTTxBuffer[ucCount] = '\r';
}

/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
int main(void)
{
  /* Chip errata */
  CHIP_Init();
  SystemCoreClockUpdate();
 
  Uart_Tx_Data_Init();
     
  DMAInit();
  UART_Initial();
  DMA_for_UART_Tx();
 
  ucComplete = 1;

  /* Infinite blink loop */
  while(1)
  {
      //上一次的DMA是否发送完毕
      if(ucComplete)
      {
          unsigned long ulDelay = 800000;
          while(ulDelay--);
         
          DMA_ActivateBasic(DMA_CHANNEL_UART_TX,
                      true,
                      false,
                      NULL,
                      NULL,
                      SPITXSAMPLES - 1);
         
          ucComplete = 0;
      }
  }
}