准备一个usb转ttl的模块, 对应的引脚的连接分为:
VCC - 3V3; GND - GND; RXD - TXD2; TXD - RXD2 ;
连接方式如下图,并且将ttl模块连接至电脑usb口:
a. 初始化说明
open终端文件时,带上如下参数 O_RDWR, O_NOCTTY, O_NONBLOCK;
b. 程序说明:
编译生成uart_send_arm发送到开发板:
$CC uart_send.c -o uart_send_arm scp uart_send_arm [email protected]:/home/root/ ssh [email protected]
使用方式:
./uart_send_arm tty设备号 -b 波特率 -w 字符
补充说明:
发送的字符列表需要全部先置0,以防止乱码
需要使用tcflush(fd,TCIOFLUSH)将前面没读取和传输完的列表清空;
c. 实现
#include
#include
#include
#include
#include
#include
#define tty_len 1024
#define w_len 1024
int main(int argc,char*argv[]){
if(argc<2|| strncmp(argv[1],"tty",3))
{
perror("请输入\"tty\"设备的参数\n");
exit(1);
}
char dev[tty_len];
char w_data[w_len];
struct termios *tio = malloc(sizeof(struct termios));
strcpy(dev, "/dev/");
strcat(dev,argv[1]);
int fd = open(dev, O_RDWR|O_NONBLOCK|O_NOCTTY);
if(fd<1){
perror("open 错误");
exit(1);
}
printf("成功打开设备%s\n",dev);
for(int i = 2;i<argc;i++)
{
// 参数 == -b : 输入波特率
if(!strcmp(argv[i], "-b"))
{
i++;
if(i >= argc){
printf("-b 后要接波特率\n");
exit(0);
}
switch(atol(argv[i])){
case 115200:
cfsetispeed(tio,B115200);
cfsetospeed(tio,B115200);
break;
case 1200:
cfsetispeed(tio,B1200);
cfsetospeed(tio,B1200);
break;
case 4800:
cfsetispeed(tio,B4800);
cfsetospeed(tio,B4800);
break;
case 9600:
cfsetispeed(tio,B9600);
cfsetospeed(tio,B9600);
break;
default:
cfsetispeed(tio,B9600);
cfsetospeed(tio,B9600);
break;
}
}
// 参数 == -w : 输入需要发送的字符串
if(!strcmp(argv[i],"-w"))
{
i++;
if(i >= argc){
printf("-w 后要接写入的字符串\n");
exit(0);
}
memset(w_data,0,sizeof(w_data));
strcpy(w_data,argv[i]);
}
}
/*termios 配置*/
// memset(tio,0,sizeof(&tio));
bzero(tio,sizeof(struct termios));
// c_cflag 用于控制终端设备的硬件设置
tio->c_cflag |= CSIZE; // charater size mask
tio->c_cflag |= CS8;
tio->c_cflag &= ~(CSTOPB); //set one stop bit
tio->c_cflag |= PARENB; //enable parity generation on output
tio->c_cflag |= PARODD; //parity is odd
tio->c_cflag |= CLOCAL; // ignore modem control lines
tcflush(fd,TCIOFLUSH);
if((tcsetattr(fd,TCSANOW,tio))<0)
{
perror("tcsetattr error");
exit(1);
}
printf("设置termios成功\n");
while(1){
if(sizeof(w_data)<=0||write(fd,w_data,sizeof(w_data))< 0)
continue;
printf("write 成功\n");
sleep(1);
}
free(tio);
close(fd);
return 0;
}
打开串口工具,将串口工具的串口、波特率、停止位、数据位、奇偶校验保持和程序中设置的一致,然后打开串口,接着在嵌入式Linux上启动程序;串口工具可以收到数据。
发送字符串的实现效果如下:
a. 初始化补充说明
termios结构体中c_iflag的INPCK位需要被设置 : 使能输入校验码检测
termios_t->c_iflag |= INPCK;
termios中c_cflag中的CREAD位需要设置:
termios_t->c_cflag |= CREAD;
b. 具体程序
#include
#include
#include
#include
#include
#include
#define tty_len 1024
#define r_len 1024
int main(int argc,char*argv[]){
if(argc<2|| strncmp(argv[1],"tty",3))
{
perror("请输入\"tty\"设备的参数\n");
exit(1);
}
char dev[tty_len];
char r_data[r_len];
struct termios *tio = malloc(sizeof(struct termios));
strcpy(dev, "/dev/");
strcat(dev,argv[1]);
int fd = open(dev, O_RDWR|O_NONBLOCK|O_NOCTTY);
if(fd<1){
perror("open 错误");
exit(1);
}
printf("成功打开设备%s\n",dev);
for(int i = 2;i<argc;i++)
{
// 参数 == -b : 输入波特率
if(!strcmp(argv[i], "-b"))
{
i++;
if(i >= argc){
printf("-b 后要接波特率\n");
exit(0);
}
switch(atol(argv[i])){
case 115200:
cfsetispeed(tio,B115200);
cfsetospeed(tio,B115200);
break;
case 1200:
cfsetispeed(tio,B1200);
cfsetospeed(tio,B1200);
break;
case 4800:
cfsetispeed(tio,B4800);
cfsetospeed(tio,B9600);
break;
default:
cfsetispeed(tio,B9600);
cfsetospeed(tio,B9600);
break;
}
}
}
/*termios 配置*/
// memset(tio,0,sizeof(&tio));
bzero(tio,sizeof(struct termios));
// c_cflag 用于控制终端设备的硬件设置
tio->c_cflag |= CREAD;
tio->c_cflag |= CSIZE; // charater size mask
tio->c_cflag |= CS8;
tio->c_cflag &= ~(CSTOPB); //set one stop bit
tio->c_cflag |= PARENB; //enable parity generation on output
tio->c_cflag |= PARODD; //parity is odd
tio->c_cflag |= CLOCAL; // ignore modem control lines
tio->c_iflag |= INPCK;
tcflush(fd,TCIOFLUSH);
if((tcsetattr(fd,TCSANOW,tio))<0)
{
perror("tcsetattr error");
exit(1);
}
printf("设置termios成功\n");
int len_c;
while(1){
memset(r_data,0,sizeof(r_data));
len_c = read(fd,r_data,sizeof(r_data));
if(len_c < 0){
perror("read error");
continue;
}else if(len_c > 0){
printf("%s",r_data);
}
sleep(1);
}
free(tio);
close(fd);
return 0;
}