You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
5.9 KiB

  1. #include <stdbool.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "board.h"
  7. #include "port.h"
  8. //
  9. #include "gpio.h"
  10. #include "main.h"
  11. #include "tim.h"
  12. #include "usart.h"
  13. //
  14. #include "stm32f429xx.h"
  15. #include "stm32f4xx_hal_tim.h"
  16. #include "stm32f4xx_hal_usart.h"
  17. /**
  18. * @brief IO状态
  19. */
  20. /**
  21. * @brief
  22. */
  23. #define LOG_RELEASE(fmt, ...) printf("" fmt, ##__VA_ARGS__);
  24. #define LOGI(fmt, ...) printf("I:" fmt, ##__VA_ARGS__);
  25. #define LOGD(fmt, ...) printf("D:" fmt, ##__VA_ARGS__);
  26. #define LOGE(fmt, ...) printf("E:" fmt, ##__VA_ARGS__);
  27. static uint8_t s_order_rxbuf;
  28. static uint8_t s_rxbuf[20];
  29. static uint8_t s_rxbuf_has_received;
  30. static bool s_rxbuf_is_ready;
  31. //连续输出PWM
  32. static bool g_continue_output_mode;
  33. static uint32_t g_pulse_num = 0;
  34. static bool g_internal_sync_mode;
  35. void set_mode_in_internal_pwm_mode() {
  36. LOG_RELEASE("内部信号同步模式\n");
  37. EXT_OEn_SET(true);
  38. PWM_OEn_SET(false);
  39. g_internal_sync_mode = true;
  40. }
  41. void set_mode_in_external_pwm_mode() {
  42. EXT_OEn_SET(false);
  43. PWM_OEn_SET(true);
  44. LOG_RELEASE("外部信号同步模式\n");
  45. g_internal_sync_mode = false;
  46. }
  47. /**
  48. * @brief
  49. *
  50. * @param husart
  51. */
  52. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
  53. if (&huart1 == huart) {
  54. /**
  55. * @brief
  56. */
  57. if (!s_rxbuf_is_ready) {
  58. if (s_order_rxbuf == 'S') {
  59. s_rxbuf[s_rxbuf_has_received] = s_order_rxbuf;
  60. s_rxbuf_has_received++;
  61. } else if (s_rxbuf_has_received != 0) {
  62. s_rxbuf[s_rxbuf_has_received] = s_order_rxbuf;
  63. s_rxbuf_has_received++;
  64. }
  65. if (s_rxbuf_has_received == 20) {
  66. s_rxbuf_is_ready = true;
  67. }
  68. }
  69. HAL_UART_Receive_IT(&huart1, &s_order_rxbuf, 1);
  70. }
  71. }
  72. void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
  73. if (&huart1 == huart) {
  74. HAL_UART_Receive_IT(&huart1, &s_order_rxbuf, 1);
  75. }
  76. }
  77. void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
  78. if (htim->Instance == TIM3) {
  79. /**
  80. * @brief
  81. */
  82. if (g_continue_output_mode) return;
  83. if (g_pulse_num == 0) {
  84. HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1);
  85. } else {
  86. g_pulse_num--;
  87. }
  88. }
  89. }
  90. /**
  91. * @brief PWM的周期
  92. *
  93. * @param target_pluse_width_us
  94. * @param targetfreq
  95. * @param arr
  96. * @return uint16_t COMPARE寄存器的数值
  97. */
  98. uint16_t get_tim_compare_value(int32_t target_pluse_width_us,
  99. int32_t targetfreq, uint16_t arr) {
  100. uint16_t comparevalue = 0;
  101. float periodus = 1.0 / targetfreq * 1000 * 1000;
  102. float duty_radio = target_pluse_width_us / periodus;
  103. if (duty_radio >= 1) duty_radio = 1;
  104. comparevalue = duty_radio * (arr + 1);
  105. if (comparevalue < 2) {
  106. return 1;
  107. }
  108. comparevalue = comparevalue - 1;
  109. return comparevalue;
  110. }
  111. /**
  112. * @brief PWM
  113. *
  114. * @param freq
  115. * @param pluse_width
  116. * @param pluse_num
  117. */
  118. void trigger_pwm(int32_t freq, float duty, int32_t pluse_num) {
  119. #if 1
  120. LOGI("I:trigger pwm freq[%d] duty[%f]us pluse_num[%d]\n", freq, duty,
  121. pluse_num);
  122. #endif
  123. //无论怎样先停止PWM输
  124. HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1);
  125. if (freq == 0) {
  126. LOGE("E:trigger pwm fail,freq == 0\n");
  127. return;
  128. }
  129. // 确定预分频参数,重载值
  130. float psc_x_arr = 84 * 1000 * 1000 / freq;
  131. uint32_t psc = 0;
  132. uint32_t arr = 65534;
  133. for (; arr > 2; arr--) {
  134. psc = psc_x_arr / arr;
  135. if (psc >= 1) {
  136. uint32_t tmparr = psc_x_arr / psc;
  137. if (tmparr >= 65534) continue;
  138. break;
  139. }
  140. }
  141. if (psc == 0) return;
  142. if (arr <= 3) return; //定时器一周期的分辨率太小了
  143. arr = psc_x_arr / psc;
  144. arr = arr - 1;
  145. psc = psc - 1;
  146. __HAL_TIM_SET_AUTORELOAD(&htim3, arr);
  147. __HAL_TIM_SET_PRESCALER(&htim3, psc);
  148. // 确定PWM通道占空比
  149. uint16_t comparevalue = duty * arr;
  150. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, comparevalue);
  151. if (pluse_num == 0) {
  152. g_continue_output_mode = true;
  153. } else {
  154. g_pulse_num = pluse_num - 1;
  155. g_continue_output_mode = false;
  156. }
  157. __HAL_TIM_SET_COUNTER(&htim3, 0);
  158. LOGI("I:trigger arr [%d] psc[%d] comparevalue[%d]\n", arr, psc, comparevalue);
  159. HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1);
  160. }
  161. void process_rxbuf() {
  162. // clang-format off
  163. /**
  164. *
  165. * @brief
  166. *
  167. * [S] [2][3][4][5][6] [7][8][9][10][11][12][13] [14][15][16][17][18][19][20]
  168. * HZ us
  169. *
  170. *
  171. */
  172. // clang-format on
  173. char freq_c[6] = {0};
  174. char pluse_width_c[8] = {0};
  175. char pluse_num_c[8] = {0};
  176. int32_t freq = 0, pluse_width = 0, pluse_num = 0;
  177. memcpy(freq_c, &s_rxbuf[1], 5);
  178. memcpy(pluse_width_c, &s_rxbuf[6], 7);
  179. memcpy(pluse_num_c, &s_rxbuf[13], 7);
  180. freq = atoi(freq_c);
  181. pluse_width = atoi(pluse_width_c);
  182. pluse_num = atoi(pluse_num_c);
  183. //使能内部,失能外部
  184. set_mode_in_internal_pwm_mode();
  185. /**
  186. * @brief pwm
  187. */
  188. LOG_RELEASE("触发PWM 频率:%dHZ,脉冲宽度:%dus,脉冲数量:%d\n", freq,
  189. pluse_width, pluse_num);
  190. float duty = pluse_width / (1 * 1000 * 1000 / freq);
  191. trigger_pwm(freq, duty, pluse_num);
  192. }
  193. void user_main() {
  194. LOG_RELEASE("同步盒子\n");
  195. LOG_RELEASE("网址:%s\n", "www.zwtime.com");
  196. LOG_RELEASE("软件版本:%s\n", VERSION);
  197. LOGI("I:wavebox sv:%s\n", VERSION);
  198. HAL_UART_Receive_IT(&huart1, &s_order_rxbuf, 1);
  199. set_mode_in_external_pwm_mode();
  200. while (true) {
  201. /**
  202. * @brief
  203. */
  204. if (s_rxbuf_is_ready) {
  205. process_rxbuf();
  206. s_rxbuf_is_ready = false;
  207. }
  208. /**
  209. * @brief
  210. */
  211. {
  212. static uint32_t lastprocess = 0;
  213. if (port_haspassedms(lastprocess) > 300) {
  214. lastprocess = HAL_GetTick();
  215. HAL_GPIO_TogglePin(DEBUG_LIGHT_PORT, DEBUG_LIGHT_PIN);
  216. }
  217. }
  218. /**/
  219. }
  220. }