📄 led8.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 + -