基于Linux的tty架构及UART驱动详解 (8)

(10) 激活配置,在完成配置后,需要激活配置使其生效。使用tcsetattr()函数:

int tcsetarr(int filedes, const struct termios *termptr); opt 指定在什么时候新的终端属性才起作用, *TCSANOW:更改立即发生 *TCSADRAIN:发送了所有输出后更改才发生。若更改输出参数则应使用此选项 *TCSAFLUSH:发送了所有输出后更改才发生。更进一步,在更改发生时未读的 所有输入数据都被删除(刷清) 例如:tcsetatrr(fd, TCSANOW, &newtio); 4.1.3. 使用流程

(1)打开串口,例如"/dev/ttySLB0"

fd = open("/dev/ttySLB0",O_RDWR | O_NOCTTY | O_NDELAY); O_NOCTTY:是为了告诉Linux这个程序不会成为这个端口上的“控制终端”。如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等等,会影响到你的进程。 O_NDELAY:这个标志则是告诉Linux这个程序并不关心DCD信号线的状态,也就是不管串口是否有数据到来,都是非阻塞的,程序继续执行。

(2)恢复串口状态为阻塞状态,用于等待串口数据的读入,用fcntl函数:

fcntl(fd,F_SETFL,0); //F_SETFL:设置文件flag为0,即默认,即阻塞状态

(3)接着测试打开的文件描述符是否应用一个终端设备,以进一步确认串口是否正确打开。

isatty(STDIN_FILENO);

(4)读写串口

串口的读写与普通文件一样,使用read,write函数 read(fd, buf ,8); write(fd,buff,8); 4.1.4. Demo

以下给出一个测温模块收取数据的例子

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <log/log.h> #include <stdlib.h> #define UART_DEVICE "/dev/ttySLB1" struct temp { float temp_max1; float temp_max2; float temp_max3; float temp_min; float temp_mean; float temp_enviromem; char temp_col[1536]; }; int main(void) { int count, i, fd; struct termios oldtio, newtio; struct temp *temp; temp = (struct temp *)malloc(sizeof(struct temp)); if (!temp) { printf("malloc failed\n"); return -1; } char cmd_buf1[] = { 0xAA, 0x01, 0x04, 0x00, 0x06, 0x10, 0x05, 0x00, 0xBB}; char cmd_buf2[] = { 0xAA, 0x01, 0x04, 0x00, 0x00, 0xA0, 0x00, 0x03, 0xBB}; char cmd_buf3[] = { 0xAA, 0x01, 0x04, 0x00, 0x03, 0x10, 0x01, 0x00, 0xBB}; char read_buf[2000]; //-----------打开uart设备文件------------------ fd = open(UART_DEVICE, O_RDWR | O_NOCTTY); if (fd < 0) { printf("Open %s failed\n", UART_DEVICE); return -1; } else { printf("Open %s successfully\n", UART_DEVICE); } //-----------设置操作参数----------------------- tcgetattr(fd, &oldtio);//获取当前操作模式参数 memset(&newtio, 0, sizeof(newtio)); //波特率=230400 数据位=8 使能数据接收 newtio.c_cflag = B230400 | CS8 | CLOCAL | CREAD | CSTOPB; newtio.c_iflag = IGNPAR; tcflush(fd, TCIFLUSH);//清空输入缓冲区和输出缓冲区 tcsetattr(fd, TCSANOW, &newtio);//设置新的操作参数 //printf("input: %s, len = %d\n", cmd_buf, strlen(cmd_buf)); //------------向urat发送数据------------------- for (i = 0; i < 9; i++) printf("%#X ", cmd_buf1[i]); count = write(fd, cmd_buf1, 9); if (count != 9) { printf("send failed\n"); return -1; } usleep(500000); memset(read_buf, 0, sizeof(read_buf)); count = read(fd, read_buf, sizeof(read_buf)); if (count > 0) { for (i = 0; i < count; i++); temp->temp_max1 = read_buf[7] << 8 | read_buf[6]; temp->temp_max2 = read_buf[9] << 8 | read_buf[8]; temp->temp_max3 = read_buf[11] << 8 | read_buf[10]; temp->temp_min = read_buf[13] << 8 | read_buf[12]; temp->temp_mean = read_buf[15] << 8 | read_buf[14]; printf("temp->temp_max1 = %f\n", temp->temp_max1 * 0.01); printf("temp->temp_max2 = %f\n", temp->temp_max2 * 0.01); printf("temp->temp_max3 = %f\n", temp->temp_max3 * 0.01); printf("temp->temp_min = %f\n", temp->temp_min * 0.01); printf("temp->temp_mean = %f\n", temp->temp_mean * 0.01); } else { printf("read temp failed\n"); return -1; } count = write(fd, cmd_buf3, 9); if (count != 9) { printf("send failed\n"); return -1; } usleep(365); memset(read_buf, 0, sizeof(read_buf)); count = read(fd, read_buf, sizeof(read_buf)); if (count > 0) { for (i = 0; i < count; i++); temp->temp_enviromem = read_buf[7] << 8 | read_buf[6]; printf("temp->temp_enviromem = %f\n", temp->temp_enviromem * 0.01); } else { printf("read enviromem failed\n"); return -1; } count = write(fd, cmd_buf2, 9); if (count != 9) { printf("send failed\n"); return -1; } usleep(70000); memset(read_buf, 0, sizeof(read_buf)); memset(temp->temp_col, 0, sizeof(temp->temp_col)); count = read(fd, read_buf, sizeof(read_buf)); printf("count = %d\n", count); if (count > 0) { for (i = 0; i < count - 7; i++) temp->temp_col[i] = read_buf[i+6]; for (i = 0; i < 1536; i++) { if (!(i%10)) printf("\n"); printf("%#X ", temp->temp_col[i]); } } else { printf("read temp colour failed\n"); return -1; } free(temp); close(fd); tcsetattr(fd, TCSANOW, &oldtio); //恢复原先的设置 return 0; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdgsp.html