AM32开源代码之代码分析 - EEprom

1. 源由

公共代码EEprom部分研读,主要就是配置参数的保存。

  • loadEEpromSettings
  • saveEEpromSettings

2. 主要函数

2.1 loadEEpromSettings

eepromBuffer数组对应的变量列表:

  1. eepromBuffer[1]: eeprom_layout_version
  2. eepromBuffer[17]: dir_reversed
  3. eepromBuffer[18]: bi_direction
  4. eepromBuffer[19]: use_sin_start
  5. eepromBuffer[20]: comp_pwm
  6. eepromBuffer[21]: VARIABLE_PWM
  7. eepromBuffer[22]: stuck_rotor_protection
  8. eepromBuffer[23]: advance_level
  9. eepromBuffer[24]: TIMER1_MAX_ARR
  10. eepromBuffer[25]: min_startup_duty, minimum_duty_cycle, stall_protect_minimum_duty
  11. eepromBuffer[26]: motor_kv
  12. eepromBuffer[27]: motor_poles
  13. eepromBuffer[28]: brake_on_stop
  14. eepromBuffer[29]: stall_protection
  15. eepromBuffer[30]: volume
  16. eepromBuffer[31]: TLM_ON_INTERVAL
  17. eepromBuffer[32]: servo_low_threshold
  18. eepromBuffer[33]: servo_high_threshold
  19. eepromBuffer[34]: servo_neutral
  20. eepromBuffer[35]: servo_dead_band
  21. eepromBuffer[36]: LOW_VOLTAGE_CUTOFF
  22. eepromBuffer[37]: low_cell_volt_cutoff
  23. eepromBuffer[38]: RC_CAR_REVERSE
  24. eepromBuffer[39]: auto_advance, USE_HALL_SENSOR
  25. eepromBuffer[40]: sine_mode_changeover_thottle_level
  26. eepromBuffer[41]: drag_brake_strength
  27. eepromBuffer[42]: driving_brake_strength, dead_time_override
  28. eepromBuffer[43]: TEMPERATURE_LIMIT
  29. eepromBuffer[44]: CURRENT_LIMIT, use_current_limit
  30. eepromBuffer[45]: sine_mode_power
  31. eepromBuffer[46]: dshot, servoPwm, EDT_ARMED, EDT_ARM_ENABLE
void loadEEpromSettings()
{
    // 从EEPROM中读取176字节到eepromBuffer
    read_flash_bin(eepromBuffer, eeprom_address, 176);

    // 根据eepromBuffer第17字节的值设置dir_reversed
    if (eepromBuffer[17] == 0x01) {
        dir_reversed = 1;
    } else {
        dir_reversed = 0;
    }

    // 根据eepromBuffer第18字节的值设置bi_direction
    if (eepromBuffer[18] == 0x01) {
        bi_direction = 1;
    } else {
        bi_direction = 0;
    }

    // 根据eepromBuffer第19字节的值设置use_sin_start
    if (eepromBuffer[19] == 0x01) {
        use_sin_start = 1;
    }

    // 根据eepromBuffer第20字节的值设置comp_pwm
    if (eepromBuffer[20] == 0x01) {
        comp_pwm = 1;
    } else {
        comp_pwm = 0;
    }

    // 根据eepromBuffer第21字节的值设置VARIABLE_PWM
    if (eepromBuffer[21] == 0x01) {
        VARIABLE_PWM = 1;
    } else {
        VARIABLE_PWM = 0;
    }

    // 根据eepromBuffer第22字节的值设置stuck_rotor_protection
    if (eepromBuffer[22] == 0x01) {
        stuck_rotor_protection = 1;
    } else {
        stuck_rotor_protection = 0;
    }

    // 根据eepromBuffer第23字节的值设置advance_level
    if (eepromBuffer[23] < 4) {
        advance_level = eepromBuffer[23];
    } else {
        advance_level = 2; // 默认值为2
    }

    // 根据eepromBuffer第24字节的值设置TIMER1_MAX_ARR
    if (eepromBuffer[24] < 49 && eepromBuffer[24] > 7) {
        if (eepromBuffer[24] < 49 && eepromBuffer[24] > 23) {
            TIMER1_MAX_ARR = map(eepromBuffer[24], 24, 48, TIM1_AUTORELOAD, TIM1_AUTORELOAD / 2);
        }
        if (eepromBuffer[24] < 24 && eepromBuffer[24] > 11) {
            TIMER1_MAX_ARR = map(eepromBuffer[24], 12, 24, TIM1_AUTORELOAD * 2, TIM1_AUTORELOAD);
        }
        if (eepromBuffer[24] < 12 && eepromBuffer[24] > 7) {
            TIMER1_MAX_ARR = map(eepromBuffer[24], 7, 16, TIM1_AUTORELOAD * 3, TIM1_AUTORELOAD / 2 * 3);
        }
        SET_AUTO_RELOAD_PWM(TIMER1_MAX_ARR);
    } else {
        tim1_arr = TIM1_AUTORELOAD;
        SET_AUTO_RELOAD_PWM(tim1_arr);
    }

    // 根据eepromBuffer第25字节的值设置min_startup_duty, minimum_duty_cycle, 和stall_protect_minimum_duty
    if (eepromBuffer[25] < 151 && eepromBuffer[25] > 49) {
        min_startup_duty = eepromBuffer[25];
        minimum_duty_cycle = eepromBuffer[25] / 3;
        stall_protect_minimum_duty = minimum_duty_cycle + 10;
    } else {
        min_startup_duty = 150;
        minimum_duty_cycle = (min_startup_duty / 2) + 10;
    }

    // 设置motor_kv
    motor_kv = (eepromBuffer[26] * 40) + 20;
#ifdef THREE_CELL_MAX
    motor_kv = motor_kv / 2;
#endif

    // 设置motor_poles
    motor_poles = eepromBuffer[27];

    // 根据eepromBuffer第28字节的值设置brake_on_stop
    if (eepromBuffer[28] == 0x01) {
        brake_on_stop = 1;
    } else {
        brake_on_stop = 0;
    }

    // 根据eepromBuffer第29字节的值设置stall_protection
    if (eepromBuffer[29] == 0x01) {
        stall_protection = 1;
    } else {
        stall_protection = 0;
    }

    // 设置音量
    setVolume(2);
    if (eepromBuffer[1] > 0) { // 这些命令在eeprom版本1才引入
#ifdef CUSTOM_RAMP

#else
        if (eepromBuffer[30] > 11) {
            setVolume(5);
        } else {
            setVolume(eepromBuffer[30]);
        }
#endif

        // 根据eepromBuffer第31字节的值设置TLM_ON_INTERVAL
        if (eepromBuffer[31] == 0x01) {
            TLM_ON_INTERVAL = 1;
        } else {
            TLM_ON_INTERVAL = 0;
        }

        // 设置servo_low_threshold和servo_high_threshold
        servo_low_threshold = (eepromBuffer[32] * 2) + 750;
        servo_high_threshold = (eepromBuffer[33] * 2) + 1750;
        servo_neutral = (eepromBuffer[34]) + 1374;
        servo_dead_band = eepromBuffer[35];

        // 根据eepromBuffer第36字节的值设置LOW_VOLTAGE_CUTOFF
        if (eepromBuffer[36] == 0x01) {
            LOW_VOLTAGE_CUTOFF = 1;
        } else {
            LOW_VOLTAGE_CUTOFF = 0;
        }

        // 设置low_cell_volt_cutoff
        low_cell_volt_cutoff = eepromBuffer[37] + 250;

        // 根据eepromBuffer第38字节的值设置RC_CAR_REVERSE
        if (eepromBuffer[38] == 0x01) {
            RC_CAR_REVERSE = 1;
        } else {
            RC_CAR_REVERSE = 0;
        }

        // 根据eepromBuffer第39字节的值设置USE_HALL_SENSOR和auto_advance
        if (eepromBuffer[39] == 0x01) {
            auto_advance = 1;
#ifdef HAS_HALL_SENSORS
            USE_HALL_SENSOR = 1;
#else
            USE_HALL_SENSOR = 0;
#endif
        } else {
            USE_HALL_SENSOR = 0;
        }

        // 设置sine_mode_changeover_thottle_level
        if (eepromBuffer[40] > 4 && eepromBuffer[40] < 26) {
            sine_mode_changeover_thottle_level = eepromBuffer[40];
        }

        // 设置drag_brake_strength
        if (eepromBuffer[41] > 0 && eepromBuffer[41] < 11) {
            drag_brake_strength = eepromBuffer[41];
        }

        // 设置driving_brake_strength和dead_time_override
        if (eepromBuffer[42] > 0 && eepromBuffer[42] < 10) {
            driving_brake_strength = eepromBuffer[42];
            dead_time_override = DEAD_TIME + (150 - (driving_brake_strength * 10));
            if (dead_time_override > 200) {
                dead_time_override = 200;
            }
            min_startup_duty = eepromBuffer[25] + dead_time_override;
            minimum_duty_cycle = eepromBuffer[25] / 2 + dead_time_override;
            throttle_max_at_low_rpm = throttle_max_at_low_rpm + dead_time_override;
            startup_max_duty_cycle = startup_max_duty_cycle + dead_time_override;
#ifdef STMICRO
            TIM1->BDTR |= dead_time_override;
#endif
#ifdef ARTERY
            TMR1->brk |= dead_time_override;
#endif
#ifdef GIGADEVICES
            TIMER_CCHP(TIMER0) |= dead_time_override;
#endif
        }

        // 设置TEMPERATURE_LIMIT
        if (eepromBuffer[43] >= 70 && eepromBuffer[43] <= 140) {
            TEMPERATURE_LIMIT = eepromBuffer[43];
        }

        // 设置CURRENT_LIMIT和use_current_limit
        if (eepromBuffer[44] > 0 && eepromBuffer[44] < 100) {
            CURRENT_LIMIT = eepromBuffer[44] * 2;
            use_current_limit = 1;
        }

        // 设置sine_mode_power
        if (eepromBuffer[45] > 0 && eepromBuffer[45] < 11) {
            sine_mode_power = eepromBuffer[45];
        }

        // 根据eepromBuffer第46字节的值设置dshot, servoPwm, 和EDT_ARMED
        if (eepromBuffer[46] >= 0 && eepromBuffer[46] < 10) {
            switch (eepromBuffer[46]) {
            case AUTO_IN:
                dshot = 0;
                servoPwm = 0;
                EDT_ARMED = 1;
                break;
            case DSHOT_IN:
                dshot = 1;
                EDT_ARMED = 1;
                break;
            case SERVO_IN:
                servoPwm = 1;
                break;
            case SERIAL_IN:
                break;
            case EDTARM:
                EDT_ARM_ENABLE = 1;
                EDT_ARMED = 0;
                dshot = 1;
                break;
            }
        } else {
            dshot = 0;
            servoPwm = 0;
            EDT_ARMED = 1;
        }

        // 设置low_rpm_throttle_limit和low_rpm_level
        if (motor_kv < 300) {
            low_rpm_throttle_limit = 0;
        }
        low_rpm_level = motor_kv / 100 / (32 / motor_poles);

        // 设置high_rpm_level
        high_rpm_level = motor_kv / 12 / (32 / motor_poles);
    }

    // 设置reverse_speed_threshold
    reverse_speed_threshold = map(motor_kv, 300, 3000, 1000, 500);
}

2.2 saveEEpromSettings

eepromBuffer 数组索引及其对应的变量整理列表:

  1. eepromBuffer[1] : eeprom_layout_version
  2. eepromBuffer[17] : dir_reversed (值为 0x01 表示启用,0x00 表示禁用)
  3. eepromBuffer[18] : bi_direction (值为 0x01 表示启用,0x00 表示禁用)
  4. eepromBuffer[19] : use_sin_start (值为 0x01 表示启用,0x00 表示禁用)
  5. eepromBuffer[20] : comp_pwm (值为 0x01 表示启用,0x00 表示禁用)
  6. eepromBuffer[21] : VARIABLE_PWM (值为 0x01 表示启用,0x00 表示禁用)
  7. eepromBuffer[22] : stuck_rotor_protection (值为 0x01 表示启用,0x00 表示禁用)
  8. eepromBuffer[23] : advance_level
void saveEEpromSettings()
{
    // 将当前EEPROM布局版本保存到eepromBuffer的第1字节
    eepromBuffer[1] = eeprom_layout_version;

    // 根据dir_reversed的值设置eepromBuffer的第17字节
    if (dir_reversed == 1) {
        eepromBuffer[17] = 0x01;
    } else {
        eepromBuffer[17] = 0x00;
    }

    // 根据bi_direction的值设置eepromBuffer的第18字节
    if (bi_direction == 1) {
        eepromBuffer[18] = 0x01;
    } else {
        eepromBuffer[18] = 0x00;
    }

    // 根据use_sin_start的值设置eepromBuffer的第19字节
    if (use_sin_start == 1) {
        eepromBuffer[19] = 0x01;
    } else {
        eepromBuffer[19] = 0x00;
    }

    // 根据comp_pwm的值设置eepromBuffer的第20字节
    if (comp_pwm == 1) {
        eepromBuffer[20] = 0x01;
    } else {
        eepromBuffer[20] = 0x00;
    }

    // 根据VARIABLE_PWM的值设置eepromBuffer的第21字节
    if (VARIABLE_PWM == 1) {
        eepromBuffer[21] = 0x01;
    } else {
        eepromBuffer[21] = 0x00;
    }

    // 根据stuck_rotor_protection的值设置eepromBuffer的第22字节
    if (stuck_rotor_protection == 1) {
        eepromBuffer[22] = 0x01;
    } else {
        eepromBuffer[22] = 0x00;
    }

    // 将advance_level保存到eepromBuffer的第23字节
    eepromBuffer[23] = advance_level;

    // 将eepromBuffer保存到EEPROM中
    save_flash_nolib(eepromBuffer, 176, eeprom_address);
}

3. 总结

  1. 当前参数表共176个字符
uint8_t eepromBuffer[176] = { 0 };
  1. 默认位置起始于0x08007C00
#define EEPROM_START_ADD (uint32_t)0x08007C00
  1. main启动时,0x08000FE0值为0xf8时,需要使用新地址参数表 //怀疑有部分备份参数(尚未找到出处)
	  if((*(uint32_t*)(0x08000FE0)) == 0xf8){
			eeprom_address = (uint32_t)0x0800F800;
		}

注:What kind of situation will use second set of parameters from eeprom_address(0x0800F800), not default EEPROM_START_ADD(0x08007C00)?

  1. 从第52字节开始的128字节,直至176为音律,详见:playBlueJayTune
    // read_flash_bin(blueJayTuneBuffer , eeprom_address + 48 , 128);
    for (int i = 52; i < 176; i += 2) {
  1. 调用底层BSP驱动EEprom代码
`AM32\Mcu\f421\Src\eeprom.c`
 ├──> void read_flash_bin(uint8_t* data, uint32_t add, int out_buff_len)
 └──> void save_flash_nolib(uint8_t* data, int length, uint32_t add)

4. 参考资料

【1】BLDC ESC 无刷直流电子调速器简介
【2】AM32开源代码之工程结构

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值