[技术问答]

HC32L170FAUA-TIM6关联串口超时问题

[复制链接]
1573|17
手机看帖
扫描二维码
随时随地手机跟帖
kktron|  楼主 | 2023-2-9 17:05 | 显示全部楼层 |阅读模式
本帖最后由 kktron 于 2023-2-13 07:56 编辑

这里看不懂   u16Period = 0xF000;u16GCMAValue = 0x0F00;  配置各种值
都会出现断包分包。

我理解是不是应该配置后,数据字节与字节 超过比如5ms, 就定时器中断?

现在我值了后发现  发的数据长比如300字节,收到200多字节就定时器超时了,
但设置的慢超时,又会不及时返回上位机,

170FAUA 也没看到空闲中断,这个DMA 配合TIM6高级定时器 什么原理呢?


void Time6_init(void)
{
    uint16_t                u16Period,u16GCMAValue;
    stc_adt_basecnt_cfg_t   stcAdtBaseCntCfg;
    stc_adt_aos_trig_cfg_t  stcAdtAosTrigCfg;

    DDL_ZERO_STRUCT(stcAdtBaseCntCfg);
    DDL_ZERO_STRUCT(stcAdtAosTrigCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, TRUE);  //ADT外设时钟使能

    stcAdtBaseCntCfg.enCntMode = AdtSawtoothMode;
    stcAdtBaseCntCfg.enCntDir = AdtCntUp;
    stcAdtBaseCntCfg.enCntClkDiv = AdtClkPClk0Div64;
    Adt_Init(M0P_ADTIM6, &stcAdtBaseCntCfg);                   //ADT载波、计数模式、时钟配置

    u16Period = 0xF000;
    Adt_SetPeriod(M0P_ADTIM6, u16Period);                      //周期设置

    u16GCMAValue = 0x0F00;
    Adt_SetCompareValue(M0P_ADTIM6, AdtCompareA, u16GCMAValue);//通用比较基准值寄存器A设置

    stcAdtAosTrigCfg.enAos0TrigSrc = AdtAosxTrigSelUart0Int;   //AOS0选择UART0中断
    stcAdtAosTrigCfg.enAos1TrigSrc = AdtAosxTrigSelUart0Int;   //AOS1选择UART0中断
    Adt_AosTrigCfg(&stcAdtAosTrigCfg);

                Adt_CfgHwClear(M0P_ADTIM6, AdtHwTrigAos0);                 //AOS0事件 清零TIM6
    Adt_CfgHwStart(M0P_ADTIM6, AdtHwTrigAos0);                 //AOS0事件触发TIM6启动
               
                Adt_CfgHwClear(M0P_ADTIM6, AdtHwTrigAos1);                 //AOS1事件 清零TIM6
    Adt_CfgHwStart(M0P_ADTIM6, AdtHwTrigAos1);                 //AOS1事件触发TIM6启动

    Adt_EnableHwStart(M0P_ADTIM6);                             //硬件启动使能
    Adt_EnableHwClear(M0P_ADTIM6);                             //硬件清零使能
    Adt_EnableHwStop(M0P_ADTIM6);                              //硬件停止使能

    Adt_ClearAllIrqFlag(M0P_ADTIM6);
    Adt_CfgIrq(M0P_ADTIM6, AdtCMAIrq, TRUE);                   //配置TIM6比较中断
    EnableNvic(ADTIM6_IRQn, IrqLevel0, TRUE);
}


/**
******************************************************************************
** \brief  Tim6_IRQHandler
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void Tim6_IRQHandler(void)
{
    volatile uint16_t len = 0;
    stc_adt_sw_sync_t stcAdtSwSync;
    stcAdtSwSync.bAdTim4 = TRUE;

    if(TRUE == Adt_GetIrqFlag(M0P_ADTIM6, AdtCMAIrq))
    {
        Adt_ClearIrqFlag(M0P_ADTIM6, AdtCMAIrq);
        Adt_ClearAllIrqFlag(M0P_ADTIM6);

        Adt_StopCount(M0P_ADTIM6);
        M0P_UART0->ICR_f.RCCF = 0;       //清中断状态位

        Dma_DisableChannel(DmaCh1);
        Dma_ClrStat(DmaCh1);             //清除通道1状态值
                        
        len = (M0P_DMAC->CONFA1)&0x0000FFFF;
        if(len == 0xFFFF) len = 1;
        else len = 0xFFFF - (M0P_DMAC->CONFA1)&0x0000FFFF - 1;
                          g_uart0_cfg.rx_len=len;
        Uart0_DMA_SendData(g_uart0_cfg.uart0RxBuf,g_uart0_cfg.rx_len);
        memset(&g_uart0_cfg.uart0RxBuf[0],0,sizeof(g_uart0_cfg.uart0RxBuf));

        Dma_SetBlockSize(DmaCh1,1);       //BC = 0 配置 DMA 通道待传输的数据块的大小为
        Dma_SetTransferCnt(DmaCh1,65535); //TC = 0 配置 DMA 通道待传输的数据块的大小为
        Dma_SetSourceAddress(DmaCh1,0x40000000);
        Dma_SetDestinationAddress(DmaCh1,(uint32_t)&g_uart0_cfg.uart0RxBuf[0]);
        Dma_EnableChannel(DmaCh1);
        Dma_ClrStat(DmaCh1);             //清除通道0状态值
    }
}
/**
******************************************************************************
** \brief  uart0_DmaCfg
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void uart0_DmaCfg(void)
{
    stc_dma_cfg_t stcDmaCfg;

    DDL_ZERO_STRUCT(stcDmaCfg);                                //初始化变量

    Sysctrl_SetPeripheralGate(SysctrlPeripheralDma,TRUE);      //使能DMAC外设时钟门控开关

    //rx dma配置
    stcDmaCfg.u32SrcAddress = 0x40000000;                      //接收数据寄存器地址,uart0的基地址
    stcDmaCfg.u32DstAddress = (uint32_t)&g_uart0_cfg.uart0RxBuf[0]; //接收缓冲
    stcDmaCfg.enSrcAddrReloadCtl = DmaMskSrcAddrReloadEnable;  //使能DMA源地址重载
    stcDmaCfg.enSrcBcTcReloadCtl = DmaMskBcTcReloadEnable;     //使能BC[3:0]和CONFA:TC[15:0]的重载功能
    stcDmaCfg.enDestAddrReloadCtl = DmaMskDstAddrReloadEnable; //使能DMA目的地址重载
    stcDmaCfg.enTransferMode = DmaMskContinuousTransfer;       //连续传输,DMAC传输完成时不清除CONFA:ENS位
    stcDmaCfg.enDstAddrMode = DmaMskDstAddrInc;                //目的地址自增
    stcDmaCfg.enSrcAddrMode = DmaMskSrcAddrFix;                //源地址固定
    stcDmaCfg.u16BlockSize = 1;                                //块传输个数,串口寄存器只能有一个数据 ,含义:数据块大小
    stcDmaCfg.u16TransferCnt = 65535;                           //块传输次数,此处设置为最大65535
    stcDmaCfg.enMode = DmaMskBlock;                            //块(Block)传输
    stcDmaCfg.enTransferWidth = DmaMsk8Bit;                    // 8 bit  字节传输
    stcDmaCfg.enRequestNum = DmaUart0RxTrig;                   //DMA硬件触发源位Uart0Rx
    stcDmaCfg.enPriority = DmaMskPriorityFix;                  //DMA 各通道优先级固定 (CH0>CH1)

    Dma_Enable();                                              //DMA模块使能
    Dma_InitChannel(DmaCh1, &stcDmaCfg);                       //DMA通道1初始化
    Dma_EnableChannel(DmaCh1);                                 //使能通道1
}

使用特权

评论回复
kktron|  楼主 | 2023-2-9 17:12 | 显示全部楼层
本帖最后由 kktron 于 2023-2-9 17:14 编辑

还有个问题就是    需要一般普通的  115200  8/none/1  模式,  不要什么多机,校验花,   是这样配置校验UartMskDataOrAddr , 模式1吗?

///<UART Init
    stcCfg.enRunMode        = UartMskMode1;          ///<模式1
    stcCfg.enStopBit        = UartMsk1bit;           ///<1bit停止位
    stcCfg.enMmdorCk        = UartMskDataOrAddr;     ///<无校验

    stcCfg.stcBaud.u32Baud  = 115200;                ///<波特率115200

    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;       ///<通道采样分频配置
    stcCfg.stcBaud.u32Pclk  = Sysctrl_GetPClkFreq(); ///<获得外设时钟(PCLK)频率值
    Uart_Init(M0P_UART0, &stcCfg);                   ///<串口初始化

使用特权

评论回复
yang377156216| | 2023-2-9 18:24 | 显示全部楼层
kktron 发表于 2023-2-9 17:12
还有个问题就是    需要一般普通的  115200  8/none/1  模式,  不要什么多机,校验花,   是这样配置校验U ...
///< HC32L170 串口0模块配置 N - 8 - 1
void App_UartCfg(void)
{
    stc_uart_cfg_t  stcCfg;
    stc_uart_multimode_t stcMulti;
    stc_uart_baud_t stcBaud;

    DDL_ZERO_STRUCT(stcCfg);
    DDL_ZERO_STRUCT(stcMulti);
    DDL_ZERO_STRUCT(stcBaud);
   
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);//UART0外设模块时钟使能
   
    stcCfg.enRunMode = UartMskMode1;     //模式1
    stcCfg.enStopBit = UartMsk1bit;      //1位停止位
    stcCfg.enMmdorCk = UartMskDataOrAddr;      //无校验
    stcCfg.stcBaud.u32Baud = 9600;       //波特率9600
    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;         //通道采样分频配置
    stcCfg.stcBaud.u32Pclk = Sysctrl_GetPClkFreq();    //获得外设时钟(PCLK)频率值
    Uart_Init(M0P_UART0, &stcCfg);       //串口初始化

    Uart_ClrStatus(M0P_UART0,UartRC);    //清接收请求
    Uart_ClrStatus(M0P_UART0,UartTC);    //清发送请求
    Uart_EnableIrq(M0P_UART0,UartRxIrq); //使能串口接收中断
    Uart_EnableIrq(M0P_UART0,UartTxIrq); //使能串口发送中断
}


使用特权

评论回复
yang377156216| | 2023-2-9 18:27 | 显示全部楼层
原理就是软件方式去模拟了硬件的串口接收超时功能,在ST 中也叫做串口空闲功能,超时时间的配置需要与当前波特率去匹配的,也就是一位所占的时间。

使用特权

评论回复
kktron|  楼主 | 2023-2-10 09:21 | 显示全部楼层

谢谢,配置串口那OK的

使用特权

评论回复
martinhu| | 2023-2-10 09:25 | 显示全部楼层
你可以看看这个例子,虽然是在L136上的,但是对于高级定时器的使用是一样的。
hc32l13x_ddl_Rev1.9.1_uart_RxInt_IdleInt.zip (538.52 KB)

使用特权

评论回复
评论
kktron 2023-2-10 09:30 回复TA
好的,谢谢 
kktron|  楼主 | 2023-2-10 09:28 | 显示全部楼层
yang377156216 发表于 2023-2-9 18:27
原理就是软件方式去模拟了硬件的串口接收超时功能,在ST 中也叫做串口空闲功能,超时时间的配置需要与当前 ...

像ST的普通定时器,定义1ms超时,每收到一字节超时清0定时器,比如配合115200bps
4ms 每byte进来,就空闲解析了

但这个TIM6 我试了各种值超时 都无法做到10~300字节各种不定长一包的  稳定超时空闲。
感觉TIM6是从开始接收到结束接收的溢出定时,所以不定长就各种分包,
不是字节&字节的定时超时,不知道理解对否

使用特权

评论回复
martinhu| | 2023-2-10 16:29 | 显示全部楼层
kktron 发表于 2023-2-10 09:28
像ST的普通定时器,定义1ms超时,每收到一字节超时清0定时器,比如配合115200bps
4ms 每byte进来,就空闲 ...

如果是F460或者F4A0的timer6,可能处理起来简单一点,如果是L17x,接收数据之后,需要(UART_RX)中断信号输出到timer6的硬件清零寄存器,把timer6的计数器清零。
而如果UART_Rx如果没有使能中断,那么要想办法在每次接收之后将RX中断标志清零,否则下次不会触发DMA或者触发timer6的硬件清零。
而F460或者F4A0,UART_RX可以是触发事件,可以不用每次必须清零标志。

使用特权

评论回复
kktron|  楼主 | 2023-2-10 17:56 | 显示全部楼层
martinhu 发表于 2023-2-10 16:29
如果是F460或者F4A0的timer6,可能处理起来简单一点,如果是L17x,接收数据之后,需要(UART_RX)中断信 ...

谢谢!
TIM6配合DMA_UART0, 在170FAUA下可以了,定义了TIM6 4ms超时,现在没问题了

新的问题又出现2个,
1.  PC  1ms间隔 压力测试发300字节数据发现溢出Hardfault进入了。
    stcDmaCfg.enMode =  DmaMskBlock;     
    stcDmaCfg.u16BlockSize = 0x01u;                  
    stcDmaCfg.u16TransferCnt = 800;
    stcDmaCfg.enTransferWidth = DmaMsk8Bit;     
    stcDmaCfg.u32DstAddress = (uint32_t)&g_uart0_obj.RxData[0];  //RXData开的1024字节

    我理解不是800字节DMA   怎么也不会超过1024 数组吧?
     
还有一个就是 收到数据后,我串口就非DMA的去返回,抓包看断开严重

   while(tx_len--)
    {
        Uart_SendDataPoll(M0P_UART0, *tx_pBuf);
        tx_pBuf++;
    }

Uart_SendDataPoll(M0P_UART0, *tx_pBuf);  为什么抓包看会断包的? 这是库函数,里面没动它。

en_result_t Uart_SendDataPoll(M0P_UART_TypeDef* UARTx, uint8_t u8Data)
{
    while(FALSE == Uart_GetStatus(UARTx,UartTxe))
    {}
    UARTx->SBUF_f.DATA = u8Data;
    while(FALSE == Uart_GetStatus(UARTx,UartTC))
    {}
    Uart_ClrStatus(UARTx,UartTC);      
    return Ok;
}
QQ图片20230210175057.png

使用特权

评论回复
kktron|  楼主 | 2023-2-10 18:00 | 显示全部楼层
本帖最后由 kktron 于 2023-2-10 18:09 编辑

这是测试170FAUA     TIM6配合DMA串口0,超时4ms  接收不定长的代码。
共享出来大家 看看指出还有什么问题

//myuart.h文件里如下#define  UART0_TX_MAX_LEN  128
#define  UART0_RX_MAX_LEN  (128+512)

void uart0_init(void);
void uart0_GpioCfg(void);
void uart0_BaseCfg(void);
void uart0_DmaCfg(void);
void uart0_Time6Cfg(uint16_t tPeriod);
void Uart0_SendData(uint8_t *tx_pBuf, uint16_t tx_len);

//uart0状态结构体
typedef struct
{
        __IO uint8_t  RxFinished;        
        __IO uint8_t  TxData[UART0_TX_MAX_LEN];
        __IO uint8_t  RxData[UART0_RX_MAX_LEN];
        __IO uint8_t  RxCopy[UART0_RX_MAX_LEN];
        __IO uint16_t TxCnt;
        __IO uint16_t RxCnt;
        __IO uint16_t RxNow;
}my_stc_uart_t;

extern my_stc_uart_t  g_uart0_obj;


//myuart.c文件里如下
my_stc_uart_t  g_uart0_obj;

/**
******************************************************************************
** \brief  uart0_init
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void uart0_init(void)
{
    uart0_GpioCfg();
    uart0_BaseCfg();
    uart0_DmaCfg();
    uart0_Time6Cfg(3000); //3000*(1/48M)*64分频 = 0.004s =4ms)  24MHz外接晶振倍频到最高48MHz
}
/**
******************************************************************************
** \brief  uart0_GpioCfg
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void uart0_GpioCfg(void)
{
    stc_gpio_cfg_t stcGpioCfg;

    DDL_ZERO_STRUCT(stcGpioCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //使能GPIO模块时钟

    ///<TX
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(GpioPortA, GpioPin9, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin9, GpioAf1); //配置PA09 端口为URART1_TX
    ///<RX
    stcGpioCfg.enDir = GpioDirIn;
    Gpio_Init(GpioPortA, GpioPin10, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin10, GpioAf1);//配置PA10 端口为URART1_RX
}
/**
******************************************************************************
** \brief  uart0_BaseCfg
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void uart0_BaseCfg(void)
{
    ///< 串口参数配置
    stc_uart_cfg_t    stcCfg;
          stc_uart_multimode_t stcMulti;
    stc_uart_baud_t   stcBaud;

    DDL_ZERO_STRUCT(stcCfg);
          DDL_ZERO_STRUCT(stcMulti);
    DDL_ZERO_STRUCT(stcBaud);
    ///< 开启外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0,TRUE);///<使能uart0模块时钟

    ///<UART Init
    stcCfg.enRunMode        = UartMskMode1;          ///<模式1
    stcCfg.enStopBit        = UartMsk1bit;           ///<1bit停止位
    stcCfg.enMmdorCk        = UartMskDataOrAddr;     ///<无校验

    stcCfg.stcBaud.u32Baud  = 115200;                ///<波特率115200,  @48MHz 下0.16%误差

    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;       ///<通道采样分频配置
    stcCfg.stcBaud.u32Pclk  = Sysctrl_GetPClkFreq(); ///<获得外设时钟(PCLK)频率值
    Uart_Init(M0P_UART0, &stcCfg);                   ///<串口初始化

    M0P_UART0->SCON_f.DMARXEN = 1; //DMA_RX使能允许

    ///<UART中断使能
    Uart_ClrStatus(M0P_UART0,UartRC);          ///<清接收请求
    Uart_ClrStatus(M0P_UART0,UartTC);          ///<清发送请求
                Uart_DisableIrq(M0P_UART0,UartTxIrq);      ///<禁止串口发送中断
    Uart_EnableIrq(M0P_UART0,UartRxIrq);       ///<使能串口接收中断
    Uart_EnableIrq(M0P_UART0,UartFEIrq);       ///<帧错误中断使能
    EnableNvic(UART0_2_IRQn, IrqLevel3, TRUE); ///<系统中断使能
}
/**
******************************************************************************
** \brief  uart0_DmaCfg
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void uart0_DmaCfg(void)
{
    stc_dma_cfg_t   stcDmaCfg;

    DDL_ZERO_STRUCT(stcDmaCfg);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralDma, TRUE);      //ADT外设时钟使能

    //DMA_Ch0_RX
    stcDmaCfg.enMode =  DmaMskBlock;                            //选择块传输
    stcDmaCfg.u16BlockSize = 0x01u;                             //块传输个数
    stcDmaCfg.u16TransferCnt = UART0_RX_MAX_LEN;                //Block模式,一次传输数据大小为 8(BlockSize),传输1次
    stcDmaCfg.enTransferWidth = DmaMsk8Bit;                     //传输数据的宽度,此处选择字(8Bit)宽度
    stcDmaCfg.enSrcAddrMode = DmaMskSrcAddrFix;                 //源地址固定
    stcDmaCfg.enDstAddrMode = DmaMskDstAddrInc;                 //目的地址自增
    stcDmaCfg.enDestAddrReloadCtl = DmaMskDstAddrReloadDisable; //禁止重新加载传输目的地址
    stcDmaCfg.enSrcAddrReloadCtl = DmaMskSrcAddrReloadDisable;  //禁止重新加载传输源地址
    stcDmaCfg.enSrcBcTcReloadCtl = DmaMskBcTcReloadDisable;     //禁止能重新加载BC/TC值
    stcDmaCfg.u32SrcAddress = (uint32_t)&(M0P_UART0->SBUF);     //指定传输源地址
    stcDmaCfg.u32DstAddress = (uint32_t)&g_uart0_obj.RxData[0]; //指定传输目的地址
    stcDmaCfg.enTransferMode = DmaMskContinuousTransfer;        //DMAC 在传输完成时清除 CONFA:ENS 位。
    stcDmaCfg.enRequestNum = DmaUart0RxTrig;                          //设置为Uart0Rx触发
    stcDmaCfg.enPriority = DmaMskPriorityFix;                   //DMA 各通道优先级固定 (CH0>CH1)
    Dma_InitChannel(DmaCh0,&stcDmaCfg);                                //初始化DMA通道0

    Dma_Enable();
    Dma_EnableChannel(DmaCh0);
    Uart_ClrStatus(M0P_UART0,UartRC);
}
/**
******************************************************************************
** \brief  uart0_Time6Cfg
** \param  tPeriod
** \retval 无
** \retval 无
******************************************************************************/
void uart0_Time6Cfg(uint16_t tPeriod)
{
    stc_adt_basecnt_cfg_t   stcAdtBaseCntCfg;
    stc_adt_aos_trig_cfg_t  stcAdtAosTrigCfg;

    DDL_ZERO_STRUCT(stcAdtBaseCntCfg);
    DDL_ZERO_STRUCT(stcAdtAosTrigCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, TRUE); //ADT外设时钟使能

    stcAdtBaseCntCfg.enCntMode = AdtSawtoothMode;
    stcAdtBaseCntCfg.enCntDir = AdtCntUp;
    stcAdtBaseCntCfg.enCntClkDiv = AdtClkPClk0Div64;
    Adt_Init(M0P_ADTIM6, &stcAdtBaseCntCfg);                 //ADT载波、计数模式、时钟配置

    Adt_SetPeriod(M0P_ADTIM6, tPeriod);                      //周期设置

    stcAdtAosTrigCfg.enAos0TrigSrc = AdtAosxTrigSelUart0Int; //AOS0选择UART0中断
    Adt_AosTrigCfg(&stcAdtAosTrigCfg);

    Adt_CfgHwStart(M0P_ADTIM6, AdtHwTrigAos0);               //AOS0事件触发TIM6启动
    Adt_CfgHwClear(M0P_ADTIM6, AdtHwTrigAos0);               //AOS0事件 清零TIM6

    Adt_EnableHwStart(M0P_ADTIM6);                           //硬件启动使能
    Adt_EnableHwClear(M0P_ADTIM6);                           //硬件清零使能

    Adt_ClearAllIrqFlag(M0P_ADTIM6);
    Adt_CfgIrq(M0P_ADTIM6, AdtOVFIrq, TRUE);                 //配置TIM6 上溢中断
    EnableNvic(ADTIM6_IRQn, IrqLevel0, TRUE);
}
/**
******************************************************************************
** \brief  UART0 数据发送
** \param  tx_pBuf,tx_len
** \retval 无
** \retval 无
******************************************************************************/
void Uart0_SendData(uint8_t *tx_pBuf, uint16_t tx_len)
{
    while(tx_len--)
    {
        Uart_SendDataPoll(M0P_UART0, *tx_pBuf);
        tx_pBuf++;
    }
}
/**
******************************************************************************
** \brief  Uart0_IRQHandler
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void Uart0_IRQHandler(void)
{
    if(Uart_GetStatus(M0P_UART0,  UartRC))
    {
        Uart_ClrStatus(M0P_UART0, UartRC);
    }
    if(Uart_GetStatus(M0P_UART0,  UartFE))
    {
        Uart_ClrStatus(M0P_UART0, UartFE);
    }
}

/**
******************************************************************************
** \brief  Tim6_IRQHandler
** \param  无
** \retval 无
** \retval 无
******************************************************************************/
void Tim6_IRQHandler(void)
{
    Adt_StopCount(M0P_ADTIM6);
    if(TRUE == Adt_GetIrqFlag(M0P_ADTIM6, AdtOVFIrq))
    {
        Dma_DisableChannel(DmaCh0);

        g_uart0_obj.RxNow = (UART0_RX_MAX_LEN - 1) - M0P_DMAC->CONFA0_f.TC;
        if(g_uart0_obj.RxNow>=UART0_RX_MAX_LEN)
        {
            g_uart0_obj.RxNow=0;
        }
        g_uart0_obj.RxCnt = g_uart0_obj.RxNow;

        for(uint16_t i = 0; i < g_uart0_obj.RxCnt; i++)
        {
            g_uart0_obj.RxCopy =g_uart0_obj.RxData;
        }

        Dma_SetTransferCnt(DmaCh0, UART0_RX_MAX_LEN);
        Dma_SetDestinationAddress(DmaCh0, (uint32_t)&g_uart0_obj.RxData[0]);
        Dma_EnableChannel(DmaCh0);
        Uart_ClrStatus(M0P_UART0,UartRC);

        g_uart0_obj.RxFinished = 1;
        Adt_ClearIrqFlag(M0P_ADTIM6, AdtOVFIrq);
    }
}

/******************************************************************************
* EOF (not truncated)
******************************************************************************/

//主函数.C里例如下
int main (void)
{
      ;略初始化
     while(1)
    {
       if(1 == g_uart0_obj.RxFinished)        {
            if(g_uart0_obj.RxCnt>0)
            {
                g_uart0_obj.TxCnt = g_uart0_obj.RxCnt;
                 g_uart0_obj.RxCnt = 0;
                Uart0_SendData((uint8_t *)&g_uart0_obj.RxCopy[0],g_uart0_obj.TxCnt);
            }
            g_uart0_obj.RxFinished = 0;
        }
   }
}





使用特权

评论回复
martinhu| | 2023-2-16 09:25 | 显示全部楼层
kktron 发表于 2023-2-10 17:56
谢谢!
TIM6配合DMA_UART0, 在170FAUA下可以了,定义了TIM6 4ms超时,现在没问题了

收到数据后,最好用中断返回,不要用查询的方式

使用特权

评论回复
zljiu| | 2023-3-4 14:59 | 显示全部楼层
感觉这个超时的时间配置的不要过长  太长了也没有用

使用特权

评论回复
tpgf| | 2023-3-4 15:25 | 显示全部楼层
kktron 发表于 2023-2-10 18:00
这是测试170FAUA     TIM6配合DMA串口0,超时4ms  接收不定长的代码。
共享出来大家 看看指出还有什么问题
...

用查询模式太浪费资源了  而且实时性也不太好

使用特权

评论回复
nawu| | 2023-3-4 15:41 | 显示全部楼层
martinhu 发表于 2023-2-16 09:25
收到数据后,最好用中断返回,不要用查询的方式

使用中断模式一定要注意中断函数的处理要干净

使用特权

评论回复
coshi| | 2023-3-4 16:07 | 显示全部楼层
kktron 发表于 2023-2-10 18:00
这是测试170FAUA     TIM6配合DMA串口0,超时4ms  接收不定长的代码。
共享出来大家 看看指出还有什么问题
...

数据量不大的话  感觉完全没有问题  主函数轮序里边还发送了数据

使用特权

评论回复
磨砂| | 2023-3-4 16:21 | 显示全部楼层
请问在楼主的代码注释中,有一个是ADT载波  这个是什么意思呢

使用特权

评论回复
晓伍| | 2023-3-4 16:32 | 显示全部楼层
磨砂 发表于 2023-3-4 16:21
请问在楼主的代码注释中,有一个是ADT载波  这个是什么意思呢

ADT和数据类型实质上是一个概念.其区别是: ADT的范畴更广,它不再局限于系统已定义并实现的数据类型,还包括用户自己定义的数据类型

使用特权

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

本版积分规则

9

主题

44

帖子

0

粉丝