stm32driver

Stm32 chassis motor drive

A, functionality,

  • 1. Equipped with FreeRTOS
  • 2, variable length data reception (IDLE+DMA)
  • 3, I2C display (motor parameters)
  • 4, incremental PI controller (DC coded motor)

Second, the overall structure

  • IO layout

  • FreeRTOSHeapUsage

  • Functional initialization

  • FreeRTOS run timing

Three, application peripherals

  • SystemCore
    • RCC
    • SYS
  • Timers
    • TIM2
    • TIM3
    • TIM4
  • Connectivity
    • I2C1
    • USART3
  • Middleware
    • FREERTOS

Four, detailed description

1, the FreeRTOS

  • freertos.c

Release only the task execution function, other content please refer to the source code

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartDefaultTask */
}

void StartTaskMotor(void *argument)
{
  /* USER CODE BEGIN StartTaskMotor */
  para_init();
  /* Infinite loop */
  for(;;)
  {
// TODO
    osDelay(10);
  }
  /* USER CODE END StartTaskMotor */
}

void StartTaskDisplay(void *argument)
{
  /* USER CODE BEGIN StartTaskDisplay */
  /* Infinite loop */
  for(;;)
  {
    // TODO
    osDelay(50);
  }
  /* USER CODE END StartTaskDisplay */
}

void StartTaskUsart(void *argument)
{
  /* USER CODE BEGIN StartTaskUsart */
  /* Infinite loop */
  for(;;)
  {
    // TODO
    osDelay(1);
  }
  /* USER CODE END StartTaskUsart */
}
Copy the code

2, variable length of data reception

  • usart.c
/* USER CODE BEGIN 0 */
#if 1
struct __FILE{
    int handle;
};
FILE __stdout;
// Define _sys_exit() to avoid semi-host mode
void _sys_exit(int x){
  x = x;
}
// Redefine the fputc function
int fputc(int ch, FILE *f){
  while((USART3->SR&0X40) = =0);  // Loop until the send is complete
  USART3->DR=(uint8_t)ch;
  return ch;
}
#endif
volatile uint8_t rx3_len = 0;  // The length of the received data
volatile uint8_t rec3_end_flag = 0;  // The data receiving completion mark
uint8_t rx3_buffer[BUFFER_SIZE] = {0};  // Receive the data cache array
/* USER CODE END 0 */
Copy the code
/* USER CODE BEGIN 1 */
void Usart3_IDLE(void) {  // IDLE reception of USART
  uint32_t tmp_flag = 0;
  uint32_t temp;
  tmp_flag = __HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE);  // Get the IDLE flag
  if((tmp_flag ! = RESET)){/ / idle
    __HAL_UART_CLEAR_IDLEFLAG(&huart3);  // Clear the flag bit
    HAL_UART_DMAStop(&huart3);  // Stop the DMA transfer
    temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);  // Get the number of data not transferred in DMA
    rx3_len =  BUFFER_SIZE - temp;  // The total number of received data is subtracted from the number of untransmitted data
    rec3_end_flag = 1;  // Accept complete flag position 1}}void DMA_Usart3_Send(uint8_t *buf,uint8_t len) {  // Serial port send encapsulation
  if(HAL_UART_Transmit_DMA(&huart3,buf,len) ! = HAL_OK) {// Check whether sending is normal. If there is an exception, enter the exception interrupt functionError_Handler(); }}/* USER CODE END 1 */
Copy the code
  • usart.h
/* USER CODE BEGIN Prototypes */
extern volatile uint8_t rx3_len;  // The length of the received data
extern volatile uint8_t rec3_end_flag; // The data receiving completion flag
extern uint8_t rx3_buffer[BUFFER_SIZE];  // Receive the data cache array
void DMA_Usart3_Send(uint8_t *buf,uint8_t len);  // Serial port send encapsulation
void Usart3_IDLE(void);
/* USER CODE END Prototypes */
Copy the code
  • stm32f1xx_it.c
/* USER CODE BEGIN Includes */
#include "usart.h"
/* USER CODE END Includes */
Copy the code
/* USER CODE BEGIN USART3_IRQn 0 */
Usart3_IDLE();
/* USER CODE END USART3_IRQn 0 */
Copy the code
  • main.c
/* USER CODE BEGIN 2 */
  // Start usart3
  __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
  HAL_UART_Receive_DMA(&huart3,rx3_buffer,BUFFER_SIZE);
  /* USER CODE END 2 */
Copy the code
  • freertos.c
/* USER CODE BEGIN Header_StartTaskUsart */
/**
* @brief Function implementing the myTaskUsart thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskUsart */
void StartTaskUsart(void *argument)
{
  /* USER CODE BEGIN StartTaskUsart */
  /* Infinite loop */
  for(;;)
  {
    if(rec3_end_flag) {  // Check whether the reception is complete
      HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);  // DEBUG
      Usart3_Handle();
    }
    osDelay(1);
  }
  /* USER CODE END StartTaskUsart */
}
Copy the code
void Usart3_Handle(a) {  // USART handler
  user_API(rx3_buffer, rx3_len);  // Analyze the data

  rx3_len = 0;  // Clear the count
  rec3_end_flag = 0;  // Clear the end of receive flag
  memset(rx3_buffer,0,rx3_len);
  HAL_UART_Receive_DMA(&huart3,rx3_buffer,BUFFER_SIZE);  // Open DMA receive again
}
Copy the code

3, I2C display

  • This section has been encapsulated as./Core/Src/User/oled*
  • Basic operation logic in freertos.c
void OLED_flash_data(a){
  show_info(motorInfo[0].ENC, 1+8*6.0);
  show_info(motorInfo[0].ADD, 1+8*6.1);
  show_info(motorInfo[0].TGT, 1+8*6.2);
  show_info(motorInfo[0].PWM, 1+8*6.3);
  show_info(motorInfo[1].ENC, 1+8*6.4);
  show_info(motorInfo[1].ADD, 1+8*6.5);
  show_info(motorInfo[1].TGT, 1+8*6.6);
  show_info(motorInfo[1].PWM, 1+8*6.7);
}
Copy the code

4. Incremental PI controller

  • This section has been encapsulated as./Core/Src/User/motor*
  • Basic operation logic in freertos.c
void StartTaskMotor(void *argument)
{
  /* USER CODE BEGIN StartTaskMotor */
  para_init();
  /* Infinite loop */
  for(;;)
  {
    check_ENC(&motorInfo[0], &motorInfo[1]);
// plus_ADD(&motorInfo[0], &motorInfo[1]);
    incremental_PI_A(&motorInfo[0]);
    incremental_PI_B(&motorInfo[1]);
    range_PWM(&motorInfo[0], &motorInfo[1].7000);
    set_PWM(&motorInfo[0], &motorInfo[1]);
    osDelay(10);
  }
  /* USER CODE END StartTaskMotor */
}
Copy the code

Five, as the use of the next machine

115200 Serial port communication format [00+0+0]

  • [0-100) = total throttle
  • If ws is down, w is down +1, s is down -1, if not +0, both are down -0
  • If AD is pressed down, a is pressed down +1, D is pressed down -1, if not +0, both are pressed down -0

Vi. Project address

Github.com/causehhc/st…