优化H桥PWM并增加平滑调光
This commit is contained in:
@@ -6,7 +6,8 @@
|
||||
#include "math.h"
|
||||
#include "timeslice.h"
|
||||
#include "RF433.h"
|
||||
#include "usr_server.h"
|
||||
#include "usr_server.h"
|
||||
#include "light_transition.h"
|
||||
|
||||
|
||||
uint16_t time_1[11]={8,10,12,14,16,18,20,22,24,26,26};
|
||||
@@ -22,15 +23,15 @@ uint8_t choose_mode_falsg=0; //ģʽֵ
|
||||
uint8_t choose_mode_bh=0; //模式变化
|
||||
|
||||
uint16_t Color_table_static[3][2]={
|
||||
{10,0}, //暖光
|
||||
{4,4}, //中性光
|
||||
{0,10}, //冷光
|
||||
{100,0}, // warm light
|
||||
{50,50}, // neutral light
|
||||
{0,100}, // cool light
|
||||
};
|
||||
|
||||
|
||||
uint16_t Color_table[3][2]={ //动态时候的数组
|
||||
{100,0}, //暖光
|
||||
{40,40}, //中性光
|
||||
{50,50}, //中性光
|
||||
{0,100}, //冷光
|
||||
};
|
||||
|
||||
@@ -45,20 +46,21 @@ void Set_timing(){
|
||||
}
|
||||
}
|
||||
}
|
||||
void Start_PWM(){
|
||||
void Start_PWM(){
|
||||
Light_Transition_RequestOn();
|
||||
deviceStatus=POWERON;
|
||||
startTimer(&timer1,1);
|
||||
}
|
||||
|
||||
|
||||
void Stop_PWM(){
|
||||
deviceStatus=POWEROFF;
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET);
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET);
|
||||
Light_Transition_RequestOff();
|
||||
deviceStatus=POWEROFF;
|
||||
}
|
||||
|
||||
|
||||
void set_mode(){
|
||||
void set_mode(){
|
||||
Light_Transition_Task();
|
||||
if(choose_mode_bh==0){
|
||||
choose_mode_bh=1;
|
||||
switch(choose_mode_falsg){
|
||||
@@ -148,7 +150,7 @@ void set_mode(){
|
||||
}
|
||||
}
|
||||
void Mode0(){ //常量
|
||||
UpdateDisplay();
|
||||
(void)0;/* transition */
|
||||
}
|
||||
|
||||
|
||||
@@ -263,8 +265,8 @@ void Mode1(){ //
|
||||
break;
|
||||
}
|
||||
}
|
||||
//UpdateDisplay();
|
||||
UpdateDisplay_1();
|
||||
//(void)0;/* transition */
|
||||
(void)0;/* transition */
|
||||
}
|
||||
|
||||
|
||||
@@ -337,12 +339,12 @@ void Mode2(){ //
|
||||
break;
|
||||
}
|
||||
}
|
||||
UpdateDisplay_1();
|
||||
(void)0;/* transition */
|
||||
}
|
||||
|
||||
void Mode3(){ //爆闪 //无
|
||||
|
||||
UpdateDisplay();
|
||||
(void)0;/* transition */
|
||||
}
|
||||
pfunc modefunctin[] = { //模式切换,一共15个模式
|
||||
Mode0,
|
||||
|
||||
@@ -31,7 +31,7 @@ pwm_ch_cap_type_t pwm_ch_cap_type;
|
||||
|
||||
|
||||
uint16_t timeCnt=0;
|
||||
uint16_t W_PWM = 10;//初始化暖光
|
||||
uint16_t W_PWM = 100;//初始化暖光
|
||||
uint16_t C_PWM = 0;
|
||||
|
||||
|
||||
@@ -56,31 +56,6 @@ void switch_pwm_pins(uint8_t red_pwm, uint8_t green_pwm, uint8_t blue_pwm)
|
||||
|
||||
|
||||
|
||||
float brightness_table[101] = {
|
||||
0.006f, 0.006f, 0.006f, 0.006f, 0.006f,
|
||||
0.006f, 0.006f, 0.006f, 0.007f, 0.008f,
|
||||
0.009f, 0.010f, 0.011f, 0.013f, 0.015f,
|
||||
0.018f, 0.020f, 0.023f, 0.026f, 0.029f,
|
||||
0.032f, 0.036f, 0.039f, 0.043f, 0.047f,
|
||||
0.052f, 0.056f, 0.061f, 0.066f, 0.071f,
|
||||
0.076f, 0.082f, 0.087f, 0.093f, 0.099f,
|
||||
0.106f, 0.112f, 0.119f, 0.126f, 0.133f,
|
||||
0.141f, 0.148f, 0.156f, 0.164f, 0.173f,
|
||||
0.181f, 0.190f, 0.199f, 0.208f, 0.218f,
|
||||
0.227f, 0.237f, 0.247f, 0.258f, 0.268f,
|
||||
0.279f, 0.290f, 0.302f, 0.313f, 0.325f,
|
||||
0.337f, 0.349f, 0.362f, 0.375f, 0.388f,
|
||||
0.401f, 0.414f, 0.428f, 0.442f, 0.456f,
|
||||
0.471f, 0.485f, 0.500f, 0.516f, 0.531f,
|
||||
0.547f, 0.563f, 0.579f, 0.595f, 0.612f,
|
||||
0.629f, 0.646f, 0.664f, 0.681f, 0.699f,
|
||||
0.718f, 0.736f, 0.755f, 0.774f, 0.793f,
|
||||
0.813f, 0.832f, 0.852f, 0.873f, 0.893f,
|
||||
0.914f, 0.935f, 0.957f, 0.978f, 1.000f,1.000f
|
||||
};
|
||||
|
||||
|
||||
|
||||
void _PWM_INIT(){
|
||||
|
||||
GPIO_InitCfg_t GPIO_InitCfg = { 0 }; // 清零初始化配置结构体
|
||||
@@ -115,37 +90,43 @@ void PWM_SetDuty(uint8_t PWMX ,uint8_t duty) {
|
||||
// }
|
||||
}
|
||||
|
||||
void UpdateDisplay(void) //静态更新 可以调节亮度
|
||||
static uint16_t scale_display_value(uint16_t value)
|
||||
{
|
||||
W_PWM_duty = W_PWM * Brightness;
|
||||
C_PWM_duty = C_PWM * Brightness;
|
||||
|
||||
if(value > 100U) value = 100U;
|
||||
if(Brightness > 10U) return value;
|
||||
return (uint16_t)(((uint32_t)value * Brightness + 5U) / 10U);
|
||||
}
|
||||
|
||||
void UpdateDisplay_1(void) //动态更新 不可以调节亮度,只能调节速度
|
||||
void UpdateDisplay(void) // static update with global brightness
|
||||
{
|
||||
W_PWM_duty = W_PWM;
|
||||
C_PWM_duty = C_PWM;
|
||||
// printf("dd=%d--%d--%d-%d-%d\r\n",choose_mode_falsg,W_PWM,C_PWM,driveMode,Brightness);
|
||||
W_PWM_duty = scale_display_value(W_PWM);
|
||||
C_PWM_duty = scale_display_value(C_PWM);
|
||||
}
|
||||
|
||||
void temperature(uint8_t data) //更新
|
||||
void UpdateDisplay_1(void) // dynamic update with global brightness
|
||||
{
|
||||
|
||||
driveMode=0;
|
||||
if(data<57&&data>=16){C_PWM= 0;W_PWM = 10;driveMode=1;}
|
||||
else if(data<77&&data>=57){C_PWM= 1;W_PWM = 7;}
|
||||
else if(data<101&&data>=77){C_PWM= 2;W_PWM = 6;}
|
||||
else if(data<123&&data>=101){C_PWM= 3;W_PWM = 5;}
|
||||
else if(data<145&&data>=123){C_PWM= 4;W_PWM = 4;}
|
||||
else if(data<167&&data>=145){C_PWM= 5;W_PWM = 3;}
|
||||
else if(data<194&&data>=167){C_PWM= 6;W_PWM = 2;}
|
||||
else if(data<210&&data>=194){C_PWM= 7;W_PWM = 1;}
|
||||
else if(data>=210){C_PWM= 10;W_PWM = 0;driveMode=2;}
|
||||
//printf("datat=%d-%d-%d\r\n",data,C_PWM,W_PWM);
|
||||
//data = 0;
|
||||
W_PWM_duty = scale_display_value(W_PWM);
|
||||
C_PWM_duty = scale_display_value(C_PWM);
|
||||
}
|
||||
|
||||
void temperature(uint8_t data) // 0=cold, 255=warm
|
||||
{
|
||||
W_PWM = (uint16_t)(((uint32_t)data * 100U + 127U) / 255U);
|
||||
C_PWM = 100U - W_PWM;
|
||||
|
||||
if(W_PWM >= 100U)
|
||||
{
|
||||
driveMode = 1;
|
||||
}
|
||||
else if(C_PWM >= 100U)
|
||||
{
|
||||
driveMode = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
driveMode = 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief app_pwm_init
|
||||
* @details
|
||||
|
||||
@@ -136,6 +136,10 @@ void switch_pwm_pins(uint8_t red_pwm, uint8_t green_pwm, uint8_t blue_pwm);
|
||||
void adc_Init();
|
||||
void My_ADC_Get_Value();
|
||||
void gpio_pullup_input_inter_test();
|
||||
void Bridge_Init(void);
|
||||
void Bridge_Off(void);
|
||||
void Bridge_Service_1ms(void);
|
||||
void Bridge_Deadtime_Expired(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -148,13 +148,13 @@ static void Encoder_key_NoCode(){
|
||||
isok=0;
|
||||
if(W_PWM==0&&C_PWM==0){
|
||||
if(Mode==0){
|
||||
W_PWM=10;
|
||||
W_PWM=100;
|
||||
C_PWM=0;
|
||||
UpdateDisplay();
|
||||
(void)0;/* transition */
|
||||
}else {
|
||||
W_PWM=10;
|
||||
W_PWM=100;
|
||||
C_PWM=0;
|
||||
UpdateDisplay_1();
|
||||
(void)0;/* transition */
|
||||
}
|
||||
}
|
||||
if(deviceStatus==POWEROFF){
|
||||
@@ -189,12 +189,12 @@ static void Encoder_key_NoCode(){
|
||||
match_success = 0;
|
||||
|
||||
if(W_PWM==0&&C_PWM==0){
|
||||
W_PWM=10;
|
||||
W_PWM=100;
|
||||
C_PWM=0;
|
||||
if(Mode==0){
|
||||
UpdateDisplay();
|
||||
(void)0;/* transition */
|
||||
}else {
|
||||
UpdateDisplay_1();
|
||||
(void)0;/* transition */
|
||||
}
|
||||
}
|
||||
if(deviceStatus==POWEROFF){
|
||||
@@ -398,7 +398,7 @@ void _433_fun(){
|
||||
choose_mode_bh=0;
|
||||
choose_mode_falsg=10;//圆环模式
|
||||
driveMode=0;
|
||||
temperature(res_data);
|
||||
temperature((uint8_t)(((uint16_t)(255U - res_data) * 255U + 119U) / 239U));
|
||||
startTimer(&timer1,1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -400,6 +400,7 @@ int main(void)
|
||||
bluetooth_init();
|
||||
|
||||
_PWM_INIT();
|
||||
Bridge_Init();
|
||||
// app_pwm_init();
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
#include "pwm.h"
|
||||
#include "mode.h"
|
||||
#include "xc_drv_gpio.h"
|
||||
#include "xc_drv_pwm.h"
|
||||
#include "xc_drv_timer.h"
|
||||
#include "light_transition.h"
|
||||
|
||||
/*
|
||||
* External H-bridge input states:
|
||||
* W: GPIO_1 high/PWM, GPIO_2 low
|
||||
* C: GPIO_1 low, GPIO_2 high/PWM
|
||||
* OFF: both low
|
||||
*
|
||||
* Single-color output uses a fixed 1 kHz hardware PWM.
|
||||
*
|
||||
* Dual-color output uses one fixed 1 ms frame:
|
||||
* OFF -> W pulse -> OFF -> C pulse -> OFF to frame end.
|
||||
* The available OFF time is distributed around both direction changes and
|
||||
* each W/C transition retains at least 50 us protection.
|
||||
* Both non-zero colors therefore produce exactly one pulse per frame (1 kHz).
|
||||
*/
|
||||
#define BRIDGE_PWM_SCALE 1000U
|
||||
#define BRIDGE_PWM_PERIOD 7U
|
||||
#define BRIDGE_MIX_SCALE 100U
|
||||
#define BRIDGE_FRAME_US 1000U
|
||||
#define BRIDGE_DEADTIME_US 50U
|
||||
#define BRIDGE_DUAL_ACTIVE_US 900U
|
||||
#define BRIDGE_TIMER_TICKS_PER_US 16U
|
||||
|
||||
#define BRIDGE_GPIO_PORT 0U
|
||||
#define BRIDGE_GPIO_MASK ((1UL << IO_PWM_W) | (1UL << IO_PWM_C))
|
||||
|
||||
#define BRIDGE_TIMER3_TLC_REG (*(volatile uint32_t *)0x4000303CUL)
|
||||
#define BRIDGE_TIMER3_TCR_REG (*(volatile uint32_t *)0x40003044UL)
|
||||
|
||||
#define BRIDGE_OFF 0U
|
||||
#define BRIDGE_W 1U
|
||||
#define BRIDGE_C 2U
|
||||
|
||||
#define BRIDGE_MODE_OFF 0U
|
||||
#define BRIDGE_MODE_SINGLE 1U
|
||||
#define BRIDGE_MODE_DUAL 2U
|
||||
|
||||
#define BRIDGE_STAGE_IDLE 0U
|
||||
#define BRIDGE_STAGE_START_SINGLE 1U
|
||||
#define BRIDGE_STAGE_START_W 2U
|
||||
#define BRIDGE_STAGE_END_W 3U
|
||||
#define BRIDGE_STAGE_START_C 4U
|
||||
#define BRIDGE_STAGE_END_C 5U
|
||||
|
||||
static volatile uint8_t active_state;
|
||||
static volatile uint8_t output_mode;
|
||||
static volatile uint8_t timer_stage;
|
||||
static volatile uint8_t pending_single_state;
|
||||
static volatile uint16_t pending_single_duty;
|
||||
static volatile uint16_t frame_w_us;
|
||||
static volatile uint16_t frame_c_us;
|
||||
static volatile uint16_t frame_wc_off_us;
|
||||
static volatile uint16_t frame_cw_off_us;
|
||||
static volatile uint16_t next_w_us;
|
||||
static volatile uint16_t next_c_us;
|
||||
static volatile uint16_t next_wc_off_us;
|
||||
static volatile uint16_t next_cw_off_us;
|
||||
static uint16_t cached_w_mix = 0xFFFFU;
|
||||
static uint16_t cached_c_mix = 0xFFFFU;
|
||||
static uint8_t bridge_ready;
|
||||
|
||||
__RAM_CODE static uint16_t clamp_mix_value(uint32_t value)
|
||||
{
|
||||
return (value > BRIDGE_MIX_SCALE) ? BRIDGE_MIX_SCALE : (uint16_t)value;
|
||||
}
|
||||
|
||||
static uint8_t pwm_index_for_state(uint8_t state)
|
||||
{
|
||||
return (state == BRIDGE_W) ? PWM0_IDX : PWM1_IDX;
|
||||
}
|
||||
|
||||
static void bridge_pin_low(uint8_t pin)
|
||||
{
|
||||
xc_gpio_mux_ctl(pin, GPIO_Mux0);
|
||||
xc_gpio_fun_sel(pin, GPIO_Dx);
|
||||
xc_gpio_direction_config(pin, GPIO_DIR_OUTPUT);
|
||||
xc_gpio_write_pin(pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
__RAM_CODE static void bridge_gpio_write(uint8_t state)
|
||||
{
|
||||
uint32_t output = 0U;
|
||||
|
||||
if (state == BRIDGE_W) {
|
||||
output = (1UL << IO_PWM_W);
|
||||
} else if (state == BRIDGE_C) {
|
||||
output = (1UL << IO_PWM_C);
|
||||
} else {
|
||||
state = BRIDGE_OFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* GPIO_1 and GPIO_2 share port 0. Write-enable bits update both pins
|
||||
* atomically, so an intermediate 11 state cannot be generated.
|
||||
*/
|
||||
gpio_port_dr_set(BRIDGE_GPIO_PORT,
|
||||
(BRIDGE_GPIO_MASK << DR_WE_LSB) | output);
|
||||
active_state = state;
|
||||
}
|
||||
|
||||
__RAM_CODE static void bridge_gpio_off(void)
|
||||
{
|
||||
bridge_gpio_write(BRIDGE_OFF);
|
||||
}
|
||||
|
||||
static void bridge_force_off(void)
|
||||
{
|
||||
xc_pwm_stop(PWM0_IDX);
|
||||
xc_pwm_stop(PWM1_IDX);
|
||||
bridge_pin_low(IO_PWM_W);
|
||||
bridge_pin_low(IO_PWM_C);
|
||||
bridge_gpio_off();
|
||||
}
|
||||
|
||||
__RAM_CODE static void bridge_gpio_state(uint8_t state)
|
||||
{
|
||||
bridge_gpio_write(state);
|
||||
}
|
||||
|
||||
__RAM_CODE static void bridge_timer_stop_fast(void)
|
||||
{
|
||||
BRIDGE_TIMER3_TCR_REG = 0U;
|
||||
}
|
||||
|
||||
__RAM_CODE static void bridge_timer_start(uint16_t duration_us)
|
||||
{
|
||||
uint32_t ticks;
|
||||
|
||||
if (duration_us == 0U) {
|
||||
duration_us = 1U;
|
||||
}
|
||||
|
||||
ticks = (uint32_t)duration_us * BRIDGE_TIMER_TICKS_PER_US;
|
||||
bridge_timer_stop_fast();
|
||||
BRIDGE_TIMER3_TLC_REG = ticks;
|
||||
BRIDGE_TIMER3_TCR_REG = 1U;
|
||||
}
|
||||
|
||||
static void bridge_start_pwm(uint8_t state, uint16_t duty)
|
||||
{
|
||||
uint8_t pwm_idx;
|
||||
uint8_t pin;
|
||||
GPIO_FUN_SEL_TypeDef function;
|
||||
|
||||
if (state != BRIDGE_W && state != BRIDGE_C) {
|
||||
Bridge_Off();
|
||||
return;
|
||||
}
|
||||
|
||||
pwm_idx = pwm_index_for_state(state);
|
||||
pin = (state == BRIDGE_W) ? IO_PWM_W : IO_PWM_C;
|
||||
function = (state == BRIDGE_W) ? PWM0 : PWM1;
|
||||
|
||||
bridge_force_off();
|
||||
xc_pwm_dutycycle_set(pwm_idx, BRIDGE_PWM_SCALE, duty);
|
||||
xc_gpio_mux_ctl(pin, GPIO_Mux0);
|
||||
xc_gpio_fun_sel(pin, function);
|
||||
xc_pwm_start(pwm_idx);
|
||||
|
||||
active_state = state;
|
||||
output_mode = BRIDGE_MODE_SINGLE;
|
||||
}
|
||||
|
||||
void Bridge_Init(void)
|
||||
{
|
||||
PWM_InitCfg_t pwm_cfg;
|
||||
Timer_InitCfg_t timer_cfg;
|
||||
|
||||
pwm_cfg.SrcClk = PWM_CLK_SRC_32M_DIV;
|
||||
pwm_cfg.DivClk = PWM_CLK_DIV0;
|
||||
pwm_cfg.DutyCycleAcc = BRIDGE_PWM_SCALE;
|
||||
pwm_cfg.DutyCycle = 0U;
|
||||
pwm_cfg.SrcEnable = PWM_EN_SEL_SELF;
|
||||
pwm_cfg.Period = BRIDGE_PWM_PERIOD;
|
||||
pwm_cfg.InvertDelay = 0U;
|
||||
pwm_cfg.InvertEnable = false;
|
||||
|
||||
pwm_cfg.OutputPin = IO_PWM_W;
|
||||
pwm_cfg.OutputInvertPin = IO_PWM_C;
|
||||
xc_pwm_init(PWM0_IDX, &pwm_cfg);
|
||||
|
||||
pwm_cfg.OutputPin = IO_PWM_C;
|
||||
pwm_cfg.OutputInvertPin = IO_PWM_W;
|
||||
xc_pwm_init(PWM1_IDX, &pwm_cfg);
|
||||
|
||||
timer_cfg.timer_src_clk = TIMER_CLK_SRC_32M_DIV;
|
||||
timer_cfg.timer_div_clk = TIMER_DIV_CLK_16MHzOr16K;
|
||||
timer_cfg.timer_mode = TIMER_MODE_SINGLE;
|
||||
xc_timer_init(TIMER3_IDX, &timer_cfg);
|
||||
NVIC_SetPriority((IRQn_Type)TIMER3_IRQn, 0);
|
||||
NVIC_EnableIRQ(TIMER3_IRQn);
|
||||
|
||||
bridge_ready = 1U;
|
||||
Bridge_Off();
|
||||
}
|
||||
|
||||
void Bridge_Off(void)
|
||||
{
|
||||
xc_timer_stop(TIMER3_IDX);
|
||||
timer_stage = BRIDGE_STAGE_IDLE;
|
||||
pending_single_state = BRIDGE_OFF;
|
||||
pending_single_duty = 0U;
|
||||
frame_w_us = 0U;
|
||||
frame_c_us = 0U;
|
||||
frame_wc_off_us = 0U;
|
||||
frame_cw_off_us = 0U;
|
||||
next_w_us = 0U;
|
||||
next_c_us = 0U;
|
||||
next_wc_off_us = 0U;
|
||||
next_cw_off_us = 0U;
|
||||
cached_w_mix = 0xFFFFU;
|
||||
cached_c_mix = 0xFFFFU;
|
||||
bridge_force_off();
|
||||
output_mode = BRIDGE_MODE_OFF;
|
||||
}
|
||||
|
||||
__RAM_CODE void Bridge_Deadtime_Expired(void)
|
||||
{
|
||||
if (!bridge_ready ||
|
||||
(deviceStatus == POWEROFF && !Light_Transition_FadeActive)) {
|
||||
Bridge_Off();
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer_stage == BRIDGE_STAGE_START_W) {
|
||||
/*
|
||||
* Latch all four durations together at the W boundary. A brightness
|
||||
* update can then never mix old and new timings inside one frame.
|
||||
*/
|
||||
frame_w_us = next_w_us;
|
||||
frame_c_us = next_c_us;
|
||||
frame_wc_off_us = next_wc_off_us;
|
||||
frame_cw_off_us = next_cw_off_us;
|
||||
bridge_gpio_state(BRIDGE_W);
|
||||
timer_stage = BRIDGE_STAGE_END_W;
|
||||
bridge_timer_start(frame_w_us);
|
||||
} else if (timer_stage == BRIDGE_STAGE_END_W) {
|
||||
bridge_gpio_off();
|
||||
timer_stage = BRIDGE_STAGE_START_C;
|
||||
bridge_timer_start(frame_wc_off_us);
|
||||
} else if (timer_stage == BRIDGE_STAGE_START_C) {
|
||||
bridge_gpio_state(BRIDGE_C);
|
||||
timer_stage = BRIDGE_STAGE_END_C;
|
||||
bridge_timer_start(frame_c_us);
|
||||
} else if (timer_stage == BRIDGE_STAGE_END_C) {
|
||||
bridge_gpio_off();
|
||||
timer_stage = BRIDGE_STAGE_START_W;
|
||||
bridge_timer_start(frame_cw_off_us);
|
||||
} else if (timer_stage == BRIDGE_STAGE_START_SINGLE) {
|
||||
timer_stage = BRIDGE_STAGE_IDLE;
|
||||
bridge_start_pwm(pending_single_state, pending_single_duty);
|
||||
} else {
|
||||
Bridge_Off();
|
||||
}
|
||||
}
|
||||
|
||||
__RAM_CODE void Bridge_Service_1ms(void)
|
||||
{
|
||||
uint32_t w_mix;
|
||||
uint32_t c_mix;
|
||||
uint32_t total;
|
||||
uint32_t total_on_us;
|
||||
uint32_t total_off_us;
|
||||
uint16_t pwm_duty;
|
||||
uint8_t single_state;
|
||||
|
||||
if (!bridge_ready ||
|
||||
(deviceStatus == POWEROFF && !Light_Transition_FadeActive)) {
|
||||
if (output_mode != BRIDGE_MODE_OFF || timer_stage != BRIDGE_STAGE_IDLE) {
|
||||
Bridge_Off();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
w_mix = clamp_mix_value(W_PWM_duty);
|
||||
c_mix = clamp_mix_value(C_PWM_duty);
|
||||
total = w_mix + c_mix;
|
||||
|
||||
if (total == 0U) {
|
||||
Bridge_Off();
|
||||
return;
|
||||
}
|
||||
|
||||
if (total > BRIDGE_MIX_SCALE) {
|
||||
w_mix = (w_mix * BRIDGE_MIX_SCALE) / total;
|
||||
c_mix = BRIDGE_MIX_SCALE - w_mix;
|
||||
total = BRIDGE_MIX_SCALE;
|
||||
}
|
||||
|
||||
/* Keep the verified fixed 1 kHz hardware PWM for a single color. */
|
||||
if (w_mix == 0U || c_mix == 0U) {
|
||||
single_state = (w_mix != 0U) ? BRIDGE_W : BRIDGE_C;
|
||||
pwm_duty = (uint16_t)((total * BRIDGE_PWM_SCALE +
|
||||
(BRIDGE_MIX_SCALE / 2U)) / BRIDGE_MIX_SCALE);
|
||||
|
||||
if (output_mode == BRIDGE_MODE_SINGLE &&
|
||||
active_state == single_state &&
|
||||
timer_stage == BRIDGE_STAGE_IDLE) {
|
||||
xc_pwm_dutycycle_set(pwm_index_for_state(single_state),
|
||||
BRIDGE_PWM_SCALE, pwm_duty);
|
||||
return;
|
||||
}
|
||||
|
||||
xc_timer_stop(TIMER3_IDX);
|
||||
timer_stage = BRIDGE_STAGE_START_SINGLE;
|
||||
pending_single_state = single_state;
|
||||
pending_single_duty = pwm_duty;
|
||||
bridge_force_off();
|
||||
output_mode = BRIDGE_MODE_OFF;
|
||||
bridge_timer_start(BRIDGE_DEADTIME_US);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cached_w_mix != w_mix || cached_c_mix != c_mix ||
|
||||
output_mode != BRIDGE_MODE_DUAL) {
|
||||
/*
|
||||
* Keep 100 us OFF at maximum dual-color brightness. The OFF time is
|
||||
* split evenly between W->C and C->W, which both absorbs interrupt
|
||||
* latency and spreads the two optical pulses across the 1 ms frame.
|
||||
*/
|
||||
total_on_us = (BRIDGE_DUAL_ACTIVE_US * total +
|
||||
(BRIDGE_MIX_SCALE / 2U)) / BRIDGE_MIX_SCALE;
|
||||
if (total_on_us < 2U) {
|
||||
total_on_us = 2U;
|
||||
}
|
||||
|
||||
next_w_us = (uint16_t)((total_on_us * w_mix +
|
||||
(total / 2U)) / total);
|
||||
if (next_w_us == 0U) {
|
||||
next_w_us = 1U;
|
||||
} else if (next_w_us >= total_on_us) {
|
||||
next_w_us = (uint16_t)(total_on_us - 1U);
|
||||
}
|
||||
next_c_us = (uint16_t)(total_on_us - next_w_us);
|
||||
|
||||
total_off_us = BRIDGE_FRAME_US - total_on_us;
|
||||
next_wc_off_us = (uint16_t)(total_off_us / 2U);
|
||||
next_cw_off_us = (uint16_t)(total_off_us - next_wc_off_us);
|
||||
|
||||
cached_w_mix = (uint16_t)w_mix;
|
||||
cached_c_mix = (uint16_t)c_mix;
|
||||
}
|
||||
|
||||
if (output_mode == BRIDGE_MODE_DUAL &&
|
||||
timer_stage != BRIDGE_STAGE_IDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer3 owns the complete repeating frame, including both full direction
|
||||
* deadtimes. Timer0 only publishes updated brightness/mix parameters.
|
||||
*/
|
||||
bridge_timer_stop_fast();
|
||||
timer_stage = BRIDGE_STAGE_START_W;
|
||||
bridge_force_off();
|
||||
output_mode = BRIDGE_MODE_DUAL;
|
||||
bridge_timer_start(next_cw_off_us);
|
||||
}
|
||||
@@ -84,6 +84,14 @@ void read_user_data(void)
|
||||
W_PWM = r_data[9];
|
||||
C_PWM = r_data[10];
|
||||
|
||||
/* Migrate the old 0..10 color mix to the new 0..100 scale. */
|
||||
if(Mode == mode0 && W_PWM <= 10U && C_PWM <= 10U && (W_PWM + C_PWM) > 0U)
|
||||
{
|
||||
uint16_t legacy_mix = W_PWM + C_PWM;
|
||||
W_PWM = (uint16_t)(((uint32_t)W_PWM * 100U + legacy_mix / 2U) / legacy_mix);
|
||||
C_PWM = 100U - W_PWM;
|
||||
}
|
||||
|
||||
is_time = r_data[12];
|
||||
// flag_1h = r_data[13];//
|
||||
// adress = r_data[14];
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "pwm.h"
|
||||
#include "mode.h"
|
||||
#include "light_transition.h"
|
||||
|
||||
volatile uint8_t Light_Transition_FadeActive;
|
||||
|
||||
static uint8_t approach_target(uint8_t current, uint8_t target)
|
||||
{
|
||||
if(current < target) return current + 1U;
|
||||
if(current > target) return current - 1U;
|
||||
return current;
|
||||
}
|
||||
|
||||
void Light_Transition_Task(void)
|
||||
{
|
||||
uint8_t target_brightness = 0U;
|
||||
uint16_t brightness_scale;
|
||||
|
||||
if(deviceStatus != POWEROFF) target_brightness = Brightness;
|
||||
brightness_scale = target_brightness * 205U;
|
||||
W_PWM_duty = approach_target(
|
||||
(uint8_t)W_PWM_duty, (uint8_t)(W_PWM * brightness_scale >> 11));
|
||||
C_PWM_duty = approach_target(
|
||||
(uint8_t)C_PWM_duty, (uint8_t)(C_PWM * brightness_scale >> 11));
|
||||
|
||||
Light_Transition_FadeActive =
|
||||
deviceStatus == POWEROFF && (W_PWM_duty != 0U || C_PWM_duty != 0U);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef LIGHT_TRANSITION_H
|
||||
#define LIGHT_TRANSITION_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern volatile uint8_t Light_Transition_FadeActive;
|
||||
|
||||
#define Light_Transition_RequestOn() (Light_Transition_FadeActive = 0U)
|
||||
#define Light_Transition_RequestOff() (Light_Transition_FadeActive = 1U)
|
||||
|
||||
void Light_Transition_Task(void);
|
||||
|
||||
#endif
|
||||
@@ -92,17 +92,26 @@ void timer0_2_init(void)
|
||||
timer_cfg.timer_div_clk = TIMER_DIV_CLK_16MHzOr16K;
|
||||
timer_cfg.timer_mode = TIMER_MODE_CYCLE;
|
||||
|
||||
/* Timer0 is the independent 1 kHz bridge direction scheduler. */
|
||||
xc_timer_init(TIMER0_IDX, &timer_cfg);
|
||||
xc_timer_set_value(TIMER0_IDX, us);
|
||||
xc_timer_start(TIMER0_IDX);
|
||||
|
||||
xc_timer_init(TIMER1_IDX, &timer_cfg);
|
||||
xc_timer_set_value(TIMER1_IDX, us);
|
||||
xc_timer_start(TIMER1_IDX);
|
||||
// Timer2 Config & Start
|
||||
// Timer2 remains at 100 us for RF433 sampling.
|
||||
xc_timer_init(TIMER2_IDX, &timer_cfg);
|
||||
xc_timer_set_value(TIMER2_IDX, 100); //10us
|
||||
xc_timer_set_value(TIMER2_IDX, 100);
|
||||
xc_timer_start(TIMER2_IDX);
|
||||
|
||||
NVIC_SetPriority((IRQn_Type)TIMER2_IRQn,0);
|
||||
NVIC_EnableIRQ((IRQn_Type)TIMER2_IRQn);
|
||||
}
|
||||
|
||||
NVIC_SetPriority((IRQn_Type)TIMER0_IRQn, 0);
|
||||
NVIC_EnableIRQ(TIMER0_IRQn);
|
||||
NVIC_SetPriority((IRQn_Type)TIMER1_IRQn, 3);
|
||||
NVIC_EnableIRQ(TIMER1_IRQn);
|
||||
NVIC_SetPriority((IRQn_Type)TIMER2_IRQn, 1);
|
||||
NVIC_EnableIRQ(TIMER2_IRQn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -117,8 +126,8 @@ void timer0_2_init(void)
|
||||
*/
|
||||
__RAM_CODE void timer0_callback(void *context)
|
||||
{
|
||||
// timer_status.t0_flag = true;
|
||||
|
||||
(void)context;
|
||||
Bridge_Service_1ms();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +144,8 @@ __RAM_CODE void timer1_callback(void *context)
|
||||
// printf("dd=%d--%d--%d-%d-%d\r\n",choose_mode_falsg,W_PWM,C_PWM,driveMode,Brightness);
|
||||
|
||||
updateTimer(&timer1);
|
||||
updateTimer(&timer2);
|
||||
updateTimer(&timer2);
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -145,84 +155,18 @@ __RAM_CODE void timer1_callback(void *context)
|
||||
* @details Timer2 handler callback function
|
||||
* @param void *context
|
||||
* @retval void
|
||||
* 100us模拟1kHZ PWM
|
||||
* Timer2 remains dedicated to 100 us RF433 sampling.
|
||||
*/
|
||||
|
||||
uint8_t aa=0;
|
||||
__RAM_CODE void timer2_callback(void *context) //10us
|
||||
__RAM_CODE void timer2_callback(void *context)
|
||||
{
|
||||
rf433_receive();
|
||||
if(deviceStatus==POWERON){
|
||||
timeCnt++;
|
||||
|
||||
if(W_PWM_duty==0){deadTime_W=0;}
|
||||
else {deadTime_W=_deadTime;}
|
||||
|
||||
if(C_PWM_duty==0){deadTime_C=0;}
|
||||
else {deadTime_C=_deadTime;}
|
||||
uint16_t totalPhase = (W_PWM_duty+deadTime_W) + (C_PWM_duty+deadTime_C) + 2*deadTime; //看注释为什么要这样加(W_PWM_duty+deadTime_W) + (C_PWM_duty+deadTime_C)
|
||||
|
||||
switch (driveMode)
|
||||
{
|
||||
case 0: // 正+反交替(周期切换)
|
||||
if (timeCnt < deadTime)
|
||||
{
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timeCnt <(deadTime + W_PWM_duty)) // 正转段
|
||||
{
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_SET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
}
|
||||
else if (timeCnt < deadTime + W_PWM_duty + deadTime) // 死区时间
|
||||
{
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
}
|
||||
else if (timeCnt < (totalPhase)) // 反转段
|
||||
{
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_SET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 主输出高
|
||||
}
|
||||
else
|
||||
{
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: // 只正转
|
||||
if(timeCnt<=W_PWM_duty){
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_SET); // 互补输出低
|
||||
aa=0;
|
||||
}else{
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
aa=1;
|
||||
}
|
||||
|
||||
break;
|
||||
case 2: // 只反转
|
||||
if(timeCnt<=C_PWM_duty){
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_SET); // 主输出高
|
||||
}else{
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
}
|
||||
break;
|
||||
default:
|
||||
xc_gpio_write_pin(IO_PWM_W, GPIO_PIN_RESET); // 互补输出低
|
||||
xc_gpio_write_pin(IO_PWM_C, GPIO_PIN_RESET); // 主输出高
|
||||
break;
|
||||
}
|
||||
if (timeCnt >= PWMMAX){timeCnt = 0;}
|
||||
|
||||
}
|
||||
(void)context;
|
||||
rf433_receive();
|
||||
}
|
||||
|
||||
|
||||
__RAM_CODE void timer3_callback(void *context)
|
||||
{
|
||||
(void)context;
|
||||
Bridge_Deadtime_Expired();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
#include "RF433.h"
|
||||
#include "ota_flash_interface.h"
|
||||
#include "ota_protocol.h"
|
||||
#include "pwm.h"
|
||||
#include "pwm.h"
|
||||
#include "light_transition.h"
|
||||
/*********************************************************************************************************************/
|
||||
|
||||
void rwip_schedule(void);
|
||||
@@ -21,7 +22,7 @@ TASK_COMPONENTS TaskComps[] =
|
||||
{0, 100, 30, ble_message_process}, //蓝牙处理任务
|
||||
{0, 0, 0, app_op_flash_on},
|
||||
{0,1,1,choice_mode},
|
||||
{0,1,1,set_mode},
|
||||
{0,5,5,set_mode},
|
||||
{0,1,1,Set_timing},
|
||||
{0,100,100,scan_433},
|
||||
{0, 100,3, Encoder_key},
|
||||
|
||||
@@ -145,14 +145,7 @@ void scan_uart(uint8_t *arr)
|
||||
case 6:
|
||||
if(POWEROFF==deviceStatus)break;
|
||||
|
||||
if(user_rx_buf[1]<=5){
|
||||
temperature(250);
|
||||
}
|
||||
else if(user_rx_buf[1]>=250){
|
||||
temperature(50);
|
||||
}else {
|
||||
temperature(227-(57 +(((user_rx_buf[1] - 5)* 110) / 245)));
|
||||
}
|
||||
temperature(user_rx_buf[1]);
|
||||
Mode=mode0;
|
||||
choose_mode_bh=0;
|
||||
choose_mode_falsg=10;//圆环模式
|
||||
|
||||
Reference in New Issue
Block a user