|
//本代码使用一个队列缓冲区接收
//本代码经过严格测试,可以适用用长时间高强度的数据通信
//对于接收部分还有一些关于一帧数据的处理部分函数需要自己写
#include<w77e58.h>
#define uchar unsigned char
#define uint unsigned int
#define POOLLEN 255
#define START_FRAME 0x7e
#define END_FRAME 0x0d
typedef struct str_rxd_pool
{
uchar pool[POOLLEN]; //接收缓冲区
uchar front; //头指针
uchar rear; //尾指针
uchar rd_byte; //暂存读数据
uchar frm_num; //缓冲区中的帧数量
uchar start_7e; //收到起始标志位
uchar end_0d; //收到结束标志位
uchar add_buf[16]; //用于存放接收缓冲的地址,可以存放16个帧地址,奇数位是首地址,偶数位是尾地址
}RXDPOOL;
RXDPOOL rxd_pool;
uchar xdata txd_buf[POOLLEN];
uchar xdata txd_len;
void sys_ini(void);
void txd_com(void);
void txd_test(void);
main()
{
sys_ini();
while(1)
{
while( rxd_pool.frm_num )
{
//这里如果再添加一个关于帧数据处理的函数,就可以实现完整的协议接收了
rxd_pool.frm_num--;
txd_test();
//发送做的比较简单,把每条命令的数据都先放到一个自己的缓冲区,然后发送
//本例只用了一个发送缓冲区
}
}
}
void sys_ini(void)
{
uchar idata i;
PMR |= 1; //开启内部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 = 1; //开放定时器0中断
ES = 1; //串行中断
EX0 = 1; //外部中断0
EX1 = 1; //外部中断1
EA = 1; //开总中断
for( i = 0; i < POOLLEN;i++ )
{
rxd_pool.pool = 0;
txd_buf = 0;
}
rxd_pool.start_7e = 0;
rxd_pool.end_0d = 0;
rxd_pool.front = 0;
rxd_pool.rear = 0;
rxd_pool.rd_byte = 0;
rxd_pool.frm_num = 0;
txd_len = 0;
}
void txd_com(void)
{
uchar idata i;
ES =0;
for( i = 0;i < txd_len;i++ )
{
SBUF = txd_buf;
while (TI ==0);
TI = 0;
//为了让发送更加可靠,这里可以添加一两个语句的延时,从而让停止位判断更加可靠
}
ES =1;
}
void txd_test(void)
{
txd_buf[0] = 0x7e;
txd_buf[1] = 0x7e;
txd_buf[2] = 0x7e;
txd_buf[3] = 0x7e;
txd_buf[4] = 0x7e;
txd_buf[5] = 0x7e;
txd_buf[6] = 0x7e;
txd_buf[7] = 0x7e;
txd_buf[8] = 0x7e;
txd_buf[9] = 0x7e;
txd_buf[10] = 0x7e;
txd_buf[11] = 0x7e;
txd_buf[12] = 0x0d;
txd_len = 13;
txd_com();
}
void serial() interrupt 4
{
uchar idata temp;
uchar idata num;
if(RI)
{
RI=0;
temp=SBUF;
if ( ( rxd_pool.start_7e )&& ( temp != END_FRAME ) && (temp != START_FRAME) ) //已经接收到起始位,同时数据不是结束位和起始位
{
rxd_pool.pool[rxd_pool.rear]=temp;
rxd_pool.rear=(rxd_pool.rear+1) % POOLLEN;
}
else
{
if( temp == START_FRAME ) //接收到包的起始位
{
if ( (rxd_pool.start_7e) && (rxd_pool.end_0d) ) //是否已经接收到起始位了
{
rxd_pool.rear = rxd_pool.add_buf[num]; //丢弃开始收到不完整的数据
}
else
{
rxd_pool.start_7e = 1; //接收正确的起始位
rxd_pool.end_0d = 1;
num = rxd_pool.frm_num*2; //起始地址
rxd_pool.add_buf[num] = rxd_pool.rear; //保存起始地址下标
}
rxd_pool.pool[rxd_pool.rear] = temp; //保存数据
rxd_pool.rear = (rxd_pool.rear+1) % POOLLEN;
}
else
{
if( rxd_pool.start_7e && ( temp == END_FRAME ) ) //接收到起始位以后接收到结束位
{
rxd_pool.end_0d = 0;
rxd_pool.start_7e = 0;
rxd_pool.pool[rxd_pool.rear] = temp;
rxd_pool.rear = (rxd_pool.rear+1) % POOLLEN;
num = rxd_pool.frm_num*2+1; //尾地址下标
if(rxd_pool.rear != 0)
//尾地址保存的时候必须要这一步,否则会出错
{
rxd_pool.add_buf[num] = rxd_pool.rear-1; //在写进后的地址已 加上1
}
else
{ //因为尾地址如果是0的时候,-1动作将回到255。而我们的数据缓冲区下标只有0-(POOLLEN-1)
//对于POOLLEN=255为0-254
rxd_pool.add_buf[num] = POOLLEN - 1;
}
rxd_pool.frm_num++; //增加一帧//成功才加一位
rxd_pool.frm_num = rxd_pool.frm_num % 16;
}
}
}
}
}