当前位置:   article > 正文

STM32 HAL库 实现控制步进电机 正转、反转、T型加减速_stm32步进电机获取步数

stm32步进电机获取步数

主要是在项目中实现的一些方法,在此做个记录,以便后续个人复习与总结

一、CubeMX的配置

1.RCC配置

2.SYS配置

3.TIM配置,因为用到了三个步进电机,所以使能步进电机的三个通道

(这里用两个定时器主要是为了学习配置多个定时器)

3.1各通道的配置 3.2 记得打开中断

4.配置串口USART(因为要实现上位机发送指令控制步进电机)

 5.GPIO配置

 

 二、KEIL5 程序编写

1.motor.c文件

  1. #include "Motor.h"
  2. #include <math.h>
  3. X_speedRampData X_srd = {STOP,CW,0,0,0,0,0}; // X加减速曲线变量
  4. __IO int32_t X_step_position = 0; // X当前位置
  5. __IO uint8_t X_MotionStatus = 0; //X是否在运动?0:停止,1:运动
  6. Y_speedRampData Y_srd = {STOP,CW,0,0,0,0,0}; // Y加减速曲线变量
  7. __IO int32_t Y_step_position = 0; // Y当前位置
  8. __IO uint8_t Y_MotionStatus = 0; //Y是否在运动?0:停止,1:运动
  9. P_speedRampData P_srd = {STOP,CW,0,0,0,0,0}; // P加减速曲线变量
  10. __IO int32_t P_step_position = 0; // P当前位置
  11. __IO uint8_t P_MotionStatus = 0; //P是否在运动?0:停止,1:运动
  12. extern TIM_HandleTypeDef htim2;
  13. extern TIM_HandleTypeDef htim3;
  14. /**
  15. * 函数功能: 相对位置运动:运动给定的步数
  16. * 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
  17. accel 加速度,实际值为accel*0.025*rad/sec^2
  18. decel 减速度,实际值为decel*0.025*rad/sec^2
  19. speed 最大速度,实际值为speed*0.05*rad/sec
  20. * 返 回 值: 无
  21. * 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始
  22. * 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且
  23. * 速度很慢,那还没达到最大速度就要开始减速
  24. */
  25. /***X电机梯形加减速***/
  26. void X_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
  27. {
  28. __IO uint16_t X_tim_count;
  29. // X达到最大速度时的步数
  30. __IO uint32_t X_max_s_lim;
  31. // X必须要开始减速的步数(如果加速没有达到最大速度)
  32. __IO uint32_t X_accel_lim;
  33. if(step < 0) // 步数为负数
  34. {
  35. X_srd.dir = CCW; // 逆时针方向旋转
  36. X_STEPMOTOR_DIR_REVERSAL();
  37. step =-step; // 获取步数绝对值
  38. }
  39. else
  40. {
  41. X_srd.dir = CW; // 顺时针方向旋转
  42. X_STEPMOTOR_DIR_FORWARD();
  43. }
  44. if(step == 1) // 步数为1
  45. {
  46. X_srd.accel_count = -1; // 只移动一步
  47. X_srd.run_state = DECEL; // 减速状态.
  48. X_srd.step_delay = 1000; // 短延时
  49. }
  50. else if(step != 0) // 如果目标运动步数不为0
  51. {
  52. // 我们的驱动器用户手册有详细的计算及推导过程
  53. // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
  54. // min_delay = (alpha / tt)/ w
  55. X_srd.min_delay = (int32_t)(A_T_x10/speed);
  56. // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
  57. // step_delay = 1/tt * sqrt(2*alpha/accel)
  58. // step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
  59. X_srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
  60. // 计算多少步之后达到最大速度的限制
  61. // max_s_lim = speed^2 / (2*alpha*accel)
  62. X_max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
  63. // 如果达到最大速度小于0.5步,我们将四舍五入为0
  64. // 但实际我们必须移动至少一步才能达到想要的速度
  65. if(X_max_s_lim == 0){
  66. X_max_s_lim = 1;
  67. }
  68. // 计算多少步之后我们必须开始减速
  69. // n1 = (n1+n2)decel / (accel + decel)
  70. X_accel_lim = (uint32_t)(step*decel/(accel+decel));
  71. // 我们必须加速至少1步才能才能开始减速.
  72. if(X_accel_lim == 0){
  73. X_accel_lim = 1;
  74. }
  75. // 使用限制条件我们可以计算出减速阶段步数
  76. if(X_accel_lim <= X_max_s_lim){
  77. X_srd.decel_val = X_accel_lim - step;
  78. }
  79. else{
  80. X_srd.decel_val = -(X_max_s_lim*accel/decel);
  81. }
  82. // 当只剩下一步我们必须减速
  83. if(X_srd.decel_val == 0){
  84. X_srd.decel_val = -1;
  85. }
  86. // 计算开始减速时的步数
  87. X_srd.decel_start = step + X_srd.decel_val;
  88. // 如果最大速度很慢,我们就不需要进行加速运动
  89. if(X_srd.step_delay <= X_srd.min_delay){
  90. X_srd.step_delay = X_srd.min_delay;
  91. X_srd.run_state = RUN;
  92. }
  93. else{
  94. X_srd.run_state = ACCEL;
  95. }
  96. // 复位加速度计数值
  97. X_srd.accel_count = 0;
  98. }
  99. X_MotionStatus = 1; // 电机为运动状态
  100. X_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
  101. __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,X_tim_count+X_srd.step_delay); // 设置定时器比较值
  102. HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1);
  103. TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_1, TIM_CCx_ENABLE);// 使能定时器通道
  104. X_STEPMOTOR_OUTPUT_ENABLE();
  105. }
  106. /***Y电机梯形加减速***/
  107. void Y_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
  108. {
  109. __IO uint16_t Y_tim_count;// X达到最大速度时的步数
  110. __IO uint32_t Y_max_s_lim;// X必须要开始减速的步数(如果加速没有达到最大速度)
  111. __IO uint32_t Y_accel_lim;
  112. if(step < 0) // 步数为负数
  113. {
  114. Y_srd.dir = CCW; // 逆时针方向旋转
  115. Y_STEPMOTOR_DIR_REVERSAL();
  116. step =-step; // 获取步数绝对值
  117. }
  118. else
  119. {
  120. Y_srd.dir = CW; // 顺时针方向旋转
  121. Y_STEPMOTOR_DIR_FORWARD();
  122. }
  123. if(step == 1) // 步数为1
  124. {
  125. Y_srd.accel_count = -1; // 只移动一步
  126. Y_srd.run_state = DECEL; // 减速状态.
  127. Y_srd.step_delay = 1000; // 短延时
  128. }
  129. else if(step != 0) // 如果目标运动步数不为0
  130. {
  131. // 我们的驱动器用户手册有详细的计算及推导过程
  132. // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
  133. // min_delay = (alpha / tt)/ w
  134. Y_srd.min_delay = (int32_t)(A_T_x10/speed);
  135. // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
  136. // step_delay = 1/tt * sqrt(2*alpha/accel)
  137. // step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
  138. Y_srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
  139. // 计算多少步之后达到最大速度的限制
  140. // max_s_lim = speed^2 / (2*alpha*accel)
  141. Y_max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
  142. // 如果达到最大速度小于0.5步,我们将四舍五入为0
  143. // 但实际我们必须移动至少一步才能达到想要的速度
  144. if(Y_max_s_lim == 0){
  145. Y_max_s_lim = 1;
  146. }
  147. // 计算多少步之后我们必须开始减速
  148. // n1 = (n1+n2)decel / (accel + decel)
  149. Y_accel_lim = (uint32_t)(step*decel/(accel+decel));
  150. // 我们必须加速至少1步才能才能开始减速.
  151. if(Y_accel_lim == 0){
  152. Y_accel_lim = 1;
  153. }
  154. // 使用限制条件我们可以计算出减速阶段步数
  155. if(Y_accel_lim <= Y_max_s_lim){
  156. Y_srd.decel_val = Y_accel_lim - step;
  157. }
  158. else{
  159. Y_srd.decel_val = -(Y_max_s_lim*accel/decel);
  160. }
  161. // 当只剩下一步我们必须减速
  162. if(Y_srd.decel_val == 0){
  163. Y_srd.decel_val = -1;
  164. }
  165. // 计算开始减速时的步数
  166. Y_srd.decel_start = step + Y_srd.decel_val;
  167. // 如果最大速度很慢,我们就不需要进行加速运动
  168. if(Y_srd.step_delay <= Y_srd.min_delay){
  169. Y_srd.step_delay = Y_srd.min_delay;
  170. Y_srd.run_state = RUN;
  171. }
  172. else{
  173. Y_srd.run_state = ACCEL;
  174. }
  175. // 复位加速度计数值
  176. Y_srd.accel_count = 0;
  177. }
  178. Y_MotionStatus = 1; // 电机为运动状态
  179. Y_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
  180. __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,Y_tim_count+Y_srd.step_delay); // 设置定时器比较值
  181. HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2);
  182. TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_2, TIM_CCx_ENABLE);// 使能定时器通道
  183. Y_STEPMOTOR_OUTPUT_ENABLE();
  184. }
  185. /***P电机梯形加减速***/
  186. void P_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
  187. {
  188. __IO uint16_t P_tim_count;
  189. // X达到最大速度时的步数
  190. __IO uint32_t P_max_s_lim;
  191. // X必须要开始减速的步数(如果加速没有达到最大速度)
  192. __IO uint32_t P_accel_lim;
  193. if(step < 0) // 步数为负数
  194. {
  195. P_srd.dir = CCW; // 逆时针方向旋转
  196. P_STEPMOTOR_DIR_REVERSAL();
  197. step =-step; // 获取步数绝对值
  198. }
  199. else
  200. {
  201. P_srd.dir = CW; // 顺时针方向旋转
  202. P_STEPMOTOR_DIR_FORWARD();
  203. }
  204. if(step == 1) // 步数为1
  205. {
  206. P_srd.accel_count = -1; // 只移动一步
  207. P_srd.run_state = DECEL; // 减速状态.
  208. P_srd.step_delay = 1000; // 短延时
  209. }
  210. else if(step != 0) // 如果目标运动步数不为0
  211. {
  212. // 我们的驱动器用户手册有详细的计算及推导过程
  213. // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
  214. // min_delay = (alpha / tt)/ w
  215. P_srd.min_delay = (int32_t)(A_T_x10/speed);
  216. // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
  217. // step_delay = 1/tt * sqrt(2*alpha/accel)
  218. // step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
  219. P_srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
  220. // 计算多少步之后达到最大速度的限制
  221. // max_s_lim = speed^2 / (2*alpha*accel)
  222. P_max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
  223. // 如果达到最大速度小于0.5步,我们将四舍五入为0
  224. // 但实际我们必须移动至少一步才能达到想要的速度
  225. if(P_max_s_lim == 0){
  226. P_max_s_lim = 1;
  227. }
  228. // 计算多少步之后我们必须开始减速
  229. // n1 = (n1+n2)decel / (accel + decel)
  230. P_accel_lim = (uint32_t)(step*decel/(accel+decel));
  231. // 我们必须加速至少1步才能才能开始减速.
  232. if(P_accel_lim == 0){
  233. P_accel_lim = 1;
  234. }
  235. // 使用限制条件我们可以计算出减速阶段步数
  236. if(P_accel_lim <= P_max_s_lim){
  237. P_srd.decel_val = P_accel_lim - step;
  238. }
  239. else{
  240. P_srd.decel_val = -(P_max_s_lim*accel/decel);
  241. }
  242. // 当只剩下一步我们必须减速
  243. if(P_srd.decel_val == 0){
  244. P_srd.decel_val = -1;
  245. }
  246. // 计算开始减速时的步数
  247. P_srd.decel_start = step + P_srd.decel_val;
  248. // 如果最大速度很慢,我们就不需要进行加速运动
  249. if(P_srd.step_delay <= P_srd.min_delay){
  250. P_srd.step_delay = P_srd.min_delay;
  251. P_srd.run_state = RUN;
  252. }
  253. else{
  254. P_srd.run_state = ACCEL;
  255. }
  256. // 复位加速度计数值
  257. P_srd.accel_count = 0;
  258. }
  259. P_MotionStatus = 1; // 电机为运动状态
  260. P_tim_count=__HAL_TIM_GET_COUNTER(&htim2);
  261. __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,P_tim_count+X_srd.step_delay); // 设置定时器比较值
  262. HAL_TIM_OC_Start_IT(&htim2,TIM_CHANNEL_3);
  263. TIM_CCxChannelCmd(TIM2,TIM_CHANNEL_3, TIM_CCx_ENABLE);// 使能定时器通道
  264. P_STEPMOTOR_OUTPUT_ENABLE();
  265. }
  266. /**
  267. * 函数功能: 定时器中断服务函数
  268. * 输入参数: 无
  269. * 返 回 值: 无
  270. * 说 明: 实现加减速过程
  271. */
  272. void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)//定时器中断处理
  273. {
  274. /*X电机*/
  275. __IO uint16_t X_tim_count=0;
  276. // X保存新(下)一个延时周期
  277. uint16_t X_new_step_delay=0;
  278. // X加速过程中最后一次延时(脉冲周期).
  279. __IO static uint16_t X_last_accel_delay=0;
  280. // X总移动步数计数器
  281. __IO static uint32_t X_step_count = 0;
  282. // X记录new_step_delay中的余数,提高下一步计算的精度
  283. __IO static int32_t X_rest = 0;
  284. //X定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
  285. __IO static uint8_t X_i=0;
  286. /*Y电机*/
  287. __IO uint16_t Y_tim_count=0;
  288. // Y保存新(下)一个延时周期
  289. uint16_t Y_new_step_delay=0;
  290. // Y加速过程中最后一次延时(脉冲周期).
  291. __IO static uint16_t Y_last_accel_delay=0;
  292. // Y总移动步数计数器
  293. __IO static uint32_t Y_step_count = 0;
  294. // X记录new_step_delay中的余数,提高下一步计算的精度
  295. __IO static int32_t Y_rest = 0;
  296. //Y定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
  297. __IO static uint8_t Y_i=0;
  298. /*P电机*/
  299. __IO uint16_t P_tim_count=0;
  300. // Y保存新(下)一个延时周期
  301. uint16_t P_new_step_delay=0;
  302. // Y加速过程中最后一次延时(脉冲周期).
  303. __IO static uint16_t P_last_accel_delay=0;
  304. // Y总移动步数计数器
  305. __IO static uint32_t P_step_count = 0;
  306. // X记录new_step_delay中的余数,提高下一步计算的精度
  307. __IO static int32_t P_rest = 0;
  308. //Y定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
  309. __IO static uint8_t P_i=0;
  310. if(htim->Instance==TIM3)
  311. {
  312. /*X电机的定时器配置*/
  313. if(__HAL_TIM_GET_IT_SOURCE(&htim3, TIM_IT_CC1) !=RESET)
  314. {
  315. // 清楚定时器中断
  316. __HAL_TIM_CLEAR_IT(&htim3, TIM_IT_CC1);
  317. // 设置比较值
  318. X_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
  319. __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,X_tim_count+X_srd.step_delay);
  320. X_i++; // 定时器中断次数计数值
  321. if(X_i==2) // 2次,说明已经输出一个完整脉冲
  322. {
  323. X_i=0; // 清零定时器中断次数计数值
  324. switch(X_srd.run_state) // 加减速曲线阶段
  325. {
  326. case STOP:
  327. X_step_count = 0; // 清零步数计数器
  328. X_rest = 0; // 清零余值
  329. // 关闭通道
  330. TIM_CCxChannelCmd(TIM3, TIM_CHANNEL_1, TIM_CCx_DISABLE);
  331. __HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_CC1);
  332. X_STEPMOTOR_OUTPUT_DISABLE();
  333. X_MotionStatus = 0; // 电机为停止状态
  334. break;
  335. case ACCEL:
  336. X_step_count++; // 步数加1
  337. if(X_srd.dir==CW)
  338. {
  339. X_step_position++; // 绝对位置加1
  340. }
  341. else
  342. {
  343. X_step_position--; // 绝对位置减1
  344. }
  345. X_srd.accel_count++; // 加速计数值加1
  346. X_new_step_delay = X_srd.step_delay - (((2 *X_srd.step_delay) + X_rest)/(4 * X_srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
  347. X_rest = ((2 * X_srd.step_delay)+X_rest)%(4 * X_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
  348. if(X_step_count >= X_srd.decel_start)// 检查是够应该开始减速
  349. {
  350. X_srd.accel_count = X_srd.decel_val; // 加速计数值为减速阶段计数值的初始值
  351. X_srd.run_state = DECEL; // 下个脉冲进入减速阶段
  352. }
  353. else if(X_new_step_delay <= X_srd.min_delay) // 检查是否到达期望的最大速度
  354. {
  355. X_last_accel_delay = X_new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)
  356. X_new_step_delay = X_srd.min_delay; // 使用min_delay(对应最大速度speed)
  357. X_rest = 0; // 清零余值
  358. X_srd.run_state = RUN; // 设置为匀速运行状态
  359. }
  360. break;
  361. case RUN:
  362. X_step_count++; // 步数加1
  363. if(X_srd.dir==CW)
  364. {
  365. X_step_position++; // 绝对位置加1
  366. }
  367. else
  368. {
  369. X_step_position--; // 绝对位置减1
  370. }
  371. X_new_step_delay = X_srd.min_delay; // 使用min_delay(对应最大速度speed)
  372. if(X_step_count >= X_srd.decel_start) // 需要开始减速
  373. {
  374. X_srd.accel_count = X_srd.decel_val; // 减速步数做为加速计数值
  375. X_new_step_delay = X_last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
  376. X_srd.run_state = DECEL; // 状态改变为减速
  377. }
  378. break;
  379. case DECEL:
  380. X_step_count++; // 步数加1
  381. if(X_srd.dir==CW)
  382. {
  383. X_step_position++; // 绝对位置加1
  384. }
  385. else
  386. {
  387. X_step_position--; // 绝对位置减1
  388. }
  389. X_srd.accel_count++;
  390. X_new_step_delay = X_srd.step_delay - (((2 * X_srd.step_delay) + X_rest)/(4 * X_srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
  391. X_rest = ((2 * X_srd.step_delay)+X_rest)%(4 * X_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
  392. //检查是否为最后一步
  393. if(X_srd.accel_count >= 0)
  394. {
  395. X_srd.run_state = STOP;
  396. }
  397. break;
  398. }
  399. X_srd.step_delay = X_new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
  400. }
  401. }
  402. /*Y电机的定时器配置*/
  403. if(__HAL_TIM_GET_IT_SOURCE(&htim3, TIM_IT_CC2) !=RESET)
  404. {
  405. // 清楚定时器中断
  406. __HAL_TIM_CLEAR_IT(&htim3, TIM_IT_CC2);
  407. // 设置比较值
  408. Y_tim_count=__HAL_TIM_GET_COUNTER(&htim3);
  409. __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,Y_tim_count+Y_srd.step_delay);
  410. Y_i++; // 定时器中断次数计数值
  411. if(Y_i==2) // 2次,说明已经输出一个完整脉冲
  412. {
  413. Y_i=0; // 清零定时器中断次数计数值
  414. switch(Y_srd.run_state) // 加减速曲线阶段
  415. {
  416. case STOP:
  417. Y_step_count = 0; // 清零步数计数器
  418. Y_rest = 0; // 清零余值
  419. // 关闭通道
  420. TIM_CCxChannelCmd(TIM3, TIM_CHANNEL_2, TIM_CCx_DISABLE);
  421. __HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_CC2);
  422. Y_STEPMOTOR_OUTPUT_DISABLE();
  423. Y_MotionStatus = 0; // 电机为停止状态
  424. break;
  425. case ACCEL:
  426. Y_step_count++; // 步数加1
  427. if(Y_srd.dir==CW)
  428. {
  429. Y_step_position++; // 绝对位置加1
  430. }
  431. else
  432. {
  433. Y_step_position--; // 绝对位置减1
  434. }
  435. Y_srd.accel_count++; // 加速计数值加1
  436. Y_new_step_delay = Y_srd.step_delay - (((2 *Y_srd.step_delay) + Y_rest)/(4 * Y_srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
  437. Y_rest = ((2 * Y_srd.step_delay)+Y_rest)%(4 * Y_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
  438. if(Y_step_count >= Y_srd.decel_start)// 检查是够应该开始减速
  439. {
  440. Y_srd.accel_count = Y_srd.decel_val; // 加速计数值为减速阶段计数值的初始值
  441. Y_srd.run_state = DECEL; // 下个脉冲进入减速阶段
  442. }
  443. else if(Y_new_step_delay <= Y_srd.min_delay) // 检查是否到达期望的最大速度
  444. {
  445. Y_last_accel_delay = Y_new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)
  446. Y_new_step_delay = Y_srd.min_delay; // 使用min_delay(对应最大速度speed)
  447. Y_rest = 0; // 清零余值
  448. Y_srd.run_state = RUN; // 设置为匀速运行状态
  449. }
  450. break;
  451. case RUN:
  452. Y_step_count++; // 步数加1
  453. if(Y_srd.dir==CW)
  454. {
  455. Y_step_position++; // 绝对位置加1
  456. }
  457. else
  458. {
  459. Y_step_position--; // 绝对位置减1
  460. }
  461. Y_new_step_delay = Y_srd.min_delay; // 使用min_delay(对应最大速度speed)
  462. if(Y_step_count >= Y_srd.decel_start) // 需要开始减速
  463. {
  464. Y_srd.accel_count = Y_srd.decel_val; // 减速步数做为加速计数值
  465. Y_new_step_delay = Y_last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
  466. Y_srd.run_state = DECEL; // 状态改变为减速
  467. }
  468. break;
  469. case DECEL:
  470. Y_step_count++; // 步数加1
  471. if(Y_srd.dir==CW)
  472. {
  473. Y_step_position++; // 绝对位置加1
  474. }
  475. else
  476. {
  477. Y_step_position--; // 绝对位置减1
  478. }
  479. Y_srd.accel_count++;
  480. Y_new_step_delay = Y_srd.step_delay - (((2 * Y_srd.step_delay) + Y_rest)/(4 * Y_srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
  481. Y_rest = ((2 * Y_srd.step_delay)+Y_rest)%(4 * Y_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
  482. //检查是否为最后一步
  483. if(Y_srd.accel_count >= 0)
  484. {
  485. Y_srd.run_state = STOP;
  486. }
  487. break;
  488. }
  489. Y_srd.step_delay = Y_new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
  490. }
  491. }
  492. }
  493. if(htim->Instance==TIM2)
  494. {
  495. /*P电机的定时器配置*/
  496. if(__HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_CC3) !=RESET)
  497. {
  498. // 清楚定时器中断
  499. __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_CC3);
  500. // 设置比较值
  501. P_tim_count=__HAL_TIM_GET_COUNTER(&htim2);
  502. __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,P_tim_count+P_srd.step_delay);
  503. P_i++; // 定时器中断次数计数值
  504. if(P_i==2) // 2次,说明已经输出一个完整脉冲
  505. {
  506. P_i=0; // 清零定时器中断次数计数值
  507. switch(P_srd.run_state) // 加减速曲线阶段
  508. {
  509. case STOP:
  510. P_step_count = 0; // 清零步数计数器
  511. P_rest = 0; // 清零余值
  512. // 关闭通道
  513. TIM_CCxChannelCmd(TIM2, TIM_CHANNEL_3, TIM_CCx_DISABLE);
  514. __HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC3);
  515. P_STEPMOTOR_OUTPUT_DISABLE();
  516. P_MotionStatus = 0; // 电机为停止状态
  517. break;
  518. case ACCEL:
  519. P_step_count++; // 步数加1
  520. if(P_srd.dir==CW)
  521. {
  522. P_step_position++; // 绝对位置加1
  523. }
  524. else
  525. {
  526. P_step_position--; // 绝对位置减1
  527. }
  528. P_srd.accel_count++; // 加速计数值加1
  529. P_new_step_delay = P_srd.step_delay - (((2 *P_srd.step_delay) + P_rest)/(4 * P_srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
  530. P_rest = ((2 * P_srd.step_delay)+P_rest)%(4 *P_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
  531. if(P_step_count >= P_srd.decel_start)// 检查是够应该开始减速
  532. {
  533. P_srd.accel_count = P_srd.decel_val; // 加速计数值为减速阶段计数值的初始值
  534. P_srd.run_state = DECEL; // 下个脉冲进入减速阶段
  535. }
  536. else if(P_new_step_delay <= P_srd.min_delay) // 检查是否到达期望的最大速度
  537. {
  538. P_last_accel_delay = P_new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)
  539. P_new_step_delay = P_srd.min_delay; // 使用min_delay(对应最大速度speed)
  540. P_rest = 0; // 清零余值
  541. P_srd.run_state = RUN; // 设置为匀速运行状态
  542. }
  543. break;
  544. case RUN:
  545. P_step_count++; // 步数加1
  546. if(P_srd.dir==CW)
  547. {
  548. P_step_position++; // 绝对位置加1
  549. }
  550. else
  551. {
  552. P_step_position--; // 绝对位置减1
  553. }
  554. P_new_step_delay = P_srd.min_delay; // 使用min_delay(对应最大速度speed)
  555. if(P_step_count >= P_srd.decel_start) // 需要开始减速
  556. {
  557. P_srd.accel_count = P_srd.decel_val; // 减速步数做为加速计数值
  558. P_new_step_delay = P_last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
  559. P_srd.run_state = DECEL; // 状态改变为减速
  560. }
  561. break;
  562. case DECEL:
  563. P_step_count++; // 步数加1
  564. if(P_srd.dir==CW)
  565. {
  566. P_step_position++; // 绝对位置加1
  567. }
  568. else
  569. {
  570. P_step_position--; // 绝对位置减1
  571. }
  572. P_srd.accel_count++;
  573. P_new_step_delay = P_srd.step_delay - (((2 * P_srd.step_delay) + P_rest)/(4 * P_srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
  574. P_rest = ((2 * P_srd.step_delay)+P_rest)%(4 * P_srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
  575. //检查是否为最后一步
  576. if(P_srd.accel_count >= 0)
  577. {
  578. P_srd.run_state = STOP;
  579. }
  580. break;
  581. }
  582. P_srd.step_delay = P_new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
  583. }
  584. }
  585. }
  586. }
  587. //==================end【By_Gerhart】======================//

2.motor.h文件 

  1. #ifndef __MOTOR_H__
  2. #define __MOTOR_H__
  3. /*引用库函数*/
  4. #include "main.h"
  5. #define X_Motor_OFF() HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_1)
  6. #define Y_Motor_OFF() HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_2)
  7. #define P_Motor_OFF() HAL_TIM_OC_Stop_IT(&htim2,TIM_CHANNEL_3)
  8. //#define Motor_EN() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
  9. //#define Motor_DIS() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)
  10. /* 电机结构体宏定义 ------------------------------------------------------------------*/
  11. typedef struct {
  12. __IO uint8_t run_state ; // 电机旋转状态
  13. __IO uint8_t dir ; // 电机旋转方向
  14. __IO int32_t step_delay; // 下个脉冲周期(时间间隔),启动时为加速度
  15. __IO uint32_t decel_start; // 启动减速位置
  16. __IO int32_t decel_val; // 减速阶段步数
  17. __IO int32_t min_delay; // 最小脉冲周期(最大速度,即匀速段速度)
  18. __IO int32_t accel_count; // 加减速阶段计数值
  19. }X_speedRampData;
  20. typedef struct {
  21. __IO uint8_t run_state ; // 电机旋转状态
  22. __IO uint8_t dir ; // 电机旋转方向
  23. __IO int32_t step_delay; // 下个脉冲周期(时间间隔),启动时为加速度
  24. __IO uint32_t decel_start; // 启动减速位置
  25. __IO int32_t decel_val; // 减速阶段步数
  26. __IO int32_t min_delay; // 最小脉冲周期(最大速度,即匀速段速度)
  27. __IO int32_t accel_count; // 加减速阶段计数值
  28. }Y_speedRampData;
  29. typedef struct {
  30. __IO uint8_t run_state ; // 电机旋转状态
  31. __IO uint8_t dir ; // 电机旋转方向
  32. __IO int32_t step_delay; // 下个脉冲周期(时间间隔),启动时为加速度
  33. __IO uint32_t decel_start; // 启动减速位置
  34. __IO int32_t decel_val; // 减速阶段步数
  35. __IO int32_t min_delay; // 最小脉冲周期(最大速度,即匀速段速度)
  36. __IO int32_t accel_count; // 加减速阶段计数值
  37. }P_speedRampData;
  38. extern X_speedRampData X_srd;
  39. extern __IO int32_t X_step_position;
  40. extern __IO uint8_t X_MotionStatus;
  41. extern Y_speedRampData Y_srd;
  42. extern __IO int32_t Y_step_position;
  43. extern __IO uint8_t Y_MotionStatus;
  44. extern P_speedRampData P_srd;
  45. extern __IO int32_t P_step_position;
  46. extern __IO uint8_t P_MotionStatus;
  47. #define STEPMOTOR_TIM_PRESCALER 3 // 步进电机驱动器细分设置为: 32 细分
  48. // 定义定时器周期,输出比较模式周期设置为0xFFFF
  49. #define STEPMOTOR_TIM_PERIOD 0xFFFF
  50. #define FALSE 0
  51. #define TRUE 1
  52. #define CW 0 // 顺时针
  53. #define CCW 1 // 逆时针
  54. #define STOP 0 // 加减速曲线状态:停止
  55. #define ACCEL 1 // 加减速曲线状态:加速阶段
  56. #define DECEL 2 // 加减速曲线状态:减速阶段
  57. #define RUN 3 // 加减速曲线状态:匀速阶段
  58. #define T1_FREQ (SystemCoreClock/(STEPMOTOR_TIM_PRESCALER+1)) // 频率ft值
  59. #define FSPR 200 //步进电机单圈步数
  60. #define MICRO_STEP 32 // 步进电机驱动器细分数
  61. #define SPR (FSPR*MICRO_STEP) // 旋转一圈需要的脉冲数
  62. // 数学常数
  63. #define ALPHA ((float)(2*3.14159/SPR)) // α= 2*pi/spr
  64. #define A_T_x10 ((float)(10*ALPHA*T1_FREQ))
  65. #define T1_FREQ_148 ((float)((T1_FREQ*0.676)/10)) // 0.676为误差修正值
  66. #define A_SQ ((float)(2*100000*ALPHA))
  67. #define A_x200 ((float)(200*ALPHA))
  68. #define X_STEPMOTOR_DIR_FORWARD() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET)
  69. #define X_STEPMOTOR_DIR_REVERSAL() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)
  70. #define Y_STEPMOTOR_DIR_FORWARD() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET)
  71. #define Y_STEPMOTOR_DIR_REVERSAL() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET)
  72. #define P_STEPMOTOR_DIR_FORWARD() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET)
  73. #define P_STEPMOTOR_DIR_REVERSAL() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET)
  74. #define X_STEPMOTOR_OUTPUT_ENABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)
  75. #define X_STEPMOTOR_OUTPUT_DISABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)
  76. #define Y_STEPMOTOR_OUTPUT_ENABLE(); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET)
  77. #define Y_STEPMOTOR_OUTPUT_DISABLE(); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET)
  78. #define P_STEPMOTOR_OUTPUT_ENABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET)
  79. #define P_STEPMOTOR_OUTPUT_DISABLE(); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET)
  80. /*可以被外部使用的函数声明*/
  81. void X_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed);
  82. void Y_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed);
  83. void P_STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed);
  84. #endif

3. tim.c中添加使能函数

  1. /* USER CODE BEGIN TIM2_Init 2 */
  2. HAL_TIM_OC_Stop_IT(&htim2,TIM_CHANNEL_3); /*停止定时器2 比较输出通道3*/
  3. TIM_CCxChannelCmd(TIM2,TIM_CHANNEL_3, TIM_CCx_DISABLE); /* 使能定时器2比较输出通道3 */
  4. __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_CC3); /* 清除指定的TIM2中断标志3 */
  5. __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_CC3); /* 使能定时器2比较输出3 */
  6. /* Enable the main output */
  7. __HAL_TIM_MOE_ENABLE(&htim2); /* 启用TIM2主输出 */
  8. HAL_TIM_Base_Start(&htim2); /* 使能定时器2 */
  9. /* USER CODE END TIM2_Init 2 */
  10. /* USER CODE BEGIN TIM3_Init 2 */
  11. HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_1); /*停止定时器3 比较输出通道1*/
  12. HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_2); /*停止定时器3 比较输出通道2*/
  13. TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_1, TIM_CCx_DISABLE); /* 使能定时器3比较输出通道1 */
  14. TIM_CCxChannelCmd(TIM3,TIM_CHANNEL_2, TIM_CCx_DISABLE); /* 使能定时器3比较输出通道2 */
  15. __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_CC1); /* 清除指定的TIM3中断标志1 */
  16. __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_CC2); /* 清除指定的TIM3中断标志2 */
  17. __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_CC1); /* 使能定时器3比较输出1 */
  18. __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_CC2); /* 使能定时器3比较输出2 */
  19. /* Enable the main output */
  20. __HAL_TIM_MOE_ENABLE(&htim3); /* 启用TIM3主输出 */
  21. HAL_TIM_Base_Start(&htim3); /* 使能定时器3 */
  22. /* USER CODE END TIM3_Init 2 */

4. main函数配置

  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. *******************孔板X轴移动の电机**********************************
  17. PUL--->PA6
  18. DIR--->PB8
  19. ENA--->PB9
  20. OPTO--->3.3V
  21. *******************加液针头Y轴移动の电机****************************************
  22. PUL--->PA7
  23. DIR--->PB7
  24. ENA--->PC7
  25. OPTO--->3.3V
  26. *******************蠕动泵の电机****************************************
  27. PUL+-->5V
  28. PUL--->PA2
  29. DIR--->PC6
  30. ENA--->PB12
  31. ******************************************************************************
  32. * 此行为测试VS2022与Keil能否同步开发
  33. */
  34. /* USER CODE END Header */
  35. /* Includes ------------------------------------------------------------------*/
  36. #include "main.h"
  37. #include "tim.h"
  38. #include "usart.h"
  39. #include "gpio.h"
  40. /* Private includes ----------------------------------------------------------*/
  41. /* USER CODE BEGIN Includes */
  42. #include "Motor.h"
  43. /* USER CODE END Includes */
  44. /* Private typedef -----------------------------------------------------------*/
  45. /* USER CODE BEGIN PTD */
  46. /* USER CODE END PTD */
  47. /* Private define ------------------------------------------------------------*/
  48. /* USER CODE BEGIN PD */
  49. /* USER CODE END PD */
  50. /* Private macro -------------------------------------------------------------*/
  51. /* USER CODE BEGIN PM */
  52. /* USER CODE END PM */
  53. /* Private variables ---------------------------------------------------------*/
  54. /* USER CODE BEGIN PV */
  55. /* USER CODE END PV */
  56. /* Private function prototypes -----------------------------------------------*/
  57. void SystemClock_Config(void);
  58. /* USER CODE BEGIN PFP */
  59. /* USER CODE END PFP */
  60. /* Private user code ---------------------------------------------------------*/
  61. /* USER CODE BEGIN 0 */
  62. uint8_t Tx_str1[] = "Wellcome_Gerhart!\r\n";
  63. uint8_t Tx_str2[] = "X1_Forward!\r\n";
  64. uint8_t Tx_str3[] = "X1_Reversal!\r\n";
  65. uint8_t Tx_str4[] = "Stop!\r\n";
  66. uint8_t Tx_str5[] = "Y1_Forward!\r\n";
  67. uint8_t Tx_str6[] = "Y1_Reversal!\r\n";
  68. uint8_t Tx_str7[] = "P1_Forward!\r\n";
  69. uint8_t Tx_str8[] = "P1_Reversal!\r\n";
  70. uint8_t Rx_dat = 0;
  71. void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)
  72. {
  73. if (huart->Instance == USART1)//这部分作用是通过串口控制电机
  74. {
  75. if (Rx_dat == 0xa1)//发送A1电机X正转
  76. {
  77. X_STEPMOTOR_AxisMoveRel(1 * 16 * 200, 9, 9, 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
  78. HAL_UART_Transmit(&huart1, Tx_str2, sizeof(Tx_str2), 500);
  79. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  80. }
  81. else if (Rx_dat == 0xa2)//发送A2电机X反转
  82. {
  83. X_STEPMOTOR_AxisMoveRel(1 * 16 * -200, 9, 9, 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
  84. HAL_UART_Transmit(&huart1, Tx_str3, sizeof(Tx_str3), 500);
  85. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  86. }
  87. else if (Rx_dat == 0xa3)//发送A3电机X停止
  88. {
  89. X_Motor_OFF();
  90. HAL_UART_Transmit(&huart1, Tx_str4, sizeof(Tx_str4), 500);
  91. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  92. }
  93. else if (Rx_dat == 0xa4)//发送A4电机Y正转
  94. {
  95. Y_STEPMOTOR_AxisMoveRel(1 * 16 * 200, 9, 9, 19);//设置Y电机参数(转数,加速度,减速度,峰值速度)
  96. HAL_UART_Transmit(&huart1, Tx_str5, sizeof(Tx_str5), 500);
  97. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  98. }
  99. else if (Rx_dat == 0xa5)//发送A5电机Y反转
  100. {
  101. Y_STEPMOTOR_AxisMoveRel(1 * 16 * -200, 9, 9, 19);//设置Y电机参数(转数,加速度,减速度,峰值速度)
  102. HAL_UART_Transmit(&huart1, Tx_str6, sizeof(Tx_str6), 500);
  103. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  104. }
  105. else if (Rx_dat == 0xa6)//发送A6电机Y停止
  106. {
  107. Y_Motor_OFF();
  108. HAL_UART_Transmit(&huart1, Tx_str4, sizeof(Tx_str4), 500);
  109. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  110. }
  111. else if (Rx_dat == 0xa7)//发送A7电机P正转
  112. {
  113. P_STEPMOTOR_AxisMoveRel(1 * 16 * 200, 9, 9, 19);//设置P电机参数(转数,加速度,减速度,峰值速度)
  114. HAL_UART_Transmit(&huart1, Tx_str7, sizeof(Tx_str7), 500);
  115. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  116. }
  117. else if (Rx_dat == 0xa8)//发送A8电机P反转
  118. {
  119. P_STEPMOTOR_AxisMoveRel(1 * 16 * -200, 9, 9, 19);//设置P电机参数(转数,加速度,减速度,峰值速度)
  120. HAL_UART_Transmit(&huart1, Tx_str8, sizeof(Tx_str8), 500);
  121. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  122. }
  123. else if (Rx_dat == 0xa9)//发送A9电机P停止
  124. {
  125. P_Motor_OFF();
  126. HAL_UART_Transmit(&huart1, Tx_str4, sizeof(Tx_str4), 500);
  127. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  128. }
  129. }
  130. }
  131. /* USER CODE END 0 */
  132. /**
  133. * @brief The application entry point.
  134. * @retval int
  135. */
  136. int main(void)
  137. {
  138. /* USER CODE BEGIN 1 */
  139. /* USER CODE END 1 */
  140. /* MCU Configuration--------------------------------------------------------*/
  141. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  142. HAL_Init();
  143. /* USER CODE BEGIN Init */
  144. /* USER CODE END Init */
  145. /* Configure the system clock */
  146. SystemClock_Config();
  147. /* USER CODE BEGIN SysInit */
  148. /* USER CODE END SysInit */
  149. /* Initialize all configured peripherals */
  150. MX_GPIO_Init();
  151. MX_TIM3_Init();
  152. MX_USART1_UART_Init();
  153. MX_TIM2_Init();
  154. /* USER CODE BEGIN 2 */
  155. HAL_UART_Transmit(&huart1, Tx_str1, sizeof(Tx_str1), 10000);
  156. HAL_UART_Receive_IT(&huart1, &Rx_dat, 1);
  157. /* USER CODE END 2 */
  158. /* Infinite loop */
  159. /* USER CODE BEGIN WHILE */
  160. while (1)
  161. {
  162. // HAL_Delay(1000);
  163. // P_STEPMOTOR_AxisMoveRel(1*16*200, 9, 9 , 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
  164. // HAL_Delay(5000);
  165. // P_STEPMOTOR_AxisMoveRel(1*16*-200, 9, 9 , 19);//设置X电机参数(转数,加速度,减速度,峰值速度)
  166. // HAL_Delay(5000);
  167. }
  168. /* USER CODE END WHILE */
  169. /* USER CODE BEGIN 3 */
  170. /* USER CODE END 3 */
  171. }
  172. /**
  173. * @brief System Clock Configuration
  174. * @retval None
  175. */
  176. void SystemClock_Config(void)
  177. {
  178. RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
  179. RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
  180. /** Initializes the RCC Oscillators according to the specified parameters
  181. * in the RCC_OscInitTypeDef structure.
  182. */
  183. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  184. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  185. RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  186. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  187. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  188. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  189. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  190. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  191. {
  192. Error_Handler();
  193. }
  194. /** Initializes the CPU, AHB and APB buses clocks
  195. */
  196. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
  197. | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  198. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  199. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  200. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  201. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  202. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  203. {
  204. Error_Handler();
  205. }
  206. }
  207. /* USER CODE BEGIN 4 */
  208. /* USER CODE END 4 */
  209. /**
  210. * @brief This function is executed in case of error occurrence.
  211. * @retval None
  212. */
  213. void Error_Handler(void)
  214. {
  215. /* USER CODE BEGIN Error_Handler_Debug */
  216. /* User can add his own implementation to report the HAL error return state */
  217. __disable_irq();
  218. while (1)
  219. {
  220. }
  221. /* USER CODE END Error_Handler_Debug */
  222. }
  223. #ifdef USE_FULL_ASSERT
  224. /**
  225. * @brief Reports the name of the source file and the source line number
  226. * where the assert_param error has occurred.
  227. * @param file: pointer to the source file name
  228. * @param line: assert_param error line source number
  229. * @retval None
  230. */
  231. void assert_failed(uint8_t* file, uint32_t line)
  232. {
  233. /* USER CODE BEGIN 6 */
  234. /* User can add his own implementation to report the file name and line number,
  235. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  236. /* USER CODE END 6 */
  237. }
  238. #endif /* USE_FULL_ASSERT */

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/782859
推荐阅读
相关标签
  

闽ICP备14008679号