基于百科荣创主车电机驱动板程序 PID控制

适用百科荣创新款主车以及麦克纳姆轮的电机驱动板,老款带电子罗盘的实测不适用

代码以及逻辑上可能会存在一些问题,错误的地方在评论区指出

 当时用的370麦轮电机,很难控制,后面指导老师让我们考虑加入pid,原本在主控板的程序里面,效果一般,后面才考虑用hal库重构电机驱动板,但是后面发现效果也没有提升多少,到后面的竞赛平台也就用了这个程序

在看原理图的时候其实发现了一些奇奇怪怪的地方,就比如说前轮可以用定时器捕获功能获取码盘,但是后轮定时器又跟定时器pwm有点冲突,用外部中断的话,有两个轮子的中断线又有冲突,然后电机的pwm又对应互补输出,电机驱动用了TIM8三路互补输出和TIM2两个输出,当时的我stm32也才刚入门,整不明白互补怎么去控制的电机,所以把互补的三路切换到了TIM3的CH1、CH2、CH3上。

码盘用的是TIM1,TIM3,TIM4和TIM5的编码器模式,原电机驱动板只采样后面两个轮子的码盘,这个时候TIM3就已经和输出PWM的TIM3冲突了,TIM3对应的是后面两个轮子的其中一个。想过用外部中断测码盘,但是前面两个电机码盘接的IO的外部中断线又冲突了。
最后是后面两个轮子用定时器TIM1和TIM4来测码盘,前面两个轮子用的是两个外部中断测码盘,又发现前后码盘有个四倍的差距,就直接在中断码盘计数那边改成了+=4和-=4……

 带pid的电机驱动板程序其实并没有多麻烦,麻烦在于挖掘CAN的通信

CuneMX的配置

如图:

 记得开启CAN中断接收

 主要就是一个

CAN中断接收

注:因为用HAL库重构了核心板程序,这里加了一些原厂程序不会有的功能,可能会导致原厂核心板程序搭配这套程序出现问题,原厂应该只会用到0x1e0的接收

u16 Stop_Time=0;
uint8_t TXmessage[8] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
uint8_t RXmessage[8];
uint32_t pTxMailbox = 0;
int Set_MP[4];
u8 Set_MP_Flag = 0;

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)//接受邮箱0挂起中断回调函数
{
	if(hcan->Instance==CAN1)
	{
        RxHeader.StdId=0x20;
		HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RxHeader,RXmessage);//获取数据
        
        
        switch(RxHeader.StdId)
        {
            case 0x1e0:{
                
                motor_set_left_top = RXmessage[0]/4;    //左前轮设定值
                motor_set_right_top = RXmessage[2]/4;   //右前轮设定值
                motor_set_left_aft = RXmessage[1]/4;    //左后轮设定值
                motor_set_right_aft = RXmessage[3]/4;   //右后轮设定值

                if(motor_set_left_top>31)motor_set_left_top-=64;
                if(motor_set_right_top>31)motor_set_right_top-=64;
                if(motor_set_left_aft>31)motor_set_left_aft-=64;
                if(motor_set_right_aft>31)motor_set_right_aft-=64;
                
                memset(RXmessage,0,8);//清空数组
                
            }break;
            case 0x1e1:{  //让电机转动指定个码盘,已废弃
                
                Set_MP[0] = ((RXmessage[1]<<8)+RXmessage[0])/4;
                Set_MP[1] = ((RXmessage[3]<<8)+RXmessage[2])/4;
                Set_MP[2] = ((RXmessage[5]<<8)+RXmessage[4])/4;
                Set_MP[3] = ((RXmessage[7]<<8)+RXmessage[6])/4;
                
                if(Set_MP[0]>8191) Set_MP[0]-=16384;
                if(Set_MP[1]>8191) Set_MP[1]-=16384;
                if(Set_MP[2]>8191) Set_MP[2]-=16384;
                if(Set_MP[3]>8191) Set_MP[3]-=16384;
                
                printf("%d,%d,%d,%d\n\n",Set_MP[0],Set_MP[1],Set_MP[2],Set_MP[3]);
                
                Set_MP_Flag = 1;
                memset(RXmessage,0,8);//清空数组
                
            }break;
            case 0x1e2:{   //停车三秒
                
                if(RXmessage[0]==0x03)
                {
                
                    Stop_Time = RXmessage[1]*72;
                }
                memset(RXmessage,0,8);//清空数组
                
            }break;
        }
        
        
        

        
        
        //printf("0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n",RXmessage[0],RXmessage[1],RXmessage[2],RXmessage[3],RXmessage[4],RXmessage[5],RXmessage[6],RXmessage[7]);
    }
	
}

以及在网上找的一个

CAN的发送函数

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//stdid:目标id
//返回值:0,成功;
//		 其他,失败;

//disp地址:0x1e
u8 CAN1_Send_Msg(u8* msg,u8 len,u32 stdid,u32 d)
{	
    u8 i=0;
	uint32_t TxMailbox;
	u8 message[8];
    TxHeader.StdId=stdid;//0X12;        //标准标识符
    TxHeader.ExtId=0;//0x12;        //扩展标识符(29位)
    TxHeader.IDE=CAN_ID_STD;    //使用标准帧
    TxHeader.RTR=CAN_RTR_DATA;  //数据帧
    TxHeader.DLC=len;    
    for(i=0;i<len;i++)
    {
		message[i]=msg[i];
	}
    
    if(HAL_CAN_AddTxMessage(&hcan, &TxHeader, message, &TxMailbox) != HAL_OK)//发送
	{
		return 1;
	}
	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 3) {}
    return 0;
}

列出一下

CAN ID对应的目标:

0x1e0:电机驱动板的速度

0x1e1:让电机转动指定个码盘        ****

0x1e2:最高权限让电机驱动板停车多少秒          ****

0x3c0:通信显示板Debug打印

0x1F1:通信显示板显示的码盘

0x0E7:主车程序的循迹板数据回传

0x2A0:ZigBee数据

0x280:WiFi数据

printf重定向

原厂程序的printf重定向:

int fputc(int ch,FILE *p)  //printf重定向到通信显示板的debug
{
    delay_ms(1);
    u8 tmp[1];
    sprintf((char*)tmp,"%c",ch);
    Send_Debug_Info((u8*)tmp,1);
    
    USART_SendData(USART1,(u8)ch);	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
    
	return ch;
}

hal库重构后的重定向

int fputc(int ch,FILE *f)
{
    
    CAN1_Send_Msg((uint8_t *)&ch,1,0x3c0,0);
    
	return ch;
}

下面是一部分的代码

设置pwm

//设置电机pwm,左前,左后,右前,右后
void set_motor(int lt,int la,int rt,int ra)
{
        
    if(rt>0)
    {
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,rt);//右前轮正转
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,0);//右前轮反转
    }else if(rt==0){
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,1000);//右前轮正转
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,1000);//右前轮反转
    }else{
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,0);//右前轮正转
        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,-rt);//右前轮反转
    }
    
    if(ra>0)
    {
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,ra);//右后轮正转
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,0);//右后轮反转
    }else if(ra==0){
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,1000);//右后轮正转
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,1000);//右后轮反转
    }else{
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,0);//右后轮正转
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,-ra);//右后轮反转
    }
    
    
    
    if(lt>0)
    {
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,lt);//左前轮正转
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,0);//左前轮反转
    }else if(lt==0){
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,1000);//左前轮正转
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,1000);//左前轮反转
    }else{
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,0);//左前轮正转
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,-lt);//左前轮反转
    }
    
    if(la>0)
    {
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,la);//左后轮正转
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,0);//左后轮反转
    }else if(la==0){
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,1000);//左后轮正转
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,1000);//左后轮反转 
    }else{
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,0);//左后轮正转
        __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,-la);//左后轮反转      
    }

}

转速 PID

//电机转速pid

float Kp = 1.2;
float Ki = 0.3;
float Kd = 2;


/*
函数功能:PID左前计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int pid_lt(int test,int set)
{
	static int Bias,Pwm,Old_Last_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Pwm=Kp*(Bias-Last_bias)+Ki*Bias+Kd*(Bias-(2*Last_bias)+Old_Last_bias);  //增量式PI控制器
	Old_Last_bias=Last_bias;	                   //保存上上一次偏差
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

/*
函数功能:PID左后计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int pid_la(int test,int set)
{
	static int Bias,Pwm,Old_Last_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Pwm=Kp*(Bias-Last_bias)+Ki*Bias+Kd*(Bias-(2*Last_bias)+Old_Last_bias);  //增量式PI控制器
	Old_Last_bias=Last_bias;	                   //保存上上一次偏差
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

/*
函数功能:PID右前计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int pid_rt(int test,int set)
{
	static int Bias,Pwm,Old_Last_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Pwm=Kp*(Bias-Last_bias)+Ki*Bias+Kd*(Bias-(2*Last_bias)+Old_Last_bias);  //增量式PI控制器
	Old_Last_bias=Last_bias;	                   //保存上上一次偏差
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

/*
函数功能:PID右后计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int pid_ra(int test,int set)
{
	static int Bias,Pwm,Old_Last_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Pwm=Kp*(Bias-Last_bias)+Ki*Bias+Kd*(Bias-(2*Last_bias)+Old_Last_bias);  //增量式PI控制器
	Old_Last_bias=Last_bias;	                   //保存上上一次偏差
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

位置PID

//码盘位置pid

float cmd_P = 3;
float cmd_I = 0.0005;
float cmd_D = 12;


/*
函数功能:PID左前计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int wz_pid_lt(int test,int set)
{
	float Kp=cmd_P,Ki=cmd_I,Kd=cmd_D;			//原例程中Kp=20,Ki=30	
	static int Bias,Pwm,Integral_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Integral_bias+=Bias;
	Pwm=Kp*Bias+Ki*Integral_bias+Kd*(Bias-Last_bias);  //位置式PI控制器
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

/*
函数功能:PID左后计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int wz_pid_la(int test,int set)
{
	float Kp=cmd_P,Ki=cmd_I,Kd=cmd_D;			//原例程中Kp=20,Ki=30	
	static int Bias,Pwm,Integral_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Integral_bias+=Bias;
	Pwm=Kp*Bias+Ki*Integral_bias+Kd*(Bias-Last_bias);  //位置式PI控制器
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

/*
函数功能:PID右前计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int wz_pid_rt(int test,int set)
{
	float Kp=cmd_P,Ki=cmd_I,Kd=cmd_D;			//原例程中Kp=20,Ki=30	
	static int Bias,Pwm,Integral_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Integral_bias+=Bias;
	Pwm=Kp*Bias+Ki*Integral_bias+Kd*(Bias-Last_bias);  //位置式PI控制器
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

/*
函数功能:PID右后计算
参    数:test:当前车速,set:设置车速
返 回 值:无
*/
int wz_pid_ra(int test,int set)
{
	float Kp=cmd_P,Ki=cmd_I,Kd=cmd_D;			//原例程中Kp=20,Ki=30	
	static int Bias,Pwm,Integral_bias,Last_bias;

	Bias=set-test;             //计算偏差
	Integral_bias+=Bias;
	Pwm=Kp*Bias+Ki*Integral_bias+Kd*(Bias-Last_bias);  //位置式PI控制器
	Last_bias=Bias;	                   //保存上一次偏差
	
	return Pwm;                        //增量输出
}

定时器中断

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //外部中断回调函数
{
    if(GPIO_Pin == GPIO_PIN_0)
    {
        if(HAL_GPIO_ReadPin(CODE_D2_GPIO_Port,CODE_D2_Pin)==1)
        {
            code_desk_left_top+=4;
        }else
        {
            code_desk_left_top-=4;
        }
    }

    if(GPIO_Pin == GPIO_PIN_4)
    {
        if(HAL_GPIO_ReadPin(CODE_B2_GPIO_Port,CODE_B2_Pin)==1)
        {
            code_desk_right_top-=4;
        }else
        {
            code_desk_right_top+=4;
        }
    }


}


u16 mp_delay=0;
int code_disk_init[4];

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim==(&htim6))//PID定时器6
  {
      static int tmp[4];
      int speed[4];

        code_desk_left_aft-=	(short)__HAL_TIM_GET_COUNTER(&htim4);	  //读取左后轮编码器数据
        code_desk_right_aft+=	(short)__HAL_TIM_GET_COUNTER(&htim1);	  //读取右后轮编码器数据
        __HAL_TIM_GET_COUNTER(&htim4) = 0;							  //计数器值重新置位
        __HAL_TIM_GET_COUNTER(&htim1) = 0;							  //计数器值重新置位

        //做减法计算速度
        speed[0]=tran_reduce(code_desk_left_top,tmp[0]);
        speed[1]=tran_reduce(code_desk_right_top,tmp[1]);
        speed[2]=tran_reduce(code_desk_left_aft,tmp[2]);
        speed[3]=tran_reduce(code_desk_right_aft,tmp[3]);

        //保存老的码盘数值
        tmp[0]=code_desk_left_top;
        tmp[1]=code_desk_right_top;
        tmp[2]=code_desk_left_aft;
        tmp[3]=code_desk_right_aft;
      

        if(Set_MP_Flag) //位置pid模式
        {
            if(mp_delay==0)
            {
                code_disk_init[0] = code_desk_left_top;
                code_disk_init[1] = code_desk_right_top;
                code_disk_init[2] = code_desk_left_aft;
                code_disk_init[3] = code_desk_right_aft;
            }
            
            if(++mp_delay>144)//执行时间
            {
                mp_delay=0;
                Set_MP_Flag=0;
            }
            
            if((abs(code_desk_left_top-(code_disk_init[0]+Set_MP[0]))<20)&&(abs(code_desk_right_top-(code_disk_init[1]+Set_MP[1]))<20)&&(abs(code_desk_left_aft-(code_disk_init[2]+Set_MP[2]))<20)&&(abs(code_desk_right_aft-(code_disk_init[3]+Set_MP[3]))<20))
            {
                mp_delay=0;
                Set_MP_Flag=0;
            }
                
            
            pwm[0]=wz_pid_lt(code_desk_left_top,code_disk_init[0]+Set_MP[0]);
            pwm[1]=wz_pid_rt(code_desk_right_top,code_disk_init[1]+Set_MP[2]);
            pwm[2]=wz_pid_la(code_desk_left_aft,code_disk_init[2]+Set_MP[1]);
            pwm[3]=wz_pid_ra(code_desk_right_aft,code_disk_init[3]+Set_MP[3]);
            
            u8 max_speed = 60;
            //不让pwm超太多
            if(pwm[0]>max_speed)pwm[0]=max_speed;
            if(pwm[1]>max_speed)pwm[1]=max_speed;
            if(pwm[2]>max_speed)pwm[2]=max_speed;
            if(pwm[3]>max_speed)pwm[3]=max_speed;
            if(pwm[0]<-max_speed)pwm[0]=-max_speed;
            if(pwm[1]<-max_speed)pwm[1]=-max_speed;
            if(pwm[2]<-max_speed)pwm[2]=-max_speed;
            if(pwm[3]<-max_speed)pwm[3]=-max_speed;
            
            //printf("%d,%d\n",code_desk_right_aft,code_disk_init[3]+Set_MP[3]);
            
        }else{
            //PID计算
            pwm[0]+=pid_lt(speed[0],motor_set_left_top);
            pwm[1]+=pid_rt(speed[1],motor_set_right_top);
            pwm[2]+=pid_la(speed[2],motor_set_left_aft);
            pwm[3]+=pid_ra(speed[3],motor_set_right_aft);
            
            //清零
            if(motor_set_left_top==0)pwm[0]=0;
            if(motor_set_right_top==0)pwm[1]=0;
            if(motor_set_left_aft==0)pwm[2]=0;
            if(motor_set_right_aft==0)pwm[3]=0;
            
            
            //不让pwm超太多
            if(pwm[0]>100)pwm[0]=100;
            if(pwm[1]>100)pwm[1]=100;
            if(pwm[2]>100)pwm[2]=100;
            if(pwm[3]>100)pwm[3]=100;
            if(pwm[0]<-100)pwm[0]=-100;
            if(pwm[1]<-100)pwm[1]=-100;
            if(pwm[2]<-100)pwm[2]=-100;
            if(pwm[3]<-100)pwm[3]=-100;
            
        }

        

        if(Stop_Time>0)
        {
            Stop_Time--;
            
            pwm[0] = 0;
            pwm[1] = 0;
            pwm[2] = 0;
            pwm[3] = 0;
        }


        //模式切换
        if(mode_flag==0) set_motor(pwm[0]*10,pwm[2]*10,pwm[1]*10,pwm[3]*10);
        if(mode_flag==1) set_motor(motor_set_left_top*10,motor_set_left_aft*10,motor_set_right_top*10,motor_set_right_aft*10);
         
//        printf("set:%3d,%3d,%3d,%3d",motor_set_left_top,motor_set_left_aft,motor_set_right_top,motor_set_right_aft);
//        printf("   pwm:%3d,%3d,%3d,%3d",pwm[0],pwm[1],pwm[2],pwm[3]);
//        printf("   speed %3d,%3d,%3d,%3d",speed[0],speed[1],speed[2],speed[3]);
//        printf("   mp:%3d,%3d,%3d,%3d",code_desk_left_top,code_desk_right_top,code_desk_left_aft,code_desk_right_aft);
//        printf("   vol:%d\n",HAL_ADC_GetValue(&hadc1));

       // printf("%d,%d,%d,%d\n\n",Set_MP[0],Set_MP[1],Set_MP[2],Set_MP[3]);
      
//        //发送给主车以及通信显示板的码盘    
//        u8 dat[]={0x02,((code_desk_left_top*4)&0xFF),(((code_desk_left_top*4) >>8)&0xFF),((code_desk_right_top*4)&0xFF),(((code_desk_right_top*4) >>8)&0xFF),0x00,(motor_volta)&0xFF,(motor_volta>>8)&0xFF};
//        u8 dat2[]={0x03,((code_desk_left_aft*4)&0xFF),(((code_desk_left_aft*4) >>8)&0xFF),((code_desk_right_aft*4)&0xFF),(((code_desk_right_aft*4) >>8)&0xFF),0x00,0x00,0x00};
//        CAN1_Send_Msg(dat,8,0x01E0,0);
//        CAN1_Send_Msg(dat2,8,0x01E1,0);
//        
//        u8 dat2[]={pwm[0],pwm[2],pwm[1],pwm[3],0x00,0x00,0x00,0x00};
//        CAN1_Send_Msg(dat2,8,0x01,0);

		
  }
}

主循环

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 */

  /* 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_ADC1_Init();
  MX_CAN_Init();
  MX_TIM2_Init();
  MX_TIM8_Init();
  MX_USART2_UART_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  MX_TIM1_Init();
  MX_TIM6_Init();
  /* USER CODE BEGIN 2 */
  
    HAL_TIM_Base_Start_IT(&htim6);
  

    HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);
    HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
    
    HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
    HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
    HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);
    
    HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_2);
    HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_3);

    //电机驱动芯片的睡眠关闭
    HAL_GPIO_WritePin(SLEEP_AB_GPIO_Port,SLEEP_AB_Pin,GPIO_PIN_SET);
    HAL_GPIO_WritePin(SLEEP_CD_GPIO_Port,SLEEP_CD_Pin,GPIO_PIN_SET);


    HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_1 | TIM_CHANNEL_2);
    HAL_TIM_Encoder_Start(&htim1,TIM_CHANNEL_1 | TIM_CHANNEL_2);



    HAL_Delay(2000);
    
    
    
    CAN1_Send_Msg("PID mode",8,0x3c0,0);   //上电默认pid模式
    CAN1_Send_Msg("\n",1,0x3c0,0);   //上电默认pid模式
    //printf("PID Mode\n");
    
    HAL_ADCEx_Calibration_Start(&hadc1);    //AD校准
    HAL_ADC_Start(&hadc1);
    
    
      // 读取RCC_CSR寄存器的值
      uint32_t resetFlags = RCC->CSR;
      printf("motor:");
      // 判断重启原因
      if ((resetFlags & RCC_CSR_SFTRSTF) != 0) {
        // 软件复位
        printf("Software Reset\n");
      } else if ((resetFlags & RCC_CSR_PORRSTF) != 0) {
        // 上电复位
        printf("Power-On Reset\n");
      } else if ((resetFlags & RCC_CSR_PINRSTF) != 0) {
        // 外部引脚复位
        printf("Pin Reset\n");
      } else if ((resetFlags & RCC_CSR_IWDGRSTF) != 0) {
        // 独立看门狗复位
        printf("Independent Watchdog Reset\n");
      } else if ((resetFlags & RCC_CSR_WWDGRSTF) != 0) {
        // 窗口看门狗复位
        printf("Window Watchdog Reset\n");
      } else if ((resetFlags & RCC_CSR_LPWRRSTF) != 0) {
        // 低功耗复位
        printf("Low-Power Reset\n");
      } else if ((resetFlags & RCC_CSR_RMVF) != 0) {
        // 电源复位
        printf("Brown-Out Reset\n");
      }
      
      // 清除复位标志
      RCC->CSR |= RCC_CSR_RMVF;

   
    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      if(key_scan()==1)
      {
          mode_flag++;
          switch(mode_flag)
          {
              case 0:CAN1_Send_Msg("PID mode\n",8,0x3c0,0);break;//发送到debug
              case 1:CAN1_Send_Msg("Common\n",8,0x3c0,0);break;
              case 2:CAN1_Send_Msg("Debug\n",6,0x3c0,0);set_motor(300,0,0,0);break;
              case 3:set_motor(0,300,0,0);break;
              case 4:set_motor(0,0,300,0);break;
              case 5:set_motor(0,0,0,300);break;
              case 6:set_motor(300,300,300,300);break;
              case 7:set_motor(0,0,0,0);break;             
              case 8:set_motor(-300,0,0,0);break;
              case 9:set_motor(0,-300,0,0);break;
              case 10:set_motor(0,0,-300,0);break;
              case 11:set_motor(0,0,0,-300);break;
              case 12:set_motor(-300,-300,-300,-300);break;
              case 13:set_motor(0,0,0,0);mode_flag=-1;break;
              
          }
         
      }


      HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
      
      
        //发送给主车以及通信显示板的码盘    
        u8 dat[]={0x02,((code_desk_left_top)&0xFF),(((code_desk_left_top) >>8)&0xFF),((code_desk_right_top)&0xFF),(((code_desk_right_top) >>8)&0xFF),0x00,(motor_volta)&0xFF,(motor_volta>>8)&0xFF};
        u8 dat2[]={0x03,((code_desk_left_aft)&0xFF),(((code_desk_left_aft) >>8)&0xFF),((code_desk_right_aft)&0xFF),(((code_desk_right_aft) >>8)&0xFF),0x00,0x00,0x00};
        
        
        CAN1_Send_Msg(dat,8,0x01E0,0);
        
      HAL_Delay(15);
        
        CAN1_Send_Msg(dat2,8,0x01F1,0);
            
            motor_volta = HAL_ADC_GetValue(&hadc1);

      
      
      
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

国赛完成,后面有机会开源hal库的主车程序,以及抛弃arduino后的从车stm32程序和视频循迹

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值