登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

梦想之鹰的天空

天高任鸟飞......放飞....心情..........放飞.....梦想

 
 
 

日志

 
 

Linux下简单的串口读写程序编写  

2010-12-31 12:19:27|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
转载自 mcu99
最终编辑 mcu99
昨天下午开始实验一个向串口发送和接受数据的程序,由于犯了一个很低级的错误,昨晚没搞出来。今天上午总算反应过来了,呵呵。程序在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);  
        }
        }
        }

下面是函数cfgetispeedcfgetospeed返回值与波特率的对应表,通过 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
  评论这张
 
阅读(743)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018