您的位置:首页 > 产品设计 > UI/UE

智能车上位机与下位机通信的例子

2015-10-28 15:28 465 查看
智能车的主板(上位机)是小车控制模块的核心,负责路况采集、行驶行为决策等重要功能。下位机(单片机)是小车执行模块的关键,负责直接操作电机、舵机等,来控制行驶的速度和方向。

通常需要上位机给下位机发送命令,如何在二者之间实现通信成为一个研究话题。本文给出了一种串口通信的方法,来实现这个功能。

上位机使用C语言编写,关键代码如下:/**

*@brief 打开串口设备

*@param Dev 类型 char* 打开串口的设备名或者目录

*@return fd 类型 int 打开成功返回设备id,否则返回-1

*/
int openDev( char* Dev )
{
int fd = open( Dev, O_RDWR );//以可读写的方式打开串口

//fd = open( Dev,O_RDWR | 0_NOCTTY | O_NONBLOCK );

//| O_NOCTTY | O_NDELAY

if( -1 == fd )
{
perror( "Can't Open Serial Port" );
return -1;
}
else
return fd;
}

/**

*@brief 设置串口通信速率

*@param fd 类型 int 打开串口的文件句柄

*@param speed 类型 int 串口速度

*@return void

*/

void set_speed( int fd, int speed )
{
int i;

int status;

struct termios Opt;

tcgetattr( fd, &Opt );

for( i = 0; i < sizeof( speed_arr ) / sizeof( int ); i++ )
{
if( speed == name_arr[ i ] )
{
tcflush( fd, TCIOFLUSH );

cfsetispeed( &Opt, speed_arr[ i ] );

cfsetospeed( &Opt, speed_arr[ i ] );

status = tcsetattr( fd, TCSANOW, &Opt );

if( status != 0 )
{
perror( "tcsetattr fd" );
return;
}

tcflush( fd, TCIOFLUSH );
}
}
}

/**

*@brief 设置串口数据位,停止位和效验位

*@param fd 类型 int 打开的串口文件句柄

*@param databits 类型 int 数据位 取值 为 7 或者8

*@param stopbits 类型 int 停止位 取值为 1 或者2

*@param parity 类型 int 效验类型 取值为N,E,O,,S

*/

int set_Parity( int fd, int databits, int stopbits, int parity )
{
struct termios options;

if( tcgetattr( fd, &options ) != 0 )
{
perror( "SetupSerial 1" );
return FALSE;
}

options.c_cflag &= ~CSIZE;

options.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG ); /*Input*/

options.c_oflag &= ~OPOST; /*Output*/

switch( databits ) /*设置数据位数*/
{
case 7:
options.c_cflag |= CS7;
break;

case 8:
options.c_cflag |= CS8;
break;

default:
fprintf( stderr, "Unsupported data size\n" );
return FALSE;
}

switch( parity )
{
case 'n':

case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */

options.c_iflag &= ~INPCK; /* Enable parity checking */
break;

case 'o':

case 'O':
options.c_cflag |= ( PARODD | PARENB ); /* 设置为奇效验*/

options.c_iflag |= INPCK; /* Disnable parity checking */
break;

case 'e':

case 'E':
options.c_cflag |= PARENB; /* Enable parity */

options.c_cflag &= ~PARODD; /* 转换为偶效验*/

options.c_iflag |= INPCK; /* Disnable parity checking */
break;

case 'S':

case 's': /*as no parity*/
options.c_cflag &= ~PARENB;

options.c_cflag &= ~CSTOPB;
break;

default:
fprintf( stderr, "Unsupported parity\n" );
return FALSE;
}

/* 设置停止位*/
switch( stopbits )
{
case 1:
options.c_cflag &= ~CSTOPB;
break;

case 2:
options.c_cflag |= CSTOPB;
break;

default:
fprintf( stderr, "Unsupported stop bits\n" );
return FALSE;
}

/* Set input parity option */
if( parity != 'n' )
options.c_iflag |= INPCK;

tcflush( fd, TCIFLUSH );

options.c_cc[ VTIME ] = 0; /* 设置超时0 seconds*/

options.c_cc[ VMIN ] = 1; /* define the minimum bytes data to be readed*/

if( tcsetattr( fd, TCSANOW, &options ) != 0 )
{
perror( "SetupSerial 3" );
return FALSE;
}
return TRUE;
}
本文使用的智能车下位机为Arduino单片机,使用相关语言编写,关键代码如下:

//接收上位机传送的信息串(实现上下通信)
void readSerial() {
if(Serial.available()) {
isDisconnect = 0;

if((ReadVal[0] = Serial.read()) == 152) {
for(int i = 1; Serial.available() && i <= 3; ++i) {
ReadVal[i] = Serial.read();
}

if(ReadVal[3] == 225) {
speedVal = ReadVal[1];
directionVal = ReadVal[2];

if(speedVal == 0 || speedVal >= 190 || speedVal <= 210
|| speedVal >= 160 || speedVal <= 170) {
motorSpeed = speedVal;
}
else {
motorSpeed = 0;
}

servoDirection = directionVal;

if(directionVal > 125) {
servoDirection = 125;
}
else if(directionVal < 55) {
servoDirection = 55;
}
}
}
}
else {
isDisconnect++;
if(isDisconnect > 10) {
motorSpeed = 0;
servoDirection = 90;
}
}
}

至此,上位机可以通过串口的方式给下位机发命令了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息