📄 serialcomm.c
字号:
/***************************************************************************
****************************************************************************
文 件 名:SerialCom.c
简要描述:完成RS-232通信协议的实现:包括初始化、通信握手、数据传输
修改记录:
接收缓冲区结构:
_____________________________________________________________________________
_____________________________________________________________________________
长度为BufferHeadLen 长度为TranBufLen
/-------/\------\ /----------------/\-------------------\
0 1 2 3 4 5 6 7 8 ................. TranBufLen+BufferHeadLen-1
-- -- -- -- -- -- -- -- -- -- -- -- --
| | | | | | | | | | ................. | | | | |
-- -- -- -- -- -- -- -- -- -- -- -- --
| | | | | | | | | | | | |
\|/ \|/\|/\|/\|/\|/\|/\|/\|/ \|/\|/\|/\|/
有效数 头 尾 有效 \---------------\/--------------------/
据总长 个数 数据
_____________________________________________________________________________
_____________________________________________________________________________
****************************************************************************
****************************************************************************/
//----------------------------------------------------------------------//
// //
// 头文件 //
// //
//----------------------------------------------------------------------//
#include "config.h"
/**********************外部变量**********************************/
EXT bit FlagRecComm; //标志RS232接收缓冲区已经没有有效数据,FLASE为已经没有有效数据
EXT bit FlagSendComm; //标志RS232发送缓冲区已经没有有效数据,FLASE为已经没有有效数据
EXT bit ReceiveBufferStaIsOK; //接收缓冲区溢出标志,FALSE表示溢出
EXT bit SendBufferStaIsOK; //发送缓冲区溢出标志,FALSE表示溢出
EXT bit SendDataOutOK; //数据(字符)发送成功标志变量,“1”表示发送成功(完成)
EXT bit ReceivePCDataFlag;
EXT volatile unsigned char ReceiveDataOut[TranBufLen+BufferHeadLen];
EXT volatile unsigned char SendDataOut[TranBufLen+BufferHeadLen];
/*************************************************
函数名称:ByteBufferInit
简要描述:缓冲区初始化,CBS-缓冲区指针, datalen-数据缓冲区长度
// 操作数据定义为unsigned char *CBS
// CBS[0]=缓冲区有效数据长度
// CBS[1]=已有数据头地址偏移量,从 0 到 (CBS[0]-1)
// CBS[2]=已有数据尾地址偏移量,从 0 到 (CBS[0]-1)
// CBS[3]=已有数据个数
// CBS[4]和CBS[5]=所有有效数据的代数和,作为通信时的校验和
// 整个缓冲区总长度=CBS[0]+BufferHeadLen,必须由使用者定义
输 入:无
输 出:无
修改日志:
*************************************************/
void ByteBufferInit(unsigned char *CBS, unsigned char datalen)
{
unsigned char i;
EA = 0;
CBS[0]=datalen; // CBS[0]=缓冲区长度
CBS[1]=0; // CBS[1]=有效数据头地址(FIFO队列的输入位置),偏移量从 0 到 (CBS[0]-1)
CBS[2]=0; // CBS[2]=有效数据尾地址(FIFO队列的输出位置),偏移量从 0 到 (CBS[0]-1)
CBS[3]=0; // CBS[3]=等待发送/读取数据个数;
CBS[4]=0; // CBS[4]=RS232接收缓冲区接收到数据包个数
CBS[5]=0; // CBS[5]=保留
for(i=6;i<datalen+6;i++)
{ CBS[i]=0; } //清零
}
/*************************************************
函数名称:ClearCommRecBuffer0
简要描述:清空接受缓冲区
输 入:无
输 出:无
修改日志:
*************************************************/
void ClearCommRecBuffer(void)
{
ReceiveDataOut[1] = 0x00; // 有效数据头地址(FIFO队列的输入位置),偏移量从 0 到 (CBS[0]-1)
ReceiveDataOut[2] = 0x00; // 有效数据尾地址(FIFO队列的输出位置),偏移量从 0 到 (CBS[0]-1)
ReceiveDataOut[3] = 0x00; // 已有数据个数
ReceiveDataOut[4] = 0x00; // 接受到的数据包个数
FlagRecComm = FALSE; //标志接收缓冲区已经没有数据
}
/*************************************************
函数名称:ClearCommRecBuffer0
简要描述:清空接受缓冲区
输 入:无
输 出:无
修改日志:
*************************************************/
void ClearCommSendBuffer(void)
{
SendDataOut[1] = 0x00; // 有效数据头地址(FIFO队列的输入位置),偏移量从 0 到 (CBS[0]-1)
SendDataOut[2] = 0x00; // 有效数据尾地址(FIFO队列的输出位置),偏移量从 0 到 (CBS[0]-1)
SendDataOut[3] = 0x00; // 已有数据个数
FlagSendComm = FALSE; //标志发送缓冲区已经没有数据
}
/*************************************************
函数名称:OpenComm
简要描述:打开并初始化RS232串口
输 入:无
输 出:无
修改日志:
*************************************************/
void OpenComm(void)
{
EA = 0;
UART0_Init (); // 调用UART初始化子程序
ByteBufferInit(ReceiveDataOut,TranBufLen); // 调用接收缓冲区初始化子程序
ByteBufferInit(SendDataOut,TranBufLen); // 调用发送缓冲区初始化子程序
// 初始化状态标志量
SendDataOutOK = FALSE; // 数据(字符)发送成功标志变量,“1”表示发送成功(完成)
SendBufferStaIsOK = TRUE; // 发送缓冲区溢出标志,FALSE表示溢出
ReceiveBufferStaIsOK = TRUE; // 接收缓冲区溢出标志,FALSE表示溢出
FlagRecComm = FALSE; // 标志RS232接收缓冲区已经没有有效数据,FALSE表示存在有效数据
}
/*************************************************
函数名称:SendCommChar
简要描述:串口0发送一个字节子程序
输 入:char ch -- 所要发送的单字节数据
输 出:无
修改日志:
*************************************************/
void SendCommChar(char ch)
{
SendBufferStaIsOK = TRUE;
if(SendDataOut[3]>=SendDataOut[0]-1) //检测已有的数据个数,即检测是否溢出,上限设大一些,防止陷入循环检测溢出死循环!!!!!!!
{
SendBufferStaIsOK = FALSE;
return;
}
SendDataOut[SendDataOut[1]+BufferHeadLen] = ch;
SendDataOut[3]++; //已有数据个数加1
_nop_(); //设置一延时
SendDataOut[1]++; //数据首地址加1
if (SendDataOut[1]>=SendDataOut[0]-1)
{
SendDataOut[1] = 0; //指针回绕
}
if (SendDataOutOK==FALSE) //如果在UART0发送中断中检测到已经没有数据了,就置标志SendDataOutOK==FALSE
//在此处若检测到此标志,则重新继续发送
{
SBUF0 = SendDataOut[SendDataOut[2]+BufferHeadLen];
SendDataOut[3]--;
_nop_();
SendDataOut[2]++;
SendDataOutOK = TRUE;
SomeNop();
}
return ;
}
/********************************************************************
函数名称:SendCommBuffer
简要描述:串口0发送缓冲区内容子程序
输 入:void *base -- 所要发送的数据块(必须是地址连续的)头指针
unsigned char size -- 所要发送数据块的总字节数
(注意:必须是字节数)
输 出:无
修改日志:
*********************************************************************/
void SendCommBuffer(void *base, unsigned char size) // 此处的size表示有多少个字节要传送
// 注意:是字节数!!!!!
{
unsigned char i=0;
if (!size) { return; }
SendBufferStaIsOK = TRUE; //置发送缓冲区溢出检测标志为1,即未溢出
if(SendDataOut[3]>=SendDataOut[0]-size-1) // 检测是否溢出
{
SendBufferStaIsOK = FALSE;
return;
}
while (i<size)
{
SendDataOut[SendDataOut[1]+BufferHeadLen] = *((unsigned char *)base+i);
SendDataOut[3]++;
i++;
SendDataOut[1]++;
if (SendDataOut[1]>=SendDataOut[0]-1)
{
SendDataOut[1] = 0;
}
}
if (SendDataOutOK==FALSE)
{
SBUF0 = SendDataOut[SendDataOut[2]+BufferHeadLen];
SendDataOutOK = TRUE;
SendDataOut[2]++;
SendDataOut[3]--;
}
}
/********************************************************************
函数名称:GetCommChar
简要描述:串口读取一个字节子程序
输 入:unsigned char idata *ch -- 接收串口字节数据的地址
输 出:bit -- 成功接收返回TRUE,否则返回FALSE
修改日志:
*********************************************************************/
//Read data from receive buffer,return 0 when no data, otherwise return 1;
bit GetCommChar(unsigned char idata *ch)
{
if (ReceiveDataOut[2]==ReceiveDataOut[1])
return FALSE; // 检测是否溢出
*ch = ReceiveDataOut[ReceiveDataOut[2]+BufferHeadLen];
ReceiveDataOut[3]--; //接收到数据个数减1
_nop_(); //设置一等待
ReceiveDataOut[2]++; //尾地址加1
if (ReceiveDataOut[2]>=ReceiveDataOut[0]-1) //如果尾地址已经到达缓冲区的最后位置,则指针回绕
{
ReceiveDataOut[2] = 0;
}
if (ReceiveDataOut[2]==ReceiveDataOut[1]) //如果首地址和尾地址相同,则说明接收到没有数据
FlagRecComm = FALSE; //标志接收缓冲区已经没有数据
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -