找回密码
 立即注册
查看: 71|回复: 6

串口接收超时触发不正确,已解决,STC8H8K64U芯片不支持接收超时中断功能

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-10-14 11:37:02

2

主题

3

回帖

82

积分

注册会员

积分
82
发表于 前天 11:43 | 显示全部楼层 |阅读模式
使用串口1,进行DMA发送和接收,想在接收时,使用串口的接收超时中断来接收不定长的数据,

void UART1_Init(void)
{
#ifdef BAUDRATE
#undef BAUDRATE
#endif
#define BAUDRATE                (115200)
#define T2_RELOAD               (65536 - (SYSCLK / BAUDRATE + 2) / 4)

    UART1_SwitchP3637();                //设置串口数据端口: RxD (P3.6), TxD (P3.7)

    UART1_Timer2BRT();                  //选择定时器2作为串口1波特率发生器
    TIMER2_TimerMode();                 //设置定时器2为定时模式
    TIMER2_1TMode();                    //设置定时器2为1T模式
    TIMER2_SetPrescale(0);              //设置定时器2的8位预分频
    TIMER2_SetReload16(T2_RELOAD);      //设置定时器2的16位重载值
    TIMER2_Run();                       //定时器2开始运行

    UART1_EnableRx();                   //使能串口1接收数据
    UART1_Mode1();                      //设置串口1为模式1 (8位数据可变波特率)
    UART1_SetIntPriority(0);            //设置中断为最低优先级
    UART1_EnableInt();                  //使能串口1中断

    DMA_UART1_SetTxAmount(99);          //设置串口DMA发送总字节数
    DMA_UART1_SetTxAddress(pu8UR1DMATxBuffer); //设置串口DMA发送缓冲区地址
    DMA_UART1_ClearTxFlag();            //清除串口发送DMA中断标志
    DMA_UART1_SetTxBusPriority(0);      //设置总线访问为最低优先级
    DMA_UART1_SetTxIntPriority(0);      //设置中断为最低优先级
    DMA_UART1_EnableTxInt();            //使能串口1DMA发送中断
    DMA_UART1_EnableTx();               //使能串口1DMA发送功能
//  DMA_UART1_TriggerTx();              //触发串口1DMA发送

    DMA_UART1_SetRxAmount(99);          //设置串口DMA接收总字节数
    DMA_UART1_SetRxAddress(pu8UR1DMARxBuffer); //设置串口DMA接收缓冲区地址
    DMA_UART1_ClearFIFO();              //清空串口DMA接收FIFO缓冲区
    DMA_UART1_ClearRxFlag();            //清除串口接收DMA中断标志
    DMA_UART1_SetRxBusPriority(0);      //设置总线访问为最低优先级
    DMA_UART1_SetRxIntPriority(0);      //设置中断为最低优先级
    DMA_UART1_EnableRxInt();            //使能串口1DMA接收中断
    DMA_UART1_EnableRx();               //使能串口1DMA接收功能
//  DMA_UART1_TriggerRx();              //触发串口1DMA接收

    //<<AICUBE_USER_UART1_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
        DMA_UART1_TriggerRx();              //触发串口1DMA接收
    //<<AICUBE_USER_UART1_INITIAL_END>>
}


串口超时设置,说实话不知道这个超时时长怎么去设置,在论坛上看的别人的

UR1TOCR = 0xC0; //开启超时中断,SCALE(bit5) = 0:使用波特率bit时钟周期; 1:使用系统时钟周期
    UR1TOTL = 0x80; //设置超时时间:128个位时钟周期=(1000000/115200)*128us
    UR1TOTH = 0x00;
    UR1TOTE = 0x00; //写完TE超时时间才会生效




////////////////////////////////////////
// 串口1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART1_ISR(void) interrupt UART1_VECTOR
{
    //<<AICUBE_USER_UART1_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码  
    if (UART1_CheckTxFlag())            //判断串口发送中断
    {
        UART1_ClearTxFlag();            //清除串口发送中断标志
    }

    if (UART1_CheckRxFlag())            //判断串口接收中断
    {
        UART1_ClearRxFlag();            //清除串口接收中断标志
                UART1_EnableTimeout();                        //使能串口接收超时中断功能控制位
    }
        
        if (UART1_CheckTimeoutFlag())       //判断串口超时中断请求标志位
    {
        UART1_ClearTimeoutFlag();       //清除串口超时中断请求标志位
                UART1_DisableTimeout();                        //清除串口接收超时中断功能控制位
                Usart1.RecvFlag=1;
                Usart1.RecvCnt=DMA_UART1_ReadRxDone();
                DMA_UART1_DisableRx();                        //清零DMA_UART1_ReadRxDone
                DMA_UART1_EnableRx();
                DMA_UART1_TriggerRx();                        //触发串口1DMA接收
    }
    //<<AICUBE_USER_UART1_ISR_CODE1_END>>
}


现在的现象是每次超时中断后,Usart1.RecvCnt=DMA_UART1_ReadRxDone();通过DMA_UART1_ReadRxDone()读取的DMA已经接收的数据为1或是2,不知道是哪一块出了问题,求教
回复

使用道具 举报 送花

3

主题

1880

回帖

608

积分

等待验证会员

积分
608
发表于 前天 11:48 | 显示全部楼层
关于串口接收超时触发不正确的问题分析与解决方案

一、问题现象描述
在使用串口1进行DMA收发操作时,采用接收超时中断接收不定长数据包时出现异常。具体表现为:
1. 超时中断触发时机不准确
2. 数据接收完整性无法保证
3. 存在数据包截断或合并现象

二、硬件配置分析
当前配置使用定时器2作为波特率发生器,工作在模式1(8位异步串行通信模式),DMA传输配置未在代码片段中体现。关键配置参数:
波特率:115200 bps
定时器模式:1T模式
重载值计算:T2RELOAD = 65536 - (SYSCLK / BAUDRATE + 2) / 4

三、超时机制实现要点
1. 硬件超时中断触发条件
串口控制器检测到接收线上空闲时间超过设定阈值
通常以帧时间为基准(1帧=10bit)
触发后产生UARTxRTOF标志位

2. 软件配置关键点
超时计数器加载值设置(RTOR寄存器)
超时中断使能控制(IERx.RTIE)
FIFO接收触发阈值配置(FCRx.RFTL)

四、典型问题排查方向
1. 时钟配置验证
SYSCLK参数是否正确定义
定时器2分频系数是否匹配系统时钟
实际波特率误差是否超过允许范围(建议

[本文内容由国芯人工智能辅助生成,仅供参考]
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:532
  • 最近打卡:2025-10-15 08:56:42
已绑定手机

47

主题

2274

回帖

7995

积分

论坛元老

积分
7995
发表于 前天 12:09 | 显示全部楼层
可能只是读取 DMA_UR1R_DONE 的时间不对,可参考这个帖子介绍:

关于寄存器DMA_UR1R_DONE的应用问题
https://www.stcaimcu.com/thread-4675-1-1.html
(出处: 国芯人工智能技术交流网站)
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-10-14 11:37:02

2

主题

3

回帖

82

积分

注册会员

积分
82
发表于 前天 14:03 | 显示全部楼层
芯片使用的是STC8H8K64U,串口波特率配置等使用的是AiCube软件生成

////////////////////////////////////////
// 串口1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART1_Init(void)
{
#ifdef BAUDRATE
#undef BAUDRATE
#endif
#define BAUDRATE                (115200)
#define T2_RELOAD               (65536 - (SYSCLK / BAUDRATE + 2) / 4)

    UART1_SwitchP3637();                //设置串口数据端口: RxD (P3.6), TxD (P3.7)

    UART1_Timer2BRT();                  //选择定时器2作为串口1波特率发生器
    TIMER2_TimerMode();                 //设置定时器2为定时模式
    TIMER2_1TMode();                    //设置定时器2为1T模式
    TIMER2_SetPrescale(0);              //设置定时器2的8位预分频
    TIMER2_SetReload16(T2_RELOAD);      //设置定时器2的16位重载值
    TIMER2_Run();                       //定时器2开始运行

    UART1_EnableRx();                   //使能串口1接收数据
    UART1_Mode1();                      //设置串口1为模式1 (8位数据可变波特率)
    UART1_SetIntPriority(0);            //设置中断为最低优先级
    UART1_EnableInt();                  //使能串口1中断

    DMA_UART1_SetTxAmount(99);          //设置串口DMA发送总字节数
    DMA_UART1_SetTxAddress(pu8UR1DMATxBuffer); //设置串口DMA发送缓冲区地址
    DMA_UART1_ClearTxFlag();            //清除串口发送DMA中断标志
    DMA_UART1_SetTxBusPriority(0);      //设置总线访问为最低优先级
    DMA_UART1_SetTxIntPriority(0);      //设置中断为最低优先级
    DMA_UART1_EnableTxInt();            //使能串口1DMA发送中断
    DMA_UART1_EnableTx();               //使能串口1DMA发送功能
//  DMA_UART1_TriggerTx();              //触发串口1DMA发送

    DMA_UART1_SetRxAmount(99);          //设置串口DMA接收总字节数
    DMA_UART1_SetRxAddress(pu8UR1DMARxBuffer); //设置串口DMA接收缓冲区地址
    DMA_UART1_ClearFIFO();              //清空串口DMA接收FIFO缓冲区
    DMA_UART1_ClearRxFlag();            //清除串口接收DMA中断标志
    DMA_UART1_SetRxBusPriority(0);      //设置总线访问为最低优先级
    DMA_UART1_SetRxIntPriority(0);      //设置中断为最低优先级
    DMA_UART1_EnableRxInt();            //使能串口1DMA接收中断
    DMA_UART1_EnableRx();               //使能串口1DMA接收功能
//  DMA_UART1_TriggerRx();              //触发串口1DMA接收

    //<<AICUBE_USER_UART1_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
        DMA_UART1_TriggerRx();              //触发串口1DMA接收
    //<<AICUBE_USER_UART1_INITIAL_END>>
}

现在其实我怀疑是串口超时这一块没有配置好,另外就是想要1个字节的超时,不知道怎么去配置,将指教
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:683
  • 最近打卡:2025-10-15 08:16:23
已绑定手机

54

主题

1917

回帖

4071

积分

论坛元老

积分
4071
发表于 前天 14:18 | 显示全部楼层
plj*** 发表于 2025-10-14 14:03
芯片使用的是STC8H8K64U,串口波特率配置等使用的是AiCube软件生成

//////////////////////////////////// ...

STC8H8K64U没有硬件超时吧
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:539
  • 最近打卡:2025-10-15 21:55:03

33

主题

2600

回帖

5727

积分

论坛元老

积分
5727
发表于 前天 15:47 | 显示全部楼层
plj*** 发表于 2025-10-14 14:03
芯片使用的是STC8H8K64U,串口波特率配置等使用的是AiCube软件生成

//////////////////////////////////// ...

这个片子没有超时中断啊,,看过手册了么?
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-10-14 11:37:02

2

主题

3

回帖

82

积分

注册会员

积分
82
发表于 前天 18:16 | 显示全部楼层
刚查了,STC8H8K64U是没有接收超时中断功能,谢谢大家
截图202510141815513686.jpg
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-16 07:46 , Processed in 0.131665 second(s), 87 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表