AM32开源代码之代码分析 - WS2812/RGB LED
1. 源由
AM32代码上目前有一个RGB三色灯,还有一个WS2812的串行灯。
目前看,WS2812和RGB三色灯变色效果:绿/红,感觉更像是动态的呼吸灯。
注:代码尚无法配置颜色,也许后续通过ESC电传报文可以配置。
2. 框架设计
2.1 初始化
WS2812串行灯初始化
main
└──> initCorePeripherals
└──> WS2812_Init
RGB三色灯GPIO初始化
main
└──> enableCorePeripherals
└──> LED_GPIO_init
2.2 动态过程
定时20Hz调用调整LED灯的状态
main
└──> initCorePeripherals
└──> MX_TIM6_Init
└──> TIM6_DAC_LPTIM1_IRQHandler
└──> tenKhzRoutine
2.3 初始化过程
2.3.1 WS2812_Init
- 中断优先级设置和使能
NVIC_SetPriority(DMA1_Ch4_7_DMAMUX1_OVR_IRQn, 3);
NVIC_EnableIRQ(DMA1_Ch4_7_DMAMUX1_OVR_IRQn);
- 功能: 这是在配置DMA通道4到7的中断优先级和使能。通过设置中断优先级,可以确保在特定情况下DMA中断能被正确处理。
- 初始化结构体定义
LL_TIM_InitTypeDef TIM_InitStruct = { 0 };
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = { 0 };
LL_TIM_BDTR_InitTypeDef TIM_BDTRInitStruct = { 0 };
LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
- 功能: 这些结构体用于存储定时器和GPIO的配置参数。
- 使能定时器TIM16的时钟
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM16);
- 功能: 使能TIM16定时器的时钟信号,使得该外设可以工作。
- 配置DMA通道
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_6, LL_DMAMUX_REQ_TIM16_CH1);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_HIGH);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_HALFWORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_HALFWORD);
- 功能:
- 请求类型: 配置DMA传输的外设请求为TIM16的CH1通道。
- 传输方向: 配置为从内存传输到外设。
- 优先级: 设置为高优先级。
- 模式: 设置为普通模式,不是循环模式。
- 地址自增模式: 配置DMA的外设地址不自增,而内存地址自增。
- 数据大小: 外设和内存的数据宽度均设置为半字(16位)。
- 配置定时器TIM16
TIM_InitStruct.Prescaler = 0;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_DOWN;
TIM_InitStruct.Autoreload = 79;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TIM_InitStruct.RepetitionCounter = 0;
LL_TIM_Init(TIM16, &TIM_InitStruct);
LL_TIM_EnableARRPreload(TIM16);
- 功能:
- 分频器: 设置为0,即不分频,使用全速的时钟信号。
- 计数模式: 配置为向下计数模式。
- 自动重装载值: 设置为79,决定定时器的周期时间。
- 时钟分频: 配置为无分频。
- 重复计数器: 设置为0。
- 使能ARR预装载: 使能ARR寄存器的预装载功能。
- 配置PWM输出通道
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.CompareValue = 0;
TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
TIM_OC_InitStruct.OCNPolarity = LL_TIM_OCPOLARITY_HIGH;
TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
LL_TIM_OC_Init(TIM16, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);
LL_TIM_OC_DisableFast(TIM16, LL_TIM_CHANNEL_CH1);
- 功能:
- 输出比较模式: 配置为PWM模式1。
- 输出状态: 初始化时禁用通道。
- 比较值: 设置为0。
- 极性: 配置为高电平有效。
- 空闲状态: 设置为低电平。
- 配置死区和刹车功能
TIM_BDTRInitStruct.OSSRState = LL_TIM_OSSR_DISABLE;
TIM_BDTRInitStruct.OSSIState = LL_TIM_OSSI_DISABLE;
TIM_BDTRInitStruct.LockLevel = LL_TIM_LOCKLEVEL_OFF;
TIM_BDTRInitStruct.DeadTime = 0;
TIM_BDTRInitStruct.BreakState = LL_TIM_BREAK_DISABLE;
TIM_BDTRInitStruct.BreakPolarity = LL_TIM_BREAK_POLARITY_HIGH;
TIM_BDTRInitStruct.BreakFilter = LL_TIM_BREAK_FILTER_FDIV1;
TIM_BDTRInitStruct.AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
LL_TIM_BDTR_Init(TIM16, &TIM_BDTRInitStruct);
- 功能:
- 死区和刹车功能: 初始化了这些功能,但在WS2812控制中通常不使用这些特性。
- GPIO 配置
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
GPIO_InitStruct.Pin = LL_GPIO_PIN_8;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_2;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- 功能:
- GPIO 时钟使能: 使能GPIOB的时钟。
- 引脚配置: 配置PB8为TIM16_CH1通道的输出引脚。
- 模式: 配置为复用功能模式,速度为高频,推挽输出,不上拉不下拉。
- 启用输出比较通道
TIM16->CCER |= 1 << 0;
- 功能: 使能TIM16的CH1通道输出比较功能。
WS2812_Init()
|
|-- 中断优先级配置和使能
| |-- NVIC_SetPriority(DMA1_Ch4_7_DMAMUX1_OVR_IRQn, 3)
| |-- NVIC_EnableIRQ(DMA1_Ch4_7_DMAMUX1_OVR_IRQn)
|
|-- 初始化结构体声明
| |-- LL_TIM_InitTypeDef TIM_InitStruct
| |-- LL_TIM_OC_InitTypeDef TIM_OC_InitStruct
| |-- LL_TIM_BDTR_InitTypeDef TIM_BDTRInitStruct
| |-- LL_GPIO_InitTypeDef GPIO_InitStruct
|
|-- 使能TIM16外设时钟
| |-- LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM16)
|
|-- DMA配置
| |-- TIM16_CH1 DMA 初始化
| |-- 配置DMA请求类型
| |-- LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_6, LL_DMAMUX_REQ_TIM16_CH1)
| |-- 配置DMA传输方向
| |-- LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_MEMORY_TO_PERIPH)
| |-- 配置DMA优先级
| |-- LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_HIGH)
| |-- 配置DMA模式
| |-- LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MODE_NORMAL)
| |-- 配置外设地址增量模式
| |-- LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT)
| |-- 配置内存地址增量模式
| |-- LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT)
| |-- 配置外设数据宽度
| |-- LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_HALFWORD)
| |-- 配置内存数据宽度
| |-- LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_HALFWORD)
|
|-- TIM16 定时器配置
| |-- 基本配置
| |-- TIM_InitStruct.Prescaler = 0
| |-- TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_DOWN
| |-- TIM_InitStruct.Autoreload = 79
| |-- TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1
| |-- TIM_InitStruct.RepetitionCounter = 0
| |-- LL_TIM_Init(TIM16, &TIM_InitStruct)
| |-- LL_TIM_EnableARRPreload(TIM16)
| |-- PWM输出通道配置
| |-- TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1
| |-- TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE
| |-- TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE
| |-- TIM_OC_InitStruct.CompareValue = 0
| |-- TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH
| |-- TIM_OC_InitStruct.OCNPolarity = LL_TIM_OCPOLARITY_HIGH
| |-- TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW
| |-- TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW
| |-- LL_TIM_OC_Init(TIM16, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct)
| |-- LL_TIM_OC_DisableFast(TIM16, LL_TIM_CHANNEL_CH1)
| |-- 死区和刹车功能配置
| |-- TIM_BDTRInitStruct.OSSRState = LL_TIM_OSSR_DISABLE
| |-- TIM_BDTRInitStruct.OSSIState = LL_TIM_OSSI_DISABLE
| |-- TIM_BDTRInitStruct.LockLevel = LL_TIM_LOCKLEVEL_OFF
| |-- TIM_BDTRInitStruct.DeadTime = 0
| |-- TIM_BDTRInitStruct.BreakState = LL_TIM_BREAK_DISABLE
| |-- TIM_BDTRInitStruct.BreakPolarity = LL_TIM_BREAK_POLARITY_HIGH
| |-- TIM_BDTRInitStruct.BreakFilter = LL_TIM_BREAK_FILTER_FDIV1
| |-- TIM_BDTRInitStruct.AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE
| |-- LL_TIM_BDTR_Init(TIM16, &TIM_BDTRInitStruct)
|
|-- GPIO配置
| |-- 使能GPIOB时钟
| |-- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB)
| |-- 配置PB8引脚为TIM16_CH1的PWM输出引脚
| |-- GPIO_InitStruct.Pin = LL_GPIO_PIN_8
| |-- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE
| |-- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH
| |-- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL
| |-- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO
| |-- GPIO_InitStruct.Alternate = LL_GPIO_AF_2
| |-- LL_GPIO_Init(GPIOB, &GPIO_InitStruct)
|
|-- 启用TIM16_CH1输出比较通道
|-- TIM16->CCER |= 1 << 0
WS2812_Init()
函数的主要目的是配置定时器TIM16、DMA通道和GPIO,以便生成合适的PWM信号来驱动WS2812 LED灯条。TIM16生成的PWM信号通过DMA传输到LED控制引脚,实现颜色控制。
注:该代码来自STM32 G071。
2.3.2 LED_GPIO_init
-
初始化 GPIO 配置结构体:将结构体
GPIO_InitStruct
初始化为零,以确保所有字段的默认值为 0。 -
使能 GPIOB 时钟:调用
LL_AHB1_GRP1_EnableClock
函数为 GPIOB 端口启用时钟。没有使能时钟的话,GPIO 端口无法正常工作。 -
复位 GPIOB 引脚输出状态:使用
LL_GPIO_ResetOutputPin
函数将 GPIOB 的 8、5、3 号引脚的输出状态复位(即输出低电平)。这通常是在初始化时保证引脚状态是已知的,防止出现不确定的信号。 -
配置 GPIOB 引脚 8、5、3 为输出模式:
Pin
: 指定要配置的引脚。Mode
: 设置为输出模式 (LL_GPIO_MODE_OUTPUT
)。Speed
: 设置引脚的输出速度为低速 (LL_GPIO_SPEED_FREQ_LOW
)。这意味着引脚在改变状态时的速度相对较慢,适用于低速信号。OutputType
: 设置为推挽输出 (LL_GPIO_OUTPUT_PUSHPULL
),适合驱动 LED 等负载。Pull
: 设置为无上拉或下拉 (LL_GPIO_PULL_NO
),表示引脚在输入状态时不接入上拉或下拉电阻。
LED_GPIO_init()
|
|-- 初始化 GPIO 配置结构体
| |-- LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 }
|
|-- 使能 GPIOB 端口的时钟
| |-- LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB)
|
|-- 复位 GPIOB 引脚的输出状态
| |-- LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_8)
| |-- LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5)
| |-- LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_3)
|
|-- 配置 GPIOB 引脚 8 为输出模式
| |-- GPIO_InitStruct.Pin = LL_GPIO_PIN_8
| |-- GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT
| |-- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW
| |-- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL
| |-- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO
| |-- LL_GPIO_Init(GPIOB, &GPIO_InitStruct)
|
|-- 配置 GPIOB 引脚 5 为输出模式
| |-- GPIO_InitStruct.Pin = LL_GPIO_PIN_5
| |-- GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT
| |-- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW
| |-- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL
| |-- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO
| |-- LL_GPIO_Init(GPIOB, &GPIO_InitStruct)
|
|-- 配置 GPIOB 引脚 3 为输出模式
| |-- GPIO_InitStruct.Pin = LL_GPIO_PIN_3
| |-- GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT
| |-- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW
| |-- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL
| |-- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO
| |-- LL_GPIO_Init(GPIOB, &GPIO_InitStruct)
此函数配置了 GPIOB 端口的 8、5、3 号引脚为推挽输出模式,主要用于驱动 LED 或其他需要控制的外设。每个引脚的输出速度设定为低速,初始状态设定为低电平。这种配置常用于简单的 LED 控制电路或其他需要简单数字信号控制的场合。
注:该代码来自Artery F421。
2.4 tenKhzRoutine
这个函数实现了一个 周期性任务,它主要用于:
- PID电机控制
- LED 状态更新
- 遥测信息更新
tenKhzRoutine()
|
|-- 更新关键计数器
| |-- duty_cycle = duty_cycle_setpoint;
| |-- tenkhzcounter++;
| |-- ledcounter++;
| |-- one_khz_loop_counter++;
|
|-- 处理未解锁的状态
| |-- if (!armed) {
| |-- 如果电池电压检测尚未完成
| |-- if (cell_count == 0) {
| |-- 如果输入已经设置且调整后的输入为0
| |-- if (inputSet && adjusted_input == 0) {
| |-- 增加解锁超时计数
| | |-- armed_timeout_count++;
| |-- 如果超时计数超过1秒
| |-- if (armed_timeout_count > LOOP_FREQUENCY_HZ) {
| |-- 如果零输入计数大于30,则执行解锁逻辑
| |-- if (zero_input_count > 30) {
| |-- armed = 1;
| |-- 启动LED指示灯
| |-- 如果电池电压低于设定值
| |-- if ((cell_count == 0) && LOW_VOLTAGE_CUTOFF) {
| |-- 计算电池单元数
| |-- 播放输入音调
| |-- else
| |-- 播放其他提示音
| |-- 如果未启用舵机PWM,重置RC车倒车标志
| |-- if (!servoPwm) { RC_CAR_REVERSE = 0; }
| |-- 如果输入不为零,则重置超时计数
| |-- else { armed_timeout_count = 0; }
| |-- 如果零输入计数不够,重置输入设置
| |-- else { inputSet = 0; armed_timeout_count = 0; }
| |-- 如果输入不为零,则重置超时计数
| |-- else { armed_timeout_count = 0; }
|
|-- 处理遥测信息
| |-- if (TLM_ON_INTERVAL) {
| |-- 增加遥测计数器
| |-- 如果遥测计数器超过设定间隔,设置发送遥测标志
| |-- if (telem_ms_count > telemetry_interval_ms * 20) {
| |-- send_telemetry = 1;
| |-- telem_ms_count = 0;
|
|-- 如果没有启用刷驱动模式,进行以下操作
| |-- if (!stepper_sine) {
| |-- 旧的电机驱动例程及反电动势检测
| |-- if (old_routine && running) {
| |-- maskPhaseInterrupts();
| |-- getBemfState();
| |-- 如果未找到过零点,继续寻找
| |-- if (!zcfound) {
| |-- 根据反电动势计数判断过零点
| |-- if (rising) {
| |-- if (bemfcounter > min_bemf_counts_up) {
| |-- zcfound = 1;
| |-- zcfoundroutine();
| |-- else if (bemfcounter > min_bemf_counts_down) {
| |-- zcfound = 1;
| |-- zcfoundroutine();
|
|-- 每1kHz进行PID控制
| |-- if (one_khz_loop_counter > PID_LOOP_DIVIDER) {
| |-- 重置1kHz计数器
| |-- one_khz_loop_counter = 0;
| |-- 如果启用电流限制且正在运行,调整占空比以限制电流
| |-- if (use_current_limit && running) {
| |-- 调整 `use_current_limit_adjust` 值
| |-- 如果调整值低于最小占空比,重置为最小占空比
| |-- if (use_current_limit_adjust < minimum_duty_cycle) {
| |-- use_current_limit_adjust = minimum_duty_cycle;
| |-- 如果调整值高于最大定时器值,重置为最大定时器值
| |-- if (use_current_limit_adjust > tim1_arr) {
| |-- use_current_limit_adjust = tim1_arr;
| |-- 如果启用防止电机堵转保护且正在运行
| |-- if (stall_protection && running) {
| |-- 调整 `stall_protection_adjust` 值
| |-- 限制调整值在0到150之间
| |-- if (stall_protection_adjust > 150) {
| |-- stall_protection_adjust = 150;
| |-- if (stall_protection_adjust <= 0) {
| |-- stall_protection_adjust = 0;
| |-- 如果启用速度控制回路且正在运行
| |-- if (use_speed_control_loop && running) {
| |-- 调整 `input_override` 值
| |-- 限制调整值在0到2047之间
| |-- if (input_override > 2047) {
| |-- input_override = 2047;
| |-- if (input_override < 0) {
| |-- input_override = 0;
| |-- 如果零过次数少于100,重置速度PID积分值
| |-- if (zero_crosses < 100) {
| |-- speedPid.integral = 0;
|
|-- 控制最大油门变化速率
| |-- if (maximum_throttle_change_ramp) {
| |-- 根据电池电压或其他条件设置最大占空比变化速率
| |-- if (zero_crosses < 150 || last_duty_cycle < 150) {
| |-- max_duty_cycle_change = RAMP_SPEED_STARTUP;
| |-- else if (average_interval > 500) {
| |-- max_duty_cycle_change = RAMP_SPEED_LOW_RPM;
| |-- else {
| |-- max_duty_cycle_change = RAMP_SPEED_HIGH_RPM;
| |-- 如果占空比变化超过最大变化速率,调整占空比
| |-- if ((duty_cycle - last_duty_cycle) > max_duty_cycle_change) {
| |-- duty_cycle = last_duty_cycle + max_duty_cycle_change;
| |-- 根据转速决定是否快速加速
| |-- if (commutation_interval > 500) {
| |-- fast_accel = 1;
| |-- temp_advance = advance_level;
| |-- else {
| |-- fast_accel = 0;
| |-- else if ((last_duty_cycle - duty_cycle) > max_duty_cycle_change) {
| |-- duty_cycle = last_duty_cycle - max_duty_cycle_change;
| |-- fast_accel = 0;
| |-- temp_advance = advance_level;
|
|-- 设置PWM输出占空比
| |-- if ((armed && running) && input > 47) {
| |-- 调整后的占空比 `adjusted_duty_cycle` 为(duty_cycle * tim1_arr) / 2000 + 1
| |-- else {
| |-- 如果启用螺旋桨制动功能,调整后的占空比为倒向计算
| |-- 如果未启用螺旋桨制动功能,调整后的占空比为正常计算
|
|-- 更新定时器的自动重装值和占空比
| |-- SET_AUTO_RELOAD_PWM(tim1_arr);
| |-- SET_DUTY_CYCLE_ALL(adjusted_duty_cycle);
|
|-- 如果定义了FIXED_DUTY_MODE或FIXED_SPEED_MODE,检查输入引脚状态
| |-- if (getInputPinState()) {
| |-- 如果输入超时,触发系统复位
| |-- if (signaltimeout > LOOP_FREQUENCY_HZ) {
| |-- NVIC_SystemReset();
| |-- else { signaltimeout = 0; }
主要功能
-
更新状态计数器:函数开始时,更新了多个计数器,如
tenkhzcounter
、ledcounter
和one_khz_loop_counter
,这些计数器用于控制不同频率下的操作。 -
电机解锁过程:函数检查是否电机已解锁(
armed
标志),如果未解锁则执行一系列检查和条件以决定是否可以解锁。这包括电池电压检测、输入状态、超时计数等。 -
遥测功能:根据定时器计算是否需要发送遥测数据,如果需要则
3. 总结
通代码分析,可以看到目前RGB和WS2812主要是对ESC进行一个状态更新。
同时,在分析了tenKhzRoutine
过程中,我们了解到ESC的主要控制逻辑,后续我们结合算法再做深入介绍。
4. 参考资料
【1】BLDC ESC 无刷直流电子调速器简介
【2】BLDC ESC 无刷直流电子调速器工作原理
【3】BLDC ESC 无刷直流电子调速器工作过程
【4】BLDC ESC 无刷直流电子调速器驱动方式
【5】AM32开源代码之工程结构