c语言串口发送接收程式模块

  • 格式:doc
  • 大小:25.00 KB
  • 文档页数:3

c语言串口发送接收程式模块
//**********************************************************************
//函数名: byte GetByte (void)
//功能: 从接收缓冲区取一个byte
//说明: 如不想等待则在调用前检测inbufsign是否为1
//参数: 无
//返回值: 接收到的数据
//示范: i=GetByte();
//***********************************************************************
byte GetByte (void)
{
char c ;
while (!inbufsign); //缓冲区空等待
CLI();
c=*getlast; //取数据
getlast ; //最后取走的数据位置加1
inbufful=0; //输入缓冲区的满标志清零
if (getlast==inbuf ILEN) getlast=inbuf; //地址到顶部回到底部
if (getlast==inlast) inbufsign=0; //地址相等置接收缓冲区空空标志,再取数前要检该标志SEI();
return (c); //取回数据
}
//**********************************************************************
//函数名: void SerialSend_handler (void)
//功能: 串口发送中断处理
//说明:
//参数:
//返回值:
//*********************************************************************** .
void SerialSend_handler (void)
{
UCSRA|=(1<<TXC); //清发送中断标志
if (outbufsign)
{
UDR=*outlast; //未发送完继续发送
outlast ; //最后传出去的字节位置加1
if (outlast==outbuf OLEN) outlast=outbuf;//地址到顶部回到底部
if (putlast==outlast) outbufsign=0; //数据发送完置发送缓冲区空标志
}
else
{
outbufsign0=0;
}
}
//********************************************************************** //函数名: void SerialIncept_handler (void)
//功能: 串口接收中断处理
//说明:
//参数:
//返回值:
//*********************************************************************** void SerialIncept_handler (void)
{
if(!inbufful) //接收缓冲区未满
{
*inlast= UDR; //放入数据
inlast ; //最后放入的位置加1
inbufsign=1;
if (inlast==inbuf ILEN) inlast=inbuf; //地址到顶部回到底部
if (inlast==getlast) inbufful=1; //接收缓冲区满置满标志
}
}
/********************************************************************** . 函数名: void SerialInit (unsigned long)
功能: 串口初始化
说明: 串口初始化成指定波特率,开接收,发送并开相应中断
参数: 需要初始化的波特率
返回值: 无
示范: SerialInit (38400);
***********************************************************************/ void SerialInit (word baud)
{
CLI();
UCSRC&=(~(1<<URSEL));
UBRRH=(byte)(baud>>8);
UBRRL=(byte)baud;
UCSRB=(1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN);
//接收中断使能,发送中断使能,接收器和发送器使能
UCSRC=(1<<URSEL)|(3<<UCSZ0); //配置帧格式: 8 个数据位, 1 个停止位*/
SEI(); //开全局中断
}
我来泼几瓢冷水:
1>用两个指针和一个位域来记录队列的位置和状态极其不合理,因为这需要9个字节,而且最后的目标代码会因为指针和位域的原因产生相当长的代码。

我个人只用了两个字节表示读写指针的位置加一个队列有效数据的计数器,一共3个字节,简单明了;
2>上述几个读写指针没有加volatile,有可能在执行读写时和中断冲突;
3>既然使用了队列缓冲,就不应该在程式中使用while语句来死等,而应该让程式体面的失败退出;这一点尤其体现在这个函数:。

byte GetByte (void)
程式有可能在这个地方死掉!
while (!inbufsign); //缓冲区空等待
4>发送中断函数:
void SerialSend_handler (void)
这简直是失败中的失败!当发送缓冲区为空的时候还产生多余的中断。

5>接收中断函数:
void SerialIncept_handler (void)
这个函数也很失败!但数据接收缓冲区满的时候,假如再来一个数据,由于您没有把硬件中的数据取走,同样会再次产生中断!也会死掉!
6>初始化函数
void SerialInit (word baud)
您在程式中添加了CLI() / SEI()
我知道您是为了在初始化的时候关掉中断,初始化完毕后再打开,看似合理,但真的合理吗?至少在我看来是很不合理!
一个系统,要初始化的模块肯定不止一个,当您初始化这个模块后就带开了中断,由于相应中断的原因,也许过了n久,您其他模块还没有初始化!
我个人的做法是:系统开始初始化前关掉中断:CLI(),等任何模块初始化完毕再打开中断SEL()
..。