STM32F407CANopenmaster

编程

 

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

87void SystemClock_Config(void);

88/* USER CODE BEGIN PFP */

89void CAN_sendTxMessage(uint32_t std_id,uint32_t length,uint8_t data[]);

90void ConvertIntTo4Byte(int32_t source);

91 int32_t ConvertByteToInt(uint8_t *byte_source);

92void do_a_PPM_Motion();

93void do_a_CSP_Motion();

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

107int 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!

");

149 printf("After power up!Send 1 to activate PPM mode or send 2 to CSP mode

");

150 RPDO1_Mapping();

151 HAL_Delay(10);

152

153/* USER CODE END 2 */

154

155/* Infinite loop */

156/* USER CODE BEGIN WHILE */

157while (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

165if(1 == uart_rx_data[0])

166 { printf("PPM TEST

");

167 do_a_PPM_Motion();

168 uart_rx_data[0] = 0;

169 }

170elseif(2 == uart_rx_data[0])

171 { printf("CSP TEST

");

172//initiate CSP mode pos array

173for(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

178if(i<=30)

179 CSP_Pos[i] = 0.5*acc*i*i; // S= 1/2*a*t*t a=100,

180else

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

195void 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;

216if (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

230if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)

231 {

232 Error_Handler();

233 }

234}

235

236/* USER CODE BEGIN 4 */

237void 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

257while(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);

265while(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);

273while(1 != can_receive_flag)

274 {;}

275if(8 != RxData[4]) //8 means CSP mode

276 printf("Set CSP mode failed

");

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);

283while(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);

291while(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);

299while(1 != can_receive_flag)

300 {;}

301if((RxData[4] & 0x04)) //0x04 means drive is operation enabled

302 printf("CSP mode enable failed

");

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);

309while(1 != can_receive_flag)

310 {;}

311for(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

",current_Pos);

316// 8. CPS_Pos[]+current position as final target position

317for(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

330void 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

",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

349while(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

",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);

358while(1 != can_receive_flag)

359 {;}

360// 3. check mode is PPM, read 0x6061

361 printf("flag3 %d

",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);

367while(1 != can_receive_flag)

368 {;}

369if(1 != RxData[4])

370 printf("Set PPM mode failed

");

371// 4. enable motor, write 0x0F to object 0x6040

372 printf("flag4 %d

",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);

378while(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);

386while(1 != can_receive_flag)

387 {;}

388if((RxData[4] & 0x04)) //0x04 means drive is operation enabled

389 printf("PPM mode enable failed

");

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);

397while(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);

405while(1 != can_receive_flag)

406 {;}

407for(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

",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

",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);

422while(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);

430while(1 != can_receive_flag)

431 {;}

432// 10. motion end

433 printf("PPM motion finished!

");

434

435}

436//TIM6 interrupt

437void HAL_TIM_PeriodElapsedCallback ( TIM_HandleTypeDef * htim )

438{

439if(htim == (&htim6))

440 {

441if(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++;

454if(CSP_num > 60)

455 CSP_flag = 0;

456 }

457 }

458}

459

460//uartEX Receive to IDLE test

461void HAL_UARTEx_RxEventCallback ( UART_HandleTypeDef * huart, uint16_t Size)

462{

463 printf("%d

",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

472void 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

478void 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

486if(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

494void 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

530int fputc(int ch,FILE *f)

531{

532 uint8_t temp[1] = {ch};

533 HAL_UART_Transmit(&huart1,temp,1,20);

534return ch;

535

536}

537

538//convert a 32bit data to 4 bytes

539void 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 = 0;

550 int32_data = (int32_data | byte_source[3])<<8;

551 int32_data = (int32_data | byte_source[2])<<8;

552 int32_data = (int32_data | byte_source[1])<<8;

553 int32_data = (int32_data | byte_source[0]);

554

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

563void 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();

568while (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*/

583void 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

", file, line) */

588/* USER CODE END 6 */

589}

590#endif /* USE_FULL_ASSERT */

 

以上是 STM32F407CANopenmaster 的全部内容, 来源链接: utcz.com/z/520410.html

回到顶部