求助:这样的代码是否有问题(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();
}
现场的表现形式是alarm_poll()执行不到,我开了看门狗的,死机应该能复位的啊 定时器停了?可能是受干扰了吧。 wye11083 发表于 2022-1-3 22:02
定时器停了?可能是受干扰了吧。
如果真的是定时器干扰停了,一切问题倒都可以解释了 wye11083 发表于 2022-1-3 22:02
定时器停了?可能是受干扰了吧。
但是其他的都没有问题,就这一块有问题,感觉好奇怪 youkebing 发表于 2022-1-3 22:36
但是其他的都没有问题,就这一块有问题,感觉好奇怪
那你仔细查查是不是其它地方有重置定时器的地方? wye11083 发表于 2022-1-3 22:39
那你仔细查查是不是其它地方有重置定时器的地方?
没有,这个小产品,代码非常少,这几天,反复看了几十遍了,没看到明显的问题,猜测几个可能:1,这片单片机问题,2,PCA被干扰,停止了。 youkebing 发表于 2022-1-3 23:02
没有,这个小产品,代码非常少,这几天,反复看了几十遍了,没看到明显的问题,猜测几个可能:1,这片单 ...
所以你加个最简单的状态检测好了。 wye11083 发表于 2022-1-3 23:29
所以你加个最简单的状态检测好了。
其实我想知道,有没有可能PCA的启动位被干扰到?我这几天已经改了程序,主循环检测相关配置寄存器,但我不确定是否是定时器被干扰,还是单片机真正死机了。主要想重现故障实在太难了。 用串口打印流程和状态信息,一般比较容易找到问题 hjjnt2008 发表于 2022-1-4 08:15
用串口打印流程和状态信息,一般比较容易找到问题
出问题的板子就一个,出问题的时间也不确定,至少10天以上,出了问题也不可能等我到现场 我之前有些简单程序就是:每执行完一次(如修改内容)就自动重新启动复位,这样抗干扰强,也不容易出错。 kundi 发表于 2022-1-4 09:27
我之前有些简单程序就是:每执行完一次(如修改内容)就自动重新启动复位,这样抗干扰强,也不容易出错。 ...
我这个没法这样,以前写程序都是定时检测寄存器的,发现寄存器错误,就重启复位。这个应用太简单了,就没搞这些措施。 youkebing 发表于 2022-1-4 09:30
我这个没法这样,以前写程序都是定时检测寄存器的,发现寄存器错误,就重启复位。这个应用太简单了,就没 ...
对了,如果允许增加外部电路元件,可以考虑用外接看门狗。 楼主,一般干扰是很难干扰到改变寄存器值的,你可以允许PCA计数器溢出中断,在中断中取反一个IO来指示进入中断。同时在主程序不断的将PCA的一些信息通过IO或串口来监控。
STC15W408AS的PWM我用来控制有刷或无刷电机,干扰很严重的场合,都没有问题。 个别问题,还有一种可能性是虚焊之类的小问题。 饭桶 发表于 2022-1-4 11:22
个别问题,还有一种可能性是虚焊之类的小问题。
这个板子我测试了,用手掰,用打火机不停的打,板子都正常。模拟了一些非正常时序加在信号上,都没有出现问题。 小李非刀 发表于 2022-1-4 11:16
楼主,一般干扰是很难干扰到改变寄存器值的,你可以允许PCA计数器溢出中断,在中断中取反一个IO来指示进入 ...
主要这个板子很难出现问题,现场出问题的就一块,至少要10好几天才能出现,在公司我测试了好久。都正常的。 把这块丢垃圾桶,换个全新的! 1a2b3c 发表于 2022-1-5 09:02
把这块丢垃圾桶,换个全新的!
希望是这片单片机的问题,暂时我计划这样处理,1,检测到计时在变的时候才喂狗,2,安装到现成测试,3,如果发现还是出问题,换一片新的单片机上去在测试 1a2b3c 发表于 2022-1-5 09:02
把这块丢垃圾桶,换个全新的!
我装在公司,4秒读一次数据,跑了1晚上,还是正常的,在测试几天看看。 你这没考虑定时器计满了翻转的情况吧,如果dly本身就是最大值65535,你这肯定执行不到你说的那个函数 yangquanneng 发表于 2022-1-5 10:45
你这没考虑定时器计满了翻转的情况吧,如果dly本身就是最大值65535,你这肯定执行不到你说的那个函数 ...
您说的是那一句?我是u16t类型 yangquanneng 发表于 2022-1-5 10:45
你这没考虑定时器计满了翻转的情况吧,如果dly本身就是最大值65535,你这肯定执行不到你说的那个函数 ...
不知道你说的是不是这个意思
我看错了,你第42行参数传的dly看混了 yangquanneng 发表于 2022-1-5 12:18
我看错了,你第42行参数传的dly看混了
不好意思,代码写的有点不规范 本帖最后由 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();
}
}
} youkebing 发表于 2022-1-5 11:48
不知道你说的是不是这个意思
这个是你的主程序吗 本帖最后由 youkebing 于 2022-1-5 18:04 编辑
modbus 发表于 2022-1-5 17:22
这个是你的主程序吗
不是的,主程序大致是,
void main(void) {
time_init();
while (1) {
clr_wdt();
time_poll();
}
}
当然,还有几句端口初始化的代码 测试一下看门狗有没有开到,试一下不喂狗会不会复位。
建议单独长时间运行带有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:01 编辑
快乐的花生壳 发表于 2022-1-20 22:15
测试一下看门狗有没有开到,试一下不喂狗会不会复位。
建议单独长时间运行带有while语句的函数来排查一下是 ...
谢谢,
我没法模拟出来不喂狗复位的情况,测试的时候,不喂狗程序也没死掉过。
我这样测试过看门狗:
打开看门狗,定时器计时到1分钟后,程序进入到一个死循环,测试一分钟后,程序重启。和实际设想一致
我放在公司,测了两个星期,一直都是正常的
现在我这样,换了个单片机(担心虚焊),检测到定时器变化的时候才喂狗,
另外,在主循环中写定时器相关配置( 防止寄存器被干扰)
你说的 STC的P31用作IO口的话也可能会导致卡死。这个是什么情况?
我没用到P31这个端口
youkebing 发表于 2022-1-21 17:00
谢谢,
我没法模拟出来不喂狗复位的情况,测试的时候,不喂狗程序也没死掉过。
我这样测试过看门狗:
建议看下下面这个帖子,我也是前天看到才搞清楚了以前出现的data内存异常的一些问题
从STM8S往STC上移植的小问题挺多
页:
[1]