STC32G128支持DMA(批量数据传输)的传输方式:今天使用AIcube 软件实现数据的接收和发送功能。
每种DMA对XRAM的读写操作都可设置4级访问优先级,硬件自动进行XRAM总线的访问仲裁,不会影响CPU的XRAM的访问。相同优先级下,不同DMA对XRAM的访问顺序如下:M2M DMA,ADC DMA, SPI DMA, URIR DMA, URIT DMA, UR2R DMA, UR2T DMA, UR3R DMA,UR3T DMA, UR4R DMA, UR4T DMA, LCM DMA, I2CR DMA, I2CT DMA, I2SR DMA, I2ST DMA
一:软件配置如下:

使用注意事项如下所示:
数据存储位置:DMA缓冲区必须定义在xdata区域,否则无法正常工作。
寄存器位数差异:读取接收长度寄存器 DMA_UR1R_DONE 时,它是个16位寄存器。用printf打印时,记得用 %hu 或强制类型转换,别把它当8位用。
中断优先级:如果数据量很大,建议适当提高串口DMA中断的优先级,防止被其他中断长时间打断导致数据覆盖。
定时器时长:超时定时器的时长要根据你的波特率调整。比如115200bps下,传输1个字节约87us,设置3-5ms是比较稳妥的选择。
二:代码如下所示:
2.1 初始化串口4
void UART4_Init(void)
{
UART4_SwitchP5253(); //设置串口数据端口: RxD4 (P5.2), TxD4 (P5.3)
UART4_Timer4BRT(); //选择定时器4作为串口4波特率发生器
UART4_EnableRx(); //使能串口4接收数据
UART4_Mode0(); //设置串口4为模式0 (8位数据可变波特率)
DMA_UART4_SetTxAmount(15); //设置串口DMA发送总字节数
DMA_UART4_SetTxAddress(pu8UR4DMATxBuffer); //设置串口DMA发送缓冲区地址
DMA_UART4_ClearTxFlag(); //清除串口发送DMA中断标志
DMA_UART4_SetTxBusPriority(2); //设置总线访问为较高优先级
DMA_UART4_SetTxIntPriority(0); //设置中断为最低优先级
DMA_UART4_EnableTxInt(); //使能串口4DMA发送中断
DMA_UART4_EnableTx(); //使能串口4DMA发送功能
// DMA_UART4_TriggerTx(); //触发串口4DMA发送
DMA_UART4_SetRxAmount(15); //设置串口DMA接收总字节数
DMA_UART4_SetRxAddress(pu8UR4DMARxBuffer); //设置串口DMA接收缓冲区地址
DMA_UART4_ClearFIFO(); //清空串口DMA接收FIFO缓冲区
DMA_UART4_ClearRxFlag(); //清除串口接收DMA中断标志
DMA_UART4_SetRxBusPriority(2); //设置总线访问为较高优先级
DMA_UART4_SetRxIntPriority(0); //设置中断为最低优先级
DMA_UART4_EnableRxInt(); //使能串口4DMA接收中断
DMA_UART4_EnableRx(); //使能串口4DMA接收功能
// DMA_UART4_TriggerRx(); //触发串口4DMA接收
//<<AICUBE_USER_UART4_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_UART4_INITIAL_END>>
}2.2 串口4的DMA 发送函数:
void UART4_DMA_Transmit(u8 *pData, u16 Size)
{
if(Size == 0) return;
Size -= 1;
DMA_UR4T_AMTH = (u8)(Size >> 8); //设置传输总字节数(低8位):n+1
DMA_UR4T_AMT = (u8)Size; //设置传输总字节数(高8位):n+1
DMA_UR4T_TXAH = (u8)((u16)pData >> 8);
DMA_UR4T_TXAL = (u8)((u16)pData);
DMA_UR4T_CR = 0xc0; //bit7 1:使能 UART4_DMA, bit6 1:开始 UART1_DMA 自动发送
}2.3 串口4的DMA接收函数:
void UART4_DMA_Receive(u8 *pData, u16 Size)
{
if(Size == 0) return;
Size -= 1;
DMA_UR4R_AMTH = (u8)(Size >> 8); //设置传输总字节数(低8位):n+1
DMA_UR4R_AMT = (u8)Size; //设置传输总字节数(高8位):n+1
DMA_UR4R_RXAH = (u8)((u16)pData >> 8);
DMA_UR4R_RXAL = (u8)((u16)pData);
DMA_UR4R_CR = 0xa1; //bit7 1:使能 UART4_DMA, bit5 1:开始 UART4_DMA 自动接收, bit0 1:清除 FIFO
}2.4 串口4的DMA的中断中处理函数:
void UART4_DMA_Interrupt(void) interrupt 13
{
if (DMA_UR4T_STA & 0x01) //发送完成
{
DMA_UR4T_STA &= ~0x01;
DmaTx4Flag = 1;
}
if (DMA_UR4T_STA & 0x04) //数据覆盖
{
DMA_UR4T_STA &= ~0x04;
}
if (DMA_UR4R_STA & 0x01) //接收完成
{
DMA_UR4R_STA &= ~0x01;
DmaRx4Flag = 1;
}
if (DMA_UR4R_STA & 0x02) //数据丢弃
{
DMA_UR4R_STA &= ~0x02;
}
}三:主函数如下所示:
if(B_1ms) //1ms到
{
B_1ms = 0;
if(RX4_TimeOut > 0) //超时计数
{
if(--RX4_TimeOut == 0)
{
//关闭接收DMA,下次接收的数据重新存放在起始地址位置,否则下次接收数据继续往后面存放。
DMA_UR4R_CR = 0x00; //bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
printf("\r\nUART4 Timeout!\r\n"); //UART4发送一个字符串
memcpy(TemBuffer,DmaBuffer,RX4_Cnt);
UART4_DMA_Transmit(TemBuffer,RX4_Cnt); //设置DMA发送缓冲区,数据长度,并启动发送
RX4_Cnt = 0;
DmaTx4Flag = 0;
DmaRx4Flag = 0;
UART4_DMA_Receive(DmaBuffer,256); //设置DMA接收缓冲区,数据长度,并启动接收
}
}
}
我要赚赏金
