serial.c
来自「功能非常完善的51串口程序包」· C语言 代码 · 共 213 行
C
213 行
#include "Serial.h"
Packet comm;
//******************数据通讯初始化函数**********************//
//输入:无
//输出:无
//说明:初始化包括定时器和中断的初始化
// 配置为使用定时器1,开串口中断,允许接收
// 波特率等参数在serial.h中设置,无需改动此函数
//********************************************************//
void Serial_Init()
{
TMOD=0x20;
SCON=0x50;
#ifdef BOUND_RATE_DOUBLE //波特率加倍时的参数
TL1=0;
TH1=256.5-CLK_FRE/(BOUND_RATE*16.0*CLK_DIV);
PCON=0x80;
#else //波特率不加倍时的参数
TL1=0;
TH1=256.5-CLK_FRE/(BOUND_RATE*32.0*CLK_DIV);
PCON=0x00;
#endif
TR1=1;
ES=1;
EA=1;
comm.rflag=COMM_IDLE;
comm.tflag=COMM_IDLE;
comm.time=COMM_TIME;
comm.rcount=0;
comm.tcount=0;
}
//******************数据接收中断函数**********************//
//输入:无
//输出:无
//说明:此函数完成数据的接收和发送功能,无需调用
// 要获取通讯接收状态可监视comm.rflag
// COMM_IDLE 0 时为空闲等待状态
// COMM_ACK 1 时为接收完成
// COMM_REING 2 时为正在接收
// 接收数据将在接收完成后更新,读取comm,dat[]即可获取数据
// 要获取通讯接收状态可监视comm.tflag
// COMM_IDLE 0 时为空闲等待状态
// COMM_ACK 1 时为发送完成
// COMM_TEING 2 时为正在发送
// 要发送数据调用Serial_Send()函数
//********************************************************//
void Serial_Int() interrupt 4
{
if (RI)
{
RI=0;
if (comm.rcount>=PACKET_LEN-1) //本次数据包接收完毕
{
uchar i;
comm.dat[PACKET_LEN-1]=SBUF; //保存最后一个接收到的数据
for (i=0;i<PACKET_LEN-1;i++)
{
comm.dat[i]=comm.temp[i]; //转存以前的接收数据
}
comm.rflag=COMM_ACK; //接收完毕标志
comm.rcount=0; //下次重新开始接收
}
else
{
comm.temp[comm.rcount]=SBUF; //保存接收数据
comm.rcount++;
comm.rflag=COMM_REING; //正在接收标志
comm.time=COMM_TIME; //重置接收计时
}
}
if (TI)
{
TI=0;
if (comm.tcount>=comm.len) //发送完毕
{
comm.tflag=COMM_IDLE;
}
else
{
SBUF=*comm.pdat;
comm.pdat++;
comm.tcount++;
}
}
}
//******************数据接收计时函数**********************//
//输入:无
//输出:无
//说明:此函数负责监视一个数据包中各数据的接收,若数据包接收
// 超时则重新启动数据接收
// 若要使用数据接收监视功能,需在主函数中循环调用此函数
//********************************************************//
void Serial_Timer()
{
if (comm.rflag==COMM_REING)
{
if (comm.time)
{
comm.time--;
}
else
{
comm.rflag=COMM_IDLE;
comm.time=COMM_TIME;
comm.rcount=0;
}
}
}
//******************数据接收状态函数**********************//
//输入:无
//输出:COMM_DATA_NOTRDY 0 数据未准备好,未接收到数据或正在接收
// COMM_DATA_ACK 1 数据接收完成,效验正确
// COMM_DATA_ERROR 2 数据接收完成,效验错误或无效验位
//说明:调用此函数后,接收状态被自动清为空闲(仅对接收完成的状态)
//********************************************************//
uchar Serial_GetDataState()
{
uchar i,a=0;
if (comm.rflag==COMM_IDLE || comm.rflag==COMM_REING)
return COMM_DATA_NOTRDY;
for (i=0;i<PACKET_LEN-1;i++) //数据效验,数据包中最后一字节为效验位,应等于包中其他数据之和(不计溢出)
{
a+=comm.dat[i];
}
if (a==comm.dat[PACKET_LEN-1])
{
comm.rflag=COMM_IDLE;
return COMM_DATA_ACK;
}
else
{
comm.rflag=COMM_IDLE;
return COMM_DATA_ERROR;
}
}
//******************数据发送函数**************************//
//输入:发送数据缓冲区指针 *pdat
// 发送数据长度 len
//输出:COMM_SENT_OK 0 数据发送正常
// COMM_SENT_BUSY 1 发送忙,需稍后重发
//说明:此函数将缓冲区内len长度的数据发送出去
//********************************************************//
uchar Serial_Sent(uchar *pdat,uchar len)
{
if (comm.tflag==COMM_TEING)
return COMM_SENT_BUSY;
comm.tflag=COMM_TEING; //开始发送,置标志
comm.len=len;
SBUF=*pdat; //发送第一个数据启动发送
comm.pdat=pdat+1;
comm.tcount=1;
return COMM_SENT_OK;
}
//*****************带效验位生成的数据发送函数*******************//
//输入:发送数据缓冲区指针 *pdat
// 发送数据长度 len
//输出:COMM_SENT_OK 0 数据发送正常
// COMM_SENT_BUSY 1 发送忙,需稍后重发
//说明:此函数自动计算效验位,将其放在缓冲区末端再将数据发送出去
// 总共发送数据长度为len+1
//注: 缓冲区的有效长度应至少为len+1,否则会产生不可知后果
//********************************************************//
uchar Serial_ValidateSent(uchar *pdat,uchar len)
{
uchar i,a=0;
if (comm.tflag==COMM_TEING)
return COMM_SENT_BUSY;
comm.pdat=pdat;
comm.tflag=COMM_TEING; //开始发送,置标志
comm.len=len+1;
for (i=0;i<len;i++)
{
a+=*pdat;
pdat++;
}
*pdat=a;
SBUF=*comm.pdat; //发送第一个数据启动发送
comm.pdat++;
comm.tcount=1;
return COMM_SENT_OK;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?