⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demo1_opex.c

📁 学完单片机就要使用实时系统在单片机上运行
💻 C
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////
// demo1_opex.c
// (C) 2004 Steve Childress stevech@san.rr.com
// See main(), below. It begins here.

#include "OPEX.h"
void OW_test_main(OPEX_TCB *);
						
void DS1820(OPEX_TCB *);

extern OPEX_TCB *schedQ, *flagwaitQ, *pendingQ;
extern  unsigned int _stack_watch;	// see Timerv1.c
						
// for the ATmega32
#define JMPBOOT "jmp 0x3c00"  	// boot in mega32

/////////////////////////////////////////////////////////////////////////////



void usart_init(void);
void io_init(void);
void timer_init(void);
	
///////////////////////////////////
char StringBuf1[128];	// global scratch buffer for string work
BYTE reporting;			// flag
BYTE mcusr;				// MCUSR at startup



//////////////////////////////////////
// LED blinker
void led_toggle(BYTE bitmask)
{
	PORTC ^= bitmask;	// PORTC has some LEDs
}



//////////////////////////////////////////////////
// the idle task. see OPEX_sched_setIdleFunc(&idle), below
// 
void idle(void)
{
	static unsigned long idlex;
	static BYTE idlemark_sec;
	
	//if (reporting)  {
		if (idlemark_sec != time.second)  {
			idlemark_sec = time.second;
			OPEX_format_time(StringBuf1, &time); 
			OPEX_puts(StringBuf1);
			sprintf_P(StringBuf1, PSTR(" calls per second to idle() = %lu "), idlex);
			OPEX_putline(StringBuf1);
			idlex = 0;
		}
		else  {
			++idlex;  // a long
		}
	//}
}


/////////////////////////////////////
//  debug tool. print report on OPEX_TCB passed
void report(OPEX_TCB *f)
{
	if (reporting)  {
		if (f != NULL)  {
			OPEX_format_time(StringBuf1,  &time);	// show current time
			OPEX_puts(StringBuf1);
			OPEX_sched_showQitem(f, StringBuf1, 0);			// show function status
		}	
	}
}

/// SCHEDULED ///////////////////////
// A task to display task queue then quit
void task_showQ(OPEX_TCB *me)
{
	int n;
	
	n = (unsigned int)me->pinfo;  // parent task can set this flag
	OPEX_sched_show_mem(StringBuf1, RAMEND);  // memory statistics (RAMEND is in io.h of AVR includes
	OPEX_sched_showQ(StringBuf1, (BYTE)n);  // do the command
	OPEX_sched_quit();	
}


// SCHEDULED ///////////////////////////////////////////////
// This task schedules itself to run the next time time changes
//  to/from daylight saving.
// If time is changed via host command, this prog is resched to run right now.
void OPEX_sched_showQitem(OPEX_TCB *f, char *p, char showflags);

void DST_monitor(OPEX_TCB *me)
{
	int dst;
	
	if (OPEX_daylight_saving_adjust())  	// possibly adjust time of day
		OPEX_sched_time_changed();		// time did change, tell scheduler 

	dst = OPEX_is_daylight_saving();		// get current DST status 1 = DST, 0 = Standard
	me->state = dst; 				// just FYI

	OPEX_sched_showQitem(me, StringBuf1, 1);
	
	// now determine when to run this again
	
	OPEX_daylight_saving_changes_at(0, &me->when); // get ending DST date for DST this year
	// run this only if not now in DST. In DST, the next time to run was set in the code above
	if (!dst)  {  // not in DST now
		--me->when.hour;		// DST ends at 1AM standard time
		if (OPEX_compare_dt(&time, &me->when) >= 0)	{	// if date/time is >= end of DST		
			++me->when.year;						// so no more DST this year
			OPEX_daylight_saving_changes_at(1, &me->when); // get starting date for DST NEXT year
		}
		else
			OPEX_daylight_saving_changes_at(1, &me->when); // get starting date for DST this year			
	}
	
	OPEX_sched_showQitem(me, StringBuf1, 1);
	// The next desired time for this task to run is in the OPEX_TCB (*me)
}
	
// SCHEDULED ///////////////////////////////////////////////
// spawn a task to do a brief mode display of the scheduler's queues
// thus, task0 will appear in the queue.
// reschedule myself to run again later
void task0(OPEX_TCB *me)
{
	OPEX_TCB *f;
	
	report(me);
	if ((f = OPEX_sched_new(&task_showQ, NULL)) != NULL)  // schedule this to run then quit
		f->pinfo = (void *)1; // set flag = brief mode
	OPEX_sched_resched(me, 0, 0, 0, 15, 0);  // run me again later
}

// SCHEDULED ///////////////////////////////////////////////
void task1(OPEX_TCB *me)
{

	led_toggle(1);	// toggle LED every second
	report(me);
	OPEX_sched_now(me);		// get current time
	me->when.tick = 0;	// tick could be non-zero if this ran a little late
	OPEX_date_add( &me->when, 0, 0, 0, 1, 0);  // run again in one second
}


// SCHEDULED ///////////////////////////////////////////////
void task2(OPEX_TCB *me)
{
	led_toggle(2);		// toggle LED eacah time run
	report(me);
	//now(&me->when);
	me->when.tick = 0;  // not really needed, but shows if tardy
	OPEX_date_add(&me->when, 0, 0, 0, rand() % 10, 0);  // random seconds mod 10 later
	me->when.tick = TicksPerSecond/2;  // on the half second
}


// SCHEDULED ///////////////////////////////////////////////
// each time this runs, it creates a new task then quits.

char task3name[10];
BYTE task3num;

void task3(OPEX_TCB *me)
{
	OPEX_TCB *f;
	char oldname[sizeof(task3name)];
	
	led_toggle(4); // toggle LED eacah time run
	//report(me);
	//OPEX_sched_showQ(StringBuf1);
	memcpy(oldname, me->name, sizeof(oldname));  // get copy of old task name
	sprintf_P(task3name, PSTR("TASK3-%d"), (int)(++task3num));
	f = OPEX_sched_new(&task3, task3name);  // make a new task
	f->when.tick = 0; // not really needed, but shows if tardy
	//                    days hrs mins secs ticks
	OPEX_sched_resched(f, 0,   0,  0,   5,   0);  // change when it will first run
	sprintf_P(StringBuf1, PSTR("%s Quitting, %s started"), oldname, f->name);
	OPEX_putline(StringBuf1);
	OPEX_sched_quit();		// abandon this task
}

struct MYINFO  {		// used by task3
		BYTE status;
		DATE_TIME mark;
	};

// SCHEDULED ///////////////////////////////////////////////
// first time run, this task adds a user data structure on
// the OPEX_TCB.
// Each time it's run thereafer, it shows the noted time and
// an incrementing state counter
// the user data also carries a counter called "state" which is shown.

void task4(OPEX_TCB *me)
{
	struct MYINFO *myinfo;  // lotta stack space for this
	
	led_toggle(8); // toggle LED eacah time run
	
	if (me->pinfo == 0)  {  // check if first time called since instantiated
		myinfo = (void *) OPEX_malloc(me, sizeof(struct MYINFO));  // get added user memory space			
		////myinfo = (void *) malloc(sizeof(struct MYINFO));  // get added user memory space
		me->pinfo = myinfo;
		myinfo->status = 0;	// initialize the state counter of this instance
		OPEX_now(&myinfo->mark);	// remember when I first ran
		////OPEX_sched_malloc(me, 32); // get some RAM, to test OPEX_sched_free, ignore return
	}
	report(me);		// show that I ran
	myinfo = me->pinfo;
	
	// print out my name, state counter, and date/time of the "first ran at mark"	
	sprintf(StringBuf1, "%s status=%d mark: ", me->name, (int)(myinfo->status++));
	OPEX_puts(StringBuf1);
	OPEX_format_date_time(StringBuf1, &myinfo->mark);
	OPEX_putline(StringBuf1);

	// reschedule me to run later
	OPEX_sched_now(me);  // get current time and add some to it
	OPEX_date_add( &me->when, 0, 0, 0, 30, TicksPerSecond/2);  // again in x seconds and 1/2 sec)
}


// SCHEDULED ///////////////////////////////////////////////
BYTE task5count = 0;

void task5(OPEX_TCB *me)
{
	OPEX_TCB *f;
	
	led_toggle(0x10); // toggle LED eacah time run
	report(me);
	if (task5count == 0)  {
		while (task5count < 3)   { 
			f = OPEX_sched_new(&task5, "Task5x");
			f->pinfo = (void *) (int) task5count;
			OPEX_sched_resched(f, 0, 0, 0, 5+task5count, 0); // run n seconds from now
			++task5count;
		}
	}
	else  {
		task5count--;
		OPEX_sched_quit();
	}		
	OPEX_sched_resched(me, 0, 0, 0, 30, 0);
}


// SCHEDULED ///////////////////////////////////////////////
// this runs once per clock tick, unless the serial port is blocking
// due to buffer full oun output from other tasks.
// every 2 seconds worth of ticks, it reports. So check time between reports = 2sec
void task6(OPEX_TCB *me)
{
	static BYTE task6n;
	
	led_toggle(0x20); 	// toggle LED eacah time run
	OPEX_sched_resched(me, 0, 0, 0, 0, 1);
	if (--task6n == 0)  {
		task6n = TicksPerSecond*2;	 
		report(me);
	}
}

// SCHEDULED ///////////////////////////////////////////////
// runs when odd numbered bits in "task7_flags" change; 
// the serial port monitor task toggles that flag when digits 0-7 come in from serial port.
BYTE task7_flags;
void task7(OPEX_TCB *me)
{
	report(me);
	sprintf_P(StringBuf1, PSTR("%s: flags are now 0x%X"), me->name, task7_flags);
	OPEX_putline(StringBuf1);
	OPEX_sched_on_flag(&task7_flags, 0xAA); // run this code again when certain bits change
}

////// SCHEDULED /////////////	
// poll I/O bit for change in state, and debounce it assuming it's a pushbutton switch.
// Assume no interrupt is possible for this I/O, so must use polling.
//  This also shows how to avoid additional static variables
// And, this is done as a finite state machine
#define task8bitno 0
void task8(OPEX_TCB *me)
{
	BYTE b, n;
		
	b = PINA & (1<<task8bitno); // get I/O bit state
		
	n = TicksPerSecond/8;	// default clock ticks to when this run again
	switch ((int)me->pinfo)  {  // finite state machine
		case 0:
			cbi(DDRA,  task8bitno); 	// make this bit an input
			sbi(PORTA, task8bitno); 	// enable the pull-up resistor
			me->pinfo = (void *)1; // am initialized, set finite state machine
			break;
		case 1:
			me->flagmask = b;	// note the state of the I/O pin
			me->pinfo = (void *)2;		// wait for a change of state
			break;
		case 2:
			if (me->flagmask != b)     { // has I/O bit changed state?
				me->pinfo = (void *)3;		// yes, check again soon for continued same bit
				n = 1; // faster poll now
			}
			break;
		case 3:
			OPEX_puts(me->name);		// display taskname
			if (me->flagmask != b)	{  // still in changed state?
				sprintf_P(StringBuf1, PSTR(" PORTA bit changed 0x%X"), b);
				OPEX_putline(StringBuf1);
				me->flagmask = b;		// note new state
				me->pinfo = (void *)2;	// look for another change in bit
			}
			else  {
				OPEX_putline(" PORTA glitch ignored");
				me->pinfo = (void *)2;	// ignore too brief state change
				break;
			}
	}					
	OPEX_sched_resched(me, 0, 0, 0, 0, n); // run again in x clock ticks
}


////// SCHEDULED /////////////	
// poll I/O bit for change in state, and debounce it assuming it's a pushbutton switch.
// This task does the state machine as in Task 8 but by changing function pointers
//  instead of the method in task8.

#define task9bitno 1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -