嵌入式Linux串口编程简介
简介
嵌入式Linux下串口编程与Linux系统下的编程没有什么区别,系统API都是一样的。嵌入式设备中串口编程是很常用的,比如会对接一些传感器模块,这些模块大多是RS232或者RS485接口,对于软件层面上来说,RS232与RS48区别不大。RS232与RS485在使用上的区别,RS232是全双工的,只能对接一个设备串口设备。RS485是半双工的总线协议,一般可以挂多个传感器设备,半双工的意思是同时只能有一个设备向串口发数据。
用到的API函数
| 函数 | 说明 |
|---|---|
| open | 打开设备,用于打开串口设备 |
| fcntl | 修改设备描述符属性参数 |
| isatty | 检测打开的描述符是否指向一个终端 |
| tcgetattr | 用来获取串口终端参数 |
| cfmakeraw | 将终端设置为原始模式,该模式下所有的输入数据以字节为单位被处理 |
| tcflush | 用于清空输入、输出缓冲区 |
| tcsetattr | 设置串口终端参数 |
| read | 读取数据 |
| write | 写数据 |
| close | 关闭串口设备 |
代码
#include<termios.h>
#include "uart.h"
/***************************************
*name : open_port
*功能描述: 打开串口
*入口参数: 串口号
*返 回 值: 成功返回文件描述符,失败返回负值
*作 者:
*修改时间:
***************************************/
int open_port(const char * com_port)
{
int fd;
if( com_port == NULL ){
printf("the port name is null\n");
return -1;
}
/*open port*/
fd = open(com_port, O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0){
fd = open(com_port, O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0){
perror("open serial port");
return -1;
}
}
printf("open %s OK!\n", com_port);
if(fcntl(fd, F_SETFL,0) < 0){
perror("fcntl F_SETFL");
}
if(isatty(fd) == 0){
perror("isatty is not a terminal device");
}
return fd;
}
/******************************
*name : set_port
*功能描述: 设置串口参数
*入口参数: fd 文件描述符, baud_rate 波特率, data_bits 数据位,
* parity 奇偶校验, stop_bits 停止位
* 调用示例: set_port(fd, 115200, 8, 'N',1);
*返 回 值: 成功返回0,失败返回-1
*作 者:
*修改:
******************************/
int set_port(int fd, int baud_rate,
int data_bits, char parity, int stop_bits)
{
struct termios new_cfg, old_cfg;
int speed_arry[]= {B2400, B4800, B9600, B19200, B38400,B57600, B115200};
int speed[]={2400,4800,9600,19200,38400,57600,115200};
int i = 0;
/*save and test the serial port*/
if(tcgetattr(fd, &old_cfg) < 0){
perror("tcgetattr");
return -1;
}
if(fcntl(fd,F_SETFL,0) < 0)//恢复为阻塞模式
{
perror("fcntl(CzjFd,F_SETFL,0)!");
}
new_cfg = old_cfg;
cfmakeraw(&new_cfg); //配置为原来配置
new_cfg.c_cflag &= ~ CSIZE; //用数据位掩码清空数据位的设置
/*set baud_rate*/
for(i = sizeof(speed_arry) / sizeof(speed_arry[0]); i > 0; i--)
{
if(baud_rate == speed[i]){
cfsetispeed(&new_cfg,speed_arry[i]);
cfsetospeed(&new_cfg,speed_arry[i]);
}
}
switch(data_bits) /*设置数据位*/
{
case 7:
new_cfg.c_cflag |= CS7;
break;
default:
case 8:
new_cfg.c_cflag |= CS8;
break;
}
switch(parity)
{
default:
case 'N':
case 'n':
{
new_cfg.c_cflag &= ~PARENB; //清除校验位
new_cfg.c_iflag &= ~(ICRNL|INPCK|IXON|IXOFF); //关闭奇偶校验 关闭软件流控
break;
}
case 'o':
case 'O':
{
new_cfg.c_cflag |= (PARODD | PARENB); //使用奇校验不是用偶校验
new_cfg.c_iflag |= INPCK;
break;
}
case 'e':
case 'E':
{
new_cfg.c_cflag |= PARENB;
new_cfg.c_cflag &= ~PARODD; //使用偶校验
new_cfg.c_iflag |= INPCK;
break;
}
case 's':
case 'S':
{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_cflag &= ~CSTOPB;
break;
}
}
new_cfg.c_iflag &= ~(ICRNL| IXON | IXOFF ); //关闭奇偶校验 关闭软件流控
new_cfg.c_oflag &= ~OPOST;
switch(stop_bits)
{
default:
case 1:
{
new_cfg.c_cflag &= ~CSTOPB;
new_cfg.c_cflag &= ~CRTSCTS; //禁用硬件流控
//new_cfg.c_cflag |= CRTSCTS; //启用硬件流控
break;
}
case 2:
{
new_cfg.c_cflag |= CSTOPB;
break;
}
}
/*set wait time*/
new_cfg.c_cc[VTIME] = 0;
new_cfg.c_cc[VMIN] = 1;
tcflush(fd, TCIFLUSH); //处理未接收字符
if((tcsetattr(fd, TCSANOW, &new_cfg)) < 0)
{
perror("tcsetattr");
return -1;
}
return 0;
}
调用测试代码:
#include "uart.h"
#include <stdio.h>
#include <unistd.h>
int main()
{
int fd = open_port("/dev/ttyS1");
if ( fd < 0 )
{
perror("open port");
return -1;
}
set_port(fd, 115200, 8, 'N',1);
char readBuf[32] ={0};
const char *pstr="hello world";
write(fd, pstr, strlen(pstr)+1);
read(fd, readBuf, sizeof(readBuf));
close(fd);
}
嵌入式Linux串口编程简介的更多相关文章
- 嵌入式linux串口编程(二)
/*com_writer.c*/#include "uart_api.h" int main(void){ int fd; char buff[BUFFER_SIZE]; if(( ...
- storysnail的Linux串口编程笔记
storysnail的Linux串口编程笔记 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据Ge ...
- linux串口编程
按照对linux系统的理解,串口编程的顺序无非就是open,read,write,close,而串口有波特率.数据位等重要参数需要设置,因此还应该用到设置函数,那么接下来就带着这几个问题去学习linu ...
- Linux串口编程详解(转)
串口本身,标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接 ...
- 嵌入式linux多进程编程
嵌入式linux多进程编程 在主程序显示文本菜单.提供例如以下服务.要求每一个服务都通过生成子进程来提供. 服务包含:日历信息显示,日期信息显示,推断闰年服务,文件复制功能,数字排序功能.退出功能. ...
- linux串口编程总结
串口本身.标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口以前被广泛用于连接计算机和终端设备和各种外部设备.尽管以太网接口和USB接口也是以一个串行流进行数据传送的.可是串口连接 ...
- linux串口编程参数配置详解(转)
1.linux串口编程需要的头文件 #include <stdio.h> //标准输入输出定义#include <stdlib.h> //标准函数 ...
- linux串口编程参数配置详解
1.linux串口编程需要的头文件 #include <stdio.h> //标准输入输出定义 #include <stdlib.h> //标准函 ...
- Linux串口编程进阶
在<Linux串口编程>编程一文中介绍了串口应用中常用的基本操作,如:串口打开关闭.串口设置.数据收发等.本篇文章主要基于常规串口操作进行了扩充,主要介绍如下操作: Linux系统使用非标 ...
随机推荐
- es6新增特性总结
定义 ES6是ECMA为JavaScript制定的第6个标准版本,标准委员会决定,标准在每年6月正式发布并作为当年的正式版本,接下来的时间里就在此版本的基础上进行改动,直到下一年6月草案就自然变成新一 ...
- CSRF攻击原理以及防御方法(写的很好)
转载地址:http://www.phpddt.com/reprint/csrf.html CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery),跟 ...
- python 爬虫,网页转PDF:OSError: No wkhtmltopdf executable found
解决办法: 代码中设置参数: path_wk = r‘D:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe‘ #wkhtmltopdf安装位置 config ...
- 数据可视化之DAX篇(十)在PowerBI中累计求和的两种方式
https://zhuanlan.zhihu.com/p/64418286 假设有一组数据, 已知每一个产品贡献的利润,如果要计算前几名产品的贡献利润总和,或者每一个产品和利润更高产品的累计贡献占总体 ...
- Quartz.Net系列(十四):详解Job中两大特性(DisallowConcurrentExecution、PersistJobDataAfterExecution)
1.DisallowConcurrentExceution 从字面意思来看也就是不允许并发执行 简单的演示一下 [DisallowConcurrentExecution] public class T ...
- Go Pentester - HTTP CLIENTS(2)
Building an HTTP Client That Interacts with Shodan Shadon(URL:https://www.shodan.io/) is the world' ...
- P2058 海港 (洛谷)
这个题复制过来真的有点恶心,懒得手打,以后再搬题面吧. 今天我双更了,AC这个题我就完成某谷春令营第一课的作业了(假的) 这个题是个双指针.非常友善.一直往里读入就可以了,遇见不是一条船的乘客输出这一 ...
- 一张图就可以完美解决Java面试频次最高、GG最高的题目!快点收藏
如果要问Java面试频次最高的题目,那么我想应该是HashMap相关了. 提到HahMap,必然会问到是否线程安全?然后牵扯出ConcurrentHashMap等,接着提及1.7和1.8实现上的区分, ...
- go : 连接数据库并插入数据
package main import ( "database/sql" "fmt" "log" "net/http" ...
- 《闲扯Redis六》Redis五种数据类型之Hash型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...