Ashton
Ashton

Reputation: 329

A simple 8051 C Interrupt event counter demo, not incrementing.

This is not an assignment, I'm just trying to learn embedded C to move away from Arduino. (based on this interrupt LED example)

I'm trying to create an interrupt input event counter. Using a debounced push switch connected to P3.2 to increment a 3-digit number on the LCD. 000 displays on startup, and a toggling LED in the interrupt does toggle off & on, but the display number is not incrementing Up. My objective is: push 1: display 001, push 2: display 002, etc. Push Reset to return to 000.

I think the problem is with the while(). When while() is commented the LCD display is rapid flashing and unclear to read, but I can see a '1' appear (with LED on)while pressing the switch -- when the switch is released the LED goes off (not toggling) and '1' clears however. With while() uncommented the LCD display is solid & clear, the LED toggles off & on, but there is no counter number increment.

The code:

// ****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
}

Any suggestions appreciated.

Upvotes: 0

Views: 1325

Answers (1)

M.M
M.M

Reputation: 141638

I think you misunderstand how the ISR works. All of your code in main except for while(1) {} is executed once, at the start of the program. Then the main thread just sits inside that while loop spinning for the rest of the execution.

The interrupt occurring does not reset the main thread back to the start of main() or anything.

Also, the code:

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

will not call cct_init() because number == 0 here, and then it calls InitINT0(). An if statement only binds to the one statement following it, unless you use { } to group statements.

According to the example you linked this should just be:

cct_init();
InitINT0();

If you want to have code in main() be executed as a result of the interrupt triggering then you will have to change your while loop to detect changes in number.

This might work:

// 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
    }
}

There's a potential bug in that the comparison number != previous_number might not be atomic. Using a unsigned char instead of an int for number seems like a good prophylactic measure.

This topic of atomicity and operations should be mentioned in documentation for the platform the 8051 is embedded in, so I'd try and look that up for confirmation.

Upvotes: 1

Related Questions