#include "STC15W4K.H" // 包含 "STC15W4K.H"寄存器定义头文件 #define FMBEGIN 0x7e // 帧头标志 unsigned char RecCount; // 串口接收计数器,全局变量在没有赋值以前系统默认为0. unsigned char RecBuf[5]; // 接收缓冲区(数据长度:帧头+3字节数据+校验和) unsigned char SendBuf[5]; // 发送缓冲区(数据长度:帧头+3字节数据+校验和) /*********************************************/ //描述:串口初始化函数,使用T1方式2自重载方式做波特率发生器 void UART_init(void) { // 下面代码设置定时器1 TMOD = 0x20; // 0010 0000 定时器1工作于方式2(8位自动重装方式) TH1 = 0xFA; // 波特率:9600 /22.1184MHZ TL1 = 0xFA; // 波特率:9600 /22.1184MHZ TR1 = 1; // 下面代码设置定串口 AUXR = 0x00; // 很关键,使用定时器1作为波特率发生器,S1ST2=0 SCON = 0x50; // 01010 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接受) // 下面代码设置中断 ES = 1; // 关键:开启了中断就必须编写相应的中断函数,哪怕是中断空函数, // 但必须有,否则程序进入中断入口地址后(这里是0023H)不能跳出,必然出错 EA = 1; } /*********************************************/ //发送一帧完整数据 void sendcombytes(unsigned char *ptr, unsigned char len) { unsigned char i; for(i=0;i<len;i++) { SBUF=*(ptr+i); while(TI==0); TI=0; } } /*********************************************/ // 串口 中断服务程序 void UART1(void) interrupt 4 { if(RI) // 只处理接收中断 { if(RecCount==5) RecCount=0; //如果已经接收了5个字符,主程序还没来得及处理又发来下一帧数据 //则RecCount清零,覆盖上一帧数据,保证数据接收不错位 RecBuf[RecCount]=SBUF; RI=0; if (RecCount==0) // 判断帧头是否正确 { if(RecBuf[RecCount]==FMBEGIN) { RecCount++; } else { RecCount=0; } } else { RecCount++; } } } /*********************************************/ unsigned char CheckSum(unsigned char *ptr, unsigned char len) { unsigned char i; unsigned char a; unsigned int Value=0; for(i=0;i<len;i++) // len结束后第一个字节为接收到的校验和 { Value = Value + ptr; } a=Value; // 长送短,传送完整低字节 return(a); } /*********************************************/ void main(void) { unsigned char i; unsigned char CheckValue; // 校验结果 UART_init(); // 串口初始化 while(1) { if(RecCount==5) // RecCount是全局变量,表示串口已收到的字节数 { RecCount=0; CheckValue=CheckSum(RecBuf,4); // 接收缓冲区4字节校验(第5字节例外) if(CheckValue==RecBuf[4]) // 如果校验正确,数据加1后发回。 { P00=!P00; SendBuf[0]=FMBEGIN; for(i=1;i<4;i++) // 1、2、3、4、5字节中2、3、4为数据 { SendBuf=RecBuf+1; } CheckValue=CheckSum(SendBuf,4); // 1、2、3、4 字节参与校验 SendBuf[4]=CheckValue; sendcombytes(SendBuf,5); } else // 接收校验错误,发回帧头 + 4个aa。 { SendBuf[0]=FMBEGIN; for(i=1;i<5;i++) // 1、2、3、4、5字节中2、3、4、5为数据 { SendBuf=0xaa; } sendcombytes(SendBuf,5); } } } } |
欢迎光临 (http://www.51hei.com/bbs/) | Powered by Discuz! X3.1 |