8051 interrupts

Thread Starter

Chalma

Joined May 19, 2013
54
Hello it's me again asking more simple questions. I'm still trying to get the hang of this 8051 stuff. I bought the c8051f020 development board, it has an onboard LED (on P1.6) that I use along with a switch SW2 (on P3.7). My goal was to have a PWM (on P1.0) line that I can turn on and off with the SW2. The PWM line I gave about a 10-15% Duty Cycle and for now I just hooked it up to some LEDs and my scope so that I can see that it is indeed outputting the PWM signal. I have the onboard LED (P1.6) as an indicator that it is indeed recognizing my push button response. you may think that the push button is silly for input the PWM but I don't know the 8051 and as I get better SW2 will be replaced with input from a different PWM source. What happens is that my program is getting stuck and I do not understand why, mainly because interrupts are not really easy to use (compared with the arduino). What I intend to happen is on bootup nothing will happen, when SW2 is pressed [mode 1] the PWM will turn on, if the button is pressed again it will turn off. Later I also intend to have the pushbutton change the PWM (i.e. no push is off, one push is 10%DC, two pushes is 50%DC, three pushes back to off ....you get it). I am posting my code below and any help would be appreciated. I would also appreciate any recommended materials to read as I am a hands on visual learner and I learn better from looking at code and building the circuit. I.E. my buddy told me to go to this place and it started talking about the 3rd bit in some register and how you cycle it but not before you call all this fancy hex code(I'm a dummy I don't understand things that way)

Rich (BB code):
#include <c8051f020.h>

#define OFF 0 //off
#define ON 1 //on
#define PWMPIN P1_0 //PWM pin is port 1 pin 1 definition

sbit button = P3^7; //Onboard Devkit SW2
sbit light = P1^6;  //onboard LED D3
sbit PWMPIN = P1^0; //PWMPIN 1 is set as pin1
int buttoncycle = 0;  //buttons status for mode of operiation 0 == OFF
unsigned char pwm_width;  //pwm 0-255 DutyCycle i.e. 217 is |[(217/255) * 100]-100|
bit pwm_flag = 0; //pwm_active?

//++++++++ Predefined functions
void pwm_setup();
void initialization(); //setting of lines
//void INT0_ISR() interrupt 19; //button Int acting like pulse in detect
void delay_in_ms(unsigned int); //delay function based on cycles per second
void pwm_setup(); //pwm predefinition
//void timer0() interrupt 1; //timer interrupt for pwm
void listen_loop(); // "listen" for the pulse
void light_it(); //SW2 LED on
void unlight_it(); //SW2 LED off
void listen_loop(); //infinite loop testing for interrupt trips etc.
void buttoncount(int); //on, off cycle ( for now... maybe add other modes)

//++++++++ 



void light_it() //function for SW2 LED (on)
{ light = ON; }

void unlight_it()  //function for SW2 LED (off)
{ light = OFF; }

void delay_in_ms(unsigned int count)
{ //mSec Delay 22.1Mhz, delay based on clock cycle
unsigned int i;
while (count)
{
    i = 221;
    while(i>0) i--; //count down 221 cycles 1ms X cycles
    count--;
}
return;
}

void pwm_setup()
{ //predef for PWM
TMOD = 0; //timer count mode
pwm_width = 217; //pwm 0-255 DutyCycle i.e. 217 is |[(217/255) * 100]-100|
EA = 1;    //global interrupts enabled
ET0 = 1;    //Timer interrupt 0 enabled
TR0 = 1;    //Timer 0 on
}

void timer0() interrupt 1
{

if(!pwm_flag) //high
{
pwm_flag = 1; //setflag
PWMPIN = 1; //set PWM o/p pin
TH0 = pwm_width; //load timer
TF0 = 0;    //clear interrupt flag
return;
}

else //LOW
{
pwm_flag = 0;    //clearflag
PWMPIN = 0;    //clear PWM o/p pin
TH0 = 255 - pwm_width;    //load timer
delay_in_ms(300);  //BAD don't do use in non interrupt mode
TF0 = 0;    //clear interrupt flag
return;
}

}

void initialization()
{
P3IF |= 0x08;    //Port 3 interrupt flag
P3MDOUT &= ~0x80;    //Port 3 output mode
P3 |= 0x80;            //Latch it
EIE2 |= 0x20;        //enable interrupt 2
EA = 1;        //enable global variables

WDTCN = 0xde;    //disable watchdog timer
WDTCN = 0xad;    //must be winthin 4 clock cycles
light = OFF;    //initial start light off

XBR2 = 0x40;    //Enable crossbar
P1MDOUT |= 0x41;    //Enable P1^0 and P1^6 as outputs (transistor pwm and green D3 LED)
P1MDIN = 0xFE;        //Port 1 input mode (p3.7 SW2 switch)
PWMPIN = 0;            //disable PWM 
}

void buttoncount(int temp) // mode 0 off mode 1 ON mode 2+ back to off
{

if (temp == 0)
{
ET0 = 0;

}

if (temp == 1)
{
ET0 = 1;
}

if (temp >= 2)
{
buttoncycle == 0;
}
buttoncount(buttoncycle); //repeat this forever
}

void INT0_ISR() interrupt 19
{
light_it();        //turn D3 on to show button is pressed
buttoncycle ++;    //cycle switch
delay_in_ms(50); //delay 50ms to show light
unlight_it();    //turn D3 off

}

main()
{
pwm_setup();    //init pwm
initialization();    //init everything else

buttoncount(0);    //continuously monitor SW2 (P3.7)
}
 
Last edited:

Thread Starter

Chalma

Joined May 19, 2013
54
you are def. right and in my frantic state to try and get the code working I goofed. I removed the offending call unto and instead inserted
Rich (BB code):
while (1){
buttoncount(buttoncycle);    //continuously monitor SW2 (P3.7)
}
I still need help however as the code still get's stuck. either in repeating the flashing and not listening to my button states or the LED (green one on P1.6) being held down. I even tried inserting return; into my void functions to no avail.
 

Arm_n_Legs

Joined Mar 7, 2007
186
Why are there "return" statements in timer interrupt routine? Return (RETI) instruction in assembly language for interrupt routine to go return to the calling routine, but they are not needed in C.

Try removing both the return statements.

cheers~:)
 

MrChips

Joined Oct 2, 2009
30,708
The return statement is a valid C statement that returns to the calling program.
An interrupt routine cannot use the return statement since it requires a return from interrupt.

Remove all return statements.
 

Thread Starter

Chalma

Joined May 19, 2013
54
Thanks to everyone. I finally discovered the source of all my heartache. I did remove the returns in other versions of my code. I KNEW what the problem was (with the button interrupt) but I did not have enough experience or know how to really understand it. I worked through it really slow and discovered that I needed to clear the flag bit of the interrupt on P3IF. being unfamiliar I found other tutorials on how to clear the flag bit of other registers then mimiced that in my code with great sucess. My code isn't perfect but at least I have a basis to work off of in getting familiar with the 8051. Thanks to all. I would still appreciate any input on books or such to help me. I love my arduino but it really holds my hand (I've never had to clear inturrupts on it 'cause it did so automatically). below is my code in case a newbie like me needs to use it as reference.
Rich (BB code):
 #include <c8051F020.h>

#define OFF 0 //off
#define ON 1 //on
#define PWMPIN P1_0 //PWM pin is port 1 pin 1 definition

sbit button = P3^7; //Onboard Devkit SW2
sbit light = P1^6; //onboard LED D3
sbit PWMPIN = P1^0; //PWMPIN 1 is set as pin1
int buttoncycle = 0; //buttons status for mode of operiation 0 == OFF
unsigned char pwm_width; //pwm 0-255 DutyCycle i.e. 217 is |[(217/255) * 100]-100|
bit pwm_flag = 0; //pwm_active?


//++++++++ Predefined functions
void pwm_setup();
void initialization(); //setting of lines
//void INT0_ISR() interrupt 19; //button Int acting like pulse in detect
void delay_in_ms(unsigned int); //delay function based on cycles per second
void pwm_setup(); //pwm predefinition
//void timer0() interrupt 1; //timer interrupt for pwm
//void listen_loop(); // "listen" for the pulse
void light_it(); //SW2 LED on
void unlight_it(); //SW2 LED off
//void listen_loop(); //infinite loop testing for interrupt trips etc.
void buttoncount(int); //on, off cycle ( for now... maybe add other modes)
//++++++++


void light_it() //function for SW2 LED (on)
{ light = ON;}

void unlight_it() //function for SW2 LED (off)
{ light = OFF;}

void delay_in_ms(unsigned int count)
{ //mSec Delay 22.1Mhz, delay based on clock cycle
unsigned int i;
while (count)
{
i = 221;
while(i>0) i--; //count down 221 cycles 1ms X cycles
count--;
}
}


void pwm_setup()
{ //predef for PWM
TMOD = 0; //timer count mode
pwm_width = 217; //pwm 0-255 DutyCycle i.e. 217 is |[(217/255) * 100]-100|
EA = 1; //global interrupts enabled
ET0 = 1; //Timer interrupt 0 enabled
TR0 = 1; //Timer 0 on
}

void timer0() interrupt 1
{
if(!pwm_flag) //high
{
pwm_flag = 1; //setflag
PWMPIN = 1; //set PWM o/p pin
TH0 = pwm_width; //load timer
TF0 = 0; //clear interrupt flag
}
else //LOW
{
pwm_flag = 0; //clearflag
PWMPIN = 0; //clear PWM o/p pin
TH0 = 255 - pwm_width; //load timer
//delay_in_ms(300); //BAD don't do use in non interrupt mode
TF0 = 0; //clear interrupt flag
}
}

void initialization()
{
P3IF = 0x08;
P3MDOUT &= ~0x80; //Port 3 output mode
P3IF |= 0x08; //Port 3 interrupt flag

P3 |= 0x80; //Latch it
EIE2 |= 0x20; //enable interrupt 2
EA = 1; //enable global variables


WDTCN = 0xde; //disable watchdog timer
WDTCN = 0xad; //must be winthin 4 clock cycles
light = OFF; //initial start light off
XBR2 = 0x40; //Enable crossbar
P1MDOUT |= 0x41; //Enable P1^0 and P1^6 as outputs (transistor pwm and green D3 LED)
P1MDIN = 0xFE; //Port 1 input mode (p3.7 SW2 switch)
PWMPIN = 0; //disable PWM
}

void buttoncount(int temp)
{
if (temp == 0) //mode 0 == off
{
ET0 = OFF; //turn clock off
};
if (temp == 1) //mode 1 == button pressed once
{
ET0 = ON; //turn clock on
delay_in_ms(800);
};
if (temp > 1) //mode 2+ back to off
{
buttoncycle = 0;
};
}

void button_ISR() interrupt 19
{
P3IF = ~0x80; //clear interrupt
light_it(); //turn D3 on to show button is pressed
buttoncycle ++; //cycle switch
delay_in_ms(50); //delay 50ms to show light
unlight_it(); //turn D3 off
//buttoncount(buttoncycle);
}

main()
{
pwm_setup(); //init pwm
initialization(); //init everything else
while (1){

buttoncount(buttoncycle); //continuously monitor SW2 (P3.7)
 


};
}
Thanks again.
 
Top