当前位置: 技术问答>linux和unix
linux新手,请教各位大人串口通讯问题(发送十六进制正常,接受数据错误)附源码
来源: 互联网 发布时间:2016-04-06
本文导语: 在linux下做了个与dlt645电表通讯的串口程序,根据我发送的数据电表会反馈一陀十六进制的数据表示表的读数.现在用串口助手测了下发现发送的数据是正常的,接受的数据是错误的(接受数据已知).怀疑是串口初始化那里...
在linux下做了个与dlt645电表通讯的串口程序,根据我发送的数据电表会反馈一陀十六进制的数据表示表的读数.现在用串口助手测了下发现发送的数据是正常的,接受的数据是错误的(接受数据已知).怀疑是串口初始化那里的问题(9600,偶效验,8,1).请各位达人看看,小弟不胜感激.
#include
#include
#include /*鏍囧噯杈撳叆杈撳嚭瀹氫箟*/
#include /*鏍囧噯鍑芥暟搴撳畾涔?/
#include /*Unix 鏍囧噯鍑芥暟瀹氫箟*/
#include
#include
#include /*鏂囦欢鎺у埗瀹氫箟*/
#include /*PPSIX 缁堢鎺у埗瀹氫箟*/
#include /*閿欒鍙峰畾涔?/
#include
#define BUFFLEN 1024 /*瀹氫箟缂撳啿鍖哄ぇ灏?/
unsigned char Buffer[BUFFLEN]; /*瀹氫箟缂撳啿鍖?/
unsigned char ReBuffer[BUFFLEN]={''}; /*瀹氫箟缂撳啿鍖?/
int fd; /*device description*/
int flag_close;
/*--------------------------------------------------------------------------------------------------------------*/
void InitCOM() /*PC鏈?32涓插彛鍒濆鍖栵紝璁剧疆娉㈢壒鐜囧拰缂撳啿鍖猴紝鐒跺悗鎵撳紑涓插彛寮€濮嬮€氳*/
{
int sfd,retv,i;
struct termios option;
fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY);
if (-1 == fd)
{
/* 涓嶈兘鎵撳紑涓插彛涓€*/
printf(" open/dev/ttyS0 閿欒锛?);
}
tcgetattr(fd,&option);//tcgetattr鍑芥暟鐢ㄤ簬鑾峰彇涓庣粓绔浉鍏崇殑鍙傛暟銆傚弬鏁癴d涓虹粓绔殑鏂囦欢鎻忚堪绗︼紝杩斿洖鐨勭粨鏋滀繚瀛樺湪termios缁撴瀯浣撲腑
bzero( &option, sizeof( option ) );
option.c_cflag |= CLOCAL | CREAD;
option.c_cflag &= ~CSIZE;
cfmakeraw(&option);//璁剧疆缁堢鐨?Raw 妯″紡,濡傛灉涓嶆槸寮€鍙戠粓绔箣绫荤殑锛屽彧鏄覆鍙d紶杈撴暟鎹紝鑰屼笉闇€瑕佷覆鍙f潵澶勭悊锛岄偅涔堜娇鐢ㄥ師濮嬫ā寮?Raw Mode)鏂瑰紡鏉ラ€氳浣跨敤鏂囦欢鎿嶄綔read鍑芥暟璇诲彇锛? /*******************************************************/
cfsetispeed(&option,B9600); /*baud 9600*/
cfsetospeed(&option,B9600);
/*******************************************************/偶
option.c_iflag |= (INPCK | ISTRIP);
option.c_cflag |= PARENB;
option.c_cflag &= ~PARODD;
//8位
option.c_cflag |= CS8;
//1位停止位
option.c_cflag &= ~CSTOPB;
option.c_cflag |= CSTOPB;
option.c_cc[VTIME] = 150;
option.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
tcsetattr(fd,TCSANOW,&option);//tcsetattr鍑芥暟鐢ㄤ簬璁剧疆缁堢鐨勭浉鍏冲弬鏁般€傚弬鏁癴d涓烘墦寮€鐨勭粓绔枃浠舵弿杩扮锛屽弬鏁?
}
/*--------------------------------------------------------------------------------------------------------------*/
void send(char *result_p)
{
int j;
unsigned short i_crc;
unsigned char *src_buf;
src_buf = Buffer;
Buffer[0]=0xfe;
Buffer[1]=0xfe;
Buffer[2]=0xfe;
Buffer[3]=0xfe;
Buffer[4]=0x68;
Buffer[5]=0x99;
Buffer[6]=0x99;
Buffer[7]=0x99;
Buffer[8]=0x99;
Buffer[9]=0x99;
Buffer[10]=0x99;
Buffer[11]=0x68;
Buffer[12]=0x01;
Buffer[13]=0x02;
Buffer[14]=0x43;
Buffer[15]=0xc3;
Buffer[16]=0x6f;
Buffer[17]=0x16;
j = write(fd,Buffer,18);
if (j == -1)
{
printf("write operation is error!");
}
}
/*--------------------------------------------------------------------------------------------------------------*/
void receive(void)
{
printf("read.....n");
unsigned char *rbuf; //it si must be a unsigned , because unsigned char --> char = sign cause ffffff
rbuf=ReBuffer;
while(1)
{
int retv=read(fd,rbuf,1);
if(retv!=-1)
{
printf("%xn",*rbuf);
}
else
{
printf("can not read data! ");
}
rbuf++;
}
}
/*--------------------------------------------------------------------------------------------------------------*/
int main()
{
InitCOM();
printf("InitCOM is OK!n");
//read thread
pthread_t id;
int ret=0;
ret=pthread_create(&id,NULL,(void *)receive,NULL);
if(ret!=0){
printf ("Create pthread error!n");
return -1;
}
send(result);
printf("send is OK!n");
printf("receive the date:n");
sleep(9);//多线程
int flag_close =close(fd);
if (flag_close==-1) /* whether sucess to close file*/
printf("Close the Device failur!n");
printf("Close the Device!n");
return 0;
}
直接拷贝过来的,所以可以直接跑
#include
#include
#include /*鏍囧噯杈撳叆杈撳嚭瀹氫箟*/
#include /*鏍囧噯鍑芥暟搴撳畾涔?/
#include /*Unix 鏍囧噯鍑芥暟瀹氫箟*/
#include
#include
#include /*鏂囦欢鎺у埗瀹氫箟*/
#include /*PPSIX 缁堢鎺у埗瀹氫箟*/
#include /*閿欒鍙峰畾涔?/
#include
#define BUFFLEN 1024 /*瀹氫箟缂撳啿鍖哄ぇ灏?/
unsigned char Buffer[BUFFLEN]; /*瀹氫箟缂撳啿鍖?/
unsigned char ReBuffer[BUFFLEN]={''}; /*瀹氫箟缂撳啿鍖?/
int fd; /*device description*/
int flag_close;
/*--------------------------------------------------------------------------------------------------------------*/
void InitCOM() /*PC鏈?32涓插彛鍒濆鍖栵紝璁剧疆娉㈢壒鐜囧拰缂撳啿鍖猴紝鐒跺悗鎵撳紑涓插彛寮€濮嬮€氳*/
{
int sfd,retv,i;
struct termios option;
fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY);
if (-1 == fd)
{
/* 涓嶈兘鎵撳紑涓插彛涓€*/
printf(" open/dev/ttyS0 閿欒锛?);
}
tcgetattr(fd,&option);//tcgetattr鍑芥暟鐢ㄤ簬鑾峰彇涓庣粓绔浉鍏崇殑鍙傛暟銆傚弬鏁癴d涓虹粓绔殑鏂囦欢鎻忚堪绗︼紝杩斿洖鐨勭粨鏋滀繚瀛樺湪termios缁撴瀯浣撲腑
bzero( &option, sizeof( option ) );
option.c_cflag |= CLOCAL | CREAD;
option.c_cflag &= ~CSIZE;
cfmakeraw(&option);//璁剧疆缁堢鐨?Raw 妯″紡,濡傛灉涓嶆槸寮€鍙戠粓绔箣绫荤殑锛屽彧鏄覆鍙d紶杈撴暟鎹紝鑰屼笉闇€瑕佷覆鍙f潵澶勭悊锛岄偅涔堜娇鐢ㄥ師濮嬫ā寮?Raw Mode)鏂瑰紡鏉ラ€氳浣跨敤鏂囦欢鎿嶄綔read鍑芥暟璇诲彇锛? /*******************************************************/
cfsetispeed(&option,B9600); /*baud 9600*/
cfsetospeed(&option,B9600);
/*******************************************************/偶
option.c_iflag |= (INPCK | ISTRIP);
option.c_cflag |= PARENB;
option.c_cflag &= ~PARODD;
//8位
option.c_cflag |= CS8;
//1位停止位
option.c_cflag &= ~CSTOPB;
option.c_cflag |= CSTOPB;
option.c_cc[VTIME] = 150;
option.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
tcsetattr(fd,TCSANOW,&option);//tcsetattr鍑芥暟鐢ㄤ簬璁剧疆缁堢鐨勭浉鍏冲弬鏁般€傚弬鏁癴d涓烘墦寮€鐨勭粓绔枃浠舵弿杩扮锛屽弬鏁?
}
/*--------------------------------------------------------------------------------------------------------------*/
void send(char *result_p)
{
int j;
unsigned short i_crc;
unsigned char *src_buf;
src_buf = Buffer;
Buffer[0]=0xfe;
Buffer[1]=0xfe;
Buffer[2]=0xfe;
Buffer[3]=0xfe;
Buffer[4]=0x68;
Buffer[5]=0x99;
Buffer[6]=0x99;
Buffer[7]=0x99;
Buffer[8]=0x99;
Buffer[9]=0x99;
Buffer[10]=0x99;
Buffer[11]=0x68;
Buffer[12]=0x01;
Buffer[13]=0x02;
Buffer[14]=0x43;
Buffer[15]=0xc3;
Buffer[16]=0x6f;
Buffer[17]=0x16;
j = write(fd,Buffer,18);
if (j == -1)
{
printf("write operation is error!");
}
}
/*--------------------------------------------------------------------------------------------------------------*/
void receive(void)
{
printf("read.....n");
unsigned char *rbuf; //it si must be a unsigned , because unsigned char --> char = sign cause ffffff
rbuf=ReBuffer;
while(1)
{
int retv=read(fd,rbuf,1);
if(retv!=-1)
{
printf("%xn",*rbuf);
}
else
{
printf("can not read data! ");
}
rbuf++;
}
}
/*--------------------------------------------------------------------------------------------------------------*/
int main()
{
InitCOM();
printf("InitCOM is OK!n");
//read thread
pthread_t id;
int ret=0;
ret=pthread_create(&id,NULL,(void *)receive,NULL);
if(ret!=0){
printf ("Create pthread error!n");
return -1;
}
send(result);
printf("send is OK!n");
printf("receive the date:n");
sleep(9);//多线程
int flag_close =close(fd);
if (flag_close==-1) /* whether sucess to close file*/
printf("Close the Device failur!n");
printf("Close the Device!n");
return 0;
}
直接拷贝过来的,所以可以直接跑
|
你接收数据错误是啥错误 ?
是不是有些特殊字符收不到 ? 如果是:
加入红色部分代码.
options.c_cc[VTIME] = 150; // 15 seconds
options.c_cc[VMIN] = 0;
options.c_cflag |= CLOCAL | CREAD;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
是不是有些特殊字符收不到 ? 如果是:
加入红色部分代码.
options.c_cc[VTIME] = 150; // 15 seconds
options.c_cc[VMIN] = 0;
options.c_cflag |= CLOCAL | CREAD;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
|
建议你看下《精通Unix下C语言编程与项目实践》的第8章《设备文件》的第8.4.1小节《操作连接串口的外设》,上面有详细的解释,这里是上面的一个打开串口程序供参考,你可以直接使用。另外你说接收的信息是错误的,是指什么意思,是返回-1,还是正确返回,当时内容错误?
代码8-3 打开设备文件函数(节自/code/chapter8/term2.c)
int OpenTTY(char *devname)
{
| int fd;
| if((fd=open(devname,O_RDWR))==-1)
| {
| fprintf(stderr, "打开终端[%s]出错!", devname);
| return(-1);
| }
| if((ioctl(fd, TCGETA, &oldtty))==-1)
| {
| fprintf(stderr, "取终端[%s]参数出错!", devname);
| close(fd);
| return(-1);
| }
| newtty=oldtty;
| newtty.c_iflag &= ~ICRNL;
| newtty.c_oflag = newtty.c_oflag & ~ONLCR & TAB0 | OPOST;
| newtty.c_lflag = newtty.c_lflag & ~ICANON & ~ECHO;
| newtty.c_cflag |= B9600;
| newtty.c_cc[VMIN]=1;
| newtty.c_cc[VQUIT]=0;
| if((ioctl(fd, TCSETA, &newtty)) == -1)
| {
| fprintf(stderr, "设置终端[%s]参数出错!", devname);
| close(fd);
| return(-1);
| }
| return(fd);
}
——————————————————————————————
《精通Unix下C语言编程与项目实践》(http://book.educity.cn/viewbook.asp?id=87 ),
本书以实际应用为目标,直接讲述在产生中最有可能知识,并提供可直接使用的应用编程模板,对初学者尤其有帮助。
代码8-3 打开设备文件函数(节自/code/chapter8/term2.c)
int OpenTTY(char *devname)
{
| int fd;
| if((fd=open(devname,O_RDWR))==-1)
| {
| fprintf(stderr, "打开终端[%s]出错!", devname);
| return(-1);
| }
| if((ioctl(fd, TCGETA, &oldtty))==-1)
| {
| fprintf(stderr, "取终端[%s]参数出错!", devname);
| close(fd);
| return(-1);
| }
| newtty=oldtty;
| newtty.c_iflag &= ~ICRNL;
| newtty.c_oflag = newtty.c_oflag & ~ONLCR & TAB0 | OPOST;
| newtty.c_lflag = newtty.c_lflag & ~ICANON & ~ECHO;
| newtty.c_cflag |= B9600;
| newtty.c_cc[VMIN]=1;
| newtty.c_cc[VQUIT]=0;
| if((ioctl(fd, TCSETA, &newtty)) == -1)
| {
| fprintf(stderr, "设置终端[%s]参数出错!", devname);
| close(fd);
| return(-1);
| }
| return(fd);
}
——————————————————————————————
《精通Unix下C语言编程与项目实践》(http://book.educity.cn/viewbook.asp?id=87 ),
本书以实际应用为目标,直接讲述在产生中最有可能知识,并提供可直接使用的应用编程模板,对初学者尤其有帮助。
|
设置的时候不定看errno的值!