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

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

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


上位机使用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;
    }
  }
}

至此,上位机可以通过串口的方式给下位机发命令了。

你可能感兴趣的:(VANET,IOV,arduino,串口通信,单片机)