当前位置: 首页 > wzjs >正文

国内返利网站怎么做免费收录平台

国内返利网站怎么做,免费收录平台,黑龙江建设网ca锁费用,做网站 好苦逼前提和背景知识 本博文中借助于TTY子系统来使用IMX6ULL_Pro开发板上的串口,关于TTY子系的详细介绍和为什么可以利用TTY子系统来使用开发板上的串口,,详情见博文 https://blog.csdn.net/wenhao_ir/article/details/145431655 【请从这篇博文的…

前提和背景知识

本博文中借助于TTY子系统来使用IMX6ULL_Pro开发板上的串口,关于TTY子系的详细介绍和为什么可以利用TTY子系统来使用开发板上的串口,,详情见博文 https://blog.csdn.net/wenhao_ir/article/details/145431655 【请从这篇博文的开头处开始看】

完整源代码

文件名:serial_send_recv.c

#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>/* set_opt(fd,115200,8,'N',1) */
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;}bzero( &newtio, sizeof( newtio ) );newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; newtio.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/newtio.c_oflag  &= ~OPOST;   /*Output*/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;else if ( nStop == 2 )newtio.c_cflag |= CSTOPB;newtio.c_cc[VMIN]  = 1;  /* 读数据时的最小字节数: 没读到这些数据我就不返回! */newtio.c_cc[VTIME] = 0; /* 等待第1个数据的时间: * 比如VMIN设为10表示至少读到10个数据才返回,* 但是没有数据总不能一直等吧? 可以设置VTIME(单位是10秒)* 假设VTIME=1,表示: *    10秒内一个数据都没有的话就返回*    如果10秒内至少读到了1个字节,那就继续等待,完全读到VMIN个数据再返回*/tcflush(fd,TCIFLUSH);if((tcsetattr(fd,TCSANOW,&newtio))!=0){perror("com set error");return -1;}//printf("set done!\n");return 0;
}int open_port(char *com)
{int fd;//fd = open(com, O_RDWR|O_NOCTTY|O_NDELAY);fd = open(com, O_RDWR|O_NOCTTY);if (-1 == fd){return(-1);}if(fcntl(fd, F_SETFL, 0)<0) /* 设置串口为阻塞状态*/{printf("fcntl failed!\n");return -1;}return fd;
}/** ./serial_send_recv <dev>*/
int main(int argc, char **argv)
{int fd;int iRet;char c;/* 1. open *//* 2. setup * 115200,8N1* RAW mode* return data immediately*//* 3. write and read */if (argc != 2){printf("Usage: \n");printf("%s </dev/ttySAC1 or other>\n", argv[0]);return -1;}fd = open_port(argv[1]);if (fd < 0){printf("open %s err!\n", argv[1]);return -1;}iRet = set_opt(fd, 115200, 8, 'N', 1);if (iRet){printf("set port err!\n");return -1;}printf("Enter a char: "); // 输入的字符利用下面的函数scanf存储在变量c中while (1){scanf("%c", &c);iRet = write(fd, &c, 1);if (iRet == 1)// printf("write: 0x%02x %c\n", c, c);printf("Write→ASCII: %d\n", c);elseprintf("can not write data\n");iRet = read(fd, &c, 1);if (iRet == 1)printf("Read→ASCII: %d\n", c);elseprintf("can not read data\n");}return 0;
}

设备文件打开函数open_port的关键代码分析

函数open_port的完整代码

代码如下:

int open_port(char *com)
{int fd;//fd = open(com, O_RDWR|O_NOCTTY|O_NDELAY);fd = open(com, O_RDWR|O_NOCTTY);if (-1 == fd){return(-1);}if(fcntl(fd, F_SETFL, 0)<0) /* 设置串口为阻塞状态*/{printf("fcntl failed!\n");return -1;}return fd;
}

关键代码fd = open(com, O_RDWR|O_NOCTTY);

fd = open(com, O_RDWR|O_NOCTTY);
  • open(com, flags):使用 open 系统调用打开串口设备。
  • com是输入函数,代表串口终端的TTY设备文件的路径和名字。
  • O_RDWR:以读写模式打开设备。
  • O_NOCTTY:如果我把代码编译成ELF可执行程序,然后在串口终端中运行这个程序,那么实际上这个标志位起不了作用,因为此时进程是肯定有控制终端的。关于这个O_NOCTTY标志位的详解,请参见我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/146177988

关键代码if(fcntl(fd, F_SETFL, 0)<0)

if(fcntl(fd, F_SETFL, 0) < 0) /* 设置串口为阻塞状态 */
{printf("fcntl failed!\n");return -1;
}
  • fcntl(fd, F_SETFL, 0) 用于设置文件状态标志:
    • F_SETFLFile Set Flags的英文缩写。
    • 0 表示清除所有非阻塞模式的标志(即阻塞模式)。
    • 这意味着:
      • 读取操作会阻塞,直到有数据可读。
      • 写入操作会阻塞,直到数据写入完成。
    • 如果 fcntl 失败,则返回 -1

串口通信参数设置函数set_opt的详解

函数set_opt的完整代码

/* set_opt(fd,115200,8,'N',1) */
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;}bzero( &newtio, sizeof( newtio ) );newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; newtio.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/newtio.c_oflag  &= ~OPOST;   /*Output*/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;else if ( nStop == 2 )newtio.c_cflag |= CSTOPB;newtio.c_cc[VMIN]  = 1;  /* 读数据时的最小字节数: 没读到这些数据我就不返回! */newtio.c_cc[VTIME] = 0; /* 等待第1个数据的时间: * 比如VMIN设为10表示至少读到10个数据才返回,* 但是没有数据总不能一直等吧? 可以设置VTIME(单位是10秒)* 假设VTIME=1,表示: *    10秒内一个数据都没有的话就返回*    如果10秒内至少读到了1个字节,那就继续等待,完全读到VMIN个数据再返回*/tcflush(fd,TCIFLUSH);if((tcsetattr(fd,TCSANOW,&newtio))!=0){perror("com set error");return -1;}//printf("set done!\n");return 0;
}

这个函数 set_opt 用于配置 Linux 下的串口通信参数,包括波特率、数据位、校验位、停止位等。


函数的各参数意义说明

int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
  • 参数

    • fd:串口设备的文件描述符
    • nSpeed:波特率,如 9600115200
    • nBits:数据位,通常为 78
    • nEvent:校验位,可选 'N'(无校验)、'E'(偶校验)、'O'(奇校验)
    • nStop:停止位,1 表示 1 位停止位,2 表示 2 位停止位
  • 返回值

    • 成功返回 0
    • 失败返回 -1 并打印错误信息

结构体termios的介绍

关于结构体termios的详细介绍,请参看我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/146187742

函数的具体内容解析

0. 初始化结构体termios实例

struct termios newtio,oldtio;

结构体newtio和oldtio用来存储串口的配置实信息,关于结构体termios的详细介绍,请参看我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/146187742

1. 获取原始串口配置

if ( tcgetattr( fd, &oldtio) != 0) { perror("SetupSerial 1");return -1;
}
  • tcgetattr(fd, &oldtio) 获取当前串口设置并存入 oldtio
  • tcgetattr 是 Linux TTY(终端)子系统 中的一个函数,它用于获取终端设备(包括串口)的当前属性。
  • 如果获取失败,打印错误并返回 -1
  • 从后面及整个代码来看,并没有再次用到oldtio所以其实这段代码可以删去。

2. 初始化新串口设置

bzero(&newtio, sizeof(newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
  • bzero(&newtio, sizeof(newtio)):清空 newtio 结构体
  • CLOCAL:让Linux系统忽略DCD (Data Carrier Detect)信号,详细的介绍见博文 https://blog.csdn.net/wenhao_ir/article/details/146187742 【搜索“要搞清楚这个字段值”】
  • CREAD:启用接收器
  • CSIZE:清除数据位设置(后续要重新设置)

3. 关闭与TTY终端有关的对本地输入的处理方式

newtio.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
newtio.c_oflag  &= ~OPOST;   /*Output*/

因为我们并不把串口当成终端来使用,所以需要关闭与TTY终端有关的对本地输入的处理方式。

  • ICANON:关闭标准输入(即设置为原始模式,不使用回车换行等字符处理)
  • ECHOECHOE:关闭回显
  • ISIG:关闭信号处理(如 CTRL+C 终止)
  • OPOST:关闭输出处理(即发送的字节不会被修改)

上面几个值的详细解释见博文 https://blog.csdn.net/wenhao_ir/article/details/146187742 【搜索“TTY终端的本地输入处理方式”】


4. 设置数据位

switch(nBits)
{case 7:newtio.c_cflag |= CS7;break;case 8:newtio.c_cflag |= CS8;break;
}
  • CS7:7 数据位
  • CS8:8 数据位(更常见)
  • 具体在这里,我们设置的是8 位数据位。

5. 设置校验位

switch(nEvent)
{case 'O': // 奇校验newtio.c_cflag |= PARENB; // 使能校验newtio.c_cflag |= PARODD; // 设置奇校验newtio.c_iflag |= (INPCK | ISTRIP); // 使能奇偶校验和去除第8位break;case 'E': // 偶校验newtio.c_iflag |= (INPCK | ISTRIP);newtio.c_cflag |= PARENB; // 使能校验newtio.c_cflag &= ~PARODD; // 设置偶校验break;case 'N': // 无校验newtio.c_cflag &= ~PARENB;break;
}
  • 'O'(奇校验):PARENB 使能校验,PARODD 设为奇校验,INPCK | ISTRIP 使能奇偶校验并去掉最高位
  • 'E'(偶校验):PARENB 使能校验,~PARODD 设为偶校验
  • 'N'(无校验):~PARENB 关闭校验
  • 具体在这里咱们设置的是无校验。

6. 设置波特率

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;
}
  • cfsetispeed(&newtio, B9600) 设置输入波特率
  • cfsetospeed(&newtio, B9600) 设置输出波特率
  • 只支持 240048009600115200,默认 9600
  • 具体在这里设置的是115200

7. 设置停止位

if (nStop == 1)newtio.c_cflag &= ~CSTOPB;
else if (nStop == 2)newtio.c_cflag |= CSTOPB;
  • CSTOPB 设为 0(默认):1 位停止位
  • CSTOPB 设为 1:2 位停止位
  • 具体在这里设置的是1位停止位。

8. 设置至少读取多少字节和超时时间

newtio.c_cc[VMIN]  = 1;  
newtio.c_cc[VTIME] = 0;
  • VMIN = 1:读取时至少要获取 1 字节才返回
  • VTIME = 0:不启用超时,即一直等下去

9. 清空缓冲区

tcflush(fd, TCIFLUSH);
  • tcflush(fd, TCIFLUSH):清空输入缓冲区,防止残留数据影响

10. 设置新参数

if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
{perror("com set error");return -1;
}
  • tcsetattr(fd, TCSANOW, &newtio) 立即生效新的串口设置
  • 当 tcsetattr 的第二个参数设置为 TCSANOW,表示立即生效,不等待当前正在传输的数据完成。
  • 若失败则返回 -1

11.小结

该函数用于配置串口的各种参数:

  • 波特率240048009600115200
  • 数据位78
  • 校验位
    • 'N' 无校验
    • 'E' 偶校验
    • 'O' 奇校验
  • 停止位12
  • 超时机制:最少读取 1 字节才返回,无超时

函数完成后,fd 对应的串口即可按照新配置进行收发数据。

关于主函数的说明

主函数很简单,没啥好说的,代码如下:

int main(int argc, char **argv)
{int fd;int iRet;char c;/* 1. open *//* 2. setup * 115200,8N1* RAW mode* return data immediately*//* 3. write and read */if (argc != 2){printf("Usage: \n");printf("%s </dev/ttySAC1 or other>\n", argv[0]);return -1;}fd = open_port(argv[1]);if (fd < 0){printf("open %s err!\n", argv[1]);return -1;}iRet = set_opt(fd, 115200, 8, 'N', 1);if (iRet){printf("set port err!\n");return -1;}printf("Enter a char: "); // 输入的字符利用下面的函数scanf存储在变量c中while (1){scanf("%c", &c);iRet = write(fd, &c, 1);if (iRet == 1)// printf("write: 0x%02x %c\n", c, c);printf("Write→ASCII: %d\n", c);elseprintf("can not write data\n");iRet = read(fd, &c, 1);if (iRet == 1)printf("Read→ASCII: %d\n", c);elseprintf("can not read data\n");}return 0;
}

交叉编译得到elf可执行程序

把源码文件复制到Ubuntu的目录 /home/book/mycode/C0035_UART_app1
在这里插入图片描述
然后运行下面的命令进行编译:

arm-buildroot-linux-gnueabihf-gcc -o serial_send_recv serial_send_recv.c

在这里插入图片描述
在这里插入图片描述

确定使用的串口的设备文件名

我们通过转接板模块将某个串口引出,如下图所示:
在这里插入图片描述
所以我们需要去查看原理图看到底转接板上的UART_A的TX和RX连接的是IMX6ULL的哪个串口。
在这里插入图片描述
在丝印层上找到上图19对应的编号:
在这里插入图片描述
可见是J5…
在这里插入图片描述
啊这…由于引脚复用,所以名字都感觉与串口无关…所以还得一个一个引脚去分析…这太花费时间了。
直接用教程提供的结论吧:“用的是IMX6ULL的第六个串口”,对应的设备文件名为:

/dev/ttymxc5

可以用下面的命令看下有哪些与tty有关的设备文件:

ls /dev/tty*

在这里插入图片描述
由此我们再去查看IMX6ULL与UART6相关的引脚。
先用那个设备树语句生成工具看下:
在这里插入图片描述
打开之后在引脚名里搜索UART,就找到了
在这里插入图片描述
从上面的截图中来看:
UART6的RX对应于E5:CSI_PIXCLK
UART6的TX对应于E5:CSI_MCLK

然后我们再回到原理图中,就可以应证了果然是UART6:
在这里插入图片描述
至于为什么UART6对应的设备文件名是/dev/ttymxc5,这就要去看设备树文件和分析TTY框架的代码了,这里就不再作展开了。具体的情况请百度网盘搜索“1-9_09_UART驱动情景分析_open”,从06分钟左右开始看,那里有详细的名字来历说明。

在开发板上测试生成的程序

先把扩展板上UART_A的TX引脚和RX引脚用杜邦线短接:
在这里插入图片描述
然后把扩展板插到开发板上,如下图所示:
在这里插入图片描述

把生成的ELF可执行程序复制到NFS网络文件目录中:
在这里插入图片描述
打开串口终端→打开开发板→挂载网络文件系统

mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt

然后执行下面的命令运行咱们生成的elf可执行程序serial_send_recv

cd /mnt/UART_app1
./serial_send_recv  /dev/ttymxc5

在这里插入图片描述
我们输入一个字符:
在这里插入图片描述
然后回车,得到下面的运行结果:
在这里插入图片描述

整个输入过程实际上我们输入了两个字符,分别为W和“Enter”,查阅博文:https://blog.csdn.net/wenhao_ir/article/details/125440879,发现两个字符的ASCII码对应如下:
在这里插入图片描述
可见,刚好是对应上的。

至此,测试完毕。

http://www.dtcms.com/wzjs/385411.html

相关文章:

  • 建网站安全太原百度网站快速优化
  • 整合营销传播的方法包括惠州企业网站seo
  • 给公司怎么做官方网站客户引流推广方案
  • 哪种网络营销方式最好网站搜索排名优化价格
  • wordpress政府主题 中文2022年搜索引擎优化指南
  • 做政府网站排行榜seo技术教程
  • 做网站大连昆明网站seo优化
  • 三网合一网站建设公司缅甸今日新闻
  • 海南住建部建设网站的网站接推广app任务的平台
  • 品牌网站的推广外包公司被辞退有补偿吗
  • wordpress网站搭建教程百度快速排名技术培训
  • wordpress 多重重庆seo关键词优化服务
  • 团队介绍网站模板百度seo如何优化关键词
  • vs做的网站图片显示不了关键词搜索量排名
  • 做原油期货关注什么网站免费顶级域名申请网站
  • 网站建设公司销售外贸seo推广
  • 网站建设需要要多少钱郑州专业网站建设公司
  • 闵行做网站公司今日国内新闻大事20条
  • 网站建设文化价格东莞百度推广优化
  • 义乌哪里有学做网站的seo教程网站优化推广排名
  • 互联网站备案谷歌seo服务
  • 英铭长沙网站建设百度关键词挖掘工具爱站网
  • 南京网站建设有限公司帮别人推广app赚钱
  • 微软网站怎么做的24小时网站建设
  • 特种操作证网上查询夫唯seo怎么样
  • 普通网站 手机网站独立站seo搜索优化
  • 网站做外部链接网络工程师是干什么的
  • 中国最好的网站器域名统一石家庄最新疫情
  • 做外国网站百度搜到长沙网站制作
  • DW如何做明星的个人网站网页推广平台