TX2通过串口或CAN和其他设备通信(一)— 串口通信
背景介绍
Jetson TX2是NVIDIA推出的一款嵌入式开发平台,TX2所提供的性能为早前版本的两倍,即能够以两倍以上的功效运行,且功率低于7.5瓦。这使得Jetson TX2能够在终端应用上运行更庞大、更深度的神经网络,让设备更加智能,具有更高的精度和更快的响应时间,以执行如图像分类、导航和语音识别等任务
需求分析
TX2应用在机器人领域通常需要和其他设备进行通信来实现对机器人的控制
本文主要介绍TX2通过串口和CAN总线和其他设备进行通信
参考之前的经验,串口通信较为普遍,相对简单,所以从串口做起
串口通信
1. 首先搞清楚TX2的接口
这个网站有TX2的配置和外设信息
但是要结合具体的载板,这里我用的是瑞泰科技的TX2 9003,可查看《RTSO-9003用户手册V1.1》
瑞泰科技只留出来两路串口,UART0为调试口,UART1为普通串口,所以咱们使用UART1
管脚 | 功能 | 管脚 | 功能 |
---|
3 | UART0_TX | 4 | UART0_RX
5 | UART1_TX | 6 | UART1_RX
这里需注意在linux下串口是一个文件,UART0为"/dev/ttyS0"",UART1为"/dev/ttyTHS2"
2.接下来进行代码部分的编写
主要参考这篇博客
分为三个部分:打开串口、串口初始化、读写串口
- 打开串口
/**
* openUart
* @param comport 想要打开的串口号
* return 失败返回-1
*/
int openUart( int comport)
{
const char *dev[] = {"/dev/ttyS0", "/dev/ttyTHS2"};
//瑞泰科技只留出来两路串口,UART0为调试口,UART1为普通串口,所以咱们使用UART1
if(comport == 0)
{
fd = open(dev[0], O_RDWR | O_NOCTTY | O_NDELAY);
if(-1 == fd)
{
perror("Can't Open Serial Port");
return (-1);
}
}
else if(comport == 1)
{
fd = open(dev[1], O_RDWR | O_NOCTTY | O_NDELAY);
if(-1 == fd)
{
perror("Can't Open Serial Port");
return (-1);
}
}
printf("fd-open=%d\n", fd);
return fd;
}
- 初始化串口
/**
* uartInit
* @param nSpeed 波特率 nBits 停止位 nEvent 奇偶校验位 nStop 停止位
* @return 返回-1为初始化失败
*/
int uartInit(int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio, oldtio;
/*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/
if ( tcgetattr( fd, &oldtio) != 0) {
perror("SetupSerial 1");
printf("tcgetattr( fd,&oldtio) -> %d\n", tcgetattr( fd, &oldtio));
return -1;
}
bzero( &newtio, sizeof( newtio ) );
/*步骤一,设置字符大小*/
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
/*设置停止位*/
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
/*设置奇偶校验位*/
switch( nEvent )
{
case 'o':
case 'O': //奇数
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'e':
case 'E': //偶数
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'n':
case 'N': //无奇偶校验位
newtio.c_cflag &= ~PARENB;
break;
default:
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;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
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[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
/*处理未接收字符*/
tcflush(fd, TCIFLUSH);
/*激活新配置*/
if((tcsetattr(fd, TCSANOW, &newtio)) != 0)
{
perror("com set error");
return -1;
}
printf("set done!\n");
return 0;
}
- 读写串口
/**
*uartSend
*@param send_buf[] 要发送的数据 length 发送的数据长度
*/
void uartSend(char send_buf[], int length)
{
int w;
w = write(fd, send_buf, length);
if(w == -1)
{
printf("Send failed!\n");
}
else
{
printf("Send success!\n");
}
}
/**
*uartSend
*@param send_buf[] 要接收的数据 length 接收的数据长度
*/
void uartRead(char receive_buf[], int length)
{
int r;
r = read(fd, receive_buf, strlen(receive_buf));
for(int i = 0; i < r; i++)
{
printf("%c", receive_buf[i]);
}
}
3. 测试
这里测试为TX2通过USB-TTL向我电脑的上位机发送数据
上位机为任意串口助手
RX接PORT_5,TX接PORT_6
波特率统一设置为115200
- 测试代码
int main(int argc , char **argv) {
fd = openUart(1); //打开串口
char test [6] = "Hello"; //用来测试
uartInit(115200, 8, 'n' , 1) ; //波特率为115200,无奇偶校验,波特率需与下位机相匹配
for(int i = 10; i > 0; i--) {
uartSend(test, strlen(test));
}
close(fd);
return 0;
}
经过测试,上位机可以成功接收数据
date : 2018.12.25