久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4133|回復: 3
收起左側

基于stm32f103rct6的PID算法控制四驅車程序—基于HAL庫的

[復制鏈接]
ID:507807 發表于 2019-7-30 20:41 | 顯示全部樓層 |閱讀模式
STM32F103RCT6PID算法控制四個電機,基于HAL,希望可以給各位一些幫助,僅供參考,請勿他用

單片機源程序如下:
  1. /* USER CODE END Header */

  2. /* Includes ------------------------------------------------------------------*/
  3. #include "main.h"
  4. #include "dma.h"
  5. #include "tim.h"
  6. #include "usart.h"
  7. #include "gpio.h"

  8. /* Private includes ----------------------------------------------------------*/
  9. /* USER CODE BEGIN Includes */
  10. #include "string.h"
  11. #include "Motr_conter.h"
  12. #include "pid.h"
  13. /* USER CODE END Includes */

  14. /* Private typedef -----------------------------------------------------------*/
  15. /* USER CODE BEGIN PTD */

  16. /* USER CODE END PTD */

  17. /* Private define ------------------------------------------------------------*/
  18. /* USER CODE BEGIN PD */

  19. /* USER CODE END PD */

  20. /* Private macro -------------------------------------------------------------*/
  21. /* USER CODE BEGIN PM */

  22. /* USER CODE END PM */

  23. /* Private variables ---------------------------------------------------------*/

  24. /* USER CODE BEGIN PV */

  25. /* USER CODE END PV */

  26. /* Private function prototypes -----------------------------------------------*/
  27. void SystemClock_Config(void);
  28. /* USER CODE BEGIN PFP */

  29. /* USER CODE END PFP */

  30. /* Private user code ---------------------------------------------------------*/
  31. /* USER CODE BEGIN 0 */
  32.                                                
  33. uint8_t Left_Front_or_Right_rear;                        //用于保存電機行駛方向的變量
  34. uint8_t RX_buff[100],Start_Flag=0;                //接收緩沖區,和電機運行開始的標志位
  35. int16_t pwm_duth_A=0,pwm_duth_B=0,pwm_duth_C=0,pwm_duth_D=0;//四個電機的pwm變量
  36. uint16_t save_Ecoder_A=0,save_Ecoder_B=0,save_Ecoder_C=0,save_Ecoder_D=0;        //保存四個電機的編碼值

  37. extern PID sPID;                        //PID結構體變量,用于改變目標值
  38. /* USER CODE END 0 */

  39. /**
  40.   * @brief  The application entry point.
  41.   * @retval int
  42.   */
  43. int main(void)
  44. {
  45.   /* USER CODE BEGIN 1 */
  46. uint8_t TX_buff[500]={"今天是個好日子,天氣有點涼快!!\n"};

  47.   /* USER CODE END 1 */
  48.   

  49.   /* MCU Configuration--------------------------------------------------------*/

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

  52.   /* USER CODE BEGIN Init */

  53.   /* USER CODE END Init */

  54.   /* Configure the system clock */
  55.   SystemClock_Config();

  56.   /* USER CODE BEGIN SysInit */

  57.   /* USER CODE END SysInit */

  58.   /* Initialize all configured peripherals */
  59.   MX_GPIO_Init();                                                //GPIO的初始化
  60.   MX_DMA_Init();                                                //DMA的初始化
  61.   MX_TIM2_Init();                                                //定時器2的初始化
  62.   MX_USART1_UART_Init();                //串口1的初始化
  63.   MX_TIM1_Init();                                                //定時器1的初始化
  64.   MX_TIM6_Init();                                                //定時器6的初始化
  65. MX_USART2_UART_Init();                        //串口2的初始化
  66.   MX_TIM3_Init();                                                //定時器3的初始化
  67.   MX_TIM4_Init();                                                //定時器4的初始化
  68.   MX_TIM5_Init();                                                //定時器5的初始化
  69.   MX_TIM8_Init();                                                //定時器8的初始化
  70.   /* USER CODE BEGIN 2 */
  71.         Motor_Stop;                                                                //電機初始化狀態位停止的
  72.         HAL_TIM_Base_Start_IT(&htim6);                                                                                                                                        //啟動定時器
  73.         HAL_UART_Transmit(&huart2,TX_buff,strlen((char*)TX_buff),1000);        //串口2發送一串數據,表示串口2工作正常
  74.         HAL_UART_Transmit(&huart1,TX_buff,strlen((char*)TX_buff),100);        //串口發送數據測試        ,表示串口1工作正常
  75.         printf("電機編碼器測試,測試通過\n");                                                                                                                //發送實驗測試名稱
  76.         IncPIDInit();                                                                                                                                                                                                                //pPID參數初始化
  77.         HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);                                                                //開始電機D編碼器接口計數
  78.         HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);                                                                //開啟電機C的編碼器接口計數
  79.         HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_ALL);                                                                //開啟電機B的編碼器接口計數
  80.         HAL_TIM_Encoder_Start(&htim5,TIM_CHANNEL_ALL);                                                                //開啟電機C的編碼器接口計數
  81.         HAL_UART_Receive_DMA(&huart2,RX_buff,5);                                                                                        //開啟串口2的DMA接收數據
  82.   /* USER CODE END 2 */

  83.   /* Infinite loop */
  84.   /* USER CODE BEGIN WHILE */
  85.   while (1)
  86.   {
  87.     /* USER CODE END WHILE */

  88.     /* USER CODE BEGIN 3 */
  89.                 if(RX_buff[0]==0x31)
  90.                 {
  91.                         if(RX_buff[1]==0x31&&RX_buff[2]==0x31&&RX_buff[3]==0x31)        Derection_Control(1,3,1,3);                                //左前行駛
  92.                 }
  93.                 if(RX_buff[0]==0x32)
  94.                 {
  95.                         if(RX_buff[1]==0x32&&RX_buff[2]==0x32&&RX_buff[3]==0x32)        Derection_Control(1,1,1,1);                                //向前行駛
  96.                 }
  97.                 if(RX_buff[0]==0x33)
  98.                 {
  99.                         if(RX_buff[1]==0x33&&RX_buff[2]==0x33&&RX_buff[3]==0x33)        Derection_Control(3,1,3,1);                                //右前行駛
  100.                 }
  101.                 if(RX_buff[0]==0x34)
  102.                 {
  103.                         if(RX_buff[1]==0x34&&RX_buff[2]==0x34&&RX_buff[3]==0x34)        Derection_Control(1,2,1,2);                                //向左平行行駛
  104.                 }
  105.                 if(RX_buff[0]==0x35)
  106.                 {
  107.                         if(RX_buff[1]==0x35&&RX_buff[2]==0x35&&RX_buff[3]==0x35)        Derection_Control(1,2,2,1);                                //順時針旋轉
  108.                 }
  109.                 if(RX_buff[0]==0x36)
  110.                 {
  111.                         if(RX_buff[1]==0x36&&RX_buff[2]==0x36&&RX_buff[3]==0x36)        Derection_Control(2,1,2,1);                                //向右平行行駛
  112.                 }
  113.                 if(RX_buff[0]==0x37)
  114.                 {
  115.                         if(RX_buff[1]==0x37&&RX_buff[2]==0x37&&RX_buff[3]==0x37)        Derection_Control(3,2,3,2);                                //左后行駛
  116.                 }
  117.                 if(RX_buff[0]==0x38)
  118.                 {
  119.                         if(RX_buff[1]==0x38&&RX_buff[2]==0x38&&RX_buff[3]==0x38)        Derection_Control(2,2,2,2);                                //向后行駛
  120.                 }
  121.                 if(RX_buff[0]==0x39)
  122.                 {
  123.                         if(RX_buff[1]==0x39&&RX_buff[2]==0x39&&RX_buff[3]==0x39)        Derection_Control(2,3,2,3);                                //右后行駛
  124.                 }
  125.                 if(RX_buff[0]==0x30)
  126.                 {
  127.                         if(RX_buff[1]==0x30&&RX_buff[2]==0x30&&RX_buff[3]==0x30)        Derection_Control(2,1,1,2);                                //逆時針旋轉
  128.                 }
  129.                 if(RX_buff[0]==0x2E)
  130.                 {
  131.                         if(RX_buff[1]==0x31&&RX_buff[2]==0x32&&RX_buff[3]==0x33)        {Derection_Control(3,3,3,3);        }                //停止
  132.                 }
  133.                 if(RX_buff[0]==0x2B)
  134.                 {
  135.                         sPID.SetPoint_A=sPID.SetPoint_B=sPID.SetPoint_C=sPID.SetPoint_D=(RX_buff[1]-0x30)*1000+(RX_buff[2]-0x30)*100+(RX_buff[3]-0x30)*10+(RX_buff[4]-0x30);                //設置行駛的速度
  136.                 }                       
  137.   }
  138.   /* USER CODE END 3 */
  139. }

  140. /**
  141.   * @brief System Clock Configuration
  142.   * @retval None
  143.   */
  144. void SystemClock_Config(void)
  145. {
  146.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  147.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  148.   /** Initializes the CPU, AHB and APB busses clocks
  149.   */
  150.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  151.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  152.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  153.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  154.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  155.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  156.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  157.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  158.   {
  159.     Error_Handler();
  160.   }
  161.   /** Initializes the CPU, AHB and APB busses clocks
  162.   */
  163.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  164.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  165.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  166.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  167.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  168.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  169.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  170.   {
  171.     Error_Handler();
  172.   }
  173.   /** Enables the Clock Security System
  174.   */
  175.   HAL_RCC_EnableCSS();
  176. }

  177. /* USER CODE BEGIN 4 */
  178.         uint8_t direction_A,direction_B,direction_C,direction_D;                                        //保存四個電機方向的變量
  179.         uint32_t Code_val_A=0,Code_val_B=0,Code_val_C=0,Code_val_D=0;                        //保存四個編碼器計數器的的值
  180.         uint16_t last_Code_val_A=0,last_Code_val_B=0,last_Code_val_C=0,last_Code_val_D=0;//保存上一秒計數器的值,與下一秒的相比較到底計數了多少次
  181. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  182. {                                                                        
  183.        
  184.         if(htim->Instance==TIM6)                                                                                                        //判斷是不是定時器6達到更新事件
  185.         {
  186.                 if(Start_Flag==1)                                                                                                                                //判斷電機的行駛標志位
  187.                 {
  188.                 direction_A=__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim5);//獲取電機A轉動的方向
  189.                 direction_B=__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim4);//獲取電機B 的旋轉方向
  190.                 direction_C=__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);//獲取電機C 的旋轉方向
  191.                 direction_D=__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2);//獲取電機D的旋轉方向
  192.                 Code_val_A=__HAL_TIM_GET_COUNTER(&htim5);                                                //讀取電機A的計數器的值
  193.                 Code_val_B=__HAL_TIM_GET_COUNTER(&htim4);                                                //讀取電機B的計數器的值
  194.                 Code_val_C=__HAL_TIM_GET_COUNTER(&htim3);                                                //讀取電機C的計數器的值
  195.                 Code_val_D=__HAL_TIM_GET_COUNTER(&htim2);                                                //讀取電機D的計數器的值
  196.                 if(direction_A==0)  save_Ecoder_A=(Code_val_A>=last_Code_val_A?Code_val_A-last_Code_val_A:Code_val_A+65535-last_Code_val_A);                                                                                                 //方向為正定時器向上計數
  197.                 if(direction_A==1)        save_Ecoder_A=(Code_val_A>last_Code_val_A?last_Code_val_A+65535-Code_val_A:last_Code_val_A-Code_val_A);                                                                                                        //方向為反轉代表計數器是向下計數                       
  198.                 if(direction_B==0)  save_Ecoder_B=(Code_val_B>=last_Code_val_B?Code_val_B-last_Code_val_B:Code_val_B+65535-last_Code_val_B);                                                                                                 //方向為正定時器向上計數
  199.                 if(direction_B==1)        save_Ecoder_B=(Code_val_B>last_Code_val_B?last_Code_val_B+65535-Code_val_B:last_Code_val_B-Code_val_B);                                                                                                        //方向為反轉代表計數器是向下計數
  200.                 if(direction_C==0)  save_Ecoder_C=(Code_val_C>=last_Code_val_C?Code_val_C-last_Code_val_C:Code_val_C+65535-last_Code_val_C);                                                                                                 //方向為正定時器向上計數
  201.                 if(direction_C==1)        save_Ecoder_C=(Code_val_C>last_Code_val_C?last_Code_val_C+65535-Code_val_C:last_Code_val_C-Code_val_C);                                                                                                        //方向為反轉代表計數器是向下計數
  202.                 if(direction_D==0)  save_Ecoder_D=(Code_val_D>=last_Code_val_D?Code_val_D-last_Code_val_D:Code_val_D+65535-last_Code_val_D);                                                                                                 //方向為正定時器向上計數
  203.                 if(direction_D==1)        save_Ecoder_D=(Code_val_D>last_Code_val_D?last_Code_val_D+65535-Code_val_D:last_Code_val_D-Code_val_D);                                                                                                        //方向為反轉代表計數器是向下計數
  204.                 if(Left_Front_or_Right_rear==0)                                                        //如果小車是按照前后左右的某一個方向行駛,將ABCD四個電機進行PID控制
  205.                 {
  206.                 pwm_duth_A+=(IncPIDCalc_C(save_Ecoder_A));        //電機A的PID算法值返回
  207.                 pwm_duth_B+=(IncPIDCalc_B(save_Ecoder_B));        //電機B的PID算法值返回
  208.                 pwm_duth_C+=(IncPIDCalc_C(save_Ecoder_C));        //電機C的PID算法值返回
  209.                 pwm_duth_D+=(IncPIDCalc_D(save_Ecoder_D));        //電機D的PID算法值返回
  210.                 }
  211.                 if(Left_Front_or_Right_rear==1)                                                                        //電機向左前或者右后行駛
  212.                 {
  213.                         pwm_duth_A+=(IncPIDCalc_C(save_Ecoder_A));                //就只進行電機AC的PID算法,不進行電機BD的算法
  214.                         pwm_duth_C+=(IncPIDCalc_C(save_Ecoder_C));                //就只進行電機AC的PID算法,不進行電機BD的算法
  215.                 }                       
  216.                 if(Left_Front_or_Right_rear==2)                                                                        //電機向右前或者左后行駛
  217.                 {
  218.                         pwm_duth_B+=(IncPIDCalc_B(save_Ecoder_B));                //就只進行電機BD的PID算法,不進行電機AC的PID算法
  219.                         pwm_duth_D+=(IncPIDCalc_D(save_Ecoder_D));                //就只進行電機BD的PID算法,不進行電機AC的PID算法
  220.                 }
  221.                 if(pwm_duth_A<0) pwm_duth_A=-pwm_duth_A;                                //處理電機A,當PWM值為負時變為正
  222.                 if(pwm_duth_B<0) pwm_duth_B=-pwm_duth_B;                                //處理電機B,當PWM值為負時變為正
  223.                 if(pwm_duth_C<0) pwm_duth_C=-pwm_duth_C;                                //處理電機C,當PWM值為負時變為正       
  224.                 if(pwm_duth_D<0) pwm_duth_D=-pwm_duth_D;                                //處理電機D,當PWM值為負時變為正
  225.                 if(pwm_duth_A>=7199)        pwm_duth_A=7200*4/6;                        //限制電機A的速度為最大占空比的百分之六十六
  226.                 if(pwm_duth_B>=7199)        pwm_duth_B=7200*4/6;                        //限制電機B的速度為最大占空比的百分之六十六                               
  227.                 if(pwm_duth_C>=7199)        pwm_duth_C=7200*4/6;                        //限制電機C的速度為最大占空比的百分之六十六
  228.                 if(pwm_duth_D>=7199)        pwm_duth_D=7200*4/6;                        //限制電機D的速度為最大占空比的百分之六十六
  229.                 Set_compare(motor_A,pwm_duth_A);                                                                //將電機A經過PID算法之后得到的PWM賦給電機,讓電機真正的按照目標運行起來
  230.                 Set_compare(motor_B,pwm_duth_B);                                                                //將電機B經過PID算法之后得到的PWM賦給電機,讓電機真正的按照目標運行起來
  231.                 Set_compare(motor_C,pwm_duth_C);                                                                //將電機C經過PID算法之后得到的PWM賦給電機,讓電機真正的按照目標運行起來
  232.                 Set_compare(motor_D,pwm_duth_D);                                                                //將電機D經過PID算法之后得到的PWM賦給電機,讓電機真正的按照目標運行起來
  233.                 last_Code_val_A=Code_val_A;                                                                                        //保存電機A的編碼值,便于進行脈沖值的計算
  234.                 last_Code_val_B=Code_val_B;                                                                                        //保存電機B的編碼值,便于進行脈沖值的計算
  235.                 last_Code_val_C=Code_val_C;                                                                                        //保存電機C的編碼值,便于進行脈沖值的計算
  236.                 last_Code_val_D=Code_val_D;                                                                                        //保存電機D的編碼值,便于進行脈沖值的計算

  237.                 }
  238.         }
  239. }




  240. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  241. {
  242.         if(huart->Instance==USART1)                                                                                                                        //判斷是不是串口1接收完成
  243.         {
  244. //                        HAL_UART_Receive_IT(&huart1,RX_buff,8);
  245.         }
  246.         if(huart->Instance==USART2)                                                                                                                        //判斷是否是串口2接收完成
  247.         {

  248.                 HAL_UART_Transmit_DMA(&huart2,RX_buff,5);                                                //DMA發送數據
  249.         }
  250. }
  251. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)                        //發送完成回調函數
  252. {
  253.         if(huart->Instance==USART2)
  254.         {
  255.                 HAL_UART_Receive_DMA(&huart2,RX_buff,5);                                                                //使能DMA接收數據
  256.         }
  257. }
  258. /* USER CODE END 4 */

  259. /**
  260.   * @brief  This function is executed in case of error occurrence.
  261.   * @retval None
  262.   */
  263. void Error_Handler(void)
  264. {
  265.   /* USER CODE BEGIN Error_Handler_Debug */
  266.   /* User can add his own implementation to report the HAL error return state */

  267.   /* USER CODE END Error_Handler_Debug */
  268. }

  269. #ifdef  USE_FULL_ASSERT
  270. /**
  271.   * @brief  Reports the name of the source file and the source line number
  272.   *         where the assert_param error has occurred.
  273.   * @param  file: pointer to the source file name
  274.   * @param  line: assert_param error line source number
  275.   * @retval None
  276.   */
  277. void assert_failed(uint8_t *file, uint32_t line)
  278. {
  279.   /* USER CODE BEGIN 6 */
  280.   /* User can add his own implementation to report the file name and line number,
  281.      tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  282.   /* USER CODE END 6 */
  283. }
  284. #endif /* USE_FULL_ASSERT */

  285. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
復制代碼

所有資料51hei提供下載:
藍牙+PID控制的小車.7z (264.82 KB, 下載次數: 91)
回復

使用道具 舉報

ID:1 發表于 2019-7-30 23:28 | 顯示全部樓層
本帖需要重新編輯補全電路原理圖,源碼,詳細說明與圖片即可獲得100+黑幣(帖子下方有編輯按鈕)
回復

使用道具 舉報

ID:584531 發表于 2019-8-17 14:45 | 顯示全部樓層
膜拜大佬
回復

使用道具 舉報

ID:80689 發表于 2019-9-28 20:37 | 顯示全部樓層
資料注釋很詳細!贊!!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 99精品在线 | 在线观看黄色电影 | 亚洲综合成人网 | 成人性生交大免费 | 91久久久www播放日本观看 | 国产精品1区 | 极情综合网 | 国产一区欧美 | 少妇一区二区三区 | 欧洲一区二区视频 | 国产精品99久 | www.操.com | 日本韩国电影免费观看 | 成人在线视频观看 | 国产一级片免费在线观看 | 91在线视频在线观看 | 高清欧美性猛交xxxx黑人猛交 | 国产成人麻豆免费观看 | 日本一区二区高清视频 | 亚洲精品乱码久久久久久按摩观 | 男女啪啪高潮无遮挡免费动态 | 91极品欧美视频 | 亚洲一区高清 | 日本免费视频 | 中文字幕不卡在线观看 | 欧美大片一区 | 91免费视频观看 | 日韩看片 | 99精品在线观看 | 免费高潮视频95在线观看网站 | 看a级黄色毛片 | 精品一区av| 国产日韩精品在线 | 欧美片网站免费 | 另类一区 | 国产精品国产三级国产aⅴ中文 | 成人18亚洲xxoo | 亚洲精品日韩精品 | 欧美一区二区三区在线视频 | 欧美综合精品 | 欧美天堂在线 |