amobbs.com 阿莫电子论坛

 找回密码
 注册
bottom↓
查看: 307|回复: 147

keil的比较运算出错

[复制链接]
发表于 2020-2-19 12:04:19 | 显示全部楼层 |阅读模式
本帖最后由 yongxiangu 于 2020-2-19 12:04 编辑

keil的版本V5.28.0.0

main.c代码
  1. #include <REGX51.H>
  2. #include "delay.h"

  3. void main()
  4. {
  5.         timer0_init();
  6.         while(1)
  7.         {
  8.                 P1 = 0x00;
  9.                 delay(500);
  10.                 P1 = 0xff;
  11.                 delay(500);
  12.         }
  13. }
复制代码


delay.c代码
  1. #include "delay.h"

  2. static unsigned int count;

  3. void timer0_init()
  4. {
  5.         TMOD = 0x01;   //设置T0为工作方式1,即16位定时器
  6.         TH0 = (65536-1000) >> 8;
  7.         TL0 = 65536-1000;
  8.        
  9.         ET0 = 1;  //开放T0中断
  10.         EA = 1;   //开放总中断开关
  11.        
  12.         TR0 = 1;  //T0开跑
  13. }

  14. void timer0_interrput() interrupt 1
  15. {
  16.         TH0 = (65536-1000) >> 8;
  17.         TL0 = 65536-1000;
  18.        
  19.         if(count>0) count--;
  20. }

  21. void delay(unsigned int t)
  22. {
  23.         count = t;
  24.         while(count>0);   //这一句经常在count为0x00ff的时候跳出
  25.         while(count>0);  //增加一句才行
  26. }
复制代码


while(count>0); 这一句经常在count为0x00ff的时候就跳出(keil debug可以发现,proteus仿真也是),增加一句while(count>0)才行。不清楚怎么回事,我也考虑过count = t之前关中断,之后开中断,也不能解决问题,只有再增加一句while(count>0)才行,但是觉得很别扭。
发表于 2020-2-19 12:07:44 | 显示全部楼层
volatile都没有是不是可以不用看了?
 楼主| 发表于 2020-2-19 12:08:10 | 显示全部楼层
将工程文件也上传一下

keil比较运算出错.rar

26.11 KB, 下载次数: 618

 楼主| 发表于 2020-2-19 12:09:48 | 显示全部楼层
takashiki 发表于 2020-2-19 12:07
volatile都没有是不是可以不用看了?

刚加了,还是出错
发表于 2020-2-19 12:14:04 来自手机 | 显示全部楼层
takashiki 发表于 2020-2-19 12:07
volatile都没有是不是可以不用看了?

8位机就有这毛病。非原子操作很容易出错(比如之前把0搬到r中,然后中断,然后再搬另一个0)。
发表于 2020-2-19 12:18:32 | 显示全部楼层
本帖最后由 lcw_swust 于 2020-2-19 12:20 编辑

主函数对count赋值时可能中断将之打断且中断里也对count赋值,从而出现意外。
估计因为16位变量在8位机里是分两次操作的。
读取count的值时也可能中途被中断修改出现意外
所以建议主函数里对count赋值或读取时先关中断。
发表于 2020-2-19 12:19:05 | 显示全部楼层
记着加ul
 楼主| 发表于 2020-2-19 12:19:10 | 显示全部楼层
keil比较运算出错.jpg
 楼主| 发表于 2020-2-19 12:19:55 | 显示全部楼层
lcw_swust 发表于 2020-2-19 12:18
主函数对count赋值时可能中断将之打断且中断里也对count赋值,从而出现意外。
估计因为16位变量在8位机里是 ...

恩,这个做了,也是出错
发表于 2020-2-19 12:20:58 | 显示全部楼层
楼主的中断服务函数和delay函数都在操作counter变量,冲突了
发表于 2020-2-19 12:22:02 | 显示全部楼层
yongxiangu 发表于 2020-2-19 12:19
恩,这个做了,也是出错

补充一下,读取也要关中断。如
int x=1;
while(x)
{
EA=0;
x=count;
EA=1;
}
发表于 2020-2-19 12:28:03 | 显示全部楼层
本帖最后由 lcw_swust 于 2020-2-19 12:31 编辑

比如
count=0x0100;
执行while(count>0); 时,分两步判断
先判断低字节为0,不满足条件,
然后中断将之减1,count=0x00FF;退出中断;
再判断高字节为0,也不满足条件,退出循环。

所以,建议主函数与中断都要使用的变量尽量只用一个字节,
这个地方呢就可以将定时器频率降低(或程序中做个分频)达到长延时的目的。
 楼主| 发表于 2020-2-19 12:38:35 | 显示全部楼层
lcw_swust 发表于 2020-2-19 12:28
比如
count=0x0100;
执行while(count>0); 时,分两步判断

非常感谢!之前只考虑了,写的时候原子操作,读取的时候也要原子操作
  1. void delay(unsigned int t)
  2. {
  3.         unsigned int temp = 1;
  4.        
  5.         EA = 0;
  6.         count = t;      //赋值操作要原子操作
  7.         EA = 1;
  8.        
  9.         while(temp>0)
  10.         {
  11.                 EA = 0;
  12.                 temp = count;   //读取操作要原子操作
  13.                 EA = 1;
  14.         }
  15. }
复制代码
发表于 2020-2-19 14:03:49 来自手机 | 显示全部楼层
原子操作很重要!
发表于 2020-2-19 14:32:52 | 显示全部楼层
只是单步调试有问题还是整个延时就不正确?
发表于 2020-2-19 14:54:01 来自手机 | 显示全部楼层
Count声明前加volatile试试
发表于 2020-2-19 18:37:33 | 显示全部楼层
楼主问题算是解决了吧。
 楼主| 发表于 2020-2-19 21:02:31 | 显示全部楼层
xingjianpeng 发表于 2020-2-19 18:37
楼主问题算是解决了吧。


解决了,按照13楼的办法
发表于 2020-2-19 21:20:36 | 显示全部楼层
大部分情况下超过1ms我都不会去用delay的
发表于 2020-2-20 14:41:52 | 显示全部楼层
变量在中断中修改,外部函数一般只读取最好。
发表于 2020-2-20 21:47:52 | 显示全部楼层
delay执行到一半时,进中断了,因为count>0 这比较不是一条汇编指令就能完成的
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号-1 )

GMT+8, 2020-4-10 08:05

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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