//来源于网络,经过调试成功运行
//优点是在中断内做的事情很少,对程序的实时性影响很小
//实际应用中,有部分函数可以不用
#i nclude <w77e58.h> //该头文件包括了51,52,80320的特殊寄存器,用在51,52上也可
#define uchar unsigned char
#define uint unsigned int
#define OLEN 255 /* size of serial transmission buffer */
uchar xdata outbuf[OLEN]; /* storage for transmission buffer */
uchar xdata outlast = 0; //最后由中断传输出去的字节位置
uchar xdata putlast = 0; //最后放入发送缓冲区的字节位置
#define ILEN 255 /* size of serial receiving buffer */
uchar xdata inbuf[ILEN];
uchar xdata inlast = 0; //最后由中断进入接收缓冲区的字节位置 unsigned
uchar xdata getlast = 0; //最后取走的字节位置
bit outbufsign; //输出缓冲区非空标志 有=1
bit inbufsign; //接收缓冲区非空标志 有=1
bit inbufful; //输入缓冲区满标志 满=1
#define CR putstring("\r\n") //CR=回车换行
uchar getbyte(void); //从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
void getline(uchar *return_line, uchar idata n);
//获取一行数据回车结束,已处理backspce和delete,必须定义最大输入字符数
void putinbuf(uchar idata c); //模拟接收到一个数据
void putbyte(uchar idata c); //放入一个字节到发送缓冲区
void putbytes(uchar *outplace,uchar idata j);
//放一串数据到发送缓冲区,自定义长度
void putstring(uchar *puts); //发送一个字符串到串口
void puthex(uchar idata c); //发送一个字节的hex码,分成两个字节发。
void putchar(uchar idata c,uchar idata j); //发送一个字节数据的asc码表达方式,需要定义小数点的位置
void putint(uint idata ui,uchar idata j); //发送一个整型数据的asc码表达方式,需要定义小数点的位置
//CR;发送一个回车换行
uchar code hex_[]={"0123456789ABCDEF"};
//*************************************************************************
//放入一个字节到发送缓冲区
void putbyte(uchar idata c)
{
uchar i,j;
ES=0; /*暂停串行中断,以免数据比较时出错*/
if ( outlast == putlast )
{
i = (0-TH1);
do
{
i--;
j = 36;
do
{
j--;
}
while( j!=0 );
}
while(i!=0);
//延时一个字节发送时间
}
outbuf[putlast] = c; //放字节进入缓冲区
putlast++; //发送缓冲区指针加一
if(putlast == OLEN ) //指针到了顶部
{
putlast = 0; //指针到了顶部换到底部
}
if (!outbufsign)
{
outbufsign=1;
// TI=1;
} //缓冲区开始为空置为有,启动发送
while(outbufsign) //
{
if( putlast == outlast )
{
outbufsign=0; //
}
else
{
SBUF = outbuf[outlast]; //未发送完继续发送
while(TI==0);
TI = 0;
outlast++; //最后传出去的字节位置加一
if( outlast == OLEN )
{
outlast = 0; //地址到顶部回到底部
}
if ( putlast == outlast )
{
outbufsign = 0; //数据发送完置发送缓冲区空标志
}
}
}
ES=1;
}
//****************************** //放一串数据到发送缓冲区
void putbytes(uchar *outplace,uchar idata j)
{
int idata i;
for(i=0;i<j;i++)
{
putbyte(*outplace);
outplace++;
}
}
//******************************
//putchar(uchar c,uchar j);发送一个字节数据的asc码表达方式,需要定义小数点的位置
void putchar(uchar idata c,uchar idata j)
{
uchar idata free[4];
uchar data i;
i = 0;
free[i++] = (c/100+0x30); //百位
if (j==3)
{
free[i++]='.';
}
free[i++] = (c%100)/10+0x30; //十位
if(j==2)
{
free[i++]='.';
}
if( j==2 && free[i-3]==0x30)
{
free[i-3]=0x20;
}
free[i++] = (c%10)+0x30; //个位
if(j==1 && free[i-3]==0x30)
{
free[i-3]=0x20;
}
if(j==1 && free[i-3]==0x20 && free[i-2]==0x30)
{
free[i-2]=0x20;
}
putbytes(free,i);
}
//******************************
//putint(uint ui,uchar j);发送一个整型数据的asc码表达方式,需要定义小数点的位置
void putint(uint idata ui,uchar idata j)
{
uchar idata free[6];
uchar data i;
i = 0;
free[i++] = (ui/10000+0x30);
if(j==5)
{
free[i++]='.';
}
free[i++]=((ui%10000)/1000+0x30);
if(j==4)
{
free[i++]='.';
}
if(j==4 && free[i-3]==0x30)
{
free[i-3]=0x20;
}
free[i++]=((ui%1000)/100+0x30);
if(j==3)
{
free[i++]='.';
}
if(j==3 && free[i-4]==0x30)
{
free[i-4]=0x20;
}
if(j==3 && free[i-4]==0x20 && free[i-3]==0x30)
{
free[i-3]=0x20;
}
free[i++]=((ui%100)/10+0x30);
if(j==2)
{
free[i++]='.';
}
if(j==2 && free[i-5]==0x30)
{
free[i-5]=0x20;
}
if(j==2 && free[i-5]==0x20 && free[i-4]==0x30)
{
free[i-4]=0x20;
}
if(j==2 && free[i-5]==0x20 && free[i-4]==0x20 && free[i-3]==0x30)
{
free[i-3]=0x20;
}
free[i++]=(ui%10+0x30);
if(j==1 && free[i-5]==0x30)
{
free[i-5]=0x20;
}
if(j==1 && free[i-5]==0x20 && free[i-4]==0x30)
{
free[i-4]=0x20;
}
if(j==1 && free[i-5]==0x20 && free[i-4]==0x20 && free[i-3]==0x30)
{
free[i-3]=0x20;
}
if(j==1 && free[i-5]==0x20 && free[i-4]==0x20 && free[i-3]==0x20 && free[i-2]==0x30)
{
free[i-2]=0x20;
}
putbytes(free,i);
}
//***************************************
//发送一个字符串到串口
void putstring(uchar *puts)
{
/*
for(;*puts!=0;puts++) //遇到停止符0结束
{
putbyte(*puts);
} //另外一种表达方式
*/
while(*puts)
{
putbyte(*puts++);
}
}
//*************************************
//发送一个字节的hex码,分成两个字节发。
void puthex(uchar idata c)
{
uint idata ch;
ch = (c>>4) & 0x0f;
putbyte(hex_[ch]);
ch = c & 0x0f;
putbyte(hex_[ch]);
}
//*************************************
//从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。
uchar getbyte(void)
{
char idata c;
while (!inbufsign); //缓冲区空等待
ES = 0;
c= inbuf[getlast]; //取数据
getlast++; //最后取走的数据位置加一
inbufful = 0; //输入缓冲区的满标志清零
if(getlast == ILEN )
{
getlast = 0; //地址到顶部回到底部
}
if(getlast == inlast)
{
inbufsign=0; //地址相等置接收缓冲区空空标志,再取数前要检该标志
}
ES=1;
return (c);
//取回数据
}
//*****************************************
//接收一行数据,必须定义放数据串的指针位置和大小
//del=0x7f,backspace=0x08,cr=0x0d,lf=0x0a
void getline (uchar *return_line, uchar idata n)
{
uchar idata cnt = 0; //定义已接收的长度
uchar idata c;
do
{
if ((c = getbyte() ) == 0x0d)
c = 0x00; //读一个字节,如果是回车换成结束符
if (c == 0x08 || c == 0x7f) //BACKSPACE 和 DEL 的处理
{
if (cnt != 0) //已经输入退掉一个字符
{
cnt--; //总数目减一
return_line--; //指针减一
putbyte (0x08); //屏幕回显的处理
putbyte (' ');
putbyte (0x08);
}
}
else
{
putbyte (*return_line = c);
//其他字符取入,回显
return_line++; //指针加一
cnt++; //总数目加一
}
}
while(cnt < n - 1 && c != 0x00 && c!=0x1b); //数目到了,回车或ESC停止
*return_line = 0; //再加上停止符0
}
//****************************
//模拟接收到一个数据
void putinbuf(uchar idata c)
{
ES=0;
if(!inbufful)
{
inbuf[inlast] = c; //放入数据 inlast++;
//最后放入的位置加一
if (inlast == ILEN)
{
inlast = 0;//地址到顶部回到底部
}
if (inlast == getlast)
{
inbufful = 1; //接收缓冲区满置满标志
}
inbufsign = 1;
}
ES=1;
}
//*****************************************
//串口中断处理
void serial(void) interrupt 4
{
if(RI)
{
RI = 0;
if( !inbufful )
{
inbuf[inlast] = SBUF; //放入数据
inlast++; //最后放入的位置加一
inbufsign=1;
if( inlast == ILEN )
{
inlast = 0;//地址到顶部回到底部
}
if (inlast == getlast)
{
inbufful = 1; //接收缓冲区满置满标志
}
}
}
}
//*****************************
//串口初始化 0xfd=19200,0xfa=9600,0xf4=4800,0xe8=2400,0xd0=1200
void serial_init(void)
{
uchar idata i;
PMR |= 0x01; //启动片内XRAM
TMOD = 0x21; // T1 mode 2 T0,mode 1 //GATE C/T M1 M0 GATE C/T M1 M0
TL1 = 0xfd; // 0xfa=4800 bps 0xfd=9600 bps
TH1 = 0xfd;
PCON = 0; //波特率不变等设置
SCON = 0x50; //串口1方式1,允许接收
IT0 = 1; //外部中断0下降沿有效
IT1 = 1; //外部中断1下降沿有效
TR0 = 0; //启动定时器0
TR1 = 1; //启动定时器1
ET0 = 0; //开放定时器0中断
ES = 1; //串行中断
EX0 = 0; //外部中断0
EX1 = 0; //外部中断1
EA = 1; //开总中断
for(i = 0;i < OLEN;i++ )
{
outbuf = 0;
inbuf = 0;
}
}
void main(void)
{
serial_init();
while(1)
{
if(getbyte()==0x55)
{
putstring("Hello,world");
CR;
putchar(0xF5,2);
CR;
putint(0x55ff,4);
CR;
}
}
} |