linux串口编程笔记

1.. 用户常见的数据通信的基本方式有两种:
并行通信;
串行通信;
串行通信是计算机常用的接口,如: RS-232-C 接口。该标准规定采用一个 DB25 芯引脚连接器或 DB9 芯引脚连接器。
芯片内部常具有 UART 控制器,其可工作于 Interrupt( 中断模式 ) DMA (直接内存访问)模式。
2. UART 的操作主要包括以下几个部分:
数据发送;
数据接收;
产生中断;
产生波特率;
Loopback 模式;
红外模式;
自动流控模式
  串口参数的配置主要包括:波特率、数据位、停止位、流控协议。
3. linux 中的串口设备文件存放于 /dev 目录下,其中串口一,串口二对应设备名依次为“ /dev/ttyS0 ”、“ /dev/ttyS1 ”。在 linux 下操作串口与操作文件相同。
4. 在使用串口之前必须设置相关配置,包括:波特率、数据位、校验位、停止位等。串口设置由下面结构体实现:
 
4.1 该结构中 c_cflag 最为重要,可设置波特率、数据位、校验位、停止位。在设置波特率时需在数字前加上‘ B ’,如 B9600 B19200 。使用其需通过“与”“或”操作方式。
4.2 输入模式 c_iflag 成员控制端口接收端的字符输入处理。
5. 串口控制函数
Tcgetattr          取属性 (termios 结构 )
Tcsetattr           设置属性 (termios 结构 )
cfgetispeed     得到输入速度
Cfgetospeed             得到输出速度
Cfsetispeed               设置输入速度
Cfsetospeed              设置输出速度
Tcdrain              等待所有输出都被传输
tcflow               挂起传输或接收
tcflush              刷清未决输入和 / 或输出
Tcsendbreak              BREAK 字符
tcgetpgrp                 得到前台进程组 ID
tcsetpgrp                  设置前台进程组 ID
6. 串口配置流程
6.1 保存原先串口配置使用 tcgetattr(fd,&oldtio) 函数
struct termios newtio,oldtio;
tcgetattr( fd,&oldtio );
6.2 激活选项有 CLOCAL CREAD, 用于本地连接和接收使能。
 newtio.c_cflag | =  CLOCAL | CREAD;
 
以下是我自己写的一个串口,仅供参考
/*****************************************************************************/
 
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
 
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
         struct termios newtio,oldtio;
         if  ( tcgetattr( fd,&oldtio)  !=  0) {
                   perror("SetupSerial 1");
                   return -1;
         }
         memset( &newtio, sizeof( newtio ) );// 将串口配置的结构体清零
         newtio.c_cflag  |=  CLOCAL | CREAD; // 激活选项有 CLOCAL CREAD, 用于本地连接和接收使能
         newtio.c_cflag &= ~CSIZE; // 使原先的数据位清零
 
         switch( nBits )// 选择数据位的个数
         {
         case 7:
                   newtio.c_cflag |= CS7;
                   break;
         case 8:
                   newtio.c_cflag |= CS8;
                   break;
         }
 
         switch( nEvent )
         {
         case 'O':// 奇校验
                   newtio.c_cflag |= PARENB;
                   newtio.c_cflag |= PARODD;
                   newtio.c_iflag |= (INPCK | ISTRIP);
                   break;
         case 'E': // 偶校验
                   newtio.c_iflag |= (INPCK | ISTRIP);
                   newtio.c_cflag |= PARENB;
                   newtio.c_cflag &= ~PARODD;
                   break;
         case 'N': // 不进行奇偶校验
                   newtio.c_cflag &= ~PARENB;
                   break;
         }
 
switch( nSpeed )// 确定输入输出函数的波特率
         {
         case 2400:
                   cfsetispeed(&newtio, B2400);
                   cfsetospeed(&newtio, B2400);
                   break;
         case 4800:
                   cfsetispeed(&newtio, B4800);
                   cfsetospeed(&newtio, B4800);
                   break;
         case 9600:
                   cfsetispeed(&newtio, B9600);
                   cfsetospeed(&newtio, B9600);
                   break;
         case 115200:
                   cfsetispeed(&newtio, B115200);
                   cfsetospeed(&newtio, B115200);
                   break;
         default:
                   cfsetispeed(&newtio, B9600);
                   cfsetospeed(&newtio, B9600);
                   break;
         }
         if( nStop == 1 )
                   newtio.c_cflag &=  ~CSTOPB;// 设置停止位为 1
         else if ( nStop == 2 )
         newtio.c_cflag |=  CSTOPB;// 设置停止位为 2
         newtio.c_cc[VTIME]  = 1;//read 调用读到数据则立即返回,否则将为每个字符最多等待 1 个时间
         newtio.c_cc[VMIN] = 0;
         tcflush(fd,TCIFLUSH);// 发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除(刷清)
         if((tcsetattr(fd,TCSANOW,&newtio))!=0)
         {
                   perror("com set error");
                   return -1;
         }
         printf("set done!\n");
         return 0;
}
 
int open_port(int fd,int comport)
{
         char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3"};
         long  vdisable;
         if (comport==1)
         {        fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);
                   if (-1 == fd){
                            perror("Can't Open Serial Port");
                            return(-1);
                   }
                   else
                            printf("open ttyS0 .....\n");
         }
         else if(comport==2)
         {        fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);
                   if (-1 == fd){
                            perror("Can't Open Serial Port");
                            return(-1);
                   }
                   else
                            printf("open ttyS1 .....\n");
         }
         else if (comport==3)
         {
                   fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY);
                   if (-1 == fd){
                            perror("Can't Open Serial Port");
                            return(-1);
                   }
                   else
                            printf("open ttyS2 .....\n");
         }
         if(fcntl(fd, F_SETFL, 0)<0)
                   printf("fcntl failed!\n");
         else
                   printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
         if(isatty(STDIN_FILENO)==0)
                   printf("standard input is not a terminal device\n");
         else
                   printf("isatty success!\n");
         printf("fd-open=%d\n",fd);
         return fd;
}
 
int main(void)
{
         int fd;
         int nread,i;
         char buff[]="Hello\n";
 
         if((fd=open_port(fd,1))<0){
                   perror("open_port error");
                   return;
         }
         if((i=set_opt(fd,115200,8,'N',1))<0){
                   perror("set_opt error");
                   return;
         }
         printf("fd=%d\n",fd);
//      fd=3;
         while(1)
         {
         完成文件的读写操作
         }
         close(fd);
         return;
}
/*****************************************************************************/
 

你可能感兴趣的:(linux,职场,休闲)