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

📄 test.c

📁 一个51单片机温度控制器,又一个示范如何在2051这样的小内存小ROM单片机上实现实时多任务小例子.使用时间片和状态机来完成任务的调度,而不是靠任务切换机制(这样小的资源是不足以支持RTOS的)
💻 C
字号:
#include <reg51.h>

code unsigned char* ver = "00000005";

sbit CS0 = P3^0;
sbit CS1 = P1^6;
sbit CS2 = P1^5;
sbit CS3 = P3^1;
sbit CS4 = P1^3;
sbit CS5 = P3^7;

sbit LIGHT = P3^3;
sbit JX = P3^4;
sbit WARM = P3^5;

//#define DATA_PORT P1

void out_cs_mask(bit n){
	CS0 = n;
	CS1 = n;
	CS2 = n;
	CS3 = n;
	CS4 = n;
	CS5 = n;
}

void out_cs(unsigned char cs, bit n){
	switch (cs){
		case 0:			CS0 = n;			break;
		case 1:			CS1 = n;			break;
		case 2:			CS2 = n;			break;
		case 3:			CS3 = n;			break;
		case 4:			CS4 = n;			break;
		case 5:			CS5 = n;			break;
	}
}

sbit CLK = P1^7;
sbit DATA = P1^4;
void spiout(unsigned char byte){
	unsigned char i;
	CLK = 0;
	for(i=0; i<8; i++){
		if(byte & 1)
			DATA = 1;
		else
			DATA = 0;
		CLK = 1;
		CLK = 0;
		byte >>= 1;
	}
}

#define a +1
#define b +2
#define c +4
#define d +8
#define e +16
#define f +32
#define g +64
//code unsigned char font[16] = "\x6f\x41\x3b\x6b" "\x4d\x76\x77\xe4" "\xf7\xf6\x00\x00" "\x00\x00\x00\x00";
code unsigned char font[16] = {
	a b c e f g,	//0
	a g,			//1
	a b d e f,		//2
	b a d g f,		//3
	a c d g,		//4
	b c d f g,		//5
	b c d e f g,	//6
	a b g,			//7
	a b c d e f g,	//8
	a b c d f g,	//9
	a b c d e g,	//A
	c d e f g,		//B
	b c e f,		//C
	a d e f g,		//D
	b c d e f,		//E
	b c d e,		//F
};
#undef a
#undef b
#undef c
#undef d
#undef e
#undef f
#undef g

#define DISP_WIDTH 6
unsigned char disp_buff[DISP_WIDTH];

unsigned char dot_pos = DISP_WIDTH;
unsigned char disp_cs = 0;
bit	time_dot_on = 0;


/*key value:
1:				(1<<2)
2:				(1<<3)
3:				(1<<7)
4:				(1<<6)
5:				(1<<5)
6:				(1<<4)
*/
#define	KEY_FUNC			(1<<5)
#define	KEY_SET				(1<<4)
#define KEY_WARM_START		(1<<6)
#define KEY_LIGHT_START		(1<<3)
#define KEY_JX_START		(1<<1)
#define KEY_ALL_START		(1<<7)
#define KEY_POWER			(1<<2)

unsigned char key_reg = 0x00, tmp_key_reg = 0x00;
unsigned char key_cs = 0;
sbit KEY_LINE = P1^2;		//键盘扫描读取线
bit disp_on = 1;
unsigned char disp_off_cs = DISP_WIDTH;
void out_disp_buff(){
	unsigned char disp_data;

	out_cs_mask(1);
	//键盘扫描
	if(key_cs == 0)
		tmp_key_reg = 0;
	disp_data = 1<<key_cs;
	spiout(disp_data);
	if(KEY_LINE)
		tmp_key_reg |= disp_data;
	else
		tmp_key_reg &= ~disp_data;
	key_cs++;
	key_cs &= 7;
	if(key_cs == 0){
		key_reg = tmp_key_reg;
//		disp_buff[5] = key_reg;
	}
	//键盘扫描完成

//	if (!disp_on){
//		out_cs_mask(1);
//		return;
//	}

	disp_data = disp_buff[disp_cs];
	if (dot_pos == disp_cs)
		disp_data |= 0x80;

	if (time_dot_on && disp_cs == 3)
		disp_data |= 0x80;


	if ((disp_cs & 1) == 1){
		unsigned char d;
		d = (disp_data & 0x80) >> 3;
		d |= (disp_data & 0x40) >> 1;
		d |= (disp_data & 0x20) << 1;
		d |= (disp_data & 0x10) << 3;
		d |= (disp_data & 0x8) >> 3;
		d |= (disp_data & 0x4) >> 1;
		d |= (disp_data & 0x2) << 1;
		d |= (disp_data & 0x1) << 3;
		disp_data = d;
	}

	//DATA_PORT = ~disp_data;
	spiout(disp_data);//~disp_data表示共阳驱动,disp_data是共阴驱动
	if (disp_on){
		out_cs(disp_cs, 0);
	} else {
		if (disp_off_cs >= DISP_WIDTH){
			out_cs_mask(1);
		} else {
			if (disp_cs == disp_off_cs){
				out_cs(disp_cs, 1);
			} else {
				out_cs(disp_cs, 0);
			}
		}
	}
	disp_cs++;
	if (disp_cs == DISP_WIDTH)
		disp_cs = 0;
}

unsigned int disp_flash = 0;
bit sys_wake_up = 0;


unsigned char temper = 20;
unsigned int temper_gate = 0;

unsigned int time_min= 0;
unsigned char time_sec= 0;
unsigned int time_ms= 0;
unsigned int sys_clock=0;
unsigned char jiffies = 0;
bit timer_isr_stop = 0;
bit warm_start = 0;
bit light_start = 0;
bit jx_start = 0;

sbit TEMPER_TEST = P3^6;	//电压比较器输出端,温度检测
sbit TEMPER_KEY = P1^1;
//unsigned int temper_test_count = 0;
unsigned int temper_test_count = 0;
unsigned int temper_not_test_count = 250;
#define TESTING 1
#define NOT_TESTING 0
bit temp_test_cycle = NOT_TESTING;

void timer_isr(void) interrupt 1 using 1{
	//测温例程
	if (temp_test_cycle == TESTING){
		temper_test_count++;
		if (!TEMPER_TEST){
			TEMPER_KEY = 0;		//开始放电
			temper_not_test_count = 2500;		//放电250个周期
#if 1
			if (temper_gate > temper_test_count){
				unsigned int diff = temper_gate - temper_test_count;
				if (diff > 80)
					temper_gate = temper_test_count;
				else
					temper_gate -= diff / 10;
			}else{
				unsigned int diff = temper_test_count - temper_gate;
				if (diff > 80)
					temper_gate = temper_test_count;
				else
					temper_gate += diff / 10;
			}
#else
			temper_gate = temper_test_count;
#endif
			temp_test_cycle = NOT_TESTING;
		}
	} else {
		temper_not_test_count--;
		if (temper_not_test_count == 0){
			TEMPER_KEY = 1;			//停止放电,开始充电
			temp_test_cycle = TESTING;
			temper_test_count = 0;
		}
	}
	//测温例程结束

	jiffies++;
	if (jiffies < 10)
		return;
	jiffies = 0;
	sys_wake_up = 1;
	sys_clock++;
	if(timer_isr_stop)
		return;
	if(!(warm_start || light_start || jx_start))
		return;
	time_ms++;
	if(time_ms == 1000)//同步闪烁与字符跳变
		disp_flash = 0;
	if (time_ms == 1000){//1000 == 1 Sec{
		time_ms = 0;
		time_sec++;
	}
	if (time_sec == 60){
		time_sec = 0;
		time_min++;
		if(time_min == 1440)
			time_min = 0;
	}
}

void timer_init(void){
	TMOD=0x02;			//自动重装模式
//	TH0=TL0=0x9b;//12M
//	TH0=TL0=0x7a;//16M
//	TH0=TL0=0x75;//16.59M
//	TH0=TL0=0x72;//17M
//	TH0=TL0=0x37;//24M
	TH0=TL0=-200;//24M
	EA=1;
	ET0=1;
	TR0=1;

	TEMPER_KEY = 0;		//开机即开始对电容放电.
}

void out_time(unsigned int out_time){
	disp_buff[3] = font[(out_time/100)%10];
	disp_buff[4] = font[(out_time/10)%10];
	disp_buff[5] = font[out_time%10];
}

void out_temper(unsigned char out_temper){
#if 0
	disp_buff[0] = 0;
	disp_buff[1] = font[(temper_gate/1000)%10];
	disp_buff[3] = font[(temper_gate/100)%10];
	disp_buff[4] = font[(temper_gate/10)%10];
	disp_buff[5] = font[temper_gate%10];
#else
	disp_buff[0] = font[(out_temper/10)%10];
	disp_buff[1] = font[out_temper%10];
#endif
}

void out_jx_light(void){
	unsigned char jx_light_st = 0;
	if (jx_start)
		jx_light_st |= 0x0f;
	if (light_start)
		jx_light_st |= 0xf0;
	disp_buff[2] = jx_light_st;
}



typedef struct temper_tab_s{
	unsigned int temper_gate;
	unsigned char temper;
}temper_tab_t;



unsigned char temper_gate2temper(unsigned int _temper_gate){
	unsigned int t = 55626;
	t /= (_temper_gate/10);
	t -= 273;
	if (t>255)
		return 0;
	return (unsigned char)t;
}

#define FUCTION_TEMPER10		0
#define FUCTION_TEMPER			1
#define FUCTION_TIME_MIN100		2
#define FUCTION_TIME_MIN10		3
#define FUCTION_TIME_MIN		4
#define FUCTION_NORMAL			5
unsigned char function_select = FUCTION_NORMAL;

bit key_set = 0;
bit key_func = 0;
bit key_power = 0;
bit key_warm_start = 0;
bit key_light_start = 0;
bit key_jx_start = 0;

#define PUSH_DELAY 200		//100ms
#define FIRST_PUSH_DELAY 500		//250ms

unsigned int light_timer_start = 0;
unsigned int light_timer = 30;		//紫外线定时时长固定为30分钟
unsigned int jx_timer_start = 0;
unsigned int jx_timer = 30;		//加香定时时长固定为30分钟
#define TEMPER_LIMIT_MAX 50			//最高可设温度
unsigned char temper_limit = 50;		//默认最高温35度
#define TIMER_LONG_MAX 360				//最长可设加热时间
unsigned int warm_timer_start = 0;
unsigned int warm_timer = 60;		//默认加热时间,单位为秒

unsigned int last_key_press_time = 0;
#define NOPRESS_TIMER_MAX 5000		//5秒

bit power_status = 1;
unsigned int set_temper_limit_delay = 32000;

void key_scan(void){
	//按键为高电平触发.
	if (key_reg){
		last_key_press_time = sys_clock;
	}else{
		if(function_select != FUCTION_NORMAL && (unsigned int)(sys_clock - last_key_press_time > NOPRESS_TIMER_MAX)){
			key_reg = KEY_FUNC;
			function_select = FUCTION_NORMAL - 1;
		}
	}

	if(key_reg & KEY_SET){
		disp_flash = 0;
		if(!key_set){//原来未按下才处理,否则不作处理.
			if (function_select != FUCTION_NORMAL)
				timer_isr_stop = 1;
			if (function_select == FUCTION_TIME_MIN100){
				warm_timer = (warm_timer/1000)*1000 + (warm_timer + 100)%1000;
			}else if (function_select == FUCTION_TIME_MIN10){
				warm_timer = (warm_timer/100)*100 + (warm_timer + 10)%100;
			}else if (function_select == FUCTION_TIME_MIN){
				warm_timer = (warm_timer/10)*10 + (warm_timer + 1)%10;
			}else if (function_select == FUCTION_TEMPER10){
				temper_limit = (temper_limit/100)*100 + (temper_limit + 10)%100;
				if (temper_limit/10 > (TEMPER_LIMIT_MAX + 9)/10)
					temper_limit = 0;
			}else if (function_select == FUCTION_TEMPER){
				temper_limit = (temper_limit/10)*10 + (temper_limit + 1)%10;
			}
			key_set = 1;
		}
	}else
		key_set = 0;

	if(key_reg & KEY_FUNC){
		disp_flash = 0;
		if(!key_func){//原来未按下,改变设置模式,否则不作处理.
			if (function_select == FUCTION_NORMAL){
				function_select = 0;
			}else{
				function_select++;
				if (function_select == FUCTION_NORMAL){
					if (timer_isr_stop){
						timer_isr_stop = 0;
						time_ms = 0;
					}
					disp_on = 1;
					if (temper_limit > TEMPER_LIMIT_MAX)
						temper_limit = TEMPER_LIMIT_MAX;
					if (warm_timer > TIMER_LONG_MAX)
						warm_timer = TIMER_LONG_MAX;
				}
			}
			key_func = 1;
		}
	}else
		key_func = 0;

	if(key_reg & KEY_WARM_START){
		if(!key_warm_start){//原来未按下,改变设置模式,否则不作处理.
			warm_start= !warm_start;
			if(warm_start)
				warm_timer_start = time_min;
			key_warm_start = 1;
		}
	}else
		key_warm_start = 0;

	if(key_reg & KEY_LIGHT_START){
		if(!key_light_start){//原来未按下,改变设置模式,否则不作处理.
			light_start= !light_start;
			if(light_start)
				light_timer_start = time_min;
			key_light_start = 1;
		}
	}else
		key_light_start = 0;

	if(key_reg & KEY_JX_START){
		if(!key_jx_start){//原来未按下,改变设置模式,否则不作处理.
			jx_start= !jx_start;
			if(jx_start)
				jx_timer_start = time_min;
			key_jx_start = 1;
		}
	}else
		key_jx_start = 0;


	if(key_reg & KEY_ALL_START){
		warm_timer_start = time_min;
		warm_start = 1;
		light_timer_start = time_min;
		light_start = 1;
		jx_timer_start = time_min;
		jx_start = 1;
	}

	if(key_reg & KEY_POWER){
		if(!key_power){//原来未按下,改变设置模式,否则不作处理.
			power_status = !power_status;
			temper_limit = temper+20;
			key_power = 1;
			disp_on = 1;
			if (temper_limit > TEMPER_LIMIT_MAX)
				temper_limit = TEMPER_LIMIT_MAX;
			set_temper_limit_delay = 32000;
		}
	}else
		key_power = 0;

	if (!power_status){
		function_select = FUCTION_NORMAL;
		timer_isr_stop = 0;
		jx_start = 0;
		light_start = 0;
		warm_start = 0;
		time_min = 0;
		time_sec = 0;
	}
}

#define FLASH_CHECK(x) disp_flash % x < x / 2
void sys_run(){
	temper_limit = temper+20;
	if (temper_limit > TEMPER_LIMIT_MAX)
		temper_limit = TEMPER_LIMIT_MAX;
	while(1){
		if (!sys_wake_up)
			continue;
		sys_wake_up = 0;
		temper = temper_gate2temper(temper_gate);
		if (set_temper_limit_delay){
			set_temper_limit_delay--;
			if (set_temper_limit_delay == 0)
				temper_limit = temper+20;
		}
		key_scan();
		if(function_select == FUCTION_NORMAL){
			if (warm_start && time_min - warm_timer_start< warm_timer){//timer_long 为0时,定时器不再作输出.
				//打开设备
				if (temper < temper_limit){			//温度高于或达到设定值停止加热
					WARM = 1;
				}else if (temper >= temper_limit)
					WARM = 0;
				disp_flash++;
				if(FLASH_CHECK(1000))
//					disp_on = 1;
					time_dot_on = 1;
				else
//					disp_on = 0;
					time_dot_on = 0;
			} else {
					//关闭设备
					WARM = 0;
//					disp_on = 1;
					time_dot_on = 0;
					warm_start = 0;
			}
			if (light_start && time_min - light_timer_start < light_timer){//light_timer 为0时,定时器不再作输出.
				//打开设备
					LIGHT = 1;
			} else {
				//关闭设备
				LIGHT = 0;
				light_start = 0;
			}
			if (jx_start && time_min - jx_timer_start < jx_timer){//jx_timer 为0时,定时器不再作输出.
				//打开设备
					JX = 1;
			} else {
				//关闭设备
				JX = 0;
				jx_start = 0;
			}
			if (!(warm_start || light_start || jx_start))//所有功能都关闭时,时间清0
				time_min = 0;
		} else {
			disp_flash++;
			if(FLASH_CHECK(1000))
				disp_on = 1;
			else
				disp_on = 0;
		}
		
		if (function_select == FUCTION_TIME_MIN100){
			disp_off_cs = 3;
			out_time(warm_timer);
			out_temper(temper_limit);
		}else if (function_select == FUCTION_TIME_MIN10){
			disp_off_cs = 4;
			out_time(warm_timer);
			out_temper(temper_limit);
		}else if (function_select == FUCTION_TIME_MIN){
			disp_off_cs = 5;
			out_time(warm_timer);
			out_temper(temper_limit);
		}else if (function_select == FUCTION_TEMPER10){
			disp_off_cs = 0;
			out_time(warm_timer);
			out_temper(temper_limit);
		}else if (function_select == FUCTION_TEMPER){
			disp_off_cs = 1;
			out_time(warm_timer);
			out_temper(temper_limit);
		}else{
			disp_off_cs = DISP_WIDTH;
			out_time(warm_start?time_min:warm_timer);
			if (warm_start && light_start && jx_start)
				out_temper(temper_limit);
			else
				out_temper(temper);
		}
		out_jx_light();
#if 0
{
unsigned char i;
disp_buff[0] = disp_buff[1] = disp_buff[2] = disp_buff[3] = disp_buff[4] = disp_buff[5] = 0;
for(i=0; i<8; i++)
{
if (key_reg &(1<<i))
	disp_buff[4] = font[i];
}
}
#endif
		if (!power_status){
			disp_off_cs = DISP_WIDTH;
			disp_on = 0;
		}
		out_disp_buff();
	}
}



void main(){
	timer_init();
	sys_run();
}


#if 0
code temper_tab_t temper_tab[100]={
	{550, 0},
	{550, 1},
	{550, 2},
	{550, 3},
	{550, 4},
	{550, 5},
	{550, 6},
	{550, 7},
	{550, 8},
	{550, 9},
	{550, 10},
	{550, 11},
	{550, 12},
	{550, 13},
	{550, 14},
	{550, 15},
	{550, 16},
	{550, 17},
	{550, 18},
	{550, 19},
	{550, 20},
	{550, 21},
	{550, 22},
	{550, 23},
	{550, 24},
	{550, 25},
	{550, 26},
	{550, 27},
	{550, 28},
	{550, 29},
	{550, 30},
	{550, 31},
	{550, 32},
	{550, 33},
	{550, 34},
	{550, 35},
	{550, 36},
	{550, 37},
	{550, 38},
	{550, 39},
	{550, 40},
	{550, 41},
	{550, 42},
	{550, 43},
	{550, 44},
	{550, 45},
	{550, 46},
	{550, 47},
	{550, 48},
	{550, 49},
	{550, 50},
	{550, 51},
	{550, 52},
	{550, 53},
	{550, 54},
	{550, 55},
	{550, 56},
	{550, 57},
	{550, 58},
	{550, 59},
	{550, 60},
	{550, 61},
	{550, 62},
	{550, 63},
	{550, 64},
	{550, 65},
	{550, 66},
	{550, 67},
	{550, 68},
	{550, 69},
	{550, 70},
	{550, 71},
	{550, 72},
	{550, 73},
	{550, 74},
	{550, 75},
	{550, 76},
	{550, 77},
	{550, 78},
	{550, 79},
	{550, 80},
	{550, 81},
	{550, 82},
	{550, 83},
	{550, 84},
	{550, 85},
	{550, 86},
	{550, 87},
	{550, 88},
	{550, 89},
	{550, 90},
	{550, 91},
	{550, 92},
	{550, 93},
	{550, 94},
	{550, 95},
	{550, 96},
	{550, 97},
	{550, 98},
	{550, 99},
};
#endif

⌨️ 快捷键说明

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