#include #include #include #include #include #include "board.h" #include "port.h" // #include "gpio.h" #include "main.h" #include "tim.h" #include "usart.h" // #include "stm32f429xx.h" #include "stm32f4xx_hal_tim.h" #include "stm32f4xx_hal_usart.h" /** * @brief 初始化所有IO状态 */ /** * @brief 底层驱动 */ #define LOG_RELEASE(fmt, ...) printf("" fmt, ##__VA_ARGS__); #define LOGI(fmt, ...) printf("I:" fmt, ##__VA_ARGS__); #define LOGD(fmt, ...) printf("D:" fmt, ##__VA_ARGS__); #define LOGE(fmt, ...) printf("E:" fmt, ##__VA_ARGS__); static uint8_t s_order_rxbuf; static uint8_t s_rxbuf[20]; static uint8_t s_rxbuf_has_received; static bool s_rxbuf_is_ready; //连续输出PWM static bool g_continue_output_mode; static uint32_t g_pulse_num = 0; static bool g_internal_sync_mode; void set_mode_in_internal_pwm_mode() { LOG_RELEASE("内部信号同步模式\n"); EXT_OEn_SET(true); PWM_OEn_SET(false); g_internal_sync_mode = true; } void set_mode_in_external_pwm_mode() { EXT_OEn_SET(false); PWM_OEn_SET(true); LOG_RELEASE("外部信号同步模式\n"); g_internal_sync_mode = false; } /** * @brief 串口数据接收回调 * * @param husart */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (&huart1 == huart) { /** * @brief 接收并处指令串口的数据 */ if (!s_rxbuf_is_ready) { if (s_order_rxbuf == 'S') { s_rxbuf[s_rxbuf_has_received] = s_order_rxbuf; s_rxbuf_has_received++; } else if (s_rxbuf_has_received != 0) { s_rxbuf[s_rxbuf_has_received] = s_order_rxbuf; s_rxbuf_has_received++; } if (s_rxbuf_has_received == 20) { s_rxbuf_is_ready = true; } } HAL_UART_Receive_IT(&huart1, &s_order_rxbuf, 1); } } void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { if (&huart1 == huart) { HAL_UART_Receive_IT(&huart1, &s_order_rxbuf, 1); } } void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM3) { /** * @brief 当触发完指定数量的脉冲时,停止触发 */ if (g_continue_output_mode) return; if (g_pulse_num == 0) { HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1); } else { g_pulse_num--; } } } /** * @brief 计算PWM的周期 * * @param target_pluse_width_us * @param targetfreq * @param arr * @return uint16_t 返回COMPARE寄存器的数值 */ uint16_t get_tim_compare_value(int32_t target_pluse_width_us, int32_t targetfreq, uint16_t arr) { uint16_t comparevalue = 0; float periodus = 1.0 / targetfreq * 1000 * 1000; float duty_radio = target_pluse_width_us / periodus; if (duty_radio >= 1) duty_radio = 1; comparevalue = duty_radio * (arr + 1); if (comparevalue < 2) { return 1; } comparevalue = comparevalue - 1; return comparevalue; } /** * @brief 触发一次PWM * * @param freq * @param pluse_width * @param pluse_num */ void trigger_pwm(int32_t freq, float duty, int32_t pluse_num) { #if 1 LOGI("I:trigger pwm freq[%d] duty[%f]us pluse_num[%d]\n", freq, duty, pluse_num); #endif //无论怎样先停止PWM输 HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1); if (freq == 0) { LOGE("E:trigger pwm fail,freq == 0\n"); return; } // 确定预分频参数,重载值 float psc_x_arr = 84 * 1000 * 1000 / freq; uint32_t psc = 0; uint32_t arr = 65534; for (; arr > 2; arr--) { psc = psc_x_arr / arr; if (psc >= 1) { uint32_t tmparr = psc_x_arr / psc; if (tmparr >= 65534) continue; break; } } if (psc == 0) return; if (arr <= 3) return; //定时器一周期的分辨率太小了 arr = psc_x_arr / psc; arr = arr - 1; psc = psc - 1; __HAL_TIM_SET_AUTORELOAD(&htim3, arr); __HAL_TIM_SET_PRESCALER(&htim3, psc); // 确定PWM通道占空比 uint16_t comparevalue = duty * arr; __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, comparevalue); if (pluse_num == 0) { g_continue_output_mode = true; } else { g_pulse_num = pluse_num - 1; g_continue_output_mode = false; } __HAL_TIM_SET_COUNTER(&htim3, 0); LOGI("I:trigger arr [%d] psc[%d] comparevalue[%d]\n", arr, psc, comparevalue); HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1); } void process_rxbuf() { // clang-format off /** * * @brief 协议 * * [S] [2][3][4][5][6] [7][8][9][10][11][12][13] [14][15][16][17][18][19][20] * 开始标志 频率值HZ 脉宽us 脉冲数 * * */ // clang-format on char freq_c[6] = {0}; char pluse_width_c[8] = {0}; char pluse_num_c[8] = {0}; int32_t freq = 0, pluse_width = 0, pluse_num = 0; memcpy(freq_c, &s_rxbuf[1], 5); memcpy(pluse_width_c, &s_rxbuf[6], 7); memcpy(pluse_num_c, &s_rxbuf[13], 7); freq = atoi(freq_c); pluse_width = atoi(pluse_width_c); pluse_num = atoi(pluse_num_c); //使能内部,失能外部 set_mode_in_internal_pwm_mode(); /** * @brief 触发一次pwm */ LOG_RELEASE("触发PWM 频率:%dHZ,脉冲宽度:%dus,脉冲数量:%d\n", freq, pluse_width, pluse_num); float duty = pluse_width / (1 * 1000 * 1000 / freq); trigger_pwm(freq, duty, pluse_num); } void user_main() { LOG_RELEASE("同步盒子\n"); LOG_RELEASE("网址:%s\n", "www.zwtime.com"); LOG_RELEASE("软件版本:%s\n", VERSION); LOGI("I:wavebox sv:%s\n", VERSION); HAL_UART_Receive_IT(&huart1, &s_order_rxbuf, 1); set_mode_in_external_pwm_mode(); while (true) { /** * @brief 处理接收到的数据 */ if (s_rxbuf_is_ready) { process_rxbuf(); s_rxbuf_is_ready = false; } /** * @brief 调制指示灯 */ { static uint32_t lastprocess = 0; if (port_haspassedms(lastprocess) > 300) { lastprocess = HAL_GetTick(); HAL_GPIO_TogglePin(DEBUG_LIGHT_PORT, DEBUG_LIGHT_PIN); } } /**/ } }