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

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

[复制链接]

该用户从未签到

1

主题

1

回帖

19

积分

新手上路

积分
19
发表于 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
回复 送花

使用道具 举报

  • TA的每日心情
    奋斗
    前天 08:59
  • 签到天数: 143 天

    [LV.7]常住居民III

    27

    主题

    1343

    回帖

    4187

    积分

    论坛元老

    积分
    4187
    发表于 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

    回帖

    19

    积分

    新手上路

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

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

    使用道具 举报

    该用户从未签到

    11

    主题

    331

    回帖

    886

    积分

    荣誉版主

    积分
    886
    发表于 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, 2024-5-19 13:05 , Processed in 0.080697 second(s), 44 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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