这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 【AIcubeV1.01L】使用AIcube配置串口1的DMA的功能,结合定时器

共1条 1/1 1 跳转至

【AIcubeV1.01L】使用AIcube配置串口1的DMA的功能,结合定时器实现空闲中断

高工
2026-05-05 20:20:25     打赏

在开发单片机时候,经常会用到数据交互的知识,采用中断的方式有些浪费CPU的资源了,这里看到STC也推出的串口的DMA功能,这里我使用串口结合定时器做超时判断,从而实现空闲中断的效果。

STC32G128 的串口1是一个非常强大且灵活的通信接口,它不仅支持最常用的异步串行通信(UART),还能配置为SPI、LIN、红外通信甚至智能卡模式

一:AI cube的配置如下所示:

07-1 串口1的DMA配置.png

这里就是打开串口1的DMA发送和接收功能,同时配置DMA发送和接收的数组、优先级别;

不过这里DMA的发送和接收的数组支持1-65535,可见STC的DMA功能很强大。二:软件代码2.1 DMA发送函数:

void UART1_DMA_Transmit(u8 *pData, u16 Size)
{
  if(Size == 0) return;
    Size -= 1;
    DMA_UR1T_CFG = 0x80;                //bit7 1:Enable Interrupt
    DMA_UR1T_STA = 0x00;
    DMA_UR1T_AMTH = (u8)(Size >> 8);    //设置传输总字节数(低8位):n+1
    DMA_UR1T_AMT  = (u8) Size;            //设置传输总字节数(高8位):n+1
    DMA_UR1T_TXAH = (u8)((u16)pData >> 8);
    DMA_UR1T_TXAL = (u8)((u16)pData);
    DMA_UR1T_CR = 0xc0;     //bit7 1:使能 UART1_DMA, bit6 1:开始 UART1_DMA 自动发送
}
2.2 DMA接收函数:

void UART1_DMA_Receive(u8 *pData, u16 Size)
{
  if(Size == 0) return;
    Size -= 1;
    DMA_UR1R_CFG = 0x80;                //bit7 1:Enable Interrupt
    DMA_UR1R_STA = 0x00;
    DMA_UR1R_AMTH = (u8)(Size >> 8);    //设置传输总字节数(低8位):n+1
    DMA_UR1R_AMT = (u8)Size;            //设置传输总字节数(高8位):n+1
    DMA_UR1R_RXAH = (u8)((u16)pData >> 8);
    DMA_UR1R_RXAL = (u8)((u16)pData);
    DMA_UR1R_CR = 0xa1;     //bit7 1:使能 UART4_DMA, bit5 1:开始 UART4_DMA 自动接收, bit0 1:清除 FIFO
    }
2.3 DMA数据回传功能函数:

void ReturnUsart1Data(u8 *pData, u16 Size)
{
    DMA_UR1R_CR = 0x00;                        //bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
    memcpy(SendBuffer1,pData,Size);
    UART1_DMA_Transmit(SendBuffer1,Size);  //设置DMA发送缓冲区,数据长度,并启动发送
    RX1_Cnt = 0;
    UART1_DMA_Receive(pu8UR1DMARxBuffer,256);  //设置DMA接收缓冲区,数据长度,并启动接收
}

采用指针的方式,将要回传的数据,放到DMA的发送函数里就可以了。

2.4 超时判断,触发函数如下所示:

        if(RX1_COUNT>0) 
            RX1_COUNT-- ;                                
        if((RX1_COUNT ==0)&& (RX1_Cnt!=0))
        {                                                                                
//        SendMessage(MW_DMAUSART1,RX1_Cnt,0);        
                b_send1 =1 ;
        }
2.5 添加到消息任务中或者是放到定时器中断中处理:

2.5.1 放到消息队列中:

case MW_DMAUSART1:                
                     ReturnUsart1Data(pu8UR1DMARxBuffer,RX1_Cnt);                                                                 
   break;

这种方式存在一个问题就是,程序运行一段时间后,DMA发送函数卡死的现象,一直向外界吐数据。不稳定;

2.5.2 放到定时器处理中:

        case 20:   
                 if(b_send1  == 1)
                    {
                       ReturnUsart1Data(pu8UR1DMARxBuffer,RX1_Cnt); 
                       b_send1 = 0 ;
                     }
这种处理方法,很稳定,估计是放到消息队列中,DMA的发送功能收到了影响。三:测试效果如下:

07-2 串口1的实物图.png

以300MS的时间间隔,发送不同数据长度的字符,运行了几十万的字节,没有发生数据丢失的情况。

四:调试过程中遇到问题、心得

4.1 开始的时候DMA配置错误,导致每次发送时候,会导致程序卡死。

4.2 采用创建数据回传消息任务时候,程序在运行一段时间后,就会发现DMA的发送函数“假死”的现象,串口1的DMA一直向外界发送数据,采用增加超时判断时间的方法,情况也是一样的,不太明白为什么会有这种情况。

4.3  使用在定时器中执行串口数据回传的功能还是很稳定的,也没有发现数据丢失的情况,推荐使用该处理方式。

4.4 DMA(直接存储器访问):当项目需要频繁、大量收发数据时,配合DMA可以解放CPU。你只需配置好缓冲区,DMA会自动完成数据搬运,非常适合用于高速数据采集或通信。结合定时器,也可以实现“空闲中断”的方式,不过需要设置好,超时判断的时间间隔。

4.5 USB-CDC虚拟串口:STC32G12K128支持通过USB直接虚拟成一个串口。就不需要USB转TTL工具,直接用Type-C数据线连接电脑就能进行串口通信,调试和产品升级都非常方便



关键词: AIcubeV1.01L     定时器     空闲     中断    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]