linux uart编程

串口: 每次传输是按位为单位进行传输的接口. 如uart, usb, 网络, sata. 一般就是只用一根数据线来接收或发送数据。 

并口: 每次传输是两位或以上为单位进行传输的接口. 一般会用多根数据线来接收或发送数据.


单工: 只能单向传输的导线
半双工: 可以双向传输的导线,但某一时刻只能一个方向传输
全双工: 可以同时双向传输, 一般用两根单向导线实现

uart: 通用异步接收传送器(串口, COM口)
uart: Universal Asynchronous Receiver and Transmitter

uart图示:
Rs232

Usb转Rs232

Usb转ttl

Rs232转Rs485

计算机里根据到底就是使用二进制, 0和1, 物理上用高低电平表示.

011010可以使用低电平, 高电平, 高电平, 低电平, ……

把数据110010发给另一计算机, 可导线把相应的电平转给对方.对方可通过判断导线的电平从而知道发过来的是数据0还是数据1

设备A发(改变导线电平): 设备B接收(判断导线电平)


发送端设备与接收端设备的收发间隔时间必须保持一致

波特率(baud rate): 一秒钟内收发多少位数据, 也可算出一位数据在导线上需保持电平状态的时间
常用的波特率: 4800, 9600, 115200
Bps(byte 字节每秒钟), bps(bit, 位每秒钟)

一般情况下, 设备都是用电源负极作地线使用, 不同的设备的电源负极对真正的地线来说压降有可能不一样,
所以, 互相通信的设备都会共用地线, 保证基准电平一致.

按帧来收发数据:
一帧的组成 : 始启位(1位), 5/6/7/8位数据, 1位奇偶校验/或者不用, 1/2位停止位

数据线空闲时是高电平, 起始位是一个持续一位时间的低电平信号, 停止位是高电平

8N1: 表示使用8位数据位, 不用校验, 1位停止位来表示数据帧.
注意:起始位没有选择, 只有一位.

//
一个最基本的串口由三根线组成:

设备A: 设备B
TXD –>— RXD
RXD —<– TXD
GND —— GND

完善点的串口多引入CTS, RTS两根线(用于硬件流控). 发送端发数据前通过RTS发出请求信号, 如果接收端可以接收数据则会回一个信号确认, 发送端再接着发出数据.
CTS –<– RTS
RTS –>– CTS

注意:硬件流控一般情况下是不用的, 除非对方在使用,否则要关闭
/
TTL电平:
二进制1: 1.8v, 3.3v, 5v
0: 0v

串口直接从cpu里引出时,是使用TTL电平的

导线越长,内阻越大. 内阻会分部分压降, 接收会有可以接收到电平时, 电压值已经下降很多.
解决这个问题: 引入RS232接口标准, 是uart的接口标准之一.

RS232的电平:
二进制1: -3 ~ -25v
0: 3 ~ 25v

ttl电平与rs232电平, 可由芯片互转換. 如MAX232, SP3232
注意: rs232只是改变uart引脚的电平,uart的线原有多少根还是多少根的

uart的接口标准还有 RS485, RS422

RS232早期是25个针脚, 可接modem, 56kb/s
后面精简为9个针脚,除了上面5个针脚外,还有4针脚可用于接modem.
RS232共有9个针脚: tx, rx, gnd, cts, rts
还有4个用于接modem(非常老的产物)

///

串口硬件需通过相应的驱动代码来配置, 而驱动是由应用程序来调用的

///
在Linux系统里,串口的设备文件是: ttyS0—ttyS3
usb转uart的设备文件: ttyUSB0 — ttyUSB1
//
1. open(“/dev/ttyS0”, O_RDWR|O_NOCTTY|O_NONBLOCK);

O_NOCTTY指定打开的串口设备文件不会成为本进程的控制终端. 在终端上执行程序后,可按”ctrl+c”键终止程序运行. 如果打开的串口设备文件成为本进程的控制终端时, 发过来数据刚好与”ctrl+c”的键码一致时,就会终止程序的运行

O_NONBLOCK指定打开串口设备文件时,不管串口的工作状态. 不加上此标志, 会一直等串口的状态恢复为空闲时再会成功打开, 有可能会死堵塞.

  1. //恢复为堵塞工作模式
    fcntl(fd, F_SETFL, 0);

    ///
    //配置波特率, 数据位, 校验位, 停止位
    struct termios opts;

    tcgetattr(fd, &opts); //先把原来的属性获取保存到opts结构体变量里
    //ioctl(fd, TCGETS, &opts);

    //在opts结构体变量修改波特率的配置
    cfsetispeed(&opts, B9600);
    cfsetospeed(&opts, B9600);

    opts.c_cflag |= CREAD|CLOCAL; //启动接收器, 不管modem的控制线状态

    /// 8N1
    opts.c_cflag &= ~CSIZE; //在c_cflag里把表示数据位的位域清零
    opts.c_cflag |= CS8;
    opts.c_cflag &= ~PARENB; //不用校验
    opts.c_cflag &= ~CSTOPB; //使用一位停止位
    opts.c_cflag &= ~CRTSCTS; //关闭硬件流件

    //如PC对PC通信,需要设raw input, raw output
    opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    opts.c_oflag &= ~OPOST;

    ///把opts变量里的属性传给串口驱动,让配置生效
    tcsetattr(fd, TCSANOW, &opts);
    //ioctl(fd, TCSETS, &opts);

//配置好后,就可以通过read/write函数收发数据了

RS232是uart接口标准之一.
RS485也是uart的接口标准之一. 使用差分传输, 远距离传输, 抗干扰能力强
云台, 舞台灯光控制, 小型飞机的控制总线

差分传输是通过两根数据线的电压差来表示0/1. 发送的数据线需两根.

例: 相差10V表示1, 相差0V表示0
tx+(5) ————–[3V]————- 2V

tx-(-5v)   ---------------[3V]------------  -8V

//

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>


int main(void)
{
    int fd, ret;

    fd = open("/dev/ttyS0", O_RDWR|O_NOCTTY|O_NONBLOCK);
    if (fd < 0)
    {
        perror("open ttyS0");
        return 1;
    }

    fcntl(fd, F_SETFL, 0); //重设为堵塞状态, 去掉O_NONBLOCK
//////////////////
    struct termios opts;
    tcgetattr(fd, &opts); //把原设置获取出来,存放在opts

    //设置波特率
    cfsetispeed(&opts, B19200);
    cfsetospeed(&opts, B19200);

    opts.c_cflag |= CLOCAL|CREAD; //忽略modem控制线, 启动接收器

    // 8N1
    opts.c_cflag &= ~PARENB; 
    opts.c_cflag &= ~CSTOPB;
    opts.c_cflag |= CS8;

    opts.c_cflag &= ~CRTSCTS; //关闭硬件流控

    opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //raw input
    opts.c_oflag &= ~OPOST; // raw output          

    tcsetattr(fd, TCSANOW, &opts);  
//////////////////
    char data[1024];

    while (1)
    {
        ret = read(fd, data, sizeof(data));
        data[ret] = 0;
        printf("got : %s\n", data);
    }
    close(fd);
    return 0;
}
  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值