232程序总结

本文总结了在开发232通信程序时遇到的变量混淆问题及其解决方案,强调了程序书写应遵循的层次递进原则,分享了如何避免CPU高占用率的技巧,并探讨了fork()函数在并发执行中的应用。此外,还提到了异或运算的特性以及在调试中使用printf函数的重要性。

出现的问题及解决思路

变量名相近,比如wrnum,wrsum,在具体的使用过程中,很容易就出现问题,而且因为相近,这个问题出现在数组(例wrbuff[wrnum],wrbuff[sum])中时,不容易被发现:
解决:https://blog.youkuaiyun.com/u012314708/article/details/52130961

心得总结

程序的书写应该遵循层层递进的原则,比如说这次的232程序中的发送程序要包含起始位、数据位、校验位、停止位。如果一上来就直接把这些东西都包括进来,可能出现问题的地方太多,不利于问题的定位。所以,可以层层递进,先保证数据可以完整的被发送与接受,然后在增加起始位,停止位,把最容易出现问题的校验位的设置放到最后。
在使用while()死循环,很容易就让就让CPU跑到100%,适当加入一些sleep函数或者是usleep函数,可以在不影响程序运行的情况下,使得CPU的占用率降下来,一般还是使用usleep函数多一点。
fork()绝对是一个神奇的函数,可以被用来创建子进程,相当于把一个CPU一分为二,通过fork的不同返回值,只需要一个简单的if进行判断就可以进入到不同的程序中,让232的发送与接受做到了同时进行。

细节

异或运算:按照abcdefgh进行异或得到的结果,跟按照hgfedcba进行异或得到的结果是不相同的。
printf:多使用printf函数,把各种参数在程序运行过程中的变化显示出来,方便判断问题出在哪里,前面的renum、resum的问题就是通过这样的方法检查出来。
ASCII:控制字符虽然会影响到printf()函数的输出显示,但控制字符本身在内存还是占据存储空间的。只影响显示,不影响存储。

程序

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>

#define SERIAL_DEV_DIR "/dev/ttyS2"

int set232port(int fd )
{
	struct termios newtermios,	oldtermios ;
	memset(&oldtermios,0,sizeof(oldtermios));	//初始化oldtermios
	if(tcgetattr(fd,&oldtermios)!=0){			//如果没有成功获取fd的参数,打印错误信息(待测试)	
		perror("set232port/tcgetattr");
		return -1;
	}
	memset(&newtermios,0,sizeof(newtermios));
	newtermios.c_cflag = newtermios.c_cflag |=CLOCAL | CREAD ;	//待测试
	newtermios.c_cflag &=~CSIZE  ;		//屏蔽其他标志
	newtermios.c_cflag |= CS8    ;		//设置字符长度为8
	newtermios.c_cflag &= ~PARENB ;		//设置为奇校验
	newtermios.c_iflag |= (INPCK | ISTRIP);//启动输入就校验,去掉第八位
	newtermios.c_cflag &= ~CSTOPB;		//设置停止位
	cfsetospeed(&newtermios, B115200);	//设置波特率
	cfsetispeed(&newtermios, B115200);
	newtermios.c_cc[VTIME] = 0;			//设置特殊控制字元
	newtermios.c_cc[VMIN]  = 0;			//设置特殊控制字元
	tcflush(fd , TCIFLUSH);
	if((tcsetattr(fd, TCSANOW, &newtermios))!=0)	//tcsetattr函数用于设置终端参数。函数在成功的时候返回0,失败的时候返回-1,并设置errno的值
	{
		perror("set232port/tcsetattr");
		return -1;
	}
	return 0;
}

int open232port(char *dir)
{
	int fd;
	fd = open(dir , O_RDWR);
	return fd ;
}

void print232usage(FILE *stream, int exit_code)
{
	fprintf(stream, "first step , come on !\n try again!\n");
	fprintf(stream, 
					"\t-h  --help     Display this usage information.\n"
					"\t-d  --device   The device ttyS[0-3] or ttySCMA[0-1]\n"
	   				"\t-b  --baudrate Set the baud rate you can select\n" 
	       			"\t-s  --string   Write the device data\n");
	exit(exit_code);
}

int send232(int fd,char buff232[]){
	int wrlong,i,wrnum;
	char wrword[11];
	sleep(3);
	memset(wrword,0,sizeof(wrword)+2);
	wrlong = strlen(buff232);
	i = wrlong;
	wrword[0] = '<';
	wrword[10] = '>';
	wrword[9] = 0x00;
	wrnum = 8;
	while(wrnum > 0){
		wrword[wrnum] = (i % 10 + 0x30);
		i = i / 10;
		wrword[9] = wrword[9] ^ wrword[wrnum] ;
		wrnum --;
	}
	write(fd, wrword, sizeof(wrword));
	printf("\n****一共>>>>发送的数据:%s,这是%d数据**",wrword,0);	
//	printf("\n发送函数这里正常");
	sleep(1);
	i = 0;
	while(i < wrlong){
		wrnum = 1 ;
		wrword[9] = 0x00;
	//	sleep(1);
		while(wrnum < 9){			
			wrword[wrnum] = buff232[i];
			wrword[9] = wrword[9]^wrword[wrnum] ;
			i++ ;
			wrnum++;
	//		printf("\n发送函数这里正常%d",i);
			if(wrnum == 9){
				write(fd, wrword,sizeof(wrword));
				sleep(1);
				printf("\n>>>>发送数据:%s,这是%d数据	Test:wrword[9] = %d",wrword,i,wrword[9]);	
			}
		}
	}
//	sleep(10);
	return 0;
}

int receive232(int fd ,char buff232[]	){
	int readflag = 0 , relong ,renum,resum = 0,nread,i;
	char reword[11],recheck[1];
	memset(buff232, 0, sizeof(buff232)+2);
	
//	printf("\nreceive函数调用了1");
	do{
		nread = read(fd,reword,sizeof(reword));
		usleep(10);
	}while(nread < 1 );
	printf("\nreceive函数调用了2");
	recheck[0] = 0x00;
	renum = 1;
	relong = 0;
	while(renum < 9){
		relong = relong * 10 + reword[renum] - 0x30;
		recheck[0] = recheck[0]^reword[renum];
		renum ++;
	}
	printf("\n	数字Test:reword[9] = %d,recheck[0] = %d",reword[9],recheck[0]);
	printf("\nreceive函数调用了3");
	printf("\n****一共<<<<收到的数据大小为:%d",relong);					
	do{
		usleep(100);
		nread = read(fd,reword,sizeof(reword));
	}while(nread < 1 );	
	printf("\nreceive函数调用了%d",relong);
	
	if(reword[0]=='<'){
		while(resum < relong)
				renum = 1;
				recheck[0] = 0x00 ;
				while(renum < 9){
					buff232[resum] = reword[renum];
					recheck[0] = recheck[0]^reword[renum];
					renum ++ ;
					resum ++ ;
					printf("\nreceive函数调用了num=%d,sum=%d,relong=%d",renum,resum ,relong);
				}
				printf("\n     num=%d,sum=%d,relong=%d",renum,resum ,relong);
				if(recheck[0] != reword[9]){
					relong = relong - 8 ;
					resum = resum - 8 ;
					printf("\n	Test:reword[9] = %d,recheck[0] = %d",reword[9],recheck[0]);
				}
				if(resum < relong){
					do{
						nread = read(fd,reword,sizeof(reword));
						usleep(10);
					}while(nread < 1);

				}
				}
	}
	printf("\n     <<<<收到的数据为:%s  , final总共:%d\n",buff232,relong);
	return 0;
}


int main(int argc , char *argv[])
{
	char writebuff[] = "abcdefghijklmnopqrstuvwxcdefghijklmnopqrstuvwxyzcdefghijklmnopqrstuvwxyz";
	char readbuff[strlen(writebuff)];
//	char recheck[1] ;
	int fd ,i ,len ,nread,wrlong,relong,wrnum,renum,resum,wrsum,readflag = 0;
	int pid ;
	int nextoption,havearg = 0;;
	extern struct termios oldtermios;	//修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”
	int speed ;
	char *device;
	int speeflag = 0, deviceflag = 0;
	const char *const shortoptions = "hd:s:b:";
//	char *xmit = "1234567890"; 
	const struct option longoptions[] = {
		{"help",	0,NULL,'h'},
		{"device",	1,NULL,'d'},
		{"string",	1,NULL,'s'},
		{"baudrate",1,NULL,'b'},
		{NULL,		0,NULL,	0}
	};
		
	if(argc < 2){
		print232usage (stdout, 0);
		exit(0);
	}
	while (1) {
		nextoption = getopt_long (argc, argv, shortoptions, longoptions, NULL);	//用来解析命令行选项参数的
		if (nextoption < 0)	//解析命令行选项参数失败则退出while(1)
			break;
		switch(nextoption){
			case 'h':
				print232usage (stdout, 0);
				break;
			case 'd':
				device = optarg;
				deviceflag = 1;
				break;
			case 'b':
				speed = atoi(optarg);
				speeflag = 1 ;
				break;
			case '?':
				print232usage (stderr, 1);
				break ;
			default:
				abort ();
		}
			
	}
		
	if ((!deviceflag)||(!speeflag)) {		//如果device跟speed都没有设置,则输出错误信息
		print232usage (stderr, 1);
		exit(0);	
	}
	
	fd = open232port(device);
	if (fd < 0){
		perror("open failed");
		return -1;
	}
	i = set232port(fd);		//设置串口的各种参数
	if (i < 0) {							//如果串口设置失败,就打印错误信息
		perror("set232port failed");
		return -1;	
	}
	pid = fork();
	if (pid < 0){
		perror("fork");
		return -1;
	}else if (pid == 0){
	//发送数据:起始位——数据——校验位——停止位
			//用于发送一共写了多少数据,把数字转化成了字符
		send232(fd, writebuff);
		sleep(10);
		exit(0);
	}else{
		//接受数据:起始位——数据——校验位——停止位		
		receive232(fd,readbuff);
		sleep(10);
		exit(0);
	}
	sleep(100);
	tcsetattr(fd,TCSANOW,&oldtermios);
	close(fd);
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值