#include "kt_fan_ac.h" #include "asm/mcpwm.h" #include "system/timer.h" #include "tone_player.h" #include "kt_led7.h" typedef struct _kt_fan_ac_var_ { kt_fan_level_type front_fan_level; // 前风扇档位 kt_fan_level_type rear_fan_level; // 后风扇档位 kt_fan_level_type lr_fan_level; // 左右风扇档位 kt_ac_level_type ac_level; // 空调档位 } _kt_fan_ac_var; static _kt_fan_ac_var kt_fan_ac_var; #define __this (&kt_fan_ac_var) #define KT_FAN_PWM_FREQ 50000 #define KT_AC_PWM_FREQ 100000 #define KT_AC_RUN_DUTY 4000 /* 空调运行占空比 40% */ #define KT_AC_BURST_MS 1000 /* AC1 断续:1s 开 / 1s 关 */ /* 1: 上电即输出不同占空比,便于示波器/万用表区分各路;量产改 0 */ #define KT_PWM_BOOT_TEST_EN 0 const u32 fan_level_duty[7] = {0, 1500, 4000, 6000, 7000, 8000, 9500}; static u16 ac_burst_timer; static u8 ac_burst_pwm_on; const char *front_fan_level_tone[7] = {TONE_FFAN_L0, TONE_FFAN_L1, TONE_FFAN_L2, TONE_FFAN_L3, TONE_FFAN_L4, TONE_FFAN_L5, TONE_FFAN_L6}; const char *rear_fan_level_tone[7] = {TONE_BFAN_L0, TONE_BFAN_L1, TONE_BFAN_L2, TONE_BFAN_L3, TONE_BFAN_L4, TONE_BFAN_L5, TONE_BFAN_L6}; const char *lr_fan_level_tone[7] = {TONE_CFAN_L0, TONE_CFAN_L1, TONE_CFAN_L2, TONE_CFAN_L3, TONE_CFAN_L4, TONE_CFAN_L5, TONE_CFAN_L6}; const char *ac_level_tone[3] = {TONE_AC_L0, TONE_AC_L1, TONE_AC_L2}; extern void mcpwm_init(struct pwm_platform_data *arg); extern void mcpwm_set_duty(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch, u16 duty); static void kt_ac_burst_stop(void) { if (ac_burst_timer) { sys_timer_del(ac_burst_timer); ac_burst_timer = 0; } } static void kt_ac_pwm_output(u16 duty) { mcpwm_set_duty(pwm_ch3, pwm_timer3, duty); } static void kt_ac_burst_cb(void *priv) { (void)priv; if (__this->ac_level != ac_level_1) { return; } ac_burst_pwm_on = !ac_burst_pwm_on; kt_ac_pwm_output(ac_burst_pwm_on ? KT_AC_RUN_DUTY : 0); } static void kt_ac_apply_mode(void) { kt_ac_burst_stop(); switch (__this->ac_level) { case ac_level_0: ac_burst_pwm_on = 0; kt_ac_pwm_output(0); break; case ac_level_1: ac_burst_pwm_on = 1; kt_ac_pwm_output(KT_AC_RUN_DUTY); ac_burst_timer = sys_timer_add(NULL, kt_ac_burst_cb, KT_AC_BURST_MS); break; case ac_level_2: ac_burst_pwm_on = 1; kt_ac_pwm_output(KT_AC_RUN_DUTY); break; default: ac_burst_pwm_on = 0; kt_ac_pwm_output(0); break; } } void kt_fan_ac_init(void) { /* * 前风扇 PB5 : MCPWM CH0 + output_channel 0(非硬件脚) * 后风扇 PB6 : MCPWM CH2 L 硬件脚 * 左右风扇 PA10: MCPWM CH4 L 硬件脚 * 空调 PB9 : MCPWM CH3 H 硬件脚(100kHz) */ #if KT_PWM_BOOT_TEST_EN /* 前15% / 后40% / 左右60% / 空调80%,上电即可区分四路 */ __this->front_fan_level = fan_level_1; __this->rear_fan_level = fan_level_2; __this->lr_fan_level = fan_level_3; __this->ac_level = ac_level_2; #else __this->front_fan_level = fan_level_0; __this->rear_fan_level = fan_level_0; __this->lr_fan_level = fan_level_0; __this->ac_level = ac_level_0; #endif struct pwm_platform_data pwm_p_data; /* 前风扇 PB5 */ pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; pwm_p_data.frequency = KT_FAN_PWM_FREQ; pwm_p_data.pwm_ch_num = pwm_ch0; pwm_p_data.pwm_timer_num = pwm_timer0; pwm_p_data.duty = fan_level_duty[__this->front_fan_level]; pwm_p_data.h_pin = KT_CFG_FRONT_FAN_PIN; pwm_p_data.l_pin = -1; pwm_p_data.h_pin_output_ch_num = 0; pwm_p_data.complementary_en = 0; mcpwm_init(&pwm_p_data); /* 后风扇 PB6 */ pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; pwm_p_data.frequency = KT_FAN_PWM_FREQ; pwm_p_data.pwm_ch_num = pwm_ch2; pwm_p_data.pwm_timer_num = pwm_timer2; pwm_p_data.duty = fan_level_duty[__this->rear_fan_level]; pwm_p_data.h_pin = -1; pwm_p_data.l_pin = KT_CFG_REAR_FAN_PIN; pwm_p_data.complementary_en = 0; mcpwm_init(&pwm_p_data); /* 左右风扇 PA10 */ pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; pwm_p_data.frequency = KT_FAN_PWM_FREQ; pwm_p_data.pwm_ch_num = pwm_ch4; pwm_p_data.pwm_timer_num = pwm_timer4; pwm_p_data.duty = fan_level_duty[__this->lr_fan_level]; pwm_p_data.h_pin = -1; pwm_p_data.l_pin = KT_CFG_LR_FAN_PIN; pwm_p_data.complementary_en = 0; mcpwm_init(&pwm_p_data); /* 空调 PB9 */ pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; pwm_p_data.frequency = KT_AC_PWM_FREQ; pwm_p_data.pwm_ch_num = pwm_ch3; pwm_p_data.pwm_timer_num = pwm_timer3; pwm_p_data.duty = 0; pwm_p_data.h_pin = KT_CFG_AIR_COND_PIN; pwm_p_data.l_pin = -1; pwm_p_data.complementary_en = 0; mcpwm_init(&pwm_p_data); kt_ac_apply_mode(); #if KT_PWM_BOOT_TEST_EN printf("PWM boot test: PB5=%u%% PB6=%u%% PA10=%u%% PB9=AC%d\n", fan_level_duty[__this->front_fan_level] / 100, fan_level_duty[__this->rear_fan_level] / 100, fan_level_duty[__this->lr_fan_level] / 100, __this->ac_level); #endif } void kt_fan_level_tone_play(kt_fan_type fan) { if (fan == fan_type_front) { char str[6] = {0}; sprintf(str, "L-%d", __this->front_fan_level); kt_led7_show_string(3, 0, (const u8 *)str, 0, 0); tone_play(front_fan_level_tone[__this->front_fan_level], 0); } else if (fan == fan_type_rear) { char str[6] = {0}; sprintf(str, "F-%d", __this->rear_fan_level); kt_led7_show_string(3, 0, (const u8 *)str, 0, 0); tone_play(rear_fan_level_tone[__this->rear_fan_level], 0); } else if (fan == fan_type_lr) { char str[6] = {0}; sprintf(str, "C-%d", __this->lr_fan_level); kt_led7_show_string(3, 0, (const u8 *)str, 0, 0); tone_play(lr_fan_level_tone[__this->lr_fan_level], 0); } else { char str[6] = {0}; sprintf(str, "AC%d", __this->ac_level); kt_led7_show_string(3, 0, (const u8 *)str, 0, 0); tone_play(ac_level_tone[__this->ac_level], 0); } } void kt_fan_level_change(kt_fan_type fan) { if (fan == fan_type_front) { __this->front_fan_level++; if (__this->front_fan_level > fan_level_6) { __this->front_fan_level = fan_level_0; } kt_fan_level_tone_play(fan_type_front); mcpwm_set_duty(pwm_ch0, pwm_timer0, fan_level_duty[__this->front_fan_level]); } else if (fan == fan_type_rear) { __this->rear_fan_level++; if (__this->rear_fan_level > fan_level_6) { __this->rear_fan_level = fan_level_0; } kt_fan_level_tone_play(fan_type_rear); mcpwm_set_duty(pwm_ch2, pwm_timer2, fan_level_duty[__this->rear_fan_level]); } else if (fan == fan_type_lr) { __this->lr_fan_level++; if (__this->lr_fan_level > fan_level_6) { __this->lr_fan_level = fan_level_0; } kt_fan_level_tone_play(fan_type_lr); mcpwm_set_duty(pwm_ch4, pwm_timer4, fan_level_duty[__this->lr_fan_level]); } else { __this->ac_level++; if (__this->ac_level > ac_level_2) { __this->ac_level = ac_level_0; } kt_fan_level_tone_play(fan_type_ac); kt_ac_apply_mode(); } }