本帖最后由 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的效率,提高系统的性能。
将代码贴出来,大家一起探讨,有不妥之处,欢迎指正。
|
共1人点赞
|
用户手册中,USART寄存器,明确说明,TXEIE位和TE位应同时写入1. 楼主验证过,调用这个函数,可以正常发送数据吗? // 启动发送数据,void usart_tx_start_sending(uint8_t *pbuff, uint16_t size)
DMA_GetTransferCnt这个函数在哪,有没有可以提供