here is the code. enjoy.
#include
#include "gpio.h"
#define LED_PORT P2
#define LED_DDR P2
#define LED_PINs 0xff //led connected to P3.0 -> P3.7
#define LED_ON(val) IO_CLR(LED_PORT, val) //output val on led_port
#define LED_OFF(val) IO_SET(LED_PORT, val) //clear val
#define DIG_PORT P3
#define DIG_DDR P3
#define DIG0 (1<<0) //digit 0 on P3.0
#define DIG1 (1<<3) //digit 1 on P3.3
#define DIG2 (1<<7) //digit 2 on P3.7
#define DIGs (DIG0 | DIG1 | DIG2)
#define DIG_ON(digs) IO_CLR(DIG_PORT, digs) //turn on digs
#define DIG_OFF(digs) IO_SET(DIG_PORT, digs) //turn off digs
unsigned char val_disp=90; //value to be displayed. 00..99
unsigned char dig_disp=0; //dig to be displayed. 0 or DIG_MAX
//a simple multi-tasking OS
//each task has a pre-define time slot (XOS_slot), + an idle slot
//user can add up to 255 tasks (including the idle task).
//each task has to take less than the time slot to finish.
//the os uses tmr0 so no task can utilize tmr0
#define MSB(word_t) ((word_t) >> 8) //highest byte of a word type
#define LSB(word_t) ((word_t) & 0xff) //lowest byte of a word type
//XOS configuration
unsigned char XOS_state; //xos state indicator
unsigned char XOS_state_prev; //previous state
unsigned short XOS_slot; //xos time slot, in terms of timer ticks (1tick=1us for 12Mhz xtal)
void XOS_isr(void) interrupt 1 { //xos interrupt on tmr0
TF0=0; //clear flag - done by hardware
//TH0=0xff-(XOS_slot >> 8); //reset th0, carry over timing errors
TH0+=-MSB(XOS_slot);
//TL0=0xff-(XOS_slot & 0x00ff); //reset tlo, carry over timing errors
TL0+=-LSB(XOS_slot);
//XOS_state=(XOS_state==XOS_STATE_MAX)? 0: XOS_state+1; //update state indicator
XOS_state++; //increment XOS_state;
}
void XOS_init(unsigned short slot) { //initiate xos to run at slot ticks
//set tmr0 to 16 bit timer operation (mode 1)
TMOD &= 0xf0; //clear tmod's lower 4 bits
TMOD |= 0x01; //not gated, tmr operation, mode 1
TF0=0; //clear flag - done by hardware
//define slot size, in tmr ticks
XOS_slot=slot; //define xos time slot
//set tmr0
//TH0=0xff-(XOS_slot >> 8); //reset th0
TH0=-MSB(XOS_slot);
//TL0=0xff-(XOS_slot & 0x00ff); //reset tlo
TL0=-LSB(XOS_slot);
//set interrupt
ET0=1; //enable tmr0 interrupt
EA=1; //enable all interrupt
TR0=1; //turn on tmr0
//set XOS state variables
XOS_state=0; //reset xos_state
XOS_state_prev=XOS_state; //reset xos_state_prev
}
//end XOS configuration
void mcu_init(void) { //initiate the mcu
DIG_OFF(DIGs); //all digits off
IO_OUT(DIG_DDR, DIGs); //digs as output
LED_OFF(LED_PINs); //all leds off
IO_OUT(LED_DDR, LED_PINs); //led_pins as output
}
//dummy task 0 - display digits
void XOS_task0(void) {
//7-segment display data
const unsigned char LED_7SEG[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98};
unsigned char dig; //the dig to be turned on
unsigned char val; //value (0..9) to be displayed
DIG_OFF(DIGs); //turn off all digits
switch (dig_disp) {
case 0: val=val_disp % 10; dig = DIG0; dig_disp+=1; break;
case 1: val=val_disp / 10; dig = DIG1; dig_disp=0; break;
//put more digs here if you have more than 2 7-segment displays
}
LED_PORT = LED_7SEG[val]; //display val
DIG_ON(dig); //turn on the current dig display
}
//xos task 1 - increment val_disp
void XOS_task1(void) {
static unsigned char task1_count=0; //how many times task1 has run
task1_count++; //update task1_count
if (task1_count==10) { //val_disp increments on every 10th run of XOS_task1
task1_count=0; //reset task count
val_disp+=1; //if task1 has run 10 times, increment val_disp
if (val_disp==100) val_disp=0; //make sure val_disp between 0..99
}
}
//xos task2 - not used
void XOS_task2(void) {
}
int main(void) {
mcu_init(); //initiate the mcu
XOS_init(10000); //time slot to be 10ms (10000us)
while (1) {
//each slot has a fixed length
switch (XOS_state) {
case 0: XOS_task0(); break; //run task0
case 1: XOS_task1(); XOS_state=0; break; //run task1
//case 2: XOS_task2(); /*XOS_state=0;*/ break; //run task2 /*, and reset XOS_state to eliminate the idle process*/
//add additional user tasks here
default: XOS_state=0; break; //reset XOS_state
}
//idle till the next tmr0 interrupt / xos time slot to run out
while (XOS_state == XOS_state_prev) continue;
XOS_state_prev=XOS_state; //update xos_state_prev
}
}