*------------------------------------------------ 本程序适用于学习交流,对读入一个字节(不带回车)读入一个字符串带回车,发送字符串函数测试成功 由于不清楚keil自带的STDIO.H函数是否是堵塞发送接受,所以本程序使用非堵塞方式发送接受,缺点是占 用一些内存,缓冲区大小可自由配置。 如果发现BUG请发送邮件到: 我的邮箱:jiangyichun1@sina.com jiangyichun1@gmail.com 我的名字+数字1,请复制,防止抄错。 我的BLOG:http://lovelytime.21ic.org
testcom.c file
介绍:由于本人08年毕业(北京——机械工业学院(bim)单外生源),有必要在最后一年整理一些东西 .串口收发例程在网上有但不多,堵塞式收发,占用CPU时间太多,本程序用中断收发,需要时读缓冲区获得数据, 本程序免费使用自由修改!如有BUG请到我BLOG上注明,谢谢! -------------------------------------------------*/ #i nclude <reg52.h>
#define max 20//定义缓冲区大小 struct comset{ char tcombuffer[max];//发送缓冲区:环状 char rcombuffer[max];//接收缓冲区 char rcount,tcount;//收发的有效数据数 char rstart,rend,tstart,tend;//当前读写起始与结束位置 char issent;//正在发送过程中1:发送,0未发送 };
struct comset a;
void inibuffer(void)//初始化缓冲区,所有数据置0或初值 { char i; for(i=0;i<max;i++) {a.rcombuffer=0;a.tcombuffer=0;} a.tcount=0;a.rcount=0;a.rstart=0;a.rend=0;a.tstart=0;a.tend=0;a.issent=0; }
void comini(void) {
SCON = 0x50; //SCON: serail mode 1, 8-bit UART, enable ucvr TMOD |= 0x20; //TMOD: timer 1, mode 2, 8-bit reload //SMOD=0; TH1 = 0xFd; //Baud:9600 fosc=11.0592MHz TL1 = 0xF4; IE |= 0x90; //Enable Serial Interrupt TR1 = 1; // timer 1 run
}
char sent(char *b,char n)//发送的字节数=发送(字符串指针,字符个数) { char i; if(n>max-a.tcount)//缓冲区字节不够拒绝发送返回0 {return 0;} for(i=0;i<n;i++) { a.tcombuffer[a.tend]=b;//向缓冲区尾部拷贝字符 a.tend++;//尾部指针++ a.tcount++;//缓冲区总字节数++ if(a.tend>max)//循环利用缓冲区 a.tend=0; if(a.tcount>=max)//达到最大值就退出(单线程程序不会达到最大值) break;
} if(a.issent==0)//如果不在发送状态就开始发送 { SBUF=a.tcombuffer[a.tstart];//发送第一个字节 a.tstart++;//其实字节后移 a.issent=1;//发送标志置一 a.tcount--;//总字节-- } return i;//返回复制到缓冲区的字节数 }
void sentoff(void)//等待发送完成,也可以发送开始就执行代码以提高效率,有些交互式需要等待发送完成才能读取输入。 { while(a.tcount!=0);//等待发送总数为0 }
char getchar(void)//从缓冲区读取一个字节 { char e; if(a.rcount>0) { e=a.rcombuffer[a.rstart];//从开头读,要求所有输入字节都有对应的函数处理 a.rstart++; a.rcount--; return e; } return 0; }
char getstring(char *c,char oeb)//返回值是读的字节数,oeb:允许输出最大字节数,c是读取字节存放的位置 { char k,l=0; sentoff();//等待发送完毕,这样才有有效输入 while(a.rstart!=(a.rend+1)%(max+1))//缓冲区不满 { for(k=a.rstart;k!=a.rend;k++,k=k%(max+1))//判断输入完的回车是否读入 { if(a.rcombuffer[k]=='\r') { while(a.rcombuffer[a.rstart]!='\r')//有则拷贝 { c[l]=a.rcombuffer[a.rstart]; a.rstart++; a.rcount--; l++; if(l==oeb)//超过允许最大值就返回 return l; } //a[l]=a.rcombuffer[a.rstart];//不复制回车符 a.rstart++;//删除回车 a.rcount--; return l; } } } //缓冲区满 while(sent("\nerror:full\n",12)!=12);//会留在缓冲区未读字节,所以输出错误提示 for(k=a.rstart;k<oeb;k++,k=(k)%(max+1))//返回最大有效的 字符数注意:OEB《max { c[l++]=a.rcombuffer[k]; } sentoff();//等到提示发送完毕 inibuffer();//初始化缓冲区,删除垃圾,由于发送较慢,有可能还有垃圾存在 return l;
}
void serial () interrupt 4 using 3 { if(RI) { RI=0; if(a.rcount<max)//缓冲区满后字节被丢弃 { a.rcount++; a.rcombuffer[a.rend]=SBUF;//不满则读入 a.rend++; if(a.rend>max)//循环利用缓冲区 a.rend=0; } } if(TI) { TI=0; if(a.tcount>0)//如有数据则发送,并设置相关标志字 { SBUF=a.tcombuffer[a.tstart]; a.tstart++; if( a.tstart>max) a.tstart=0; a.tcount--; } else a.issent=0;//否则设置停止发送字 } }
void main()//测试函数 { char f,n[20],k=0;
comini(); inibuffer();
while(sent("my test\r\n",9)!=9); sentoff(); while(sent("1.inset your name.\r\n",20)!=20); while(sent("2.inset your age.\r\n",19)!=19);
while((f=getchar())==0);//输入字符不回显,不要输入回车 switch(f) { case '1': while(sent("inset your name:",16)!=16);
k=getstring(n,20);//输入字符串不回显,需要回车结束 while(sent(n,k)!=k);//回显 break; case '2': while(sent("age:",4)!=4); k=getstring(n,2); while(sent(n,k)!=k); break; } while(1);//停机
}
相关链接:http://blog.21ic.com/uploadfile-/2007-6/629788290.rar |