系统:ubuntu22.04
虚拟机版本:VMware workstation 16 pro(16.1.2)
VMware tools文件(iso)一般在虚拟机目录下,如果没有,这是下载网址,找到对应的虚拟机版本下载解压缩并挂载即可;
通过如下步骤,挂载VMware tools
虚拟机设置CD/DVD
使用ISO映像文件-
选择VMware Workstation\linux.iso-
点击确定
右击图标,选择连接
为了方便自动化安装,新建如下文件install_vm_t.sh:
#!/bin/bash
mkdir vm_tool
cp /media/liu/VMware\ Tools/* ./vm_tool/
cd ./vm_tool/
tar -zxvf VMwareTools-10.3.23-17030940.tar.gz
cd ./vmware-tools-distrib
sudo ./vmware-install.pl
sudo apt-get install open-vm-tools-desktop
安装时,直接在终端输入:bash install_vm_t.sh
安装完,在终端输入:reboot
重启一下
同样为了方便卸载,新建如下文件uninstall_vm_t.sh
cd ~/vm_tools/vmware-tools-distrib/bin/
sudo ./vmware-uninstall-tools.pl
sudo apt-get autoremove open-vm-tools open-vm-tools-desktop
卸载时,直接在终端输入:bash uninstall_vm_t.sh
安装成功后,重启;
然后,讲文件夹属性设置为共享,在vmware上勾选共享文件夹。
需求:读取uart的输入输出波特率
- 保证程序健壮性
命令的传入参数大于2,并且判断是否是tty设备- 使用方式: 命令 tty名称
- 需要用到的函数:
a. 头文件:
#include <termios.h>
#include <unistd.h>
,termios.h头文件的地址在/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/include/bits/
下
b. termios 结构体 至少包含下列成员:
- tcflag_t c_iflag; /* 输入模式 */
- tcflag_t c_oflag; /* 输出模式*/
- tcflag_t c_cflag; /* 控制模式 */
- tcflag_t c_lflag; /* 当地模式 */
- cc_t c_cc[NCCS]; /* 特殊字符 */
- speed_t c_ispeed; /* 输入速度 */
- speed_t c_ospeed; /* 输出速度 */
c. int tcgetattr(int fd, struct termios ? * ?termios_p) :
作用:读取fd的相关属性,以termios结构体的方式放入termios_p
返回值:成功返回0,失败返回-1,并且设置errnod. cfgetispeed() 获得传入的波特率,同termios_p->c_ispeed
e. cfgetospeed() 获得传出的波特率,同termios_p->c_ospeed
- open 函数的传参补充说明
O_NOCTTY : 如果路径名指向终端设备(man 4 tty), 即使进程没有控制终端, 他也不会成为进程的控制终端
O_NDELAY: no delay, 文件以非阻塞模式打开. 返回的文件描述符上的 open ()或任何后续 I/O 操作都不会导致调用进程等待。
/*
uart.c
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char *argv[]){
if(argc<2||strncmp(argv[1],"tty",3))
{
printf("请在命令后加一个参数,并且参数名以tty开头\n");
exit(1);
}
strcpy(dev,"/dev/");
strcat(dev,argv[1]);
int fd = open(dev,O_RDWR|O_NOCTTY|O_NDELAY);
if(fd < 0){
perror("open error");
exit(1);
}
printf("顺利打开 %s 设备\n",dev);
struct termios *tio = malloc(sizeof(struct termios));
if(tcgetattr(fd,tio) != 0){
perror("tcgetattr error");
exit(1);
}
printf("输出的 baud is %d\n",cfgetospeed(tio));
printf("输入的 baud is %d\n",cfgetispeed(tio));
close(fd);
return 0;
}
ps. 在ubuntu 22.04中如果需要输入中文,需要在 settings/region and language 中进入Manage installeed Languages中安装中文并应用。接着,在keyboard 的input sources中+选中chinese,接着选中Chinese(intelligent pinyin)
a. 置零termios结构体,初始化
- CLOCAL 忽略调制解调器控制线
- CREAD 使能接收器.
- CSIZE
b. 配置uart的波特率、数据位、停止位、校验方式、硬件流控
波特率配置:通过cfsetispeed 和cfsetospeed配置
数据位:termio结构体的控制模式c_cflag的参数CSIZE 字符尺寸掩码. 值可以是 CS5, CS6, CS7, or CS8
停止位:CSTOPB 拉高两位停止位,拉低一位停止位;c_cflag第六位置1或0
校验方式(只关注奇偶校验):通过PARENB 使能(c_cflag第8位置1) 输出奇偶校验生成和输入奇偶校验;PAROAD拉高(c_cflag第9位置1),奇校验,反之,偶校验;
硬件流控:CRTSCTS, 使能RTS/CTS流控(最高位置1)c. 需要用到的函数:
- bzero(void *s, size_t count) 清零
- int tcsetattr(int fd, int optional_actions, const struct termios ? * ?termios_p)**;
作用:设置fd的终端相关属性。Option _ actions 指定更改何时生效:
返回值:成功返回0,失败返回-1,并且设置errno
- TCSANOW:立即生效
- TCSADRAIN:更改发生在写入 fd 的所有输出被传输之后。更改影响输出的参数时应使用此选项。
- TCSAFLUSH:更改发生在所有写入 fd 引用的对象的输出被传输之后,所有已接收但未读取的输入将在更改发生之前被丢弃。
- int tcflush(int fd, int queue_selector); 本篇暂时不需要
作用:根据 queue _ selector 的值,丢弃写入 fd 引用但未传输的对象的数据,或接收但未读取的数据,后续读写需要用到TCIFLUSH: 刷新已接收但未读取的数据
TCOFLUSH:刷新已写入但未传输的数据。
TCIOFLUSH:刷新已接收但未读取的数据和已写入但未传输的数据。
/*
uart_w.c
*/
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
char dev[1024];
int main(int argc,char *argv[]){
if(argc<2||strncmp(argv[1],"tty",3))
{
printf("请在命令后加一个参数,并且参数名以tty开头\n");
exit(1);
}
strcpy(dev,"/dev/");
strcat(dev,argv[1]);
//printf("%s\n",dev);
int fd = open(dev,O_RDWR|O_NOCTTY|O_NDELAY);
if(fd < 0){
perror("open error");
exit(1);
}
printf("顺利打开 %s 设备\n",dev);
struct termios newtio,*tio = malloc(sizeof(struct termios));
if(tcgetattr(fd,tio) != 0){
perror("tcgetattr error");
exit(1);
}
printf("设置前\n");
printf("输出的 baud is %ld\n",cfgetospeed(tio));
printf("输入的 baud is %ld\n",cfgetispeed(tio));
bzero(&newtio,sizeof(struct termios));
newtio.c_cflag |= CLOCAL|CREAD;
newtio.c_cflag &= ~CSIZE;
// 波特率 需要在命令中输入 且位置固定为第二个参数 数据位 7bit 停止位 1bit 校验方式 奇校验 硬件流控 NONE
tio->c_cflag |= (0x01<<8)|(0x01<<9)|(0040);
//newtio.c_cflag |= CS7;
//newtio.c_cflag |= PARENB;
//newtio.c_cflag |= PARODD;
//newtio.c_cflag &= ~CSTOPB;
//newtio.c_iflag |= INPCK;
switch(atoll(argv[2])){
case 50:
cfsetispeed(&newtio,B50);
cfsetospeed(&newtio,B50);
break;
case 57600:
cfsetispeed(&newtio,B57600);
cfsetospeed(&newtio,B57600);
break;
case 115200:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
break;
case 1200:
cfsetispeed(&newtio,B1200);
cfsetospeed(&newtio,B1200);
break;
case 4800:
cfsetispeed(&newtio,B4800);
cfsetospeed(&newtio,B4800);
break;
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
/*newtio.c_cc[VTIME]=0;
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);*/
if(tcsetattr(fd,TCSANOW,&newtio)<0)
{
perror("tcsetattr error");
exit(1);
}
if(tcgetattr(fd,&newtio) != 0){
perror("tcgetattr error");
exit(1);
}
printf("设置后\n");
printf("输出的 baud is %ld\n",newtio.c_ospeed);
printf("输入的 baud is %ld\n",cfgetispeed(&newtio));
close(fd);
return 0;
}
说明:
波特率的速度值输出的是10进制结果,与termios.h中定义的八进制的值是一致的;