智能小车地盘控制(二)代码实现

1、功能分类

由于本例是基于STM32CubeIDE开发,在前一篇文章中配置好,点击保存便会自动生成初始化的代码,用户只需要添加应用代码即可。主要包括编码器功能、PWM功能、定时器功能、串口通信功能。

2、代码
2.1 main函数

main函数中主要是设置一些变量的初始化,开启各个外围接口,在while循环内发送里程信息。

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
  pulseR = 0; //右轮电机PWM值变量
  pulseL = 0; //左轮电机PWM值变量

  SpdSum1 = 0; //右编码器计数值
  SpdSum2 = 0; //左编码器计数值
  dir1=0; //右编码器方向 1:正,2:负
  dir2=0; //左编码器方向

  uint8_t j=0;

  ENC_Clear_Speed_Buffer(); //编码器计数值求平均时缓存初始化
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  MX_TIM4_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim1);//timer1定时器开,设置1ms定时,用于更新PWM值等功能
  ret1 = HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);//开启右编码器功能
  HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL); //开启左编码器功能
  delay_init(72); //利用systick定时器实现延时函数功能初始化
  //disable LN298
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
  //开启串口接收中断
  HAL_UART_Receive_IT(&huart1, (uint8_t*)USART_RX_BUF, sizeof(USART_RX_BUF));
//开启PWM定时器
  //HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_2);
  //HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_3);
  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

	  /*
	   * uart overrun error self recovery
	   * 本例测试中出现串口overrun错误,在此回复串口功能,不一定需要,根据实际情况定。
	   * */
	  cr1its  = READ_REG(huart1.Instance->CR1);;
	  if((cr1its & USART_CR1_RXNEIE) ==0)
		  HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
		  
	  delay_ms(20);
	  
	  if(stateHandle&0x01)//
	  {
			 x_data.odoemtry_float=position_x;//单位mm
			 y_data.odoemtry_float=position_y;//单位mm
			 theta_data.odoemtry_float=theta;//单位rad
			 vel_linear.odoemtry_float=linear_vel;//单位mm/s
			 vel_angular.odoemtry_float=angular_vel;//单位rad/s

	   //将所有里程计数据存到要发送的数组
			 odometry_data[0] =0xAA; //发送包头字节1
			 odometry_data[1] =0x55;//发送包头字节2
			 odometry_data[2] =0x01;//功能码,未定义
			 odometry_data[3] =0x14;//发送数据包中数据的长度,分别包括X方向位移(float型,四个字节)、Y方向位移,角度、线速度、角速度,共20个字节

		for(j=0;j<4;j++)
		{
			odometry_data[j+4]=x_data.odometry_char[j];
			odometry_data[j+8]=y_data.odometry_char[j];
			odometry_data[j+12]=theta_data.odometry_char[j];
			odometry_data[j+16]=vel_linear.odometry_char[j];
			odometry_data[j+20]=vel_angular.odometry_char[j];
		}
     sndCRCVal = CRC16(odometry_data,USART_SEN_LEN-4);//计算CRC值
		 odometry_data[24] =sndCRCVal;
		 odometry_data[25] =sndCRCVal>>8;
		 odometry_data[26]=0x0d;//添加结束
		 odometry_data[27]=0x0a;//添加结束

		HAL_UART_Transmit(&huart1,odometry_data,sizeof(odometry_data),0xfff); //发送至上位机
		stateHandle&=0xFE;//
	  }

	  car_control(rightdata.d,leftdata.d);	 //将接收到的左右轮速度赋给小车

  }
  /* USER CODE END 3 */
}
2.2 1ms定时器

1ms定时器,重写更新回调函数,当定时器达到设置的时间时,会进入响应的定时器中断响应函数,中断响应函数根据不同的中断标志位判断是哪种类型的定时器中断,进而调用不同的中断处理函数。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM1)
	{
		stateHandle |= 0x01; //对应main函数中的while循环的状态值

		//encoder1
		SpdSum1 = (int16_t)(__HAL_TIM_GET_COUNTER(&htim2));//获取右编码器脉冲的计数值
		__HAL_TIM_SET_COUNTER(&htim2, 0);//编码器脉冲计数清零

		hSpeed_Buffer1[bSpeed_Buffer_Index] = SpdSum1;//right,存入数组作求平均用。

		//encoder2
		SpdSum2 = (int16_t)(__HAL_TIM_GET_COUNTER(&htim3));//获取左编码器脉冲的计数值
		__HAL_TIM_SET_COUNTER(&htim3, 0);//编码器脉冲计数清零

		hSpeed_Buffer2[bSpeed_Buffer_Index] = SpdSum2;//left,存入数组作求平均用。

		//储存编码数(脉冲数),用于里程计计算
		Milemeter_L_Motor= (float)SpdSum2;//(float)temp2; //储存脉冲数组
		Milemeter_R_Motor= (float)SpdSum1 ;//float)temp4;
		odometry(Milemeter_R_Motor,Milemeter_L_Motor);//计算里程

		bSpeed_Buffer_Index++;//数组移位
		if(bSpeed_Buffer_Index >=SPEED_BUFFER_SIZE)
		{
			bSpeed_Buffer_Index=0;//缓存左右轮编码数到数组变量清零
		}

		ENC_Calc_Average_Speed();//计算三次电机的平均编码数

		pulseR = (uint16_t)Gain1(); //电机A转动 PID调节控制right
		htim4.Instance->CCR2 = pulseR;//更新PWM值
		pulseL = (uint16_t)Gain2(); //电机B转动 PID调节控制left
		htim4.Instance->CCR3 = pulseL;
	}
}
2.3 串口通信—接收中断
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//TO-DO uart receive process
/**
 * 与上位机通信协议,自定义
 * 包头 0x55 0xAA
 * 功能码 0x01->开始,0x03->停止,0x04->others
 * length
 * data
 * CRC 2 bytes
 * 示例:0x55 0xAA 0x01 0x0a,dir1,dir2,spd1_B1,spd1_B2 spd1_B3 spd1_B4 spd2_B1 spd2_B2 spd2_B3 spd2_B4 CRCL,CRCH (dirx=1->forward,dirx=2->backward),速度为float型,左右两便速度值各四各字节
 */
/* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function should not be modified, when the callback is needed,
		   the HAL_UART_RxCpltCallback could be implemented in the user file
   */
  if(huart->Instance == USART1)
  {
	  if(flag!=1)
	  {
		  if(state == 0)
		  {
			  if(aRxBuffer[0] ==0x55)
			      header = 0x0055;
			  else if(aRxBuffer[0] ==0xAA)
			  {
				  header=(header<<8)|aRxBuffer[0];
				  if(header==0x55AA)
				  {//收到包头
					  state=1;
					  USART_RX_BUF[0]=0x55;
					  USART_RX_BUF[1]=0xAA;
					  recv_cnt=2;
				  }
			  }
			  else
				  header = 0;
		  }
		  else if(state ==1)
		  {
			  USART_RX_BUF[recv_cnt++]=aRxBuffer[0];
			  state =2;
		  }
		  else if(state ==2)
		  {
			  pkt_len=aRxBuffer[0];
			  USART_RX_BUF[recv_cnt++]=pkt_len;
			  if(pkt_len==10) //在此要判断一下接收到的数据长度要和用户设置的一致,不一致可能是通信丢包等问题导致这一帧数据错误,如果数据长度超过接收数组长度,会导致hardfault中断!!!!
				  state=3;
			  else
				  state=0;
		  }
		  else if(state ==3)
		  {
			 USART_RX_BUF[recv_cnt++]=aRxBuffer[0];
		     if(recv_cnt-4==pkt_len) //pkt_len
		    	 state=4;

		  }
		  else if(state == 4)
		  {
			  USART_RX_BUF[recv_cnt++]=aRxBuffer[0];
			  state=5;
		  }
		  else if(state == 5)
		  {
			  USART_RX_BUF[recv_cnt++]=aRxBuffer[0];
			  checksum = CRC16(USART_RX_BUF,USART_REC_LEN-2);
			  if (checksum == (uint16_t)(USART_RX_BUF[14]<<8|USART_RX_BUF[15]))  //ros 14<<8 sscom 15<<8
			  {
				  if(USART_RX_BUF[2]==0x01)
				  {

					  dir1 = USART_RX_BUF[4];
					  dir2 = USART_RX_BUF[5];
					  for(t=0;t<4;t++)
					  {
						  rightdata.data[t]=USART_RX_BUF[t+6];
						  leftdata.data[t]=USART_RX_BUF[t+10];
					  }

					  //储存左右轮速度命令值
					  odometry_right=rightdata.d;//单位mm/s
					  odometry_left=leftdata.d;//单位mm/s
					  if(dir1==1)
					  {
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
					  }
					  if(dir1==2)
					  {
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
					  }
					  if(dir2==1)
					  {
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
					  }
					  else if(dir2==2)
					  {
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
						  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
					  }
					  else
					  {

					  }
				  }
				  if(USART_RX_BUF[2]==0x03)
				  {
					  // stop motor
					  HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_2);
					  HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_3);
					  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
					  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
					  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
					  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
				  }
			  }
			  state=0;
			  recv_cnt=0;

		  }
	  }
	  HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
  }

}

完整代码地址链接:stm32

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值