📄 uart.c
字号:
//PC reads MCU instruction structure: (by interrupt, ACII code display)
//format: start byte | type | device id | device add | length n | chksum | stop byte
//value? 'n' 'y' | 'r' | 0x01 | x | x | x |0x13 0x10
//byte? 2 | 1 | 1 | 1 | 1 | 1 | 2
#include <reg51.h>
//#include <config.h>
//declaration
sbit P1_0 = P1 ^ 0;
sbit P1_1 = P1 ^ 1;
sbit P1_2 = P1 ^ 2;
sbit P1_3 = P1 ^ 3;
sbit P1_4 = P1 ^ 4;
sbit P1_5 = P1 ^ 5;
sbit P1_6 = P1 ^ 6;
sbit P1_7 = P1 ^ 7;
#define F_ST1 0x6e //start byte n
#define F_ST2 0x79 //start byte y
#define F_R 0x72 //read r
#define F_W 0x77 //write w
#define F_D 0x64 //data d
#define F_B 0x62 //respond b
#define F_C 0x63 //resend instruction c
#define F_Q 0x71 //quit q
#define F_ADDR 0x31 //device address 0-9
#define F_END 0x7a //end byte z
#define F_SPACE 0x30 //space 0
#define F_ERR1 0x31 //error1,flagerr 1
#define F_ERR2 0x32 //error2 2
//define value
#define S_MAXBUF 16 //send/receive buffer size
#define FIELD_MAXBUF 48 //minimum buffer, bigger than 48 bits?coz protocol based on //20 bytes per transmission
#define communicationing P1_7 //communication mode
#define ERRFRAME_MAX 5 //continuous NOFRAME_CNT frame error
#define ERR_NOCNTMAX_RESEND \
if(++errframe_cnt<=ERRFRAME_MAX) resend_frame(); else errframe_cnt=communicationing=0;
//if over ERRFRAME_MAX, then stop communication ERR_NOCNTMAX_RESEND
//public
unsigned char databuf[FIELD_MAXBUF],errframe_cnt;
//function prototype
//void send(unsigned char ch);
//unsigned char receive(void);
//unsigned char CharToHex(unsigned char bChar);
//unsigned char HexToChar(unsigned char bHex);
//void com_init(unsigned int baud_rate);
//FUNCTIONS
/////////////////////////////////////////////////////////////////////
//function name?send()
//function?send one ASCII code to serial port
//input?ch-to be sent ASCII code
/////////////////////////////////////////////////////////////////////
void send(unsigned char ch)
{ SBUF=ch; while(TI==0);TI=0; }
/////////////////////////////////////////////////////////////////////
//function name?receive()
//function?receive one byte from serial
//return?one ASCII code
/////////////////////////////////////////////////////////////////////
unsigned char receive(void)
{while(RI==0);RI=0;return SBUF;}
/////////////////////////////////////////////////////////////////////
//function?CharToHex()
//function?convert ASCII code to 16 bits
//input?ASCII code
//return?16bits
/////////////////////////////////////////////////////////////////////
unsigned char CharToHex(unsigned char bChar)
{
if((bChar>=0x30)&&(bChar<=0x39)) //0x30='0'; 0x39='9'
bChar -= 0x30;
else if((bChar>=0x41)&&(bChar<=0x46))//capital letter 0x41='A'; 0x46='F'
bChar -= 0x37;
else if((bChar>=0x61)&&(bChar<=0x66))//small letter 0x61='a'; 0x66='f'
bChar -= 0x57;
else
bChar = 0xff;
return bChar;
}
/////////////////////////////////////////////////////////////////////
//Function name?HexToChar()
//Function?convert 16 bits to ASCII code
//Input ?16 bits
//Return?ASCII code
/////////////////////////////////////////////////////////////////////
unsigned char HexToChar(unsigned char bHex)
{
if((bHex>=0)&&(bHex<=9))
bHex += 0x30;
else if((bHex>=10)&&(bHex<=15)) //capital letter
bHex += 0x37;
else
bHex = 0xff;
return bHex;
}
/////////////////////////////////////////////////////////////////////
//Function name?com_int()
//Function?initialized serial
//Forma6t? [baud_rate],n,8,1
//Input?baud_rate
/////////////////////////////////////////////////////////////////////
void com_init(unsigned int baud_rate)
{
EA=1;ES=1;//ET1=1;
SCON = 0x50; /* 0x52;//SCON */
TMOD = 0x20; /*0x20;// TMOD */
TCON = 0x60; /*0x60;// TCON */
PCON=PCON&0x7f;
switch(baud_rate) //baud rate setting
{
case 1200:
TL1=0xe8;TH1=0Xe8;break;//1200
case 2400:
TL1=0xf4;TH1=0Xf4;break;//2400
case 4800:
TL1=0xfa;TH1=0Xfa;break;//4800
case 9600:
TL1=0xfd;TH1=0Xfd;break;//9600
case 19200:
PCON=PCON|0x80;TL1=0xfd;TH1=0Xfd;break;//19200
case 38400:
PCON=PCON|0x80;TL1=0xfe;TH1=0Xfe;break;//38400
default:
TL1=0xfd;TH1=0Xfd;break;//9600
}
}
/////////////////////////////////////////////////////////////////////
//Function name?resend_frame()
//Funcion?resend frame
//Note?Acknowledge PC to resend
/////////////////////////////////////////////////////////////////////
void resend_frame(void)
{
send(F_ST1);
send(F_ST2);
send(F_C);
send(F_SPACE);
send(F_SPACE);//send checksum
send(F_END);
}
/////////////////////////////////////////////////////////////////////
//Function name?quit_frame()
//Fucntion?send quit frame
//Function note?acknowledge PC to quit communication
/////////////////////////////////////////////////////////////////////
void quit_frame(void)
{
send(F_ST1);
send(F_ST2);
send(F_Q);
send(F_ERR1);
send(F_ERR1);//Send checksum
send(F_END);
}
/////////////////////////////////////////////////////////////////////
//Function name?com_int()
//Function description?serial interrupt
/////////////////////////////////////////////////////////////////////
void com_int()interrupt 4
{
unsigned char i,csaddr,clen,csum,tempbuf[S_MAXBUF];
csum=0;
if(receive()==F_ST1)
{//frame guide 1
if(receive()==F_ST2)
{//frame guide 2
communicationing=1;//set flag to indicate start commication
switch(receive())
{
case F_R://read instruction 'r '
if(receive()==F_ADDR)
{
P1_2=!P1_2;//correct address
csaddr=CharToHex(receive())<<4;
csaddr+=CharToHex(receive());
clen=CharToHex(receive())<<4;
clen+=CharToHex(receive());
csum=csaddr+clen;
i=CharToHex(receive())<<4;
i+=CharToHex(receive());
if(i==csum) //checksum verification
{
if(receive() ==F_END) //end correct frame
{
//start sending data
csum=0;
send(F_ST1);
send(F_ST2);
send(F_D);
send(HexToChar((clen&0xf0)>>4));
send(HexToChar(clen&0x0f));
csum+=clen;
for(i=0;i<clen;i++)
{
send(HexToChar((databuf[i+csaddr]&0xf0)>>4));
send(HexToChar(databuf[i+csaddr]&0x0f));
csum+=databuf[i+csaddr];
}
//if(csum>127)?csum-=128;
send(HexToChar((csum&0xf0)>>4));
send(HexToChar(csum&0x0f));
send(F_END);
//end data sending
P1_0=! P1_0;
}
else
{
ERR_NOCNTMAX_RESEND
break;
}//end wrong indicator
}
else
{
ERR_NOCNTMAX_RESEND
break;
}//wrong checksum
}//wrong address
break;
case F_W://write instruction from PC, w
if(receive()==F_ADDR)
{//correct address
csaddr=CharToHex(receive()) <<4;
csaddr+=CharToHex(receive());
clen=CharToHex(receive()) <<4;
clen+=CharToHex(receive());
csum=csaddr+clen;
for(i=0;i<clen;i++)
{
tempbuf[i+csaddr]=CharToHex(receive())<<4;
tempbuf[i+csaddr]+=CharToHex(receive());
csum+=tempbuf[i+csaddr];
}
i=CharToHex(receive()) <<4;
i+=CharToHex(receive());
if(csum!=i)
{
ERR_NOCNTMAX_RESEND
break;
}//checksum error
if(F_END!=receive())
{
ERR_NOCNTMAX_RESEND
break;
}//end byte error
for(i=csaddr;i<clen+csaddr;i++)
databuf[i-csaddr]=tempbuf[i-csaddr];//save correct data
} //PC acknowledge after success receiving data
//start send respond byte
send(F_ST1);
send(F_ST2);
send(F_B);
send(F_SPACE);
send(F_SPACE);//send checksum
send(F_END);//acknowledge
P1_1=!P1_1;
break;
case F_Q://quit communication
csaddr=receive();
csum+=csaddr;//csaddr as quit register
if(csaddr!=F_ERR1 && csaddr!=F_ERR2)
{
ERR_NOCNTMAX_RESEND
break;
}
if(csum!=receive())
{
ERR_NOCNTMAX_RESEND
break;
}
if(F_END!=receive())
{
ERR_NOCNTMAX_RESEND
break;
}
communicationing=0;//error and quit communication
break;
default:
resend_frame();//request resend
}
}
}
if(!communicationing)
quit_frame();//send quit byte?tell PC quit communication
}
void main(void)
{
unsigned char i;
for (i=0;i<FIELD_MAXBUF;i++)
databuf[i]=i+0x30;
com_init(38400);
while(1)
{
/* may add other instruction */
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -