【问题标题】:A simple 8051 C Interrupt event counter demo, not incrementing.一个简单的 8051 C 中断事件计数器演示,不递增。
【发布时间】:2015-02-08 17:21:13
【问题描述】:

这不是作业,我只是想学习嵌入式 C 以摆脱 Arduino。 (基于this interrupt LED example

我正在尝试创建一个中断输入事件计数器。使用连接到 P3.2 的去抖动按钮开关来增加 LCD 上的 3 位数字。启动时显示 000,并且中断中的切换 LED 确实会关闭和打开,但显示编号不会递增。我的目标是:push 1:显示 001,push 2:显示 002,等等。按下 Reset 回到 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
}

任何建议表示赞赏。

【问题讨论】:

  • 代码在中断期间或while() 循环中似乎没有改变显示,那么除了 LED 之外,为什么任何可见的东西都应该改变?
  • 您可以在 AVR 上使用嵌入式 C,它将使用您的 Arduino 硬件,让您免于 8051 的恐惧。

标签: c embedded interrupt 8051


【解决方案1】:

我认为您误解了 ISR 的工作原理。除了 while(1) {} 之外,您在 main 中的所有代码都在程序开始时执行一次。然后主线程就在 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 可能不是原子的。对number 使用unsigned char 而不是int 似乎是一种很好的预防措施。

应该在嵌入 8051 的平台的文档中提到原子性和操作这一主题,因此我会尝试查找以确认。

【讨论】:

  • 我失去了最初的 LCD 显示器。我将不得不采取不同的方法。我不能在这里发布我修改后的代码。处理您的建议。
  • @Ashton start previous_number 关闭到不同的值以获得初始显示
猜你喜欢
  • 2011-03-03
  • 2013-03-27
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 2013-04-03
相关资源
最近更新 更多