打印
[综合信息]

【华大测评】+串口DMA收发数据

[复制链接]
12435|54
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lesheng002|  楼主 | 2020-10-15 14:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 lesheng002 于 2020-10-15 14:36 编辑

串口传输用中断实现的话,要频繁的进入中断函数,这样无疑增加MCU的负担,干扰正常程序的运行,对于一些实时性强的应用,如数字显示应用中,液晶屏显示可能受影响而不能正常显示。用DMA实现串口收发数据,进行数据收发过程中,不需要MCU的干预,由DMA独立完成数据的收发,接收或者发送完成后才进入中断做后续处理,因此MCU使用效率更高。
华大提供的例程中,对于串口DMA收发的应用比较简单,我这里结合以前的经验将串口收发用DMA实现。

使用华大免费提供的DEMO板D的基础上实现,MCU型号是HC32F460,当前例程使用的资源简单介绍
1,拥有 2 个 DMA 控制单元,共 8 个独立通道, 可以独立操作不同的 DMA 传输功能;
2,有4个串行收发器模块(USART单元),能够灵活地与外部设备进行全双工数据交换;


实现了功能,
1,系统滴答初始化及延时,
2,串行收发数据,用DMA实现,一次收发数据最大USART_DATA_BUFF_SIZE-1个字符,
3,用接收超时中断实现一次接收数据少于(USART_DATA_BUFF_SIZE-1)个字符的传输,


有4个文件,分别如下

  Systick.c 系统滴答文件
/******************************************************************************
* 文件名  :SysTick.c
* 描述    :SysTick 系统滴答时钟10us中断函数库,中断时间可自由配置,
*           常用的有 1us 10us 1ms 中断。         
* 实验平台:华大HC32F460
* 硬件连接:-----------------
*          |                 |
*          |      无         |
*          |                 |
*           -----------------
* 库版本  :
*
* 作者    :David liu  
* 博客    :https://blog.csdn.net/qq_15548761
**********************************************************************************/
#include "systick.h"
#include    "usart.h"

volatile uint32_t TimingDelay;

uint16_t        mainDelayMS;

uint16_t        beepCnt;
uint8_t                beepTimes;

uint16_t        TimerSoundON;
uint16_t        TimerSoundOFF;


/*
* 函数名:SysTick_Init
* 描述  :启动系统滴答定时器 SysTick
* 输入  :无
* 输出  :无
* 调用  :外部调用
*/
void SysTick_Init(void)
{
    stc_irq_regi_conf_t stcIrqRegiCfg;
        /* SystemFrequency / 1000    1ms中断一次
         * SystemFrequency / 100000         10us中断一次
         * SystemFrequency / 1000000 1us中断一次
         */
        TimingDelay = 0;
        if (SysTick_Config(SystemCoreClock / 1000))
        while(1);
   
//  SysTick->LOAD  = (uint32_t)((SystemCoreClock / 1000) - 1UL);                         /* set reload register */
//  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
//  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
//  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
//                   SysTick_CTRL_TICKINT_Msk   |
//                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
    /* Set USART RX error IRQ */
//    stcIrqRegiCfg.enIRQn = SysTick_IRQn;
//    stcIrqRegiCfg.pfnCallback = &SysTick_IRQHandler;
//    stcIrqRegiCfg.enIntSrc = USART_RTO_NUM;
//    enIrqRegistration(&stcIrqRegiCfg);
//    NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
//    NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
//    NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
}


/*
* 函数名:Delay_us
* 描述  :us延时程序,1ms为一个单位
* 输入  :- nTime
* 输出  :无
* 调用  :Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
*       :外部调用
*/

void SysTickDelay_ms(__IO uint32_t nTime)
{
  TimingDelay = nTime;

  while(TimingDelay != 0)
  {
      __nop();
      usart_rxData_process();
  }
}

void        BIBI_CntDown(void);
/*
* 函数名:TimingDelay_Decrement
* 描述  :获取节拍程序
* 输入  :无
* 输出  :无
* 调用  :在 SysTick 中断函数 SysTick_Handler()调用
*/  
void SysTick_IRQHandler(void)
{
    static  uint16_t  timeCnt = 0;
    if(TimingDelay)
        TimingDelay--;
        if(mainDelayMS)
                mainDelayMS--;

        timeCnt++;
        if(timeCnt >= 500)
        {
                timeCnt = 0;
        }
        BIBI_CntDown();
       
}


void        BIBI_CntDown(void)
{
        if(beepCnt)                //        蜂鸣器延时
        {
                beepCnt--;
                if(!beepCnt)
                {
                        if(!beepTimes)
                                BeepOut(0);
                        else
                        {
                                beepTimes--;
                                if(beepTimes%2)
                                {
                                        beepCnt = TimerSoundOFF;
                    BeepOut(0);
                                }
                                else
                                {
                    BeepOut(1);
                                        beepCnt = TimerSoundON;
                                }
                        }
                }
        }
}


void        BIBI_Start(uint8_t        bibiTimes)
{
        {
                beepTimes = bibiTimes*2-1;
                BeepOut(1);
                beepCnt = DEF_BIBI_DELAY_TIMER;
        TimerSoundON  = DEF_BIBI_DELAY_TIMER ;
                TimerSoundOFF = DEF_BIBI_DELAY_TIMER ;
        }
}


void        BIBI_LongStart(uint8_t        bibiTimes)
{
        {
                beepTimes = bibiTimes*2-1;
                BeepOut(1);
                beepCnt = DEF_LONG_BIBI_DELAY;
        TimerSoundON  = DEF_LONG_BIBI_DELAY ;
                TimerSoundOFF = DEF_BIBI_DELAY_TIMER ;
        }
}

/*****************************************************************
      void  Buzzer(unsigned char idata  SoundType );
*****************************************************************/
void Buzzer(unsigned char  SoundType )
{
//    switch(SoundType)
//        {
//        case SHORT_BI   :   TimerSoundON  = DEF_BIBI_DELAY_TIMER ;
//                                        TimerSoundOFF = DEF_BIBI_DELAY_TIMER ;
//                                                        beepTimes     = 1 ;          // On  1-time
//                                                        break;
//                case SHORT_BI_2 :   TimerSoundON  = DEF_BIBI_DELAY_TIMER ;
//                                                        TimerSoundOFF = DEF_BIBI_DELAY_TIMER ;
//                                                        beepTimes     = 3 ;          // On, Off, On
//                                                        break;
//                case SHORT_BI_3 :   TimerSoundON  = DEF_BIBI_DELAY_TIMER ;
//                                        TimerSoundOFF = DEF_BIBI_DELAY_TIMER ;
//                                                        beepTimes     = 5 ;          // On, Off, On, Off, On ( 3-times)
//                                                        break;
//                case LONG_BI    :   TimerSoundON  = DEF_BIBI_DELAY_TIMER*3 ;
//                                        TimerSoundOFF = DEF_BIBI_DELAY_TIMER ;
//                                                        beepTimes     = 9;           // On  10/2=5 times
//                                                        break;
//                case LONG_BI_2  :   TimerSoundON  = DEF_BIBI_DELAY_TIMER*3 ;
//                                        TimerSoundOFF = DEF_BIBI_DELAY_TIMER ;
//                                                        beepTimes     = 19;           //  On, Off, 10 times
//                                                        break;
//        }
        BeepOut(1);
        beepCnt = TimerSoundON;
}



void Sound_KeyOK(void)
{
//    Buzzer(SHORT_BI);
}

void Sound_KeyError(void)
{
//    Buzzer(SHORT_BI_2);
}

void Sound_AxisError(void)
{
//    Buzzer(LONG_BI);
}



/************************* *****END OF FILE***********************************/


  SysTick.h
#ifndef __SYSTICK_H
#define __SYSTICK_H

#include "hc32_ddl.h"

#define                DEF_BIBI_DELAY_TIMER                20        //80
#define                DEF_LONG_BIBI_DELAY                        80        //300
#define     TIME_READ_COUNTER       15

#define     BeepOut(x)     // x = x

void SysTick_Init(void);
void Delay_10us(__IO uint32_t nTime);
void SysTickDelay_ms(__IO uint32_t nTime);

void Sound_KeyOK(void);
void Sound_KeyError(void);
void Sound_AxisError(void);


#endif /* __SYSTICK_H */
串行数据收发实现文件
usart.h
#ifndef __USART_H__
#define __USART_H__

#include "hc32_ddl.h"
#include <stdio.h>
#include "hc32f46x_dmac.h"

#define     USART_DATA_BUFF_SIZE        100
#define     USART_ARRAY_SIZE        3

#define     ENABLE_USART_DMA        1

/* DMAC */
#define USART_DMA_UNIT                        (M4_DMA1)
#define RX_DMA_CH                          (DmaCh0)
#define RX_DMA_TRG_SEL                     (EVT_USART3_RI)
#define TX_DMA_CH                          (DmaCh1)
#define TX_DMA_TRG_SEL                     (EVT_USART3_TI)

/* DMA block transfer complete interrupt */
#define RX_DMA_BTC_INT_NUM                 (INT_DMA1_TC0)
#define RX_DMA_BTC_INT_IRQn                (Int002_IRQn)
#define TX_DMA_BTC_INT_NUM                 (INT_DMA1_TC1)
#define TX_DMA_BTC_INT_IRQn                (Int001_IRQn)


/* USART channel definition */
#define USART_CH                        (M4_USART3)

/* USART baudrate definition */
#define USART_BAUDRATE                  (115200ul)

/* USART RX Port/Pin definition */
#define USART_RX_PORT                   (PortE)
#define USART_RX_PIN                    (Pin04)
#define USART_RX_FUNC                   (Func_Usart3_Rx)

/* USART TX Port/Pin definition */
#define USART_TX_PORT                   (PortE)
#define USART_TX_PIN                    (Pin05)
#define USART_TX_FUNC                   (Func_Usart3_Tx)

/* USART interrupt number  */
#define USART_RI_NUM                    (INT_USART3_RI)
#define USART_EI_NUM                    (INT_USART3_EI)
#define USART_TI_NUM                    (INT_USART3_TI)
#define USART_TCI_NUM                   (INT_USART3_TCI)
#define USART_RI_IRQn                    (Int003_IRQn)
#define USART_EI_IRQn                    (Int004_IRQn)
#define USART_TI_IRQn                    (Int005_IRQn)
#define USART_TCI_IRQn                   (Int006_IRQn)
#define USART_RTO_NUM                    (INT_USART3_RTO)
#define USART_RTO_IRQn                    (Int007_IRQn)

/* Timer0 unit definition */
#define TMR_UNIT                        (M4_TMR02)
#define TMR_FCG_PERIPH                  (PWC_FCG2_PERIPH_TIM02)

extern  uint8_t  rcvBuff[USART_ARRAY_SIZE][USART_DATA_BUFF_SIZE];
extern  uint8_t  rcvPoint ;
extern  uint8_t  rcvReceived ;
extern  uint8_t  sndBuff[USART_DATA_BUFF_SIZE];

void USART_Config(void);
void Usart_Rx_Tx(void);
void UsartRxErrProcess(void);

void    usart_tx_start_sending(uint8_t *pbuff, uint16_t  size);
void    usart_rxData_process(void);

#endif
usart.c

#include "usart.h"


uint8_t  rcvBuff[USART_ARRAY_SIZE][USART_DATA_BUFF_SIZE];
uint8_t  rcvPoint = 0;
uint8_t  rcvReceived = 0;
uint8_t  rcvCount = 1;
uint8_t  sndBuff[USART_DATA_BUFF_SIZE];


//  DMA接收完成回调函数,或者接收超时中断函数中调用
//  当前一组数据接收完成后的操作
void    usart_rx_receive_finish(void)
{
#if     (ENABLE_USART_DMA == 1)
    uint16_t  cnt;

    DMA_ChannelCmd(USART_DMA_UNIT, RX_DMA_CH,  Disable);
    cnt = DMA_GetTransferCnt(USART_DMA_UNIT, RX_DMA_CH);
    rcvBuff[rcvPoint][0] = USART_DATA_BUFF_SIZE - cnt ;
    rcvReceived++;
    rcvPoint++;
    if(rcvPoint >= USART_ARRAY_SIZE)
        rcvPoint = 0;
    /* Initialize DMA. */
    DMA_SetBlockSize(USART_DMA_UNIT, RX_DMA_CH, 1);
    DMA_SetTransferCnt(USART_DMA_UNIT, RX_DMA_CH, USART_DATA_BUFF_SIZE-1);
    DMA_SetDesAddress(USART_DMA_UNIT, RX_DMA_CH, (uint32_t)(&rcvBuff[rcvPoint][1]));
    DMA_ChannelCmd(USART_DMA_UNIT, RX_DMA_CH,  Enable);
#else
    rcvBuff[rcvPoint][0] = rcvCount-1;
    rcvReceived++;
    rcvCount = 1;
    rcvPoint++;
    if(rcvPoint >= USART_ARRAY_SIZE)
        rcvPoint = 0;
#endif
}

//  启动发送数据,
void    usart_tx_start_sending(uint8_t *pbuff, uint16_t  size)
{
    uint16_t i;
    for(i  = 0; i < size; i++)
    {
        sndBuff[i] = *pbuff++;
    }
#if     (ENABLE_USART_DMA == 1)
    DMA_SetBlockSize(USART_DMA_UNIT, TX_DMA_CH, 1);
    DMA_SetTransferCnt(USART_DMA_UNIT, TX_DMA_CH, size);
    DMA_SetSrcAddress(USART_DMA_UNIT, TX_DMA_CH, (uint32_t)(&sndBuff[0]));
    /* Enable the specified DMA channel. */
    DMA_ChannelCmd(USART_DMA_UNIT, TX_DMA_CH, Enable);

    /* Clear DMA flag. */
    DMA_ClearIrqFlag(USART_DMA_UNIT, TX_DMA_CH, TrnCpltIrq);
        USART_FuncCmd(USART_CH, UsartTx, Enable);
    USART_FuncCmd(USART_CH, UsartTxEmptyInt, Enable);
#else
#endif
}

#if     (ENABLE_USART_DMA == 1)
/**
*******************************************************************************
** \brief DMA block transfer complete irq callback function.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void usart_rx_Dma_IrqCallback(void)
{
    DMA_ClearIrqFlag(USART_DMA_UNIT, RX_DMA_CH, TrnCpltIrq);
    usart_rx_receive_finish();
}


/**
*******************************************************************************
** \brief DMA block transfer complete irq callback function.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void usart_tx_Dma_IrqCallback(void)
{
    DMA_ClearIrqFlag(USART_DMA_UNIT, TX_DMA_CH, TrnCpltIrq);
    /* Enable the specified DMA channel. */
    DMA_ChannelCmd(USART_DMA_UNIT, TX_DMA_CH, Disable);
        USART_FuncCmd(USART_CH, UsartTx, Disable);
}
#endif


/**
*******************************************************************************
** \brief USART RX irq callback function.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void UsartRxIrqCallback(void)
{
    rcvBuff[rcvPoint][rcvCount++] = USART_RecData(USART_CH);
//    USART_FuncCmd(USART_CH, UsartTxAndTxEmptyInt, Enable);
    if(rcvCount >= USART_DATA_BUFF_SIZE-1)
    {
        usart_rx_receive_finish();
    }
}

/**
*******************************************************************************
** \brief USART RX error irq callback function.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void UsartErrIrqCallback(void)
{
    if (Set == USART_GetStatus(USART_CH, UsartFrameErr))
    {
        USART_ClearStatus(USART_CH, UsartFrameErr);
    }

    if (Set == USART_GetStatus(USART_CH, UsartParityErr))
    {
        USART_ClearStatus(USART_CH, UsartParityErr);
    }

    if (Set == USART_GetStatus(USART_CH, UsartOverrunErr))
    {
        USART_ClearStatus(USART_CH, UsartOverrunErr);
    }
}


/**
*******************************************************************************
** \brief USART RX Timer out irq callback function.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void usart_rx_timeOut_IrqCallback(void)
{
    {
        TIMER0_Cmd(TMR_UNIT, Tim0_ChannelA,Disable);
        USART_ClearStatus(USART_CH, UsartRxTimeOut);
        usart_rx_receive_finish();
    }
}


#if     (ENABLE_USART_DMA == 1)
/**
*******************************************************************************
** \brief Initialize DMA.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void DmaInit(void)
{
    stc_dma_config_t stcDmaInit;
    stc_irq_regi_conf_t stcIrqRegiCfg;

    /* Enable peripheral clock */
    PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DMA1,Enable);

    /* Enable DMA. */
    DMA_Cmd(USART_DMA_UNIT,Enable);

    /* Initialize DMA. */
    MEM_ZERO_STRUCT(stcDmaInit);
    stcDmaInit.u16BlockSize = 1u; /* 1 block */
    stcDmaInit.u16TransferCnt = USART_DATA_BUFF_SIZE-1;
    stcDmaInit.u32SrcAddr = ((uint32_t)(&USART_CH->DR)+2ul); /* Set source address. */
    stcDmaInit.u32DesAddr = (uint32_t)(&rcvBuff[0][1]);     /* Set destination address. */
    stcDmaInit.stcDmaChCfg.enSrcInc = AddressFix;  /* Set source address mode. */
    stcDmaInit.stcDmaChCfg.enDesInc = AddressIncrease;  /* Set destination address mode. */
    stcDmaInit.stcDmaChCfg.enIntEn = Enable;       /* Enable interrupt. */
    stcDmaInit.stcDmaChCfg.enTrnWidth = Dma8Bit;   /* Set data width 8bit. */
    DMA_InitChannel(USART_DMA_UNIT, RX_DMA_CH, &stcDmaInit);

    /* Enable the specified DMA channel. */
    DMA_ChannelCmd(USART_DMA_UNIT, RX_DMA_CH, Enable);

    /* Clear DMA flag. */
    DMA_ClearIrqFlag(USART_DMA_UNIT, RX_DMA_CH, TrnCpltIrq);

    /* Enable peripheral circuit trigger function. */
    PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_PTDIS,Enable);

    /* Set DMA trigger source. */
    DMA_SetTriggerSrc(USART_DMA_UNIT, RX_DMA_CH, RX_DMA_TRG_SEL);

    /* Initialize DMA. */
    MEM_ZERO_STRUCT(stcDmaInit);
    stcDmaInit.u16BlockSize = 1u; /* 1 block */
    stcDmaInit.u16TransferCnt = USART_DATA_BUFF_SIZE-1;
    stcDmaInit.u32SrcAddr = (uint32_t)(&sndBuff[1]); /* Set source address. */
    stcDmaInit.u32DesAddr = ((uint32_t)(&USART_CH->DR));     /* Set destination address. */
    stcDmaInit.stcDmaChCfg.enSrcInc = AddressIncrease;  /* Set source address mode. */
    stcDmaInit.stcDmaChCfg.enDesInc = AddressFix;  /* Set destination address mode. */
    stcDmaInit.stcDmaChCfg.enIntEn = Enable;       /* Enable interrupt. */
    stcDmaInit.stcDmaChCfg.enTrnWidth = Dma8Bit;   /* Set data width 8bit. */
    DMA_InitChannel(USART_DMA_UNIT, TX_DMA_CH, &stcDmaInit);

    /* Set DMA trigger source. */
    DMA_SetTriggerSrc(USART_DMA_UNIT, TX_DMA_CH, TX_DMA_TRG_SEL);

    /* Set DMA block transfer complete IRQ */
    stcIrqRegiCfg.enIRQn = RX_DMA_BTC_INT_IRQn;
    stcIrqRegiCfg.pfnCallback = &usart_rx_Dma_IrqCallback;
    stcIrqRegiCfg.enIntSrc = RX_DMA_BTC_INT_NUM;
    enIrqRegistration(&stcIrqRegiCfg);
    NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
   
    stcIrqRegiCfg.enIRQn = TX_DMA_BTC_INT_IRQn;
    stcIrqRegiCfg.pfnCallback = &usart_tx_Dma_IrqCallback;
    stcIrqRegiCfg.enIntSrc = TX_DMA_BTC_INT_NUM;
    enIrqRegistration(&stcIrqRegiCfg);
    NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
}
#endif

void Timer0Init(void);

//  串行数据收发器配置函数
void USART_Config(void)
{
        en_result_t enRet = Ok;
    stc_irq_regi_conf_t stcIrqRegiCfg;
        uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART3;
        const stc_usart_uart_init_t stcInitCfg =
        {
        UsartIntClkCkOutput,
        UsartClkDiv_1,
        UsartDataBits8,
        UsartDataLsbFirst,
        UsartOneStopBit,
        UsartParityNone,
        UsartSamleBit8,
        UsartStartBitFallEdge,
        UsartRtsEnable,
        };

        /* Enable peripheral clock */
        PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);

        /* Initialize USART IO */
        PORT_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_FUNC, Disable);
        PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);

#if     (ENABLE_USART_DMA == 1)
    DmaInit();
#endif
    Timer0Init();

        /* Initialize UART */
        enRet = USART_UART_Init(USART_CH, &stcInitCfg);
        if (enRet != Ok)
        {
                while (1)
                {
                }
        }

        /* Set baudrate */
        enRet = USART_SetBaudrate(USART_CH, USART_BAUDRATE);
        if (enRet != Ok)
        {
                while (1)
                {
                }
        }
   
#if     (ENABLE_USART_DMA == 0)
         /* Set USART RX IRQ */
    stcIrqRegiCfg.enIRQn = USART_RI_IRQn;
    stcIrqRegiCfg.pfnCallback = &UsartRxIrqCallback;
    stcIrqRegiCfg.enIntSrc = USART_RI_NUM;
    enIrqRegistration(&stcIrqRegiCfg);
    NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
#endif   
    /* Set USART RX error IRQ */
    stcIrqRegiCfg.enIRQn = USART_EI_IRQn;
    stcIrqRegiCfg.pfnCallback = &UsartErrIrqCallback;
    stcIrqRegiCfg.enIntSrc = USART_EI_NUM;
    enIrqRegistration(&stcIrqRegiCfg);
    NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
   
    /* Set USART RX error IRQ */
    stcIrqRegiCfg.enIRQn = USART_RTO_IRQn;
    stcIrqRegiCfg.pfnCallback = &usart_rx_timeOut_IrqCallback;
    stcIrqRegiCfg.enIntSrc = USART_RTO_NUM;
    enIrqRegistration(&stcIrqRegiCfg);
    NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
   
    /*Enable TX && RX && RX interrupt function*/
        USART_FuncCmd(USART_CH, UsartRx, Enable);
    USART_FuncCmd(USART_CH, UsartRxInt, Enable);
   
    USART_FuncCmd(USART_CH, UsartTimeOut, Enable);
    USART_FuncCmd(USART_CH, UsartTimeOutInt, Enable);
}


/**
*******************************************************************************
** \brief Initliaze Timer0.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
void Timer0Init(void)
{
    stc_clk_freq_t stcClkTmp;
    stc_tim0_base_init_t stcTimerCfg;
    stc_tim0_trigger_init_t StcTimer0TrigInit;

    MEM_ZERO_STRUCT(stcClkTmp);
    MEM_ZERO_STRUCT(stcTimerCfg);
    MEM_ZERO_STRUCT(StcTimer0TrigInit);

    /* Timer0 peripheral enable */
    PWC_Fcg2PeriphClockCmd(TMR_FCG_PERIPH, Enable);

    /* Clear CNTAR register for channel A */
    TIMER0_WriteCntReg(TMR_UNIT, Tim0_ChannelA, 0u);
    TIMER0_WriteCntReg(TMR_UNIT, Tim0_ChannelB, 0u);

    /* Config register for channel A */
    stcTimerCfg.Tim0_CounterMode = Tim0_Async;
    stcTimerCfg.Tim0_AsyncClockSource = Tim0_XTAL32;
    stcTimerCfg.Tim0_ClockDivision = Tim0_ClkDiv8;
    stcTimerCfg.Tim0_CmpValue = 3200u;
    TIMER0_BaseInit(TMR_UNIT, Tim0_ChannelA, &stcTimerCfg);

    /* Clear compare flag */
    TIMER0_ClearFlag(TMR_UNIT, Tim0_ChannelA);

    /* Config timer0 hardware trigger */
    StcTimer0TrigInit.Tim0_InTrigEnable = false;
    StcTimer0TrigInit.Tim0_InTrigClear = true;
    StcTimer0TrigInit.Tim0_InTrigStart = true;
    StcTimer0TrigInit.Tim0_InTrigStop = false;
    TIMER0_HardTriggerInit(TMR_UNIT, Tim0_ChannelA, &StcTimer0TrigInit);
}


//  对接收到的一组数据进行分析处理
//  该函数在延时函数中调用,以获得及时响应
void usart_rxData_process(void)
{
    static uint8_t  txPoint = 0;
    if(rcvReceived > 0)
    {
        rcvReceived--;
        usart_tx_start_sending(&rcvBuff[txPoint][1], rcvBuff[txPoint][0]);
        txPoint++;
        if(txPoint>=USART_ARRAY_SIZE)
            txPoint = 0;
    }
}
对于经常使用串口收发数据的应用,用DMA实现提供MCU的效率,提高系统的性能。
将代码贴出来,大家一起探讨,有不妥之处,欢迎指正。

使用特权

评论回复
评论
h32446975 2021-7-31 12:40 回复TA
用户手册中,USART寄存器,明确说明,TXEIE位和TE位应同时写入1. 楼主验证过,调用这个函数,可以正常发送数据吗? // 启动发送数据,void usart_tx_start_sending(uint8_t *pbuff, uint16_t size) 
a1466536341 2021-7-2 14:27 回复TA
DMA_GetTransferCnt这个函数在哪,有没有可以提供 
沙发
lesheng002|  楼主 | 2020-10-15 20:51 | 只看该作者
以上代码经验证测试运行OK的

使用特权

评论回复
板凳
lrzxc1| | 2021-4-29 15:14 | 只看该作者
多谢楼主分享经验

使用特权

评论回复
地板
sadicy| | 2021-7-16 15:02 | 只看该作者
这大段代码,也真是拼了

使用特权

评论回复
5
里面有晴雨| | 2021-7-17 08:59 | 只看该作者
这个代码很长,楼主真是拼了。

使用特权

评论回复
6
kkzz| | 2021-8-1 22:29 | 只看该作者
串口的DMA串口传输完成中断怎么理解

使用特权

评论回复
7
hudi008| | 2021-8-1 22:29 | 只看该作者
串口使用dma方式 是什么配置

使用特权

评论回复
8
lzmm| | 2021-8-1 22:30 | 只看该作者
可以发用dma,收用普通中断吗

使用特权

评论回复
9
minzisc| | 2021-8-1 22:30 | 只看该作者
串口dma怎么接受数据

使用特权

评论回复
10
selongli| | 2021-8-1 22:30 | 只看该作者
只采用查询用此函数还可以?

使用特权

评论回复
11
fentianyou| | 2021-8-1 22:30 | 只看该作者
串口dma缓冲区是先进先出吗  

使用特权

评论回复
12
xiaoyaodz| | 2021-8-1 22:30 | 只看该作者
循环模式如何设置发送周期?

使用特权

评论回复
13
febgxu| | 2021-8-1 22:30 | 只看该作者
串口dma最多发送多少个

使用特权

评论回复
14
sdlls| | 2021-8-1 22:30 | 只看该作者
串口中断和DMA中断一起使用行么

使用特权

评论回复
15
pixhw| | 2021-8-1 22:31 | 只看该作者

开启串口DMA空闲中断接收不定长度数据  

使用特权

评论回复
16
lesheng002|  楼主 | 2021-8-5 10:19 | 只看该作者
lzmm 发表于 2021-8-1 22:30
可以发用dma,收用普通中断吗

肯定可以

使用特权

评论回复
17
lesheng002|  楼主 | 2021-8-8 15:38 | 只看该作者
sdlls 发表于 2021-8-1 22:30
串口中断和DMA中断一起使用行么

可以的,你怎么用可以自己选择,并没有严格要求

使用特权

评论回复
18
lesheng002|  楼主 | 2021-8-8 15:46 | 只看该作者
febgxu 发表于 2021-8-1 22:30
串口dma最多发送多少个

查看用户手册15章,可知有2个参数,一是数据块,二是传输次数,传输次数最大65535个,你说的最多发送多少个,那么如果一个块的数据为1字节,那么最大可以发送65535个数据

使用特权

评论回复
19
lesheng002|  楼主 | 2021-8-8 15:50 | 只看该作者
xiaoyaodz 发表于 2021-8-1 22:30
循环模式如何设置发送周期?

发送周期完全是你自己来控制,如果数据准备好了,发送完成立即启动下一次发送周期,如果你的数据没有准备好,可以延迟发送或者你可以用定时器设置定时发送

使用特权

评论回复
20
lesheng002|  楼主 | 2021-8-8 15:55 | 只看该作者
fentianyou 发表于 2021-8-1 22:30
串口dma缓冲区是先进先出吗

好像没有这个说法,DMA设置中,目标地址或源地址可以指定为固定,递增,递减,重载或者不连续跳转,因而没有固定规律,由你自己定义

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

93

帖子

0

粉丝