youkebing 发表于 2022-1-3 20:25:42

求助:这样的代码是否有问题(STC15W408AS)

本帖最后由 youkebing 于 2022-1-3 20:29 编辑

一个小项目上用到了STC单片机,当时现场一个板子出现了一个问题(运行了大约1个月,死机出现两次),
我不知道我这样的代码是否有问题!代码中不涉及中断,中断是关闭的,是简单的时序控制,其他的几个板子运行都正常,搞得有点晕。
#include "config.h"
//PCA定时器
static u16t time_cnt(void) {
    u8t h;
    u8t l;
    u16t cc;

    while (1) {
      h = CH;
      l = CL;
      if (h == CH) {
            cc = h;
            cc <<= 8;
            cc = cc | l;
            return cc;
      }
    }
}
void time_init(void) {
    //CR = 0;
    CMOD = 0;
    CR = 1;
}

void time_start(u16t *c) {
    *c = time_cnt();
}
u8t time_expired(u16t u, u16t dly) {
    u = time_cnt() - u;
    if (u > dly) {
      return 1;
    }
    return 0;
}

//static u8t _cnt10ms;
void time_poll(void) {
    static u16t dly;
    static u8t cnt;

    //0.1s
    if (time_expired(dly, 10*1000) == 0) {
      return;
    }
    time_start(&dly);
    cnt++;
    if (cnt <= 10) {
      return;
    }
    cnt = 0;

    alarm_poll();
}

youkebing 发表于 2022-1-3 20:32:31

现场的表现形式是alarm_poll()执行不到,我开了看门狗的,死机应该能复位的啊

wye11083 发表于 2022-1-3 22:02:56

定时器停了?可能是受干扰了吧。

youkebing 发表于 2022-1-3 22:35:43

wye11083 发表于 2022-1-3 22:02
定时器停了?可能是受干扰了吧。

如果真的是定时器干扰停了,一切问题倒都可以解释了

youkebing 发表于 2022-1-3 22:36:31

wye11083 发表于 2022-1-3 22:02
定时器停了?可能是受干扰了吧。

但是其他的都没有问题,就这一块有问题,感觉好奇怪

wye11083 发表于 2022-1-3 22:39:28

youkebing 发表于 2022-1-3 22:36
但是其他的都没有问题,就这一块有问题,感觉好奇怪

那你仔细查查是不是其它地方有重置定时器的地方?

youkebing 发表于 2022-1-3 23:02:41

wye11083 发表于 2022-1-3 22:39
那你仔细查查是不是其它地方有重置定时器的地方?

没有,这个小产品,代码非常少,这几天,反复看了几十遍了,没看到明显的问题,猜测几个可能:1,这片单片机问题,2,PCA被干扰,停止了。

wye11083 发表于 2022-1-3 23:29:48

youkebing 发表于 2022-1-3 23:02
没有,这个小产品,代码非常少,这几天,反复看了几十遍了,没看到明显的问题,猜测几个可能:1,这片单 ...

所以你加个最简单的状态检测好了。

youkebing 发表于 2022-1-3 23:35:55

wye11083 发表于 2022-1-3 23:29
所以你加个最简单的状态检测好了。

其实我想知道,有没有可能PCA的启动位被干扰到?我这几天已经改了程序,主循环检测相关配置寄存器,但我不确定是否是定时器被干扰,还是单片机真正死机了。主要想重现故障实在太难了。

hjjnt2008 发表于 2022-1-4 08:15:37

用串口打印流程和状态信息,一般比较容易找到问题

youkebing 发表于 2022-1-4 09:03:03

hjjnt2008 发表于 2022-1-4 08:15
用串口打印流程和状态信息,一般比较容易找到问题

出问题的板子就一个,出问题的时间也不确定,至少10天以上,出了问题也不可能等我到现场

kundi 发表于 2022-1-4 09:27:54

我之前有些简单程序就是:每执行完一次(如修改内容)就自动重新启动复位,这样抗干扰强,也不容易出错。

youkebing 发表于 2022-1-4 09:30:52

kundi 发表于 2022-1-4 09:27
我之前有些简单程序就是:每执行完一次(如修改内容)就自动重新启动复位,这样抗干扰强,也不容易出错。 ...

我这个没法这样,以前写程序都是定时检测寄存器的,发现寄存器错误,就重启复位。这个应用太简单了,就没搞这些措施。

kundi 发表于 2022-1-4 11:15:45

youkebing 发表于 2022-1-4 09:30
我这个没法这样,以前写程序都是定时检测寄存器的,发现寄存器错误,就重启复位。这个应用太简单了,就没 ...

对了,如果允许增加外部电路元件,可以考虑用外接看门狗。

小李非刀 发表于 2022-1-4 11:16:42

楼主,一般干扰是很难干扰到改变寄存器值的,你可以允许PCA计数器溢出中断,在中断中取反一个IO来指示进入中断。同时在主程序不断的将PCA的一些信息通过IO或串口来监控。
STC15W408AS的PWM我用来控制有刷或无刷电机,干扰很严重的场合,都没有问题。

饭桶 发表于 2022-1-4 11:22:07

个别问题,还有一种可能性是虚焊之类的小问题。

youkebing 发表于 2022-1-4 12:31:24

饭桶 发表于 2022-1-4 11:22
个别问题,还有一种可能性是虚焊之类的小问题。

这个板子我测试了,用手掰,用打火机不停的打,板子都正常。模拟了一些非正常时序加在信号上,都没有出现问题。

youkebing 发表于 2022-1-4 12:32:58

小李非刀 发表于 2022-1-4 11:16
楼主,一般干扰是很难干扰到改变寄存器值的,你可以允许PCA计数器溢出中断,在中断中取反一个IO来指示进入 ...

主要这个板子很难出现问题,现场出问题的就一块,至少要10好几天才能出现,在公司我测试了好久。都正常的。

1a2b3c 发表于 2022-1-5 09:02:12

把这块丢垃圾桶,换个全新的!

youkebing 发表于 2022-1-5 10:13:26

1a2b3c 发表于 2022-1-5 09:02
把这块丢垃圾桶,换个全新的!

希望是这片单片机的问题,暂时我计划这样处理,1,检测到计时在变的时候才喂狗,2,安装到现成测试,3,如果发现还是出问题,换一片新的单片机上去在测试

youkebing 发表于 2022-1-5 10:14:58

1a2b3c 发表于 2022-1-5 09:02
把这块丢垃圾桶,换个全新的!

我装在公司,4秒读一次数据,跑了1晚上,还是正常的,在测试几天看看。

yangquanneng 发表于 2022-1-5 10:45:34

你这没考虑定时器计满了翻转的情况吧,如果dly本身就是最大值65535,你这肯定执行不到你说的那个函数

youkebing 发表于 2022-1-5 11:17:46

yangquanneng 发表于 2022-1-5 10:45
你这没考虑定时器计满了翻转的情况吧,如果dly本身就是最大值65535,你这肯定执行不到你说的那个函数 ...

您说的是那一句?我是u16t类型

youkebing 发表于 2022-1-5 11:48:04

yangquanneng 发表于 2022-1-5 10:45
你这没考虑定时器计满了翻转的情况吧,如果dly本身就是最大值65535,你这肯定执行不到你说的那个函数 ...

不知道你说的是不是这个意思

yangquanneng 发表于 2022-1-5 12:18:41

我看错了,你第42行参数传的dly看混了

youkebing 发表于 2022-1-5 13:52:56

yangquanneng 发表于 2022-1-5 12:18
我看错了,你第42行参数传的dly看混了

不好意思,代码写的有点不规范

youkebing 发表于 2022-1-5 14:01:20

本帖最后由 youkebing 于 2022-1-5 14:09 编辑

yangquanneng 发表于 2022-1-5 12:18
我看错了,你第42行参数传的dly看混了

命名不好,有时的确会看乱,我把自己的代码命名改了一下,谢谢
修正过的代码:
#include "config.h"

//#definePCA_INIT() do { CMOD = 0; CR = 1;} while(0)
#definePCA_INIT() do { CMOD = 0; CCON = 0x40;} while(0)
//PCA定时器
u16t time_now(void) {
    u8t h;
    u8t l;
    u16t cc;

    while (1) {
      h = CH;
      l = CL;
      if (h == CH) {
            cc = h;
            cc <<= 8;
            cc = cc | l;
            return cc;
      }
    }
}
void time_init(void) {
    PCA_INIT();
}

u8t time_expired(u16t t, u16t tout) {
    t = time_now() - t;
    if (t > tout) {
      return 1;
    }
    return 0;
}

//static u8t _cnt10ms;
void time_poll(void) {
    static u16t _t;
    static u8t _cnt;

    //add
    PCA_INIT();

    if (time_expired(_t, 10*1000)) {
      _t = time_now();
      _cnt++;
      if (_cnt >= (u8t)10) {
            _cnt = 0;
            //0.1s
            alarm_poll();
      }
    }
}

modbus 发表于 2022-1-5 17:22:54

youkebing 发表于 2022-1-5 11:48
不知道你说的是不是这个意思

这个是你的主程序吗

youkebing 发表于 2022-1-5 18:02:57

本帖最后由 youkebing 于 2022-1-5 18:04 编辑

modbus 发表于 2022-1-5 17:22
这个是你的主程序吗

不是的,主程序大致是,


void main(void) {
    time_init();
    while (1) {
      clr_wdt();
      time_poll();
    }
}

当然,还有几句端口初始化的代码

快乐的花生壳 发表于 2022-1-20 22:15:19

测试一下看门狗有没有开到,试一下不喂狗会不会复位。
建议单独长时间运行带有while语句的函数来排查一下是否卡死在while里。比如time_now()和PCA_INIT()。
如果是“”alarm_poll()执行不到“”,那么假设程序没有卡死,那可能是cnt一直小于11,会不会是未知错误一直把cnt给初始化了?程序代码非常少的话,可以试试把static u8t cnt;这句定义在全局变量u8t cnt=0;。
我记得五六年前用过这款芯片,好像也是遇到过定时器停止的问题,后面好像是更改程序解决的问题,太久不记得具体细节了。

可以参考下:
1.可以试试在VCC里增大22uF以上的电容。
2.STC的P31用作IO口的话也可能会导致卡死。
3.STC的定义在data的变量溢出有时keil不会报错也有可能会导致运行一段时间卡死。

youkebing 发表于 2022-1-21 17:00:13

本帖最后由 youkebing 于 2022-1-21 17:01 编辑

快乐的花生壳 发表于 2022-1-20 22:15
测试一下看门狗有没有开到,试一下不喂狗会不会复位。
建议单独长时间运行带有while语句的函数来排查一下是 ...

谢谢,
我没法模拟出来不喂狗复位的情况,测试的时候,不喂狗程序也没死掉过。
我这样测试过看门狗:
打开看门狗,定时器计时到1分钟后,程序进入到一个死循环,测试一分钟后,程序重启。和实际设想一致

我放在公司,测了两个星期,一直都是正常的

现在我这样,换了个单片机(担心虚焊),检测到定时器变化的时候才喂狗,
另外,在主循环中写定时器相关配置( 防止寄存器被干扰)

你说的 STC的P31用作IO口的话也可能会导致卡死。这个是什么情况?
我没用到P31这个端口


快乐的花生壳 发表于 2022-1-27 12:56:24

youkebing 发表于 2022-1-21 17:00
谢谢,
我没法模拟出来不喂狗复位的情况,测试的时候,不喂狗程序也没死掉过。
我这样测试过看门狗:


建议看下下面这个帖子,我也是前天看到才搞清楚了以前出现的data内存异常的一些问题
从STM8S往STC上移植的小问题挺多
页: [1]
查看完整版本: 求助:这样的代码是否有问题(STC15W408AS)