昨天下午开始实验一个向串口发送和接受数据的程序,由于犯了一个很低级的错误,昨晚没搞出来。今天上午总算反应过来了,呵呵。程序在Ubuntu下用GCC编译通过。现在把代码贴在下面。 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> void set_speed(int, int); int main() { int fd,flag,wr_num=0,rd_num=0; struct termios term; speed_t baud_rate_i,baud_rate_o; char send_buf[]="hello,serial!",recv_buf[20]; fd=open("/dev/ttyS0",O_RDWR|O_NONBLOCK); if(fd==-1) printf("can not open the COM1!\n"); else printf("open COM1 ok!\n"); flag=tcgetattr(fd,&term);/*取得终端设备fd的属性,存放在termios类型的结构体term中*/ baud_rate_i=cfgetispeed(&term);/*从term中读取输入波特率*/ baud_rate_o=cfgetospeed(&term);/*从term中读取输出波特率*/ printf("输入波特率是%d,输出波特率是%d,文件描述符是%d\n",baud_rate_i,baud_rate_o,fd); set_speed(fd,9600);/*设置波特率*/ flag=tcgetattr(fd,&term);/*以下三行读取设置之后的波特率,用cfgetispeed和cfgetospeed得到的波特率是一个序号,可以通过查表(表见程序后面)得到真正的波特率,比如返回13,对应的实际波特率是9600。我这里没有做转换,直接把13输出了。*/ baud_rate_i=cfgetispeed(&term); baud_rate_o=cfgetospeed(&term); printf("输入波特率是%d,输出波特率是%d,文件描述符是%d\n",baud_rate_i,baud_rate_o,fd); while(1) { wr_num=write(fd,send_buf,sizeof(send_buf));/*先写入*/ if(wr_num>0) printf("write success!\n"); else printf("write fail!\n"); sleep(1); rd_num=read(fd,recv_buf,sizeof(recv_buf));/*再读出*/ if(rd_num>0) printf("we can read \"%s\" from the COM1.total:%d characters\n",recv_buf,rd_num); else printf("read fail!\n"); sleep(2); } } /***下面这个set_speed的子程序是在网上别的文章中摘抄过来的,就直接调用了,省了自己编写的麻烦***/ int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; void set_speed(int fd, int speed){ int i; int status; struct termios Opt; tcgetattr(fd, &Opt); for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr[i]); cfsetospeed(&Opt, speed_arr[i]); status = tcsetattr(fd, TCSANOW, &Opt); if (status != 0) { perror("tcsetattr fd1"); return; } tcflush(fd,TCIOFLUSH); } } } 下面是函数cfgetispeed和cfgetospeed返回值与波特率的对应表,通过 man cfsetispeed 可以找到,虽然文档里面没有标返回值标号,但是从第一个开始按0数的话,数到13恰好就是9600,我在程序中还试过用set_speed把波特率设为4800,结果返回的是12。证明这样查表应该是正确的,但我不明白为什么不能直接返回像4800和9600这样的数,因为此前在别人的程序中看到似乎是可以直接返回的,这个地方暂时还不太明白。 B0 B50 B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 B4800 B9600 B19200 B38400 B57600 B115200 B230400 最后注意一点,就是我昨天晚上犯的很弱智的错误,没有连接串口的接收引脚和发送引脚。因为这个串口程序是本机自收自发的,因此一定要用一根导线之类的东西把计算机九针串口的2、3引脚连起来,否则自己发送的数据自己接受不到。如果没有导线的话,随便一个金属的物品也行(注意着点,别把电脑捅坏,也别捅错地方连了电电着自己。呵呵,不过一般应该没太大问题,但小心些总是没错的^_^)。我就是在运行程序之后,再用一个螺丝刀同时触碰这两个引脚的。 下面是程序运行结果: ======================== admin@admin-desktop:/myfiles/test$ ./serial open COM1 ok! 输入波特率是13,输出波特率是13,文件描述符是3 输入波特率是13,输出波特率是13,文件描述符是3 write success! read fail!(这个时候还没用螺丝刀去连收发管脚呢,因此接收不到,但发送是成功的。) write success! read fail! write success! we can read "hello,serial!" from the COM1.total:14 characters(连上了,呵呵) write success! we can read "hello,serial!" from the COM1.total:14 characters write success! we can read "hello,serial!" from the COM1.total:14 characters |
评论