一个简单的8051 C中断事件计数器演示,不递增。

时间:2015-02-08 17:21:14

标签: c embedded interrupt 8051

这不是一项任务,我只是想学习嵌入式C来远离Arduino。 (基于this interrupt LED example

我正在尝试创建一个中断输入事件计数器。使用连接到P3.2的去抖动按钮开关增加LCD上的3位数字。 000在启动时显示,并且中断中的切换LED会切换到&打开,但显示数字没有递增。我的目标是:按1:显示001,按2:显示002等。按“重置”返回000。

我认为问题在于while()。当while()被注释时,LCD显示器快速闪烁并且不清楚读取,但我可以看到在按下开关时出现“1”(LED亮) - 当开关松开时LED熄灭(不切换)然而''1'清除了。随着while()取消注释,LCD显示屏仍然稳固。清除,LED熄灭&打开,但没有计数器增量。

代码:

// ****Event counter using external interrupt 0****

#include<reg51.h>
#include "lcd4bit.h"
void cct_init(void);
void InitINT0(void);
sbit LED = P2^3;       // Int status LED     
unsigned char str1[]="Line2";
char stringy[3] = {'0','0','0'};
char count = 0;
int number = 0;

void main()
{
 char count = 0;
 if (number != 0)
 cct_init();     // Make all ports zero
 InitINT0();      // Intialize INT0 interrupts
    stringy[count]=(number%10)+48;
  number/=10;
 init_lcd();
  gotoxy_lcd(1,1); //(Col, Line#)
    print_lcd("Line One");
    gotoxy_lcd(1,2);
    print_lcd(stringy);
    while(1)
    { }
}

void cct_init(void) // Init CCT function
{
    P3 = 0x04;    // Make P3.2 (INT0) pin high only
}

void InitINT0(void) // External INT0 pin interrupt init function
{
    IT0 = 1;      //Edge triggered interrupt mode (Neg)
    EX0 = 1;      //Enable external interrupt INT0
    EA  = 1;      //Enable global interrupts
}

void external0_isr(void) interrupt 0   // Inturrupt 0 ISR
{
    number = number + 1;
    LED = ~LED;   // Toggle LED
}

任何建议表示赞赏。

1 个答案:

答案 0 :(得分:1)

我认为您误解了ISR的工作原理。除while(1) {}之外的所有代码都在程序开始时执行一次。然后主线程就位于while循环内部,以便执行其余的操作。

发生中断不会将主线程重置回main()或其他任何内容。

此外,代码:

if (number != 0)
cct_init();     // Make all ports zero
InitINT0();      // Intialize INT0 interrupts

不会在此处cct_init()致电number == 0,然后调用InitINT0()if语句仅绑定到其后的一个语句,除非您使用{ }对语句进行分组。

根据您链接的示例,这应该只是:

cct_init();
InitINT0();

如果您希望在中断触发后执行main()中的代码,则必须更改while循环以检测number中的更改。

这可能有效:

// global var
volatile int number = 0;  

// in main() instead of your existing while loop
int previous_number = 0;

while (1)
{
    if ( number != previous_number )
    {
         previous_number = number;
         // put your LCD updating code here
         // possibly you should disable the interrupt before the LCD code
         // and re-enable the interrupt afterwards
    }
}

有一个潜在的错误,因为比较number != previous_number可能不是原子的。对unsigned char使用int代替number似乎是一种很好的预防措施。

这个关于原子性和操作的主题应该在8051所嵌入的平台的文档中提到,所以我试着去查看确认。