STM32F407控制CANopen從站
前面我有篇文章——CAN&CANopen,講清楚了CAN通訊是怎么一回事,沒有舉具體的例子,這篇文章我就用一個具體的例子,讓大家更好的理解具體是怎么用,
硬體準備:STM32F407ZGT6開發板+ IXXAT CAN卡+支持CANopen通訊的驅動器
目標效果:STM32通過CAN口控制驅動器完成PPM和CSP模式的運動控制,對PPM和CSP模式沒有概念的參我的另一篇文章——我理解的運動控制系統,里面有詳細介紹,
首先,完成STM32的基本配置,我用的cubeMX,這個弄起來快,
第一步,系統時鐘配置,注意紅框標記的地方,我的HSE是8Mhz的,根據你的開發板修改,F407支持的最高頻率是168Mhz,不可超過,關于時鐘配置的細節可以參官方的參考手冊,這里不展開講了,

第二步,配置HSE為陶瓷晶振,

第三步,配置下載和除錯介面,

第四步,CAN控制配置,我設定的波特率是1Mbps,這也是CAN總線支持的最高通訊速率,CAN總線上的所有設備波特率必須一樣,這是能通訊的前提,不然解出來的都是錯誤幀,還要使能CAN的接收中斷,


第五步,配置USART,這個是為了除錯方便和接收控制命令用的,

使能USART的中斷

USART的發送和接收都是DMA傳輸,網傳接收和發送的DMA不可以同時使用,實測可以解決,DMA非常方便,

第六步,配置TIMER,這個是CSP模式定時發送資料用的,總線是168Mhz的,168-1的預分頻之后就是1Mhz,向上計數10000就是10ms,

需要開啟TIM6的中斷

第七步,工程配置,我用的KEIL,在工具鏈中選擇MDK-ARM,版本V5,

代碼生成配置,選擇所有已用的庫到工程,每個外設配置生成單獨的.c/.h檔案,方便查看和管理,再次生產代碼前先備份,再次生成前保留用戶代碼,這個一定要選,并且還要寫在用戶代碼區,不然重生成后代碼都被洗掉了,不再需要的配置再重生成代碼的時候洗掉,這個可選,檔案少編譯的更快,把所有沒有使用的引腳都設定為模擬模式,這樣可以減少功耗,

第八步,點擊GENERATE CODE生成代碼,然后用你的IDE打開工程,
到這里cubeMX的配置就已經完成了,接下來就直接開始在IDE中上代碼了,
CAN控制器的初始化中沒有配置CAN的濾波器,這個需要我們手動配置,代碼放在can.c的void MX_CAN1_Init(void)函式中,如下:
/* USER CODE BEGIN CAN1_Init 2 */
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.SlaveStartFilterBank = 14;
if(HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig))
{
Error_Handler();
}
HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
/* USER CODE END CAN1_Init 2 */
這里說下濾波器配置的兩種模式,一個是串列模式,一個是掩碼模式,串列模式就是ID在串列中的報文可以通過,其他的都不能通過,不在串列中的都不能通過,這個比較好理解,掩碼模式就是掩碼暫存器中對應bit為1的表示關心,報文中ID的對應bit位也必須為1;掩碼暫存器中對應bit為0的表示不關心,報文ID的對應bit位可為0或1,如現在配置的都是0x0000,表示任何ID的資料都接收,因為現在是把STM32做CANopen的master,需要接收總線上的所有資料,最后一行HAL_CAN_ActivateNotification是為了使能接收郵箱的中斷,
接下來就是初始化各個外設,這里遇到兩個坑,第一個是DMA的初始化要在使用DMA的外設之前,不然就不會成功,第二個是使能定時器中斷的時候要先停止定時器中斷,追溯源代碼發現是函式有個狀態沒復位,停止中斷的函式里面將這個狀態復位了,這個可能與韌體版本有關,我這個V1.27.0是這樣,STM32G474的庫也不需要這樣操作,USART的DMA接收我用了擴展函式HAL_UARTEx_ReceiveToIdle_DMA,這個非常方便,
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_TIM6_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim6);
HAL_TIM_Base_Stop_IT(&htim6); // stop_IT function is necessary ,for reset state ,else TIMER won't work
HAL_TIM_Base_Start_IT(&htim6);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,uart_rx_data,uart_rx_max);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
HAL_CAN_Start(&hcan1);
/* USER CODE END 2 */
到這里,主要的配置就已經完成了,接下來就是細化各個功能函式了,不再詳細介紹,我直接把main.c的代碼全部復制到文章末尾了,可以直接復制去測驗和研究,
本文只是拋磚引玉的介紹了怎樣配置和使用STM32F407的CAN控制器,怎樣發送CAN報文去控制從站驅動器,沒有涉及到整個CANopen主站的協議,如網路管理,錯誤處理這些都沒有做,對于特定的專案我覺得可以根據需要去設計功能,不一定要實作協議的全部細節,后續有時間再弄個完整的CANopen master協議堆疊,關于驅動器除錯和配置部分這里沒有涉及,參見對于驅動器廠家的除錯和使用說明即可,文章中比較陌生的名詞,可以參見我的另外兩篇文章-——我理解的運動控制系統和CAN&CANopen,
CAN與CANOPEN - Let'sDoSomething - 博客園 (cnblogs.com)
我理解的運動控制系統 - Let'sDoSomething - 博客園 (cnblogs.com)
1 /* USER CODE BEGIN Header */ 2 /** 3 ****************************************************************************** 4 * @file : main.c 5 * @brief : Main program body 6 ****************************************************************************** 7 * @attention 8 * 9 * Copyright (c) 2022 STMicroelectronics. 10 * All rights reserved. 11 * 12 * This software is licensed under terms that can be found in the LICENSE file 13 * in the root directory of this software component. 14 * If no LICENSE file comes with this software, it is provided AS-IS. 15 * 16 ****************************************************************************** 17 */ 18 /* USER CODE END Header */ 19 /* Includes ------------------------------------------------------------------*/ 20 #include "main.h" 21 #include "can.h" 22 #include "dma.h" 23 #include "tim.h" 24 #include "usart.h" 25 #include "gpio.h" 26 27 /* Private includes ----------------------------------------------------------*/ 28 /* USER CODE BEGIN Includes */ 29 #include "stdio.h" 30 #include "string.h" 31 /* USER CODE END Includes */ 32 33 /* Private typedef -----------------------------------------------------------*/ 34 /* USER CODE BEGIN PTD */ 35 36 /* USER CODE END PTD */ 37 38 /* Private define ------------------------------------------------------------*/ 39 /* USER CODE BEGIN PD */ 40 /* USER CODE END PD */ 41 42 /* Private macro -------------------------------------------------------------*/ 43 /* USER CODE BEGIN PM */ 44 45 /* USER CODE END PM */ 46 47 /* Private variables ---------------------------------------------------------*/ 48 49 /* USER CODE BEGIN PV */ 50 uint8_t testData[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; 51 //CAN transmit data field, 8 bytes 52 uint8_t object_data[8]={0}; 53 //CSP mode conuts, work until CSP_num > CSP_MAX_NUM 54 uint8_t CSP_num = 0; 55 //csp mode max number, generate CSP_pos relatively 56 uint8_t CSP_MAX_NUM = 61; 57 //CSP_flag, 0 means unused/finished, 1 means CSP is working 58 uint8_t CSP_flag = 0; 59 //CAN transmit mailbox 60 uint32_t TxMailBox = CAN_TX_MAILBOX0; 61 //CAN transmit frame struct 62 CAN_TxHeaderTypeDef TxHeader; 63 //for CAN communication store data 64 uint8_t RxData[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 65 //store CAN receive data temporarily, convert byte to int used 66 uint8_t can_Frame_DataField[4] ={0}; 67 //store CAN communication PDO data temporarily ,length could be longer/shorter ,upon PDO length 68 uint8_t PDO_DataField[4] = {0}; 69 //CAN Receive frame struct 70 CAN_RxHeaderTypeDef RxHeader; 71 //CAN receive flag ,set by can_receive interrupt ,reset by other function 72 uint8_t can_receive_flag = 0; 73 //store uart receive data 74 uint8_t uart_rx_data[]={0}; 75 //max uart receive length 76 uint16_t uart_rx_max = 255; 77 //store result for ConvertInttoFourByte function 78 uint8_t byte_value[4] = {0}; 79 //store CSP mode position points 80 int32_t CSP_Pos[61]={0}; 81 //CSP mode acceleration, larger and faster , smaller and slower 82 uint32_t acc = 5; 83 84 /* USER CODE END PV */ 85 86 /* Private function prototypes -----------------------------------------------*/ 87 void SystemClock_Config(void); 88 /* USER CODE BEGIN PFP */ 89 void CAN_sendTxMessage(uint32_t std_id,uint32_t length,uint8_t data[]); 90 void ConvertIntTo4Byte(int32_t source); 91 int32_t ConvertByteToInt(uint8_t *byte_source); 92 void do_a_PPM_Motion(); 93 void do_a_CSP_Motion(); 94 void RPDO1_Mapping(); 95 96 /* USER CODE END PFP */ 97 98 /* Private user code ---------------------------------------------------------*/ 99 /* USER CODE BEGIN 0 */ 100 101 /* USER CODE END 0 */ 102 103 /** 104 * @brief The application entry point. 105 * @retval int 106 */ 107 int main(void) 108 { 109 /* USER CODE BEGIN 1 */ 110 111 /* USER CODE END 1 */ 112 113 /* MCU Configuration--------------------------------------------------------*/ 114 115 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 116 HAL_Init(); 117 118 /* USER CODE BEGIN Init */ 119 120 /* USER CODE END Init */ 121 122 /* Configure the system clock */ 123 SystemClock_Config(); 124 125 /* USER CODE BEGIN SysInit */ 126 127 /* USER CODE END SysInit */ 128 /* Initialize all configured peripherals */ 129 MX_GPIO_Init(); 130 MX_DMA_Init(); 131 MX_USART1_UART_Init(); 132 133 MX_TIM6_Init(); 134 MX_CAN1_Init(); 135 /* USER CODE BEGIN 2 */ 136 HAL_TIM_Base_Start(&htim6); 137 HAL_TIM_Base_Stop_IT(&htim6); // stop_IT function is necessary ,for reset state ,else TIMER won't work 138 HAL_TIM_Base_Start_IT(&htim6); 139 140 __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); 141 HAL_UARTEx_ReceiveToIdle_DMA(&huart1,uart_rx_data,uart_rx_max); 142 __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); 143 144 HAL_CAN_Start(&hcan1); 145 146 HAL_Delay(50); //delay would be necessary ,shorter time is also OK 147 148 printf("This is CAN communication test program!\n"); 149 printf("After power up!Send 1 to activate PPM mode or send 2 to CSP mode\n"); 150 RPDO1_Mapping(); 151 HAL_Delay(10); 152 153 /* USER CODE END 2 */ 154 155 /* Infinite loop */ 156 /* USER CODE BEGIN WHILE */ 157 while (1) 158 { 159 /* USER CODE END WHILE */ 160 161 /* USER CODE BEGIN 3 */ 162 HAL_Delay(500); 163 HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_3); 164 165 if(1 == uart_rx_data[0]) 166 { printf("PPM TEST\n"); 167 do_a_PPM_Motion(); 168 uart_rx_data[0] = 0; 169 } 170 else if(2 == uart_rx_data[0]) 171 { printf("CSP TEST\n"); 172 //initiate CSP mode pos array 173 for(int i=0;i<CSP_MAX_NUM;i++) 174 { 175 //means explanation: physic formula S= 1/2*acc*(t*t) 176 // S= 1/2*a*t*t a=100, acceleration 30points ,dec 30 points 177 // Vmax= 30*a = 30*100 = 3000 178 if(i<=30) 179 CSP_Pos[i] = 0.5*acc*i*i; // S= 1/2*a*t*t a=100, 180 else 181 CSP_Pos[i] = CSP_Pos[i-1]+acc*(CSP_MAX_NUM/2)-0.5*acc*(2*(i - CSP_MAX_NUM/2)-1); 182 } 183 do_a_CSP_Motion(); 184 uart_rx_data[0] = 0; 185 } 186 187 } 188 /* USER CODE END 3 */ 189 } 190 191 /** 192 * @brief System Clock Configuration 193 * @retval None 194 */ 195 void SystemClock_Config(void) 196 { 197 RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 198 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 199 200 /** Configure the main internal regulator output voltage 201 */ 202 __HAL_RCC_PWR_CLK_ENABLE(); 203 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 204 205 /** Initializes the RCC Oscillators according to the specified parameters 206 * in the RCC_OscInitTypeDef structure. 207 */ 208 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 209 RCC_OscInitStruct.HSEState = RCC_HSE_ON; 210 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 211 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 212 RCC_OscInitStruct.PLL.PLLM = 4; 213 RCC_OscInitStruct.PLL.PLLN = 168; 214 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 215 RCC_OscInitStruct.PLL.PLLQ = 4; 216 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 217 { 218 Error_Handler(); 219 } 220 221 /** Initializes the CPU, AHB and APB buses clocks 222 */ 223 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK 224 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; 225 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 226 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 227 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 228 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; 229 230 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) 231 { 232 Error_Handler(); 233 } 234 } 235 236 /* USER CODE BEGIN 4 */ 237 void do_a_CSP_Motion() 238 { 239 //steps 1. disable motor, write 0x06 to object 0x6040 240 // 2. chang mode to CSP, write 0x08 to object 0x6060 241 // 3. check mode is CSP, read 0x6061 242 // 4. set CSP cycle-time, write 0x32 to object 0x6060,unit is ms 243 // 5. enable motor, write 0x0F to object 0x6040 244 // 6. check motor is enabled, read 0x6041 245 // 7. read current position, read 0x607A 246 // 8. CPS_Pos[]+current position as final target position 247 // 9. start remote node 248 // 10. send target position by PDO and follow SYNC command 0x80 249 // 11. CSP motion finished 250 // 251 //steps 1. disable motor, write 0x06 to object 0x6040 252 object_data[0]=0x2B;object_data[1]=0x40;object_data[2]=0x60;object_data[3]=0x00; 253 object_data[4]=0x06;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 254 can_receive_flag = 0; 255 CAN_sendTxMessage(0x601,8,object_data); 256 HAL_Delay(1); //HAL_DELAY() delay 1ms is necessary, else will stick here 257 while(1 != can_receive_flag) 258 {;} //HAL_DELAY() delay 1ms is necessary, else will stick here 259 // 2. chang mode to CSP, write 0x08 to object 0x6060 260 object_data[0]=0x2F;object_data[1]=0x60;object_data[2]=0x60;object_data[3]=0x00; 261 object_data[4]=0x08;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 262 can_receive_flag = 0; 263 CAN_sendTxMessage(0x601,8,object_data); 264 HAL_Delay(1); 265 while(1 != can_receive_flag) 266 {;} 267 // 3. check mode is CSP, read 0x6061 268 object_data[0]=0x40;object_data[1]=0x61;object_data[2]=0x60;object_data[3]=0x00; 269 object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 270 can_receive_flag = 0; 271 CAN_sendTxMessage(0x601,8,object_data); 272 HAL_Delay(1); 273 while(1 != can_receive_flag) 274 {;} 275 if(8 != RxData[4]) //8 means CSP mode 276 printf("Set CSP mode failed\n"); 277 // 4. set CSP cycle-time, write 0x32 to object 0x6060,unit is ms 278 object_data[0]=0x2F;object_data[1]=0xC2;object_data[2]=0x60;object_data[3]=0x00; 279 object_data[4]=0x32;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 280 can_receive_flag = 0; 281 CAN_sendTxMessage(0x601,8,object_data); 282 HAL_Delay(1); 283 while(1 != can_receive_flag) 284 {;} 285 // 5. enable motor, write 0x0F to object 0x6040 286 object_data[0]=0x2B;object_data[1]=0x40;object_data[2]=0x60;object_data[3]=0x00; 287 object_data[4]=0x0F;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 288 can_receive_flag = 0; 289 CAN_sendTxMessage(0x601,8,object_data); 290 HAL_Delay(1); 291 while(1 != can_receive_flag) 292 {;} 293 // 6. check motor is enabled, read 0x6041 294 object_data[0]=0x40;object_data[1]=0x41;object_data[2]=0x60;object_data[3]=0x00; 295 object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 296 can_receive_flag = 0; 297 CAN_sendTxMessage(0x601,8,object_data); 298 HAL_Delay(10); 299 while(1 != can_receive_flag) 300 {;} 301 if((RxData[4] & 0x04)) //0x04 means drive is operation enabled 302 printf("CSP mode enable failed\n"); 303 // 7. read current position, read 0x607A 304 object_data[0]=0x40;object_data[1]=0x64;object_data[2]=0x60;object_data[3]=0x00; 305 object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 306 can_receive_flag = 0; 307 CAN_sendTxMessage(0x601,8,object_data); 308 HAL_Delay(1); 309 while(1 != can_receive_flag) 310 {;} 311 for(int i=0;i<4;i++) 312 can_Frame_DataField[i]=RxData[i+4]; 313 int32_t current_Pos; 314 current_Pos = ConvertByteToInt(can_Frame_DataField); 315 printf("current pos is %d\n",current_Pos); 316 // 8. CPS_Pos[]+current position as final target position 317 for(int i=0;i<61;i++) 318 CSP_Pos[i] = CSP_Pos[i] + current_Pos; 319 // 9. start remote node 320 object_data[0]=0x01;object_data[1]=0x00; 321 can_receive_flag = 0; 322 CAN_sendTxMessage(0x00,2,object_data); 323 HAL_Delay(20); 324 325 // 10. send target position by PDO and follow SYNC command 0x80 326 CSP_flag = 1; 327 CSP_num = 0; 328 } 329 //do_a_PPM_Motion 330 void do_a_PPM_Motion() 331 { 332 //steps 1. disable motor, write 0x06 to object 0x6040 333 // 2. chang mode to PPM, write 0x01 to object 0x6060 334 // 3. check mode is PPM, read 0x6061 335 // 4. enable motor, write 0x0F to object 0x6040 336 // 5. check motor is enabled, read 0x6041 337 // 6. set profile velocity, write 0x6081 338 // 7. read current position, read 0x6064 339 // 8. add 5000 counts on current position as target position,write 0x607A 340 // 9. start motion, write 0x0F to object 0x6040 341 // 10. motion end 342 //steps 1. disable motor, write 0x06 to object 0x6040 343 printf("flag1 %d\n",can_receive_flag); 344 object_data[0]=0x2B;object_data[1]=0x40;object_data[2]=0x60;object_data[3]=0x00; 345 object_data[4]=0x06;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 346 can_receive_flag = 0; 347 CAN_sendTxMessage(0x601,8,object_data); 348 HAL_Delay(1); //HAL_DELAY() delay 1ms is necessary, else will stick here 349 while(1 != can_receive_flag) 350 {;} //HAL_DELAY() delay 1ms is necessary, else will stick here 351 // 2. chang mode to PPM, write 0x01 to object 0x6060 352 printf("flag2 %d\n",can_receive_flag); 353 object_data[0]=0x2F;object_data[1]=0x60;object_data[2]=0x60;object_data[3]=0x00; 354 object_data[4]=0x01;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 355 can_receive_flag = 0; 356 CAN_sendTxMessage(0x601,8,object_data); 357 HAL_Delay(1); 358 while(1 != can_receive_flag) 359 {;} 360 // 3. check mode is PPM, read 0x6061 361 printf("flag3 %d\n",can_receive_flag); 362 object_data[0]=0x40;object_data[1]=0x61;object_data[2]=0x60;object_data[3]=0x00; 363 object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 364 can_receive_flag = 0; 365 CAN_sendTxMessage(0x601,8,object_data); 366 HAL_Delay(1); 367 while(1 != can_receive_flag) 368 {;} 369 if(1 != RxData[4]) 370 printf("Set PPM mode failed\n"); 371 // 4. enable motor, write 0x0F to object 0x6040 372 printf("flag4 %d\n",can_receive_flag); 373 object_data[0]=0x2B;object_data[1]=0x40;object_data[2]=0x60;object_data[3]=0x00; 374 object_data[4]=0x0F;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 375 can_receive_flag = 0; 376 CAN_sendTxMessage(0x601,8,object_data); 377 HAL_Delay(1); 378 while(1 != can_receive_flag) 379 {;} 380 // 5. check motor is enabled, read 0x6041 381 object_data[0]=0x40;object_data[1]=0x41;object_data[2]=0x60;object_data[3]=0x00; 382 object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 383 can_receive_flag = 0; 384 CAN_sendTxMessage(0x601,8,object_data); 385 HAL_Delay(10); 386 while(1 != can_receive_flag) 387 {;} 388 if((RxData[4] & 0x04)) //0x04 means drive is operation enabled 389 printf("PPM mode enable failed\n"); 390 // 6. set profile velocity, write 10000 to 0x6081 391 392 object_data[0]=0x23;object_data[1]=0x81;object_data[2]=0x60;object_data[3]=0x00; 393 object_data[4]=0x10;object_data[5]=0x27;object_data[6]=0x00;object_data[7]=0x00; 394 can_receive_flag = 0; 395 CAN_sendTxMessage(0x601,8,object_data); 396 HAL_Delay(1); 397 while(1 != can_receive_flag) 398 {;} 399 // 7. read current position, read 0x6064 400 object_data[0]=0x40;object_data[1]=0x64;object_data[2]=0x60;object_data[3]=0x00; 401 object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 402 can_receive_flag = 0; 403 CAN_sendTxMessage(0x601,8,object_data); 404 HAL_Delay(1); 405 while(1 != can_receive_flag) 406 {;} 407 for(int i=0;i<4;i++) 408 can_Frame_DataField[i]=RxData[i+4]; 409 int32_t current_Pos; 410 current_Pos = ConvertByteToInt(can_Frame_DataField); 411 printf("current pos is %d\n",current_Pos); 412 // 8. add 50000 counts on current position as target position, write 0x607A 413 int32_t target_Pos; 414 target_Pos = current_Pos + 5000; 415 printf("current pos is %d\n",current_Pos); 416 ConvertIntTo4Byte(target_Pos); 417 object_data[0]=0x23; object_data[1]=0x7A; object_data[2]=0x60; object_data[3]=0x00; 418 object_data[4]=byte_value[0];object_data[5]=byte_value[1];object_data[6]=byte_value[2];object_data[7]=byte_value[3]; 419 can_receive_flag = 0; 420 CAN_sendTxMessage(0x601,8,object_data); 421 HAL_Delay(1); 422 while(1 != can_receive_flag) 423 {;} 424 // 9. start motion, write 0x1F to object 0x6040 425 object_data[0]=0x2B;object_data[1]=0x40;object_data[2]=0x60;object_data[3]=0x00; 426 object_data[4]=0x1F;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 427 can_receive_flag = 0; 428 CAN_sendTxMessage(0x601,8,object_data); 429 HAL_Delay(1); 430 while(1 != can_receive_flag) 431 {;} 432 // 10. motion end 433 printf("PPM motion finished!\n"); 434 435 } 436 //TIM6 interrupt 437 void HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef * htim ) 438 { 439 if(htim == (&htim6)) 440 { 441 if(1 == CSP_flag) 442 { 443 //send PDO 444 TxHeader.DLC = 4; 445 TxHeader.RTR = CAN_RTR_DATA; 446 ConvertIntTo4Byte(CSP_Pos[CSP_num]); 447 CAN_sendTxMessage(0x201,4,byte_value); 448 449 //send SYNC 450 TxHeader.DLC = 0; 451 TxHeader.RTR = CAN_RTR_REMOTE; 452 CAN_sendTxMessage(0x80,0,byte_value); 453 CSP_num++; 454 if(CSP_num > 60) 455 CSP_flag = 0; 456 } 457 } 458 } 459 460 //uartEX Receive to IDLE test 461 void HAL_UARTEx_RxEventCallback ( UART_HandleTypeDef * huart, uint16_t Size) 462 { 463 printf("%d \n",Size); 464 HAL_UART_Transmit_DMA(&huart1,uart_rx_data,Size); 465 466 HAL_UARTEx_ReceiveToIdle_DMA(&huart1,uart_rx_data,uart_rx_max); 467 __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT); 468 } 469 470 471 //CAN RX interrupt 472 void HAL_CAN_RxFifo0MsgPendingCallback ( CAN_HandleTypeDef * hcan ) 473 { 474 HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&RxHeader,RxData); 475 can_receive_flag = 1; 476 } 477 //CAN send message 478 void CAN_sendTxMessage(uint32_t std_id,uint32_t length,uint8_t data[]) 479 { 480 TxHeader.StdId = std_id; 481 TxHeader.DLC = length; 482 TxHeader.IDE = CAN_ID_STD; 483 TxHeader.RTR = CAN_RTR_DATA; 484 TxHeader.TransmitGlobalTime = DISABLE; 485 486 if(HAL_CAN_AddTxMessage(&hcan1,&TxHeader,data,(uint32_t *)CAN_TX_MAILBOX0) != HAL_OK) 487 { 488 printf("CAN1 error"); 489 } 490 491 } 492 493 // Mapping 0x607A to RPDO1 COB-ID 0x201 494 void RPDO1_Mapping() 495 { 496 497 //step 1. 0x601 0x23 0x00 0x14 0x01 0x01 0x02 0x00 0x80 498 object_data[0]=0x23;object_data[1]=0x00;object_data[2]=0x14;object_data[3]=0x01; 499 object_data[4]=0x01;object_data[5]=0x02;object_data[6]=0x00;object_data[7]=0x80; 500 CAN_sendTxMessage(0x601,8,object_data); 501 HAL_Delay(10); 502 // 2. 0x601 0x2F 0x00 0x14 0x02 0xFF 503 object_data[0]=0x2F;object_data[1]=0x00;object_data[2]=0x14;object_data[3]=0x02; 504 object_data[4]=0xFF;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x80; 505 CAN_sendTxMessage(0x601,8,object_data); 506 HAL_Delay(10); 507 // 3. 0x601 0x2F 0x00 0x16 0x00 0x00 508 object_data[0]=0x2F;object_data[1]=0x00;object_data[2]=0x16;object_data[3]=0x00; 509 object_data[4]=0x00;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 510 CAN_sendTxMessage(0x601,8,object_data); 511 HAL_Delay(10); 512 // 4.0x601 0x23 0x00 0x16 0x01 0x20 0x00 0x7A 0x60 513 object_data[0]=0x23;object_data[1]=0x00;object_data[2]=0x16;object_data[3]=0x01; 514 object_data[4]=0x20;object_data[5]=0x00;object_data[6]=0x7A;object_data[7]=0x60; 515 CAN_sendTxMessage(0x601,8,object_data); 516 HAL_Delay(10); 517 // 5. 0x601 0x2F 0x00 0x16 0x00 0x01 518 object_data[0]=0x2F;object_data[1]=0x00;object_data[2]=0x16;object_data[3]=0x00; 519 object_data[4]=0x01;object_data[5]=0x00;object_data[6]=0x00;object_data[7]=0x00; 520 CAN_sendTxMessage(0x601,8,object_data); 521 HAL_Delay(10); 522 // 6. 0x601 0x23 0x00 0x14 0x01 0x01 0x02 0x00 0x00 523 object_data[0]=0x23;object_data[1]=0x00;object_data[2]=0x14;object_data[3]=0x01; 524 object_data[4]=0x01;object_data[5]=0x02;object_data[6]=0x00;object_data[7]=0x00; 525 CAN_sendTxMessage(0x601,8,object_data); 526 HAL_Delay(10); 527 } 528 529 //re-define printf 530 int fputc(int ch,FILE *f) 531 { 532 uint8_t temp[1] = {ch}; 533 HAL_UART_Transmit(&huart1,temp,1,20); 534 return ch; 535 536 } 537 538 //convert a 32bit data to 4 bytes 539 void ConvertIntTo4Byte(int32_t source) 540 { 541 byte_value[0] = 0xFF & source; 542 byte_value[1] = 0xFF &(source >> 8); 543 byte_value[2] = 0xFF &(source >> 16); 544 byte_value[3] = 0xFF &(source >> 24); 545 } 546 //convert 4 byte data to int32_t 547 int32_t ConvertByteToInt(uint8_t *byte_source) 548 { 549 int32_t int32_data = https://www.cnblogs.com/cariohu/p/0; 550 int32_data = https://www.cnblogs.com/cariohu/p/(int32_data | byte_source[3])<<8; 551 int32_data = https://www.cnblogs.com/cariohu/p/(int32_data | byte_source[2])<<8; 552 int32_data = https://www.cnblogs.com/cariohu/p/(int32_data | byte_source[1])<<8; 553 int32_data = https://www.cnblogs.com/cariohu/p/(int32_data | byte_source[0]); 554 555 return int32_data; 556 } 557 /* USER CODE END 4 */ 558 559 /** 560 * @brief This function is executed in case of error occurrence. 561 * @retval None 562 */ 563 void Error_Handler(void) 564 { 565 /* USER CODE BEGIN Error_Handler_Debug */ 566 /* User can add his own implementation to report the HAL error return state */ 567 __disable_irq(); 568 while (1) 569 { 570 //printf("%s %S",__FILE__,__DATE__); 571 } 572 /* USER CODE END Error_Handler_Debug */ 573 } 574 575 #ifdef USE_FULL_ASSERT 576 /** 577 * @brief Reports the name of the source file and the source line number 578 * where the assert_param error has occurred. 579 * @param file: pointer to the source file name 580 * @param line: assert_param error line source number 581 * @retval None 582 */ 583 void assert_failed(uint8_t *file, uint32_t line) 584 { 585 /* USER CODE BEGIN 6 */ 586 /* User can add his own implementation to report the file name and line number, 587 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 588 /* USER CODE END 6 */ 589 } 590 #endif /* USE_FULL_ASSERT */
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/465120.html
標籤:嵌入式
上一篇:Docker與GU 安裝管理配置
