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

📄 led8.c

📁 嵌入式系统中的一个显示器的驱动程序
💻 C
字号:
#include <AT89X51.h>	// use philips 89v51RD2
sfr WDTC = 0xC0;	//watch dog
sfr WDTD = 0x85;

void initial_system();	////串口方式1,允许接收,定时器1方式2,定时器0方式1
char get();			//读取串口,如超过312.5uS则置超时标志 time_overflow=0xFF
void put(char);
void display();		//显示disp_buffer[0~13]中的数,16bit表示一位LED,disp_buffer[1]==最左边的LED disp_buffer[0].7==1表示同时显示一个小数点,其他LED以此类推
void self_test();	//自测模式,依次点亮LED的每一笔段
void delay(unsigned int time);	//软件延时
void ModbusCrc(unsigned char x);// modbus协议CRC校验, R7为输入校验字节,CRC2为校验字
void clear_dog();		// clear watch dog time

unsigned char code SEG7[]={0x7D,0x0C,0xB5,0x9D,0xCC,0xD9,0xF9,0x0D,0xFD,0xDD,0xED,0xF8,0x71,0xBC,0xF1,0xE1,0x80,0x70,0x00};//字符0~9,'A'~'F','-','L',' '
unsigned char xdata buffer[25];
unsigned char xdata disp_buffer[14];//一个是串口接收缓存,另一个是显示缓存
unsigned char time_overflow;	//超时标志位
unsigned int  CRC2;		//用于CRC校验函数的变量

main(){
unsigned char i;
	initial_system();
	while(1)
	{
		while(get()!= 0x01)
			;		//wait myself address
		buffer[0]= 0x01;
		i= 1;
		time_overflow=0x00;
		while(time_overflow==0x00){
			buffer[i]= get();
			i++;
			if(i>25)	i=25;
		}
		if(i<25){		//三个功能:06H--写一位LED, 10H--写全部7位LED, 16H--自测,依次点亮LED的每一笔段
			switch(buffer[1]){	//select the fuction code
				case	0x10:	//写多寄存器,格式: 01,10,00,01,00,07,0e,14Byte data,CRC_high,CRC_low
					if(i!=24 || buffer[2]!=0x00 || buffer[3]!=0x00 || buffer[4]!=0x00 || buffer[5]!=0x07 || buffer[6]!=0x0E)//一共收23位数据,加上超时出错执行一次i++,所以i=24
						break;		//地址不是从0001开始的,写字节数不等于14 word的,都认为出错
					for(i=0,CRC2=0xFFFF;i<21;i++)
						ModbusCrc(buffer[i]);//计算crc
					if((buffer[22]==CRC2/256) && (buffer[21]==CRC2%256)){
							for(i=0;i<14;i++)
								disp_buffer[i]= buffer[i+7];
							display();
							for(i=0,CRC2=0xFFFF;i<6;i++)		//计算并返回报文
								ModbusCrc(buffer[i]);
							buffer[6]= CRC2%256;
							buffer[7]= CRC2/256;
							for(i=0;i<8;i++)
								put(buffer[i]);
					}
					break;
				case	0x06:	//写单寄存器,格式: 01,06,address_high,address_low,data_high,data_low,CRC
					if(i!=9 || buffer[2]!=0x00 || buffer[3]>0x06)
						break;	//地址不是从0001开始的,都认为出错
					for(i=0,CRC2=0xFFFF;i<6;i++)
						ModbusCrc(buffer[i]);//计算crc
					if((buffer[7]==CRC2/256) && (buffer[6]==CRC2%256)){
							i= buffer[3];
							disp_buffer[i*2]= buffer[4];
							disp_buffer[i*2+1]= buffer[5];
							display();
							for(i=0;i<8;i++)
								put(buffer[i]);		//正常处理返回报文
					}
					break;
			   	case	0x16:		//附加功能自我测试,格式: 01,16,ff,ff,ff,ff,ff,ff,ff,ff,CRC
					for(i=0,CRC2=0xFFFF;i<10;i++)
						ModbusCrc(buffer[i]);//计算crc
					if(buffer[2]==0xff && buffer[3]==0xff && buffer[4]==0xff && buffer[5]==0xff && buffer[6]==0xff && buffer[7]==0xff && buffer[8]==0xff && buffer[9]==0xff)
							if((buffer[11]==CRC2/256) && (buffer[10]==CRC2%256)){
								for(i=0;i<12;i++)
									put(buffer[i]);
								self_test();
							}
					break;
				case	0x03:
					for(i=0,CRC2=0xFFFF;i<6;i++)
						ModbusCrc(buffer[i]);//计算crc
						disp_buffer[0]=1;//---------
						display();//------------
					if((buffer[4]==0) && (buffer[5]==1) && (buffer[6]==CRC2%256) && (buffer[7]==CRC2/256)){//只允许读一个字节
						buffer[2]= 2;//byte of counts
						buffer[3]= buffer[4]= 0;//response data
						for(i=0,CRC2=0xFFFF;i<5;i++)
							ModbusCrc(buffer[i]);//计算crc
						buffer[5]= CRC2%256;	buffer[6]=CRC2/256;//CRC
						for(i=0;i<7;i++)
							put(buffer[i]);
					 }
					break;
				}
		}
	}
}

void initial_system(){
unsigned char i;
	P2= 0xff;
	P0= 0xff;	//笔段全亮
	delay(65000);
	delay(65000);
	SCON = 0x50; //串口方式1,允许接收
	TMOD = 0x21; //定时器1方式2,定时器0方式1
	TR1 = 1; //设定时器1开始计数
	TH1=TL1= 0xFD; //11.0592MHz 9600波特率
	TH0=TL0= 0x00;
	TI = 1;
	if((WDTC & 0x04)== 0){		//是上电复位,初始化显示	
		for(i=0;i<14;i++)
			disp_buffer[i]= 0x10; // '-'
	}
	display();
	WDTC= 0x0b;	// start watch_dog, about 5s overflow
}


void display(){
unsigned char i,ch,latch;
	i= 0;
	latch= 0x02;
	while(latch >0){
		ch= disp_buffer[i+1];
		if (disp_buffer[i] < 0x80)		//最高位为1,表示本位要显示一个小数点
			P0= SEG7[ch];
		else
			P0= SEG7[ch] | 0x02;		//显示一个小数点
		P2= latch;
		delay(20);
		P2= 0x00;
		latch= latch <<1;
		i= i+2;
	}
}

void self_test(){
unsigned char i;
	P2= 0xff;
	P0= 0x01;
	delay(50000);
	delay(50000);
	for(i=0;i<7;i++){
		P0= P0<<1;
		clear_dog();
		delay(50000);
		delay(50000);
	}
	P2= 0xff;
	P0= 0xff;	//笔段全亮
	while(1);
}

void delay(unsigned int time){
unsigned int v_delay;
	for(v_delay=0; v_delay<time; v_delay++);
}

void ModbusCrc(unsigned char x)
{
unsigned char k,v;
CRC2=CRC2^x;
for(k=0;k<8;k++)
      {
      v=CRC2 %2;
      CRC2=CRC2>>1;
      if(v==1) {CRC2=CRC2^0xa001;}
      }
}

char get(){
	time_overflow= 0x00;
	TF0= 0;
	TH0= 0xF0;	//about 5ms @ 12 clock
	TR0=1;			//计数一次=1.085us @ 11.0592MHz / 12 colck mode 
	while(RI==0){	
		clear_dog();
		if(TF0==1){
			time_overflow=0xFF;
			return(0);
		}
	}
	RI= 0;
	return(SBUF);
}

void put(char ch)
{
	TI= 0;
	SBUF= ch;
	while(!TI);
}

void clear_dog()
{
	WDTC= 0x0b;	//clear dog
}

⌨️ 快捷键说明

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