2017-03-16 14:42:22 flowers_wikey 阅读数 817

上一篇博客是串口的打开及配置,这一篇我将要把读写串口及串口关闭的操作详细介绍一下。

读串口

读串口就是接收串口数据,通过read来实现。

read函数原型:

  1. #include <unistd.h>      
  2. ssize_t read(int fd, void *buf, size_t count);    
#include <unistd.h>    
ssize_t read(int fd, void *buf, size_t count);  

参数说明:

  • fd:文件描述符
  • *buf:缓冲区,读取的数据会被放到这个缓冲区中去
  • count:请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。
如下两句代码即可:

  1. nread=read(fd,buff,8);//读串口   
  2. printf(”nread=%d,%s\n”,nread,buff);   
nread=read(fd,buff,8);//读串口 
printf("nread=%d,%s\n",nread,buff); 
注意:
read默认为阻塞模式,若在open操作中设置O_NONBLOCK则是非阻塞模式。在阻塞模式中,read没有读到数据会阻塞住,直到收到数据;非阻塞模式read没有读到数据会返回-1不会阻塞。

如果是非阻塞模式,read要放在循环中保证持续读数据:

  1. while(1) {  
  2. 非阻塞read(设备1);  
  3. if(设备1有数据到达)  
  4.   处理数据;  
  5. 非阻塞read(设备2);  
  6. if(设备2有数据到达)  
  7.   处理数据;  
  8. …  
  9. sleep(n);  
  10. }  
while(1) { 
非阻塞read(设备1);
if(设备1有数据到达)
处理数据;
非阻塞read(设备2);
if(设备2有数据到达)
处理数据;
...
sleep(n);
}
sleep(n)的目的是为了做个延迟防止一直在循环做无用功,在延迟等待的时候可以调度其它进程。

如果是阻塞模式,便可以直接调用read,不用放在while循环中。

阻塞模式有出现一个问题,见下面代码:

  1. #include<unistd.h>  
  2. #include<stdlib.h>  
  3. int main(void){  
  4.     char buf[10];  
  5.     int n;  
  6.     n=read(STDIN_FILENO,buf,10);  
  7.     if(n<0){  
  8.         perror(”read STDIN_FILENO”);  
  9.         exit(1);  
  10.     }  
  11.     write(STDOUT_FILENO,buf,n);  
  12.     return 0;  
  13. }  
#include<unistd.h>

#include<stdlib.h> int main(void){ char buf[10]; int n; n=read(STDIN_FILENO,buf,10); if(n<0){ perror("read STDIN_FILENO"); exit(1); } write(STDOUT_FILENO,buf,n); return 0; }编译后执行如下图所示:

运行结果

大家可以看到第一次输入hello没有问题,第二次输入helloworldhelloworld后helloworld这10个字符打印出来,程序退出后,Shell继续读取用户输入的命令,于是读走了终端设备输入缓冲区中剩下的字符和换行符当做一条命令去处理,运行不了显示未找到命令。

写串口

写串口即发送数据,用write函数,write函数原型如下:

  1. #include <unistd.h>  
  2. ssize_t write(int fd, const void *buf, size_t count);  
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数含义同read相同,需要注意的也同read相同.设置阻塞非阻塞也会同样的影响到write.

我上传的代码有阻塞模式的,也有非阻塞模式的,大家看open中有无设置O_NONBLOCK即可判断阻塞或是非阻塞模式。非阻塞模式read和write要放在while循环中

关闭串口

close函数,函数原型:

  1. #include<unistd.h>    
  2. int close(int fd);  
#include<unistd.h>  
int close(int fd);
关闭串口就这一个知识点,没有其它的了。

代码资源链接:http://download.csdn.net/detail/specialshoot/9438578


2013-11-07 18:00:15 autowanglei 阅读数 2105

写串口 etho XXX > /dev/***   //XXX:数据    /dev/***:串口名
读串口cat /dev/*** 
2018-12-06 10:21:34 qq_34806812 阅读数 339

前言

在Linux中,对于非root用户,默认没有串口设备的读写权限。本文将讨论如何让普通用户拥有串口设备的读写权限。
1. 问题描述

通过编程读写串口打开设备时,提示没有权限

[Errno 13] Permission denied: '/dev/ttyUSB0'

    1

2.问题分析
2.1 通过命令查看ttyUSB0权限

dev@dev:~$ ls -l /dev/ttyUSB0

crw-rw---- 1 root dialout 4, 64 10月 12 14:08 /dev/ttyUSB0

    1
    2
    3

可以看到owner 是 root,所属用户组为 dialout
2.2 查看dialout用户组成员

dev@dev:~$ grep 'dialout' /etc/group

dialout:x:20:

    1
    2
    3

我们发现普通用户dev并没有在dialout组。
因此,我们将普通用户dev加入到dialout就可以解决这个问题。
3.问题处理
3.1 临时处理

dev@dev:~$ sudo chmod 777 /dev/ttyUSB0

    1

3.2 永久处理
3.2.1查看当前用户

dev@dev:~$ whoami

dev

    1
    2
    3

3.2.2 当前用户加入dialout组

处理命令(dev为我的用户名,需要修改为自己用户名)

dev@dev:~$ sudo usermod -aG dialout dev

    1

注意:
新增用户到用户组使用usermod 命令
命令参数如下:

usermod -aG {group-name} username

    1

3.2.3 重启

重启后上述命令就生效了
4.验证

dev@dev:~$ grep 'dialout' /etc/group

dialout:x:20:dev

    1
    2
    3

在这里插入图片描述

这里使用的是python读取串口数据,代码可以参考博文 Python串口读写实现
---------------------  
作者:itas109  
来源:CSDN  
原文:https://blog.csdn.net/itas109/article/details/83027431  
版权声明:本文为博主原创文章,转载请附上博文链接!

2017-03-15 14:51:49 flowers_wikey 阅读数 2597
                                  串口操作(下)
以下是我写的一些程序,主要就是实现给串口发送命令,接收串口反馈给PC机的信息,并且把信息保存在文件中。













































































































































































对文件夹(保存反馈信息)的内容进行处理,可以根据指定的日期,或者其他要求进行数据处理。例如下面的程序中就是根据日期,一句一句读取,将自己想要的信息再保存在文件中。(其实就是文件读取的一些简单操作吐舌头吐舌头
下面贴出我写的程序代码,阅读性比较差,但是基本功能还是可以实现的。









































































希望将来的你会感激现在努力的自己。不忘初心,方得始终!!!!程序员,撸起袖子干奋斗奋斗奋斗



















2018-07-21 09:00:56 clivin 阅读数 327

参考连接

1. 概念和用途

根据man手册解释,dd命令用途是转换和复制文件,在这个过程中可以改变输入输出流中块的大小。相比较于简单的copy命令,其用途更加广泛。

利用强大的dd命令,可以完成下列任务:

  复制文件
  格式文件
  备份数据
  烧录镜像
  测试硬盘
  销毁数据
  创建分区
  读写串口
  截取屏幕
  ......

 

2. 命令详解

linux 命令往往带有很多参数,dd命令也不例外。下面对dd命令的参数进行具体解释。


[sudo]   dd  [count=?, <c/ /o/i>bs=?, conv=?, seek=?, skip=?, <i/o>flag=?, status=?]  if=<address> of=<address>


if=file 输入文件名或设备地址,如文件、目录、挂载盘、镜像、闪存、键盘等。

文件:/home/hujia/.bashrc  目录:/etc

SD卡:/dec/mmcblk0          硬盘:/dev/hhd1

of=file 输出文件名或设备地址,如文件、硬盘、U盘、闪存、显示屏、串口等。

文件:/tmp/etc.bak              目录: /dev/sdc1/

串口:/dev/ttyS0                  

ibs=bytes 一次读取块大小,默认b=512字节。

ibs=<n>{c、w、b、K、M、G......}

obs=bytes

一次写入块大小,默认b=512字节。

conv=notrunc 给定条件下,输出文件会被截断到开头变为0字节或者截断到seek=n 处。

obs=<n>{c、w、b、K、M、G......}
bs=bytes

一次读取和写入块大小,默认b=512字节。

在未在conv中规定数据读写要求时,输入数据会尽快的复制到输出端,即使数据大小小于块大小。

bs=<n>{c、w、b、K、M、G......}
cbs=bytes 一次转换块大小,默认b=512字节,可将拥有不同块大小的文件转化为同一块大小文件。 cbs=<n>{c、w、b、K、M、G......}
skip=n

输出文件跳过n个块大小后复制。

iflag=skip_bytes条件下,跳过n个字节后复制。

 
seek=n

从头截断输出文件到n个块大小处,再在末尾写入内容。

oflag=skip_bytes条件下,跳过n个字节后复制

 
count=n

不是完全读取输入文件,读取前n个块大小。

iflag=count_bytes条件下,读取单位为字节。

注:从管道读取数据可以减少,因为读取操作标准不同。

 
status=level 信息传输状态的显示,none、noxfer、progress

none 、        不打印错误信息

noxfer 、      不打印传输速率与大小

progress  、 每读取一个块打印,有延迟

conv=conversion

[,conversion]

转换文件的格式等,

ascii、ebcdic、ibm、block、unblock、

lcase、ucase、sparse、swab、sync、

excl、nocreat、notrunc、noerror、

fdatasyn、fsync

ascii、将ebcdic转化为ascii,会默认删除转化               块的尾部空格

ebcdic、 将ascii转化为ebcdic,会默认增 加转              化块的尾部空格

ibm、 把ASCIl码转换为alternate EBCDIC码

block、固定块输出

unblock、不固定块输出

lcase、字母转化为小写

ucase、字母转化为大写

sparse、寻找文件中\0字符,用于稀疏文件

swab、交换输出字节

sync、把每个输入记录的大小都调到ibs的大小           (用NUL填充)

excl、输出文件存在时失败

nocreat、输出文件必须事先存在

notrunc、不截断输出文件

noerror、错误后继续执行

fdatasyn、完成之前输出数据同步

fsync、完成之前输出数据和元数据同步

iflag=flag[,flag]… 输入数据的控制

append、 在现有文件末尾添加输入数据,须和                    conv=notrunc连用

cio、        并发IO

direct、    直接IO,绕开系统缓存,读取单位为                   系统定义块的

directory、不能读写目录

dsync、     同步IO读写数据

sync、       同步IO读写数据和元数据

nocache、清空数据缓存

nonblock、使用非阻塞I / O

noatime、  不更新文件的访问时间戳

noctty、      不要将文件指定为dd的控制终端

nofollow、   不要遵循符号链接

nolinks、     如果文件有多个硬链接,则失败。

binary、       使用二进制I / O

text、           使用文本I / O

fullblock、    从输入中累积完整的块后写入

count_bytes、count字节计数

skip_bytes、skip字节计数

seek_bytes、seek字节计数

oflag=flag[,flag]… 输出数据的控制

3.应用实例

[1] 烧录镜像文件:作系统盘时需要将镜像文件(*.img、*.iso等)烧录到移动设备,下面就举例将Raspberry Pi的raspbian.img镜像烧录到SD卡和将ubuntu镜像ubuntu18.04.iso烧录到U盘的步骤。

#显示所有设备,SD /dev/mmcblk0,U盘 /dev/sdb
ls /dev/ 

#烧录镜像到SD卡
sudo umount /dev/mmcblk0   
sudo dd if=~/Downloads/raspbian.img of=/dev/mmcblk0 bs=32M

#烧录镜像到U盘
sudo umount /dev/sdb  
sudo dd if=~/Downloads/ubuntu18.04.iso of=/dev/sdb bs=32M

注:在烧录前需要卸载设备,另外需要有对设备操作的权限。

[2] 备份文件:linux文件中最需要备份的部分是/etc,通常我们对其目录下的文件误操作后如果没有备份往往面临重装系统的局面,因为很多重要的系统设置都在这个目录下,笔者曾经误删过/etc/default/grub,但是后来重新安装GRUB就找回了这个文件。总之,这个文件夹很重要。

#整个系统备份,移动硬盘/dev/sdb
sudo umount /dev/sdb
sudo dd if=/dev/sda of=/dev/sdb bs=32M

#/etc的备份,整个U盘作备份
sudo umount /dev/sdb
sudo dd if=/etc of=/dev/sdb bs=32M

#/etc创建一个备份文件
sudo dd if=/etc | gzip < /media/ai/backup/ubuntu_bankup/etc.zip

[3] 数据操作:要处理偏移量或大小不是I / O块大小的倍数的数据,可以使用“skip_bytes”,“seek_bytes”和“count_bytes”标志。以下shell命令在磁盘和磁带之间的512 KiB块中复制数据,但不在磁盘的开头保存或恢复4 KiB标签。

disk=/dev/rdsk/c0t1d0s2
tape=/dev/rmt/0

# Copy all but the label from disk to tape.
(dd bs=4k skip=1 count=0 && dd bs=512k) <$disk >$tape

# Copy from tape back to disk, but leave the disk label alone.
(dd bs=4k seek=1 count=0 && dd bs=512k) <$tape >$disk

[4] 硬盘恢复:硬盘有固态硬盘、机械硬盘等,其虽然是非易失性存储介质,但是放置和使用时间久,难免会出现数据失真和硬盘坏道等一系列问题。这是,我们可以采用dd命令恢复硬盘数据,处理硬盘坏道。同时dd命令也可以测试硬盘的读写速度。

#恢复磁盘数据
dd if=/dev/sda of=/dev/sda 或dd if=/dev/hda of=/dev/hda

#用\0填充磁盘坏道,获得最大有效存储量
dd conv=noerror,sync iflag=fullblock </dev/sda1 > /mnt/rescue.img

[5] 读写串口:

#dd命令写串口
sudo dd /tmp/command.txt /dev/ttyS0

待续:/dev/zero 和 /dev/null 两个虚拟设备的使用

 

 

 

注:以上内容来自官方解释、其他博客和个人经验。

 

Linux串口编程

阅读数 912

Linux命令study

阅读数 588

没有更多推荐了,返回首页