《2022年串口发送接收程序模块程序 .pdf》由会员分享,可在线阅读,更多相关《2022年串口发送接收程序模块程序 .pdf(7页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、串口发送接收程序模块程序日期:2008-09-12 来源:net 作者:佚名 字体:大中 小(投递新闻)/*;*公 司:xx;*模 块:serial.c;*功 能:串口中断服务程序,仅需做简单调用即可完成串口输入输出的处理;*出入均设有缓冲区,大小可任意设置;*芯 片:AMEGA16;*说 明:未利用串口发送硬件BUFF;*设 计:李耀峰;*时 间:2005-11-24;*版 本:V1.0;*记 录:;*/*可供使用的函数名:extern void PutByte(byte c);/放入一个字节到发送缓冲区extern void PutString(byte*puts);/发送一个定义在程序存
2、储区的字符串到串口extern void PutBytes(byte*outplace,byte j);/发送一串数据extern void PutHEX(byte c);/发送一个字节的hex 码,分成两个字节发extern byte GetByte(void);/从接收缓冲区取一个byte extern void SerialInit(word baud);/串口初始化extern byte inbufsign;/接收缓冲区数据,有数据=1。#define CR PutString(rn)/发送一个回车换行#define NUL putstring(0)/发送一个空格*/#include#
3、include#define byte unsigned char#define word unsigned int#define OLEN 20/串口发送缓冲大小#define ILEN 20/串口接收缓冲大小byte outbufOLEN;/发送缓冲byte inbufILEN;/接收数据缓冲byte*outlast=outbuf;/最后由中断传输出去的字节位置名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 7 页 -byte*putlast=outbuf;/最后放入发送缓冲区的字节位置byte*inlast=inbuf;/最后接收到接收缓冲区的字节位置byte*getlas
4、t=inbuf;/最后从发送缓冲区取走的字节位置struct data/位定义 unsigned bit0:1;unsigned bit1:1;unsigned bit2:1;unsigned bit3:1;unsigned bit4:1;unsigned bit5:1;unsigned bit6:1;unsigned bit7:1;bit_flag;#define outbufsign0 bit_flag.bit0/缓冲区数据发完标志发完 0#define outbufsign bit_flag.bit1/发送缓冲区非空标志有=1#define inbufful bit_flag.bit2/
5、接收缓冲区满标志满=1/#define inbufsign bit_flag.bit3/接收缓冲区非空标志有=1/byte outbufsign0;/缓冲区数据发完标志发完 0/byte outbufsign;/发送缓冲区非空标志有=1/byte inbufful;/接收缓冲区满标志满=1 byte inbufsign;/接收缓冲区非空标志有=1#define CR PutString(rn)/CR=回车换行#define SPACE PutByte(0 x20)/发送一个空格。#pragma interrupt_handler SerialIncept_handler:12/串口接收中断函数
6、#pragma interrupt_handler SerialSend_handler:14/串口发送中断函数/*/函 数 名:void PutByte(byte c)/功 能:放入一个字节到发送缓冲区/说 明:/参 数:/返 回 值:/示 范:PutByte(0 x00);/*void PutByte(byte c)CLI();/暂停串行中断,以免数据比较时出错while(outlast-putlast)=2)&(outlast putlast)|(outlast 名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 7 页 -putlast)&(OLEN-(putlast-out
7、last)=2)SEI();c+;c-;CLI();*putlast=c;/放字节进入缓冲区putlast+;/发送缓冲区指针加1 if(putlast=outbuf+OLEN)putlast=outbuf;/指针到了顶部换到底部outbufsign=1;if(!outbufsign0)/缓冲区无数据 outbufsign0=1;UDR=*outlast;/未发送完继续发送outlast+;/最后传出去的字节位置加1 if(outlast=outbuf+OLEN)outlast=outbuf;/地址到顶部回到底部if(putlast=outlast)outbufsign=0;/数据发送完置发送
8、缓冲区空标志/缓冲区开始为空置为有,启动发送SEI();/*/函 数 名:void PutString(byte*puts)/功 能:发送字符串到串口/说 明:/参 数:发送的字符串/返 回 值:/示 范:putstring(rn)/*void PutString(byte*puts)for(;*puts!=0;puts+)/遇到停止符0 结束PutByte(*puts);/*/函 数 名:void PutBytes(byte*outplace,byte j)/功 能:放一串数据到发送缓冲区,需要定义发送的字节数/说 明:/参 数:*outplace:发送的字节数据首地址指针j:发送的字节数量
9、/返 回 值:/*void PutBytes(byte*outplace,byte j)名师资料总结-精品资料欢迎下载-名师精心整理-第 3 页,共 7 页 -int i;for(i=0;i4)&0 x0f;PutByte(hex_ch);ch=c&0 x0f;PutByte(hex_ch);SPACE;/*/函 数 名:byte GetByte(void)/功 能:从接收缓冲区取一个byte/说 明:如不想等待则在调用前检测inbufsign 是否为 1/参 数:无/返 回 值:接收到的数据/示 范:i=GetByte();/*byte GetByte(void)char c;while(!
10、inbufsign);/缓冲区空等待CLI();c=*getlast;/取数据getlast+;/最后取走的数据位置加1 inbufful=0;/输入缓冲区的满标志清零if(getlast=inbuf+ILEN)getlast=inbuf;/地址到顶部回到底部名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 7 页 -if(getlast=inlast)inbufsign=0;/地址相等置接收缓冲区空空标志,再取数前要检该标志SEI();return(c);/取回数据/*/函 数 名:void SerialSend_handler(void)/功 能:串口发送中断处理/说 明:/参
11、 数:/返 回 值:/*void SerialSend_handler(void)UCSRA|=(1TXC);/清发送中断标志if(outbufsign)UDR=*outlast;/未发送完继续发送outlast+;/最后传出去的字节位置加1 if(outlast=outbuf+OLEN)outlast=outbuf;/地址到顶部回到底部if(putlast=outlast)outbufsign=0;/数据发送完置发送缓冲区空标志 else outbufsign0=0;/*/函 数 名:void SerialIncept_handler(void)/功 能:串口接收中断处理/说 明:/参 数:
12、/返 回 值:/*void SerialIncept_handler(void)if(!inbufful)/接收缓冲区未满*inlast=UDR;/放入数据inlast+;/最后放入的位置加1 inbufsign=1;if(inlast=inbuf+ILEN)inlast=inbuf;/地址到顶部回到底部名师资料总结-精品资料欢迎下载-名师精心整理-第 5 页,共 7 页 -if(inlast=getlast)inbufful=1;/接收缓冲区满置满标志 /*函 数 名:void SerialInit(unsigned long)功 能:串口初始化说 明:串口初始化成指定波特率,开接收,发送并
13、开相应中断参 数:需要初始化的波特率返 回 值:无示 范:SerialInit(38400);*/void SerialInit(word baud)CLI();UCSRC&=(18);UBRRL=(byte)baud;UCSRB=(1RXCIE)|(1TXCIE)|(1RXEN)|(1TXEN);/接收中断使能,发送中断使能,接收器与发送器使能UCSRC=(1URSEL)|(3用两个指针和一个位域来记录队列的位置和状态极其不合理,因为这需要9 个字节,而且最后的目标代码会因为指针和位域的原因产生相当长的代码。我个人只用了两个字节表示读写指针的位置加一个队列有效数据的计数器,一共3 个字节,简
14、单明了;2上述几个读写指针没有加volatile,有可能在执行读写时和中断冲突;3既然使用了队列缓冲,就不应该在程序中使用while 语句来死等,而应该让程序体面的失败退出;这一点尤其体现在这个函数:byte GetByte(void)程序有可能在这个地方死掉!while(!inbufsign);/缓冲区空等待4发送中断函数:名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 7 页 -void SerialSend_handler(void)这简直是失败中的失败!当发送缓冲区为空的时候还产生多余的中断。5接收中断函数:void SerialIncept_handler(void)这
15、个函数也很失败!但数据接收缓冲区满的时候,如果再来一个数据,由于你没有把硬件中的数据取走,同样会再次产生中断!也会死掉!6初始化函数void SerialInit(word baud)你在程序中添加了CLI()/SEI()我知道你是为了在初始化的时候关掉中断,初始化完毕后再打开,看似合理,但真的合理吗?至少在我看来是很不合理!一个系统,要初始化的模块肯定不止一个,当你初始化这个模块后就带开了中断,由于相应中断的原因,也许过了n 久,你其它模块还没有初始化!我个人的做法是:系统开始初始化前关掉中断:CLI(),等所有模块初始化完毕再打开中断SEL()参考链接:http:/ 名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 7 页 -