DMA+LeUart传输数据

DMA+LeUart的功能。只是知道EFM32针对LeUart做了很多的优化。例如在EM2的情况下,无论是发送还是接收,都可以自动唤醒DMA,进行传输,大大的降低了整个板子运行时候的功耗。

硬件准备:

TG STKLEUart0TxPD4RxPD5.  TG STK20pin扩展口上已经有这两个IO口,分别是12PinPD4Tx),14PinPD5Rx)。

软件准备:

1.使用CMSIS3.0的库了

2.DMA channel 0 作为Rx接收通道,接受数据的长度为1字节。。呵呵。

3.DMA channel 1 作为Tx发送通道,发送数据的长度为10字节。

4.平时进入EM2模式,在接受完毕之后,发送一次10字节的数据。

5.自己犯过一次无限Tx发送的错误,后来发现是逻辑错误。前提是我将Tx发送放在了主循环里面。当Rx接收到数据之后,会触发DMA中断。中断退出之后,在主循环中会触发Tx发送。然后继续进入EM2.而此时Tx发送完毕,又会触发DMA中断,然后又退出EM2,继续运行主程序中的Tx触发函数,周而复始,无限循环。

6.如果要使用call back函数,则必须使能该通道上的DMA中断。每个通道都有一个中断标志。CH0DONE~CH7DONE,外加一个ERROR标志

例程:这次例程会比较长。呵呵

#include "em_chip.h"

#include "efm32.h"

#include "em_cmu.h"

#include "em_emu.h"

#include "em_leuart.h"

#include "em_dma.h"

#include "em_gpio.h"

unsigned char ucRx_Ok = 0;

/* DEFINES */

#define DMA_RX_CHANNEL    0

#define RX_BUF_MAX        1

#define DMA_TX_CHANNEL    1

#define TX_BUF_MAX        10

unsigned char ucRx_Buffer[RX_BUF_MAX];

unsigned char ucTx_Buffer[TX_BUF_MAX] = {'G','e','c','k','o',',','!','!','!','\0',};

/* DMA control block, must be aligned to 256. */

#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

/* DMA init structure */

DMA_Init_TypeDef dmaInit;

/* DMA callback structure */

DMA_CB_TypeDef cb[DMA_CHAN_COUNT];

 

void LeUart_Initial_IO(void)

{

    CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);

    

  /* Reseting and initializing LEUART0 */

  LEUART_Reset(LEUART0);

  

  LEUART_Init_TypeDef leuart1Init =

  {

      .enable   = leuartEnable,     /* Activate data reception on LEUn_RX pin. */

      .refFreq  = 0,                  /* Inherit the clock frequenzy from the LEUART clock source */

      .baudrate = 9600,               /* Baudrate = 9600 bps */

      .databits = leuartDatabits8,    /* Each LEUART frame containes 8 databits */

      .parity   = leuartNoParity,     /* No parity bits in use */

      .stopbits = leuartStopbits1,    /* Setting the number of stop bits in a frame to 2 bitperiods */

  };

  

  LEUART_Init(LEUART0, &leuart1Init);

  /* Route LEUART0 RX pin to DMA location 0 */

  LEUART0->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | LEUART_ROUTE_LOCATION_LOC0;

  GPIO_PinModeSet(gpioPortD,            /* Port */

                  5,                    /* Port number */

                  gpioModeInputPull,    /* Pin mode is set to input only, with pull direction given bellow */

                  1);                   /* Pull direction is set to pull-up */

  GPIO_PinModeSet(gpioPortD,            /* Port */

                  4,                    /* Port number */

                  gpioModePushPull,     /* Pin mode is set to input only, with pull direction given bellow */

                  1);

}

void DMAInit(void)

{

    /* Initializing the DMA */

    dmaInit.hprot = 0;

    dmaInit.controlBlock = dmaControlBlock;

    DMA_Init(&dmaInit);

}

void LeUartRxReceiveComplete(unsigned int channel, bool primary, void *user)

{

    DMA_ActivateBasic(DMA_RX_CHANNEL,

                      true,

                      false,

                      NULL,

                      NULL,

                      RX_BUF_MAX - 1);

    GPIO_PinOutSet(gpioPortD, 7);

    ucRx_Ok = 1;

}

void LeUartTxTransmitComplete(unsigned int channel, bool primary, void *user)

{

    /* Disable DMA wake-up from LEUART1 TX */

    LEUART0->CTRL &= ~LEUART_CTRL_TXDMAWU;

    GPIO_PinOutClear(gpioPortD, 7);

}

void DMA_Initial_IO(void)

{

    //Setting up Rx DMA

    /* Setting up channel */

    /* Setting call-back function */  

    cb[DMA_RX_CHANNEL].cbFunc  = LeUartRxReceiveComplete;

    cb[DMA_RX_CHANNEL].userPtr = NULL;

    

    DMA_CfgChannel_TypeDef chnlCfg =

    {

        .highPri   = false,                     /* Normal priority */

        .enableInt = true,                     /* No interupt enabled for callback functions */

        .select    = DMAREQ_LEUART0_RXDATAV,    /* Set LEUART0 RX data avalible as source of DMA signals */

        .cb        = &(cb[DMA_RX_CHANNEL]),

    };

    DMA_CfgChannel(DMA_RX_CHANNEL, &chnlCfg);

    

    /* Setting up channel descriptor */

    DMA_CfgDescr_TypeDef descrCfg =

    {

        .dstInc  = dmaDataInc1,       /* Increment destination address by one byte */

        .srcInc  = dmaDataIncNone,    /* Do no increment source address  */

        .size    = dmaDataSize1,      /* Data size is one byte */

        .arbRate = dmaArbitrate1,     /* Rearbitrate for each byte recieved*/

        .hprot   = 0,                 /* No read/write source protection */

    };

    DMA_CfgDescr(DMA_RX_CHANNEL, true, &descrCfg);

    

    /* Starting the transfer. Using Basic Mode */

    DMA_ActivateBasic(DMA_RX_CHANNEL,                /* Activate channel selected */

                      true,                       /* Use primary descriptor */

                      false,                      /* No DMA burst */

                      (void *) &ucRx_Buffer,            /* Destination address */

                      (void *) &LEUART0->RXDATA,  /* Source address*/

                      RX_BUF_MAX - 1);               /* Size of buffer minus1 */

    

    /* Make sure the LEUART wakes up the DMA on RX data */

    LEUART0->CTRL = LEUART_CTRL_RXDMAWU;

    

    

    //Setting up Tx DMA

    /* Setting up channel */

    /* Setting call-back function */  

    cb[DMA_TX_CHANNEL].cbFunc  = LeUartTxTransmitComplete;

    cb[DMA_TX_CHANNEL].userPtr = NULL;

    

    DMA_CfgChannel_TypeDef chnlCfg1 =

    {

        .highPri   = false,                     /* Normal priority */

        .enableInt = true,                     /* No interupt enabled for callback functions */

        .select    = DMAREQ_LEUART0_TXEMPTY,    /* Set LEUART0 RX data avalible as source of DMA signals */

        .cb        = &(cb[DMA_TX_CHANNEL]),

    };

    DMA_CfgChannel(DMA_TX_CHANNEL, &chnlCfg1);

    

    /* Setting up channel descriptor */

    DMA_CfgDescr_TypeDef descrCfg1 =

    {

        .dstInc  = dmaDataIncNone,    /* Do no increment source address  */

        .srcInc  = dmaDataInc1,       /* Increment destination address by one byte */

        .size    = dmaDataSize1,      /* Data size is one byte */

        .arbRate = dmaArbitrate1,     /* Rearbitrate for each byte recieved*/

        .hprot   = 0,                 /* No read/write source protection */

    };

    DMA_CfgDescr(DMA_TX_CHANNEL, true, &descrCfg1);

    

    /* Set new DMA destination address directly in the DMA descriptor */

    dmaControlBlock[DMA_TX_CHANNEL].DSTEND = &LEUART0->TXDATA;

    dmaControlBlock[DMA_TX_CHANNEL].SRCEND = ucTx_Buffer + TX_BUF_MAX - 1;

}

void main(void)

{

    /* Initialize chip */

    CHIP_Init();

    

    /* Start LFXO, and use LFXO for low-energy modules */

    CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);

    

    /* Enabling clocks, all other remain disabled */

    CMU_ClockEnable(cmuClock_CORELE, true);     /* Enable CORELE clock */

    CMU_ClockEnable(cmuClock_DMA, true);        /* Enable DMA clock */

    CMU_ClockEnable(cmuClock_GPIO, true);       /* Enable GPIO clock */

    CMU_ClockEnable(cmuClock_LEUART0, true);    /* Enable LEUART0 clock *

    DMAInit();

    LeUart_Initial_IO();

    DMA_Initial_IO();

    GPIO_PinModeSet(gpioPortD, 7, gpioModePushPull, 0);

    

    while (1)

    {

        EMU_EnterEM2(true);

        if(ucRx_Ok)//判断是否有接收到数据,如果有,则启动一次发送。

        {

            LEUART0->CTRL = LEUART_CTRL_TXDMAWU;

            DMA_ActivateBasic(DMA_TX_CHANNEL,                  /* Activate channel selected */

                              true,                         /* Use primary descriptor */

                              false,                        /* No DMA burst */

                              NULL,                         /* Keep destination address */

                              NULL,                         /* Keep source address*/

                              TX_BUF_MAX - 1);                 /* Size of buffer minus1 */

            ucRx_Ok = 0;

        }

    }}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值