找回密码
 立即注册
查看: 833|回复: 3

STC89系列单片机程序运行异常(疑似全局变量突变)

[复制链接]

1

主题

1

回帖

21

积分

新手上路

积分
21
发表于 2023-6-12 10:49:02 | 显示全部楼层 |阅读模式
本帖最后由 lywang 于 2023-6-12 10:56 编辑

最近用STC89C52做一个小例程,发现出现了意想不到的问题。

我的调试过程如下,求大神帮助解惑。
keil默认8级优化。
1.从官网下载STCISP下载例程,用的定时器0产生1ms中断.代码如下

#include "reg51.h"
//-----------------------------------------------

/* define constants */
#define FOSC 11059200L

#define T1MS (65536-FOSC/12/1000)   //1ms timer calculation method in 12T mode


sbit TEST_LED = P1^0;               //work LED, flash once per second
sbit TEST_LED2 = P1^1;               //work LED, flash once per second
sbit TEST_LED3 = P1^2;               //work LED, flash once per second
/* define variables */
unsigned int  u16Time1ms;                                                //1000 times counter

//-----------------------------------------------

/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
    TL0 = T1MS;                     //reload timer0 low byte
    TH0 = T1MS >> 8;                //reload timer0 high byte
      
    TEST_LED = !TEST_LED;
    u16Time1ms++;
}

//-----------------------------------------------

/* main program */
void main()
{               
    TMOD = 0x01;                    //set timer0 as mode1 (16-bit)
    TL0 = T1MS;                     //initial timer0 low byte
    TH0 = T1MS >> 8;                //initial timer0 high byte
    TR0 = 1;                        //timer0 start running
    ET0 = 1;                        //enable timer0 interrupt
    EA = 1;                         //open global interrupt switch
    u16Time1ms = 0;                      //initial counter

      
    while (1)
{

//                        if(u16Time1ms > 500)               //1ms * 1000 -> 1s
//                        {
//                                TEST_LED2 = !TEST_LED2;
//                                u16Time1ms = 0;
//                        }                       



                }
}
step1:测试中断是否产生1ms时基,中断反装P1.0,结果如下图
STC89系列单片机程序运行异常(疑似全局变量突变)-1.png
step2:1ms中断里添加全局变量,while中进行循环执行500ms翻转P1.1,程序与结果如下

#include "reg51.h"



//-----------------------------------------------

/* define constants */
#define FOSC 11059200L

#define T1MS (65536-FOSC/12/1000)   //1ms timer calculation method in 12T mode


sbit TEST_LED = P1^0;               //work LED, flash once per second
sbit TEST_LED2 = P1^1;               //work LED, flash once per second
sbit TEST_LED3 = P1^2;               //work LED, flash once per second
/* define variables */
unsigned int  u16Time1ms;                                                //1000 times counter



//-----------------------------------------------

/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
    TL0 = T1MS;                     //reload timer0 low byte
    TH0 = T1MS >> 8;                //reload timer0 high byte
      
                TEST_LED = !TEST_LED;
                u16Time1ms++;


}

//-----------------------------------------------

/* main program */
void main()
{               
    TMOD = 0x01;                    //set timer0 as mode1 (16-bit)
    TL0 = T1MS;                     //initial timer0 low byte
    TH0 = T1MS >> 8;                //initial timer0 high byte
    TR0 = 1;                        //timer0 start running
    ET0 = 1;                        //enable timer0 interrupt
    EA = 1;                         //open global interrupt switch
    u16Time1ms = 0;                      //initial counter

      
                while (1)
                {



                        if(u16Time1ms > 500)               //1ms * 1000 -> 1s
                        {
                                TEST_LED2 = !TEST_LED2;
                                u16Time1ms = 0;
                        }                       



                }
}


要命的是,时间不对了。我立马查看了变量定义的unsigned int类型没问题不会一出的。
STC89系列单片机程序运行异常(疑似全局变量突变)-2.png
看了下放在中断里的P1.0,还是1ms正常的。
STC89系列单片机程序运行异常(疑似全局变量突变)-3.png

此刻我觉得不妙,全局变量被异常改变了。可是我没有数据和指针哇,头大
step3:我把while(1)里的500ms逻辑放到中断执行,惊人的正常了。程序与结果如下


#include "reg51.h"



//-----------------------------------------------

/* define constants */
#define FOSC 11059200L

#define T1MS (65536-FOSC/12/1000)   //1ms timer calculation method in 12T mode


sbit TEST_LED = P1^0;               //work LED, flash once per second
sbit TEST_LED2 = P1^1;               //work LED, flash once per second
sbit TEST_LED3 = P1^2;               //work LED, flash once per second
/* define variables */
unsigned int  u16Time1ms;                                                //1000 times counter



//-----------------------------------------------

/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
    TL0 = T1MS;                     //reload timer0 low byte
    TH0 = T1MS >> 8;                //reload timer0 high byte
      
                TEST_LED = !TEST_LED;
                u16Time1ms++;

                        if(u16Time1ms > 500)               //1ms * 1000 -> 1s
                        {
                                TEST_LED2 = !TEST_LED2;
                                u16Time1ms = 0;
                        }               
}

//-----------------------------------------------

/* main program */
void main()
{               
    TMOD = 0x01;                    //set timer0 as mode1 (16-bit)
    TL0 = T1MS;                     //initial timer0 low byte
    TH0 = T1MS >> 8;                //initial timer0 high byte
    TR0 = 1;                        //timer0 start running
    ET0 = 1;                        //enable timer0 interrupt
    EA = 1;                         //open global interrupt switch
    u16Time1ms = 0;                      //initial counter

      
                while (1)
                {



//                        if(u16Time1ms > 500)               //1ms * 1000 -> 1s
//                        {
//                                TEST_LED2 = !TEST_LED2;
//                                u16Time1ms = 0;
//                        }                       



                }
}
P1.1正常了,救命

STC89系列单片机程序运行异常(疑似全局变量突变)-1.png

请问到底出了什么问题!!!!!!

STC89系列单片机程序运行异常(疑似全局变量突变)-4.png
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2023-6-12 18:37:46 | 显示全部楼层
通过你的描述我猜测问题可能出在多字节变量的一致性上
你定义了一个16位的变量 u16Time1ms
在定时器中断里面对它进行累加,在主循环里进行判断处理,这样就可能出现这种情况
当 u16Time1ms = 0x00ff 时,主循环里先读取 u16Time1ms 的低8位数据跟 500 的低8位进行相减比较
然后产生了中断,在中断里又对 u16Time1ms 进行了累加,结果 u16Time1ms = 0x0100
中断完成回到主循环后,继续读取 u16Time1ms 的高8位内容与 500 进行相减比较
这样的话,在主循环里与 500 进行比较的值实际上就变成 0x01ff,而非预期的 0x00ff

如果累加、判断都在中断里执行就不会遇到这种情况,所以你的 step3 是正常的。
回复 支持 2 反对 0

使用道具 举报 送花

1

主题

1

回帖

21

积分

新手上路

积分
21
发表于 2023-6-13 09:56:28 | 显示全部楼层
乘风*** 发表于 2023-6-12 18:37
通过你的描述我猜测问题可能出在多字节变量的一致性上
你定义了一个16位的变量 u16Time1ms
在定时器中断里 ...

太感谢了,应该就是前后台系统临界的问题。
回复 支持 反对

使用道具 举报 送花

11

主题

340

回帖

929

积分

荣誉版主

积分
929
发表于 2023-7-21 13:39:35 来自手机 | 显示全部楼层
本帖最后由 熊仔 于 2023-7-21 13:43 编辑

中断中使用的全局变量,加上volatile修饰,禁止优化。
在中断外的函数读和修改变量,需要关闭中断,才能正确读取和赋值。

当然51单片机如果是8位变量,不需要关中断。
stc32 如果变量放edata,8,16,32位都不用关中断,也能正确运行。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 02:25 , Processed in 0.269833 second(s), 67 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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