发新帖我要提问
12
返回列表
打印
[技术讨论]

在基本的串口收发的阴沟里翻了船,请大神支支招

[复制链接]
楼主: linxi6414
手机看帖
扫描二维码
随时随地手机跟帖
21
将重要的变量定义时加上volatile试试

使用特权

评论回复
22
Unarty| | 2022-12-16 15:37 | 只看该作者
Unarty 发表于 2022-12-16 15:01
你的 RX_DATA_TIME 是什么时候置位的?? 在if 里面 把RX_DATA_TIME = 0xFFFF. 试试

刚刚看了一下, 有一种可能叫中断重入,也就是正在执行 RX_DATA_TIME---, 时进入了串口接收中断,虽然串口中对其赋值,但由于中断返回时正在执行的变量值已经压入了栈,所以其操作的目标值就不是串口内赋值的新值,而是进入前的值。 我对51不太熟悉了,不知道是不是可以嵌套中断,如果是可以把 定时器中断优先级加大,可心避免如上中断重入的可能可以试试。

使用特权

评论回复
23
linxi6414|  楼主 | 2022-12-17 15:56 | 只看该作者
yyy71cj 发表于 2022-12-16 14:59
看你的代码,你这翻船,不冤哪。
你对串口通信存在太多的误解。
1、既然是收发命令控制,反复开关串口中断 ...

针对你提出的1 2项该如何处理?
至于3项,留有足够的时间,应该不会冲突。

使用特权

评论回复
24
zlf1208| | 2022-12-18 15:14 | 只看该作者
本帖最后由 zlf1208 于 2022-12-18 15:16 编辑
linxi6414 发表于 2022-12-17 15:56
针对你提出的1 2项该如何处理?
至于3项,留有足够的时间,应该不会冲突。 ...

还是前面说的那句话:时序错误,不是中断没处理好就是通讯协议没处理好。

再给你二个忠告:
一、程序的可靠性是设计出来的不是调试出来的!错误的算法,即使调试结果看上去正常,程序也还是错误的!
二、深刻理解硬件的操作机制,特别是中断机制!用好中断没想象的那么容易。

要改变思维,从算法上确保流程是正确的,上手一个项目,首先设计算法,不是直接写代码,有时候甚至要画流程图,一张图胜过千言万语,并且易于理解,方便分析程序的逻辑关系。

使用特权

评论回复
25
linxi6414|  楼主 | 2022-12-18 20:20 | 只看该作者
现在将if(RX_DATA_TIME==0&&RX_EN_B==1)改为if(RxNum==7&&RX_EN_B==1),删除RX_DATA_TIME这个变量,跑了很多久,都是正常的,但是这样就面临另外一个问题,如果说我的串口数据不是固定的长度,就会出错。只是目前是固定的长度,目前不出问题,总感觉不稳定。

使用特权

评论回复
26
zchong| | 2022-12-19 14:06 | 只看该作者
别弄那么麻烦,被动接收的那端,就老老实实接收,然后根据帧格式进行解析,正确解析一帧后就返回数据。

使用特权

评论回复
27
binoo7| | 2022-12-19 14:42 | 只看该作者
linxi6414 发表于 2022-12-15 16:44
现在只是写了一个测试程序,用的是就是TTL串口,其它部分都没有工作,只是单独测试串口收发,都不正常, ...

这个其实很容易解决,你有官方例程吗?直接用官方例程测试一下就行了啊,如果官方例程没问题,那就是你处理的问题。然后再一步一步分析一下

使用特权

评论回复
28
linxi6414|  楼主 | 2022-12-19 16:09 | 只看该作者
zlf1208 发表于 2022-12-18 15:14
还是前面说的那句话:时序错误,不是中断没处理好就是通讯协议没处理好。

再给你二个忠告:

针对这个程序,到底该如何修改?真心请求指教。

使用特权

评论回复
29
makesoft| | 2022-12-19 20:05 | 只看该作者
半双工需要给总线留静默时间,比如说modbus协议就有帧头帧尾3.5字节时间的要求,自己定协议需要考虑这些问题。

使用特权

评论回复
30
linxi6414|  楼主 | 2022-12-23 10:25 | 只看该作者
yyy71cj 发表于 2022-12-21 14:01
还是年轻不懂事啊!老衲掐指一算,你的关键问题在第三项,去掉就好了!你竟然还自以为没事……[em:tsj30: ...

实际的程序是流程是这样的:
主站是固定的发送读,每隔50ms读一次从站,无论有没有收到数据,主站都是每隔50ms发送一次读从站的数据,从站是被动的,如果没有收到主站的数据,就一直处于静默的状态,从站收到正确的读(必须通过modbus校验)后马上返回数据至主站。如果说主站收到的数据有问题或者未收到数据,就要报错,现在把RX_DATA_TIME这个变量由原来在定时器中断中减改为加,把提前返回数据的问题解决了,可是又出现了一个新问题,会偶尔的出现数据错误,用逻辑分析仪监测了,时序是百分百没有问题的,但是数据是错误的,差了一位,从站明明返回的数据是14位,主站却只读到13位,少了一位,并且数据中有错误的,监测的结果如下:
从站实际返回:0xb3,0x61,0x64,0xe3,0x63,0xea,0x8e,0x44,0x1e,0x96,0x01,0x9c,0x43,0x75
主站实际收到:0xb3, 0x58,0xd6,0x63,0xea,0x8e,0x44,0x1e,0x96,0x01,0x9c,0x43,0x75

使用特权

评论回复
31
linxi6414|  楼主 | 2022-12-23 14:42 | 只看该作者
yyy71cj 发表于 2022-12-23 14:08
通信是485?232?422?

实际的主站和从站均采用485通讯模式,现在在主板端的单片机串口上直接上逻辑分析仪可以看到实际的收发数据。
分析了一下,估计是因为串口的中断级别太低造成的,因为485用的是串口4,这个串口的中断级别本来就低,再加上主板用了一个外部中断0(中断程序简单,关中断,功能标记,延迟标记,三行程序),定时器1中断,系统里所有的时间减和加都在此处进行,东西比较多,但是都是处理时间的加或减,没有复杂的计算。定时器0,只标识一个标志变量,到时间后就关中断,将一个标志变量置0。定时器2为串口提供波特率发生器。定时器3为外部脉冲输入检测,用于计数,由于是低频检测(100hz),没有使能中断,只是通过固定的时间去读缓存值,读完清零。

使用特权

评论回复
32
linxi6414|  楼主 | 2022-12-23 15:43 | 只看该作者
主要是中断1中处理的事情比较多,全部的程序如下:void Timer0_Int() interrupt 3  //定时器1中断服务函数
void Timer0_Int() interrupt 3  //定时器1中断服务函数
{   
    if(MOT_LOW==0&&Auto_Manual_B==1&&SYS_Error_B==0)
    {
        if(Lower_Knives_Time>0)
        {
            Lower_Knives_Time--;
            if(Lower_Knives_Time<1||DOW_Limit==1)
            {
                Lower_Knives_Time=0;
                if(DOW_Limit==1)
                {
                    LOW_S_EN=1;
                }               
                MOT_LOW=1;
                MOT_HIG=1;
                if(Pump_Delay>0)
                {
                    Pump_Delay_Tim=Pump_Delay*100;
                }
                else
                {
                    MOT_Pump=1;
                    READ_SEC_ADC_TIM=10;
                }                                
            }
        }
    }
    if(CC1101_RX_TIM>0)//CC1101接收被中断后的延迟
    {
        CC1101_RX_TIM--;
    }
    if(SYS_READ_Elec>0)//系统ADC采样时间间隔
    {
        SYS_READ_Elec--;
    }
    if(READ_SYS_ADC_TIM>0)//主电机电机ADC采样时间间隔
    {
        READ_SYS_ADC_TIM--;
    }
    if(READ_SEC_ADC_TIM>0)//行程电机ADC采样时间间隔
    {
        READ_SEC_ADC_TIM--;
    }

    if(SYS_TR_MAX_TIM>0)//485通讯间隔
    {
        SYS_TR_MAX_TIM--;
    }
    if(RX_EN_B==1&&RX_DATA_TIME<3)//485接收到信号后延迟,用于解码
    {
        RX_DATA_TIME++;
        if(RX_DATA_TIME>=2)
        {
            IIC_SDA=1;
        }        
    }
    if(READ_TMP_TIM>0)//读取温度时间间隔
    {
        READ_TMP_TIM--;
    }
    if(SYS_MOT_STAR_TIM>0)//主电机启动时长
    {
        SYS_MOT_STAR_TIM--;
    }               
    if(CC1101_RST_TIM>0)
    {
        CC1101_RST_TIM--;
    }
    if(Pump_Delay_Tim>0&&MOT_Pump==0)//油泵延迟关闭时间
    {
        Pump_Delay_Tim--;
        if(Pump_Delay_Tim==0&&MOT_Pump==0)
        {
            MOT_Pump=1;
            READ_SEC_ADC_TIM=10;
        }
    }                  
    if(SYS_DOW_POW_TIM>0&&Reclosing_B==0&&Reclosing_EN==1)//检测电网是否中断
    {
        SYS_DOW_POW_TIM--;
        if(SYS_DOW_POW_TIM==0)
        {
            T4T3M=0x00;
            SYS_DOW_POW_TIM=3;
            if(T3L<2)
            {
                if(Reclosing_ERR_B)
                {
                    Reclosing_ERR_B=0;
                    Reclosing_B=10;
                    Auto_Manual_B=0;
                    MOT_Star=1;MOT_Run=1;
                    MOT_HIG=1;MOT_LOW=1;MOT_Pump=1;MOT_Left=1;MOT_Right=1;MOT_Front=1;MOT_After=1;
                }
                else
                {
                    T3L=0x00;
                    T3H=0x00;
                    T4T3M=0x0e;
                    Reclosing_ERR_B=1;               
                }
            }
            else
            {
                T3L=0x00;
                T3H=0x00;
                T4T3M=0x0e;
                Reclosing_ERR_B=0;            
            }
        }
    }
}

使用特权

评论回复
33
天意无罪| | 2022-12-23 17:18 | 只看该作者
问题:如果你的小板回复数据是判断接收的数据是否完整和正确,那肯定不会出现你说的上述情况。
如果出现,那你最好是仿真调试一下,另外看一下主板接收到的小板非正常情况下回复的数据是什么?这种现象有没有时间规律?

使用特权

评论回复
34
linxi6414|  楼主 | 2022-12-23 17:37 | 只看该作者
天意无罪 发表于 2022-12-23 17:18
问题:如果你的小板回复数据是判断接收的数据是否完整和正确,那肯定不会出现你说的上述情况。
如果出现, ...

修改了延迟变量之后,不会再提前返回数据了,从站一切正常了,但是主站却出现了数据错误的问题,估计是由于串口的中断优先级过低造成的,监测了几个小时,算下来,平均每小时会出现15至20次的数据错误,每秒通讯20次,整体算下来,这个错误率还是很低的,目前只能这样算了,反正程序中有MODBUS校验处理,错误的数据只能丢弃不要,不然改硬件太麻烦了。

使用特权

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

本版积分规则