⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testc.c

📁 对读入一个字节(不带回车)读入一个字符串带回车
💻 C
字号:
/*------------------------------------------------
本程序适用于学习交流,对读入一个字节(不带回车)读入一个字符串带回车,发送字符串函数测试成功
由于不清楚keil自带的STDIO.H函数是否是堵塞发送接受,所以本程序使用非堵塞方式发送接受,缺点是占
用一些内存,缓冲区大小可自由配置。
如果发现BUG请发送邮件到:
我的邮箱:jiangyichun1@sina.com
		  jiangyichun1@gmail.com
		我的名字+数字1,请复制,防止抄错。
我的BLOG:http://lovelytime.21ic.org

testcom.c file

介绍:由于本人08年毕业(北京——机械工业学院(bim)单外生源),有必要在最后一年整理一些东西
.串口收发例程在网上有但不多,堵塞式收发,占用CPU时间太多,本程序用中断收发,需要时读缓冲区获得数据,
本程序免费使用自由修改!如有BUG请到我BLOG上注明,谢谢!
-------------------------------------------------*/
#include <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[i]=0;a.tcombuffer[i]=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[i];//向缓冲区尾部拷贝字符
		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);//停机


}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -