liunx下串口通信

    技术2022-07-17  70

    Linux下编程的过程有些固定,很多都是比如打开、配置、关闭等等

    串口通信流程:打开串口ttySn--->初始化串口--->读写(read、write)--->关闭串口

    串口设置

    最基本的设置串口包括波特率设置,效验位和停止位设置。

    串口的设置主要是设置 struct termios 结构体的各成员值。

    struct termio { unsigned short c_iflag; /* 输入模式标志 */ unsigned short c_oflag; /* 输出模式标志 */ unsigned short c_cflag; /* 控制模式标志*/ unsigned short c_lflag; /* local mode flags */ unsigned char c_line; /* line discipline */ unsigned char c_cc[NCC]; /* control characters */ };

    串口控制函数

    tcgetattr 取属性(termios结构) tcsetattr 设置属性(termios结构) cfgetispeed 得到输入速度 cfgetospeed 得到输出速度 cfsetispeed 设置输入速度 cfsetospeed 设置输出速度 tcdrain   等待所有输出都被传输 tcflow   挂起传输或接收 tcflush   刷清未决输入和/或输出 tcsendbreak 送BREAK字符 tcgetpgrp 得到前台进程组ID tcsetpgrp 设置前台进程组ID

    串口.h文件   usart.h

    /********************************************************************************* * Copyright: (C) 2018 Yujie * All rights reserved. * * Filename: usart.h * Description: 串口配置 * * Version: 1.0.0(08/27/2018) * Author: yanhuan <yanhuanmini@foxmail.com> * ChangeLog: 1, Release initial version on "08/23/2018 17:28:51 PM" * ********************************************************************************/ #ifndef _USART_H #define _USART_H //串口相关的头文件 #include<stdio.h> /*标准输入输出定义*/ #include<stdlib.h> /*标准函数库定义*/ #include<unistd.h> /*Unix 标准函数定义*/ #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> /*文件控制定义*/ #include<termios.h> /*PPSIX 终端控制定义*/ #include<errno.h> /*错误号定义*/ #include<string.h> //宏定义 #define FALSE -1 #define TRUE 0 int UART0_Open(int fd,char*port); void UART0_Close(int fd) ; int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity); int UART0_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity) ; int UART0_Recv(int fd, char *rcv_buf,int data_len); int UART0_Send(int fd, char *send_buf,int data_len); #endif

    串口测试函数    usart_test.c

    /********************************************************************************* * Copyright: (C) 2018 Yujie * All rights reserved. * * Filename: usart_test.c * Description: 串口测试 * * Version: 1.0.0(08/27/2018) * Author: yanhuan <yanhuanmini@foxmail.com> * ChangeLog: 1, Release initial version on "08/23/2018 17:28:51 PM" * ********************************************************************************/ #include "usart.h" #include<stdio.h> /*标准输入输出定义*/ #include<stdlib.h> /*标准函数库定义*/ #include<unistd.h> /*Unix 标准函数定义*/ #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> /*文件控制定义*/ #include<termios.h> /*PPSIX 终端控制定义*/ #include<errno.h> /*错误号定义*/ #include<string.h> int main(int argc, char **argv) { int fd = -1; //文件描述符,先定义一个与程序无关的值,防止fd为任意值导致程序出bug int err; //返回调用函数的状态 int len; int i; char rcv_buf[256]; char send_buf[256]; if(argc != 3) { printf("Usage: %s /dev/ttySn 0 #(send data)\n",argv[0]); printf("Usage: %s /dev/ttySn 1 #1(receive data)\n",argv[0]); printf("open failure : %s\n", strerror(errno)); return FALSE; } fd = UART0_Open(fd,argv[1]); //打开串口,返回文件描述符 // fd=open("dev/ttyS1", O_RDWR); //printf("fd= \n",fd); do { err = UART0_Init(fd,115200,0,8,1,'N'); printf("Set Port Exactly!\n"); sleep(1); }while(FALSE == err || FALSE == fd); if(0 == strcmp(argv[2],"0")) //开发板向pc发送数据的模式 { fgets(send_buf,256,stdin); //输入内容,最大不超过40字节,fgets能吸收回车符,这样pc收到的数据就能自动换行 for(i = 0;i < 10;i++) { len = UART0_Send(fd,send_buf,40); if(len > 0) printf(" %d time send %d data successful\n",i,len); else printf("send data failed!\n"); sleep(1); } UART0_Close(fd); } else //开发板收到pc发送的数据的模式 { while (1) //循环读取数据 { len = UART0_Recv(fd, rcv_buf,sizeof(rcv_buf)); if(len > 0) { rcv_buf[len] = '\0'; printf("receive data is %s\n",rcv_buf); } else { printf("cannot receive data\n"); } sleep(1); } UART0_Close(fd); } }

    串口编译   makefile

    CC=arm-linux-gcc all: CC *.c -o usart clear: rm usart

     

    程序在开发板上运行,打开对应的串口;另一端接在串口调试助手,打开串口调试助手。

    程序可以改进很多,同时读写、select设置非阻塞、数据结构优化等等,等有时间会改进。

     

    对于两块开发板之间的通信,可以把程序修改成select同时读写,注意是用pc上的gcc还是arm上的交叉编译,还要注意串口线的RX和TX接线。

    最合适的指导书:https://blog.csdn.net/yanhuan136675/article/details/82766466

       

    Processed: 0.013, SQL: 9