Linux下串口通信编程

一、串口程序需要的头文件

#include <stdio.h>         //标准输入输出定义
#include <stdlib.h>        //标准函数库定义
#include <unistd.h>       //Unix标准函数定义
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>          //文件控制定义
#include <termios.h>     //POSIX中断控制定义
#include <errno.h>        //错误号定义

二、打开串口

串口位于/dev中,可作为标准文件的形式打开,其中:
串口1 /dev/ttyS0
串口2 /dev/ttyS1

int open_com(char *device_name)
{
    int fd = 0;
/*O_RDWR以读写的方式打开,O_NOCTTY是通知Linux系统这个程序不会成为这个端口的控制终端*/
    if (0 > (fd = open(device_name, O_RDWR|O_NOCTTY)))
    {
        perror("Open Comport Fail:");
        return 0;
    }

    return fd;
}/* ----- End of open_com()  ----- */

三、串口的基本设置

最基本的串口设置包括波特率、校验位和停止位设置,且串口设置主要使用termios.h头文件中定义的termios结构,如下:
struct termios
{
   tcflag_t  c_iflag;   //输入模式标志
   tcflag_t  c_oflag;  //输出模式标志
   tcflag_t  c_cflag;  //控制模式标志
   tcflag_t  c_lflag;   //本地模式标志
   cc_t   c_line;              //line discipline
   cc_t   c_cc[NCC];    //control characters
}

该结构中c_cflag最为重要,可设置波特率、数据位、校验位、停止位。

/**************************************************************************************
 *  Description:设置波特率,数据位,校验位,停止位
 *   Input Args:
 *  Output Args:
 * Return Value:
 *************************************************************************************/
int set_com_opt(int fd, int nSpeed, int nBits, unsigned char nEvent, int nStop)
{
    struct termios opt, oldopt;

    tcgetattr(fd, &oldopt);	//保存原先串口配置
    tcgetattr(fd, &opt);	
    switch (nSpeed)
    {
      case 2400:
          cfsetispeed(&opt, B2400);//输入波特率
          cfsetospeed(&opt, B2400);//输出波特率
          break;
      case 4800:
          cfsetispeed(&opt, B4800);
          cfsetospeed(&opt, B4800);
          break;
      case 9600:
          cfsetispeed(&opt, B9600);
          cfsetospeed(&opt, B9600);
          break;
      case 57600:
          cfsetispeed(&opt, B57600);
          cfsetospeed(&opt, B57600);
          break;
      case 115200:
          cfsetispeed(&opt, B115200);
          cfsetospeed(&opt, B115200);
          break;
      default:
          cfsetispeed(&opt, B9600);
          cfsetospeed(&opt, B9600);
          break;
    }
	/*设置校验位*/
    switch (nEvent)
    {
	/*奇校验*/
      case 'O':
          opt.c_cflag |= PARENB;	//enable parity
          opt.c_cflag |= PARODD;
          opt.c_cflag |= (INPCK | ISTRIP);
          break;
	/*偶校验*/
      case 'E':
          opt.c_cflag |= (INPCK | ISTRIP);
          opt.c_cflag |= PARENB;
          opt.c_cflag &= ~PARODD;
          break;
	/*无校验*/
      case 'N':
          opt.c_cflag &= ~PARENB;	//清除校验位
          opt.c_cflag &= ~INPCK;	 //disable pairty checking
          break;
    }
	/*停止位设置*/
    if (nStop == 1)
    {
        opt.c_cflag &= ~CSTOPB;
        opt.c_cflag &= ~CSIZE;
    }
    else if (nStop == 2)
    {
        opt.c_cflag |= CSTOPB;
        opt.c_cflag &= CSIZE;
    }
	/*数据位设置*/
    switch (nBits)
    {
      case 7:
          opt.c_cflag |= CS7;
          break;
      case 8:
          opt.c_cflag |= CS8;
          break;
    }
	/*软件流控制屏蔽*/
    opt.c_iflag &= ~(IXON | IXOFF | IXANY);

	/*设置最少字符和等待时间*/
    opt.c_cc[VTIME] = 0;
	opt.c_cc[VMIN] = 0;
	/*转换到行方式输入*/
    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //Input
    opt.c_oflag &= ~OPOST;      //Output

    tcflush(fd, TCIOFLUSH);//刷清输入输出队列

    tcsetattr(fd, TCSANOW, &opt);//立即激活配置

    return 0;
} /* ----- End of set_com_opt()  ----- */
四、初始化串口
int init_comport (char * dev_name,int nSpeed )
{
    int     fd = 0;

    if(0 == (fd = open_com(dev_name)))
    {
        printf("Open device %s fail!\n",dev_name);
        return -1;
    }

    set_com_opt(fd,nSpeed,8,'N',1);//设置数据位为八位,无校验位,停止位为1位
    printf("Initialize device [%s] :%d,S8N1\n",dev_name,nSpeed);

    return fd;
} /* ----- End of init_comport()  ----- */

五、主函数实现

主函数通过两个进程分别负责接收数据和发送数据。

int main(int argc, char **argv)
{
    /* declare variant */
    int             fd = 0;
    struct timeval  timeout;
    unsigned char   buff[BUFF_SIZE];
    int             read_size = 0;
    pid_t           pid;

    if (argc != 3)
    {
        printf("Usage:%s [Device] [Baud Rate]\n", argv[0]);
        exit(0);
    }
	/*初始化com口*/
    fd = init_comport(argv[1], atoi(argv[2]));

    if (fd == -1)
    {
        printf("Initialize UART Fail!\n");
        exit(1);
    }
	/*子进程执行写操作*/
    if (0 == (pid = fork()))
    {
        char w_buff[BUFF_SIZE];
        while (1)
        {
            scanf("%s",w_buff);
            if (0 > write(fd, w_buff, strlen(w_buff)))
            {
                perror("Write Serial Fail:");
                exit(-1);
            }
            memset(w_buff, 0x00, BUFF_SIZE);
        }

    }

    timeout.tv_sec = 0;
    timeout.tv_usec = 50;        //wait for 50ms
	/*父进程执行读操作*/
    while (1)
    {
        memset(buff, 0x00, sizeof(buff));
        if (0 > (read_size = read(fd, buff, BUFF_SIZE)))
        {
            perror("Read Serial Fail:");
            exit(-1);
        }
        if (read_size > 0)
            printf("%s", buff);
        fflush(stdout);  
    }
    close(fd);
    return 0;
}                               /* ----- End of main() ----- */
六、编译执行

编译:

通过tftp下载到开发板内存中


执行程序

设置串口调试助手波特率115200,数据位8,校验位无、停止位1,在串口调试助手中发送huangyidong 在开发板终端上打印huangyidong 
在中断打印yanshifu后回车,串口中断收到数据yanshifu。

到此Linux下串口通信程序演示完。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值