完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
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); } } |
|
|
|
只有小组成员才能发言,加入小组>>
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
3545 浏览 0 评论
3457 浏览 9 评论
3131 浏览 16 评论
3643 浏览 1 评论
9354 浏览 16 评论
1503浏览 3评论
733浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
751浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2541浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
2069浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-5-8 10:46 , Processed in 1.442633 second(s), Total 76, Slave 57 queries .
Powered by 电子发烧友网
© 2015 www.ringvoyeur.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191