Orangepi Zero2——Linux串口开发

串口的认识

串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方

式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简

单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成

本,特别适用于远距离通信,但传送速度较慢

  • 是设备间接线通信的一种方式

  • 数据一位一位地顺序传送

  • 双向通信,全双工

  • 传送速度相对较慢

UART

异步串行是指UART(Universal Asynchronous Receiver/Transmitter),通用异步接收/发送。

UART包含TTL电平的串口和RS232电平的串口

RS-232

也称标准串口,最常用的一种[串行通讯接口,比如我们的电脑主机的9针串口 ,最高速率为20kb/s

RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其传送距离最大为约15米。所以RS-232适

合本地设备之间的通信

RS232电平

  • 逻辑1为-3~-15V的电压, 逻辑0为3~15V的电压

TTL

TTL是Transistor-Transistor Logic,即晶体管-晶体管逻辑的简称,它是计算机处理器控制的设备内部各部分之间通信的标准技术。

TTL电平

  • TTL电平信号应用广泛,是因为其数据表示采用二进制规定,

  • +5V等价于逻辑”1”,0V等价于逻辑”0”。

  • 数字电路中,由TTL电子元器件组成电路的电平是个电压范围,规定:

    • 输出高电平>=2.4V,输出低电平<=0.4V;
    • 输入高电平>=2.0V,输入低电平<=0.8V

笔记本电脑通过TTL电平与单片机通信 :USB转TTL,使用ch340芯片

香橙派有三个串口驱动设备文件

在这里插入图片描述

  • 三个引脚的为s0,是串口调试信息的接口

  • 两排引脚的为s5,是串口通信的接口

  • 香橙派没有s1

wiringPi示例代码

在 examples/serialTest.c

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringSerial.h>
 
int main ()
{
    int fd ;
    int count ;
    unsigned int nextTime ;
 	//serialOpen是对open函数的封装
    //该函数主要设置结构体struct termios,也就是设备参数初始化,将结构体的参数配置完毕通过函数发送给内核,进而配置硬件的寄存器
    if ((fd = serialOpen ("/dev/ttyS2", 115200)) < 0)
    {
        fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
        return 1 ;
    }
 
    if (wiringPiSetup () == -1)
    {
        fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
        return 1 ;
    }
 
    nextTime = millis () + 300 ;
 
    for (count = 0 ; count < 256 ; )
    {
        if (millis () > nextTime)
        {
        printf ("\nOut: %3d: ", count) ;
        fflush (stdout) ;
        serialPutchar (fd, count) ;
        nextTime += 300 ;
        ++count ;
        }
 
        delay (3) ;
 
        while (serialDataAvail (fd))
        {
        printf (" -> %3d", serialGetchar (fd)) ;
        fflush (stdout) ;
        }
    }
    
    printf ("\n") ;
    return 0 ;
}
  • WiringPi库是也是基于LinuxC库的,分析串口源码可以下载C库一起分析

  • C库、内核与应用层的关系图如下:

在这里插入图片描述

基于wiringPi的串口开发

串口通信是全双工的,可以创建两个线程

#include <stdio.h> 
#include <string.h> 
#include <errno.h>  
#include <wiringPi.h> 
#include <wiringSerial.h>
#include <pthread.h>
#include <stdlib.h> 
#include <unistd.h>

int fd; //打开串口的描述符
 
void* Sendhandler() 
{ 
    char *sendBuf; 
    sendBuf = (char *)malloc(32*sizeof(32));
 
    while(1){ 
        memset(sendBuf,'\0',32); 
        scanf("%s",sendBuf); 
        //如果不是\0就一直发送
        while(*sendBuf){ 
            serialPutchar (fd, *sendBuf++) ; 
        } 
    } 
}
 
void* Revhandler() 
{ 
    while(1){ 
        //检测串口通道是否有数据
        while (serialDataAvail(fd)) { 
            printf ("%c", serialGetchar(fd)) ; 
            fflush (stdout) ; 
        } 
    }
}
 
int main () 
{ 
    int count ; 
    unsigned int nextTime ; 
 
    pthread_t idSend; 
    pthread_t idRev; 
 
    if ((fd = serialOpen ("/dev/ttyS5", 115200)) < 0) { 
        fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ; 
        return 1 ; 
    }
    pthread_create(&idSend, NULL,Sendhandler,NULL); 
    pthread_create(&idRev, NULL,Revhandler,NULL); 
 
    if (wiringPiSetup () == -1) { 
        fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ; 
        return 1 ; 
    }
 
    while(1){sleep(10);} 
 
    printf ("\n") ; 
    return 0 ; 
}

自己实现串口通信

完成功能:

  • 通过自己封装的open,write,read函数来完成串口的通信

实现流程:

  • 首先要打开文件,得到文件的句柄,在封装的open函数中将termios结构体和status控制字发送给内核,完成硬件的初始化,传输和读取数据就是对句柄进行读写操作

uartTool.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "wiringSerial.h"

int myserialOpen (const char *device, const int baud) 
{ 
	struct termios options ; 
	speed_t myBaud ; 
	int status, fd ; 

	switch (baud){ 
		case   9600: myBaud =   B9600 ; break ; 
		case 115200: myBaud = B115200 ; break ; 
	}
	if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) 
	return -1 ; 
	
	fcntl (fd, F_SETFL, O_RDWR) ; 

// Get and modify current options: 

	tcgetattr (fd, &options) ; //
	 
	cfmakeraw (&options) ; 
	cfsetispeed (&options, myBaud) ; //设置波特率
	cfsetospeed (&options, myBaud) ;
	 
	options.c_cflag |= (CLOCAL | CREAD) ;
	options.c_cflag &= ~PARENB ; //无校验位
	options.c_cflag &= ~CSTOPB ; //1位停止位
	options.c_cflag &= ~CSIZE ; //用数据位掩码清空数据位设置
	options.c_cflag |= CS8 ; //数据位为8
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ; 
	options.c_oflag &= ~OPOST ; 
	 
	options.c_cc [VMIN] = 0 ; 
	options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) 
	 
	tcsetattr (fd, TCSANOW, &options) ; //
	 
	ioctl (fd, TIOCMGET, &status); //status是控制字
	 
	status |= TIOCM_DTR ; 
	status |= TIOCM_RTS ; 
	 
	ioctl (fd, TIOCMSET, &status); 
	
	usleep (10000) ; // 10mS 
	
	return fd ; 	
}

void serialSendstring (const int fd, const char *s) 
{ 
	int ret;
	ret = write (fd, s, strlen (s)); 
	if (ret < 0) 
		printf("Serial Sendstring Error\n"); 
}

int serialGetstring (const int fd, char *buffer) 
{ 
	int n_read; 
	n_read = read(fd, buffer,32); 
	return n_read; 
}

uartTool.h

int myserialOpen (const char *device, const int baud) ;

void serialSendstring (const int fd, const char *s) ;

int serialGetstring (const int fd, char *buffer) ;

uartTest.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <pthread.h>
#include "uartTool.h"


int fd;

void* readSerial()
{
   char buffer[32];
   while(1){
       memset(buffer,'\0',sizeof(buffer));
       serialGetstring(fd, buffer);
         printf("GET->%s\n",buffer);
   }
}

void* sendSerial()
{
   char buffer[32];
   while(1){
       memset(buffer,'\0',sizeof(buffer));
   	scanf("%s",buffer);
   	serialSendstring(fd, buffer);
   }
}

int main(int argc, char **argv)
{
   char deviceName[32] = {'\0'};
   pthread_t readt;
   pthread_t sendt;

   if(argc < 2){
       printf("uage:%s /dev/ttyS?\n",argv[0]);
       return -1;
   }
    
   strcpy(deviceName, argv[1]);
    
   if( (fd = myserialOpen(deviceName, 115200)) == -1){
       printf("open %s error\n",deviceName);
       return -1;
   }
    
   pthread_create(&readt, NULL, readSerial,NULL);
   pthread_create(&sendt, NULL, sendSerial,NULL);
    
   while(1){sleep(10);}

}
gcc uartTest.c uartTool.c -lpthread
./a.out /dev/ttyS5
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值