#include "pwm.h" #define TIMING_TICK 1800000 #define INTERVAL_TICK 30000 #define CLCK 48 pwm_message_t pwm_message={.s_hardware_frequency=1}; // uint32_t s_hardware_frequency; //单位ms,保存现在的PWM频率 // uint32_t s_hardware_duty; //单位ms,保存现在的PWM占空比 // uint32_t s_large_period; //单位ms,保存现在的定时周期 // uint32_t s_large_duty = 100; //单位ms,保存现在的定时占空比 /** * @brief s_large_duty是由s_large_period与INTERVAL_TIME决定 * s_large_duty = INTERVAL_TIME/s_large_period * 例如:s_large_period=1800000 * s_large_duty = (30000/1800000)*100 * */ uint32_t begin_ticket; uint8_t update_large_period_count; bool enableFlag = false; void HOOK_pwm_module_set_pwm_duty(uint32_t frequency, uint32_t duty) { ozone_pwm_control_set_pwm_duty(frequency, duty); } void HOOK_pwm_stop(void) { HOOK_pwm_module_set_pwm_duty(0, 0); //关闭PWM输出 port_fan_set(false); //风扇结束工作 } bool HOOK_pwm_is_enable(void) { return enableFlag; } /** * @brief 按键按下后调用这个方法更新定时周期 * */ void update_large_period(void) { uint32_t large_period; update_large_period_count++; switch (update_large_period_count) { case 1: large_period = 1 * TIMING_TICK; break; case 2: large_period = 2 * TIMING_TICK; break; case 3: large_period = 3 * TIMING_TICK; break; case 4: large_period = 4 * TIMING_TICK; break; case 5: update_large_period_count = 0; large_period = 0 * TIMING_TICK; break; } pwm_module_set_pwm_output_1( large_period, pwm_message.s_large_duty); //将更新后的周期以及现在的占空比,进行设置 } /** * @brief 一直工作的时间定时的占空比为100, * 间歇时间设置300000 * @param freq * @param duty */ void pwm_module_set_pwm_output_1(uint32_t large_period, uint32_t large_duty) { pwm_module_set_pwm_output_2(pwm_message.s_hardware_frequency, pwm_message.s_hardware_duty, large_period, large_duty); } /** * @brief 定时和PWM * * @param hardware_period pwm频率 * @param hardware_duty pwm占空比 * @param large_period 定时周期 * @param large_duty 定时占空比 */ void pwm_module_set_pwm_output_2(uint32_t hardware_period, uint32_t hardware_duty, uint32_t large_period, uint32_t large_duty) { pwm_message.s_hardware_frequency = hardware_period; pwm_message.s_hardware_duty = hardware_duty; pwm_message.s_large_period = large_period; pwm_message.s_large_duty = large_duty; begin_ticket = get_sys_ticket(); enableFlag = true; HOOK_pwm_module_set_pwm_duty(pwm_message.s_hardware_frequency, pwm_message.s_hardware_duty); } void pwm_module_stop_pwm(void) { enableFlag = false; } void pwm_module_loop(void) { if (!enableFlag) { HOOK_pwm_stop(); return; } if (port_haspassedms(begin_ticket) % pwm_message.s_large_period <= pwm_message.s_large_period * pwm_message.s_large_duty / 100) { if (!HOOK_pwm_is_enable()) { HOOK_pwm_module_set_pwm_duty(pwm_message.s_hardware_frequency, pwm_message.s_hardware_duty); } } else { enableFlag = false; HOOK_pwm_stop(); } } //###################################################### double calculate_top(double target_frequency) { int clck = 0; int target_frequency_hz = 0; int top = 0; clck = CLCK * 1000 * 1000; target_frequency_hz = (int)target_frequency * 1000; // printf("target_frequency_hz%d\n", target_frequency_hz); top = clck / target_frequency_hz; // printf("top%d\t\n", top); return top; } double calculate_MAT2(double top, double duty) { double percentage_duty = 0; double Mat2 = 0; percentage_duty = duty / 100; Mat2 = top * percentage_duty; return Mat2; } void ozone_pwm_control_set_pwm_duty(uint32_t frequency, uint32_t duty) { double top = 0; double Mat2 = 0; if (frequency > CLCK * 1000) { printf("out of range\n"); return; } top = calculate_top(frequency); //根据需要的频率计算出TOP(自动重装载值) if (top == 0) { return; } Mat2 = calculate_MAT2(top, duty); printf("top:\t%2.lf\n", top); printf("MAT2:\t%2.lf\n", Mat2); printf("MAT3:\t%2.lf\n", top); T16Nx_Disable(T16N0); t16n0_1_init(); T16Nx_SetMAT2(T16N0, Mat2); if (duty == 100) { T16Nx_SetMAT3(T16N0, top - 1); } else { T16Nx_SetMAT3(T16N0, top); } T16Nx_SetTOP1(T16N0, top); } //######################################################