//Redirect serial port one int fputc(int ch,FILE *stream) { HAL_UART_Transmit( & amp;huart1,( uint8_t *) & amp;ch,1,0xFFFF); return ch; } //typedef struct __FILE FILE; When using printf, add #include<stdio.h>;
2. Serial port interrupt callback function
uint8_t g_ucUsart3ReceiveData; //Save the data received by serial port 3 main.c HAL_UART_Receive_IT( & amp;huart3, & amp;g_ucUsart3ReceiveData,1); //Serial port three receives data and is opened in main.c //Reimplement the serial port interrupt callback function in it.c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == & amp;huart3)//Determine the interrupt source { if(g_ucUsart3ReceiveData == 'A') motorPidSetSpeed(1,1);//Previous motion HAL_UART_Receive_IT( & amp;huart3, & amp;g_ucUsart3ReceiveData, 1);//Continue interrupt reception } } //Declare external variables in usart.c extern uint8_t g_ucUsart3ReceiveData; //Save the data received by serial port 3
3.pwm
HAL_TIM_PWM_Start( & amp;htim1,TIM_CHANNEL_1); // Turn on timer 1 channel 1 PWM output HAL_TIM_PWM_Start( & amp;htim1,TIM_CHANNEL_4); // Turn on timer 1 channel 4 PWM output __HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_1, 40);//Modify duty cycle
4. Level configuration
HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET);//Set AIN1 PB13 to low level HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_SET); //Set BIN1 PB3 to high level HAL_Delay(1000); //Twice will cause the motor to reverse direction. HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_SET);//Set AIN1 PB13 to high level HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_RESET); //Set BIN1 PB3 to low level
5. Motor
//Anti-redefinition function #ifndef MOTOR_H__ #define MOTOP_H__ #endif //Define macros to facilitate transplantation #define AIN1_RESET HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET)//Set Set AIN1 PB13 to low level #define AIN1_SET HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_SET)//Set AIN1 PB13 is high level #define BIN1_RESET HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_RESET) //Set BIN1 PB3 to low level #define BIN1_SET HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_SET)//Set AIN1 PB13 is high level //How the motor works void Motor_Set (int motor1,int motor2) { //Set the selection direction according to the positive and negative parameters if(motor1 < 0) BIN1_SET; else BIN1_RESET; if(motor2 < 0) AIN1_SET; else AIN1_RESET; //motor1 sets the speed of motor B if(motor1 < 0) { if(motor1 < -99) motor1 = -99;//Exceeds PWM amplitude //When it is negative, the smaller the absolute value, the larger the PWM duty cycle. //Current motor1 -1 -99 //Give register or function 99 1 __HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_1, (100 + motor1));//Modify timer 1 Channel 1 PA8 Pulse changes duty cycle } else{ if(motor1 > 99) motor1 = 99; //Now it is 0 1 99 //We assign the value 0 1 99 __HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_1, motor1);//Modify timer 1 channel 1 PA8 Pulse changes duty cycle } //motor2 sets the speed of motor A if(motor2 < 0) { if(motor2 < -99) motor2 = -99;//Exceeds PWM amplitude //When it is negative, the smaller the absolute value is, the larger the PWM duty cycle is. //Current motor2 -1 -99 //Give register or function 99 1 __HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_4, (100 + motor2));//Modify timer 1 pass Channel 4 PA11 Pulse changes the duty cycle } else{ if(motor2 > 99) motor2 = 99; //Now it is 0 1 99 //We assign the value 0 1 99 __HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_4, motor2);//Modify timer 1 channel 4 PA11 Pulse changes duty cycle } }
6.OLED:
The two pins of OLED
7. Enable timer and scheduled interrupt for encoder speed measurement
HAL_TIM_Encoder_Start( & amp;htim2,TIM_CHANNEL_ALL);//Start timer 2 encoder speed measurement HAL_TIM_Encoder_Start( & amp;htim4,TIM_CHANNEL_ALL);//Start timer 4 HAL_TIM_Base_Start_IT( & amp;htim2); //Enable timer 2 interrupt HAL_TIM_Base_Start_IT( & amp;htim4); //Enable timer 4 interrupt HAL_TIM_Base_Start_IT( & amp;htim1); //Enable timer 1 interrupt //Defined variables placed in stm32f1xx_it.c short Encode1Count = 0;// short Encode2Count = 0; float Motor1Speed = 0.00; float Motor2Speed = 0.00; uint16_t TimerCount=0; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == & amp;htim1)//htim1 500HZ 2ms interrupt once { TimerCount + + ; if(TimerCount %5 == 0)//Execute once every 10ms { Encode1Count = (short)__HAL_TIM_GET_COUNTER( & amp;htim4); Encode2Count = (short)__HAL_TIM_GET_COUNTER( & amp;htim2); __HAL_TIM_SET_COUNTER( & amp;htim4,0); __HAL_TIM_SET_COUNTER( & amp;htim2,0); Motor1Speed = (float)Encode1Count*100/9.6/11/4; Motor2Speed = (float)Encode2Count*100/9.6/11/4; TimerCount=0; } } }
8. Redirect fputc
int fputc(int ch,FILE *stream) { HAL_UART_Transmit( & amp;huart1,( uint8_t *) & amp;ch,1,0xFFFF); return ch; }
9.Bluetooth control speed
extern uint8_t g_ucUsart3ReceiveData; //Save the data received by serial port 3 int InitSpeed = 50; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == & amp;huart3) { if(g_ucUsart3ReceiveData == 'U') { InitSpeed + = 5; if(InitSpeed >= 100) InitSpeed=100; MotorGo(InitSpeed); } if(g_ucUsart3ReceiveData == 'D') { InitSpeed -= 5; if(InitSpeed <= 0) InitSpeed=0; MotorGo(InitSpeed); } HAL_UART_Receive_IT( & amp;huart3, & amp;g_ucUsart3ReceiveData, 1);//Continue interrupt reception } \t }
10.pid parameter adjustment:
//in the .h file #ifndef __PID_H #define __PID_H //Declare a structure type typedef struct { float target_val;//target value float actual_val;//actual value float err;//Current deviation float err_last;//Last deviation float err_sum;//Error cumulative value float Kp,Ki,Kd;//proportion, integral, differential coefficient } tPid; //Declare function float P_realize(tPid * pid, float actual_val); void PID_init(void); float PI_realize(tPid * pid, float actual_val); float PID_realize(tPid * pid, float actual_val); #endif //.c file #include "pid.h" //Define a structure type variable tPid pidMotor1Speed; //Assign initial value to structure type variable void PID_init() { pidMotor1Speed.actual_val=0.0; pidMotor1Speed.target_val=5; pidMotor1Speed.err=0.0; pidMotor1Speed.err_last=0.0; pidMotor1Speed.err_sum=0.0; pidMotor1Speed.Kp=10; pidMotor1Speed.Ki=5; pidMotor1Speed.Kd=0; } //PID control function float PID_realize(tPid * pid, float actual_val) { pid->actual_val = actual_val;//Pass the real value pid->err = pid->target_val - pid->actual_val; current error = target value - actual value pid->err_sum + = pid->err;//Error cumulative value = current error cumulative sum //Use PID control output = Kp*current error + Ki*accumulated error value + Kd*(current error-last error) pid->actual_val = pid->Kp*pid->err + pid->Ki*pid->err_sum + pid->Kd*(pid->err - pid->err_last); //Save the last error: assign this error to the last error pid->err_last = pid->err; return pid->actual_val; } //In the interrupt function if(TimeCount ==0)//Every 20ms { MotorGo(PID_realize( & amp;pidMotor1Speed,MotorSpeed)); TimeCount=0; } extern tPid pidMotor1Speed;//Declare structure variables PID_init();//Initialization in .c file