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

  1. 中断优先级设置和使能
NVIC_SetPriority(DMA1_Ch4_7_DMAMUX1_OVR_IRQn, 3);
NVIC_EnableIRQ(DMA1_Ch4_7_DMAMUX1_OVR_IRQn);
  • 功能: 这是在配置DMA通道4到7的中断优先级和使能。通过设置中断优先级,可以确保在特定情况下DMA中断能被正确处理。
  1. 初始化结构体定义
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的配置参数。
  1. 使能定时器TIM16的时钟
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM16);
  • 功能: 使能TIM16定时器的时钟信号,使得该外设可以工作。
  1. 配置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位)。
  1. 配置定时器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寄存器的预装载功能。
  1. 配置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。
    • 极性: 配置为高电平有效。
    • 空闲状态: 设置为低电平。
  1. 配置死区和刹车功能
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控制中通常不使用这些特性。
  1. 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通道的输出引脚。
    • 模式: 配置为复用功能模式,速度为高频,推挽输出,不上拉不下拉。
  1. 启用输出比较通道
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

  1. 初始化 GPIO 配置结构体:将结构体 GPIO_InitStruct 初始化为零,以确保所有字段的默认值为 0。

  2. 使能 GPIOB 时钟:调用 LL_AHB1_GRP1_EnableClock 函数为 GPIOB 端口启用时钟。没有使能时钟的话,GPIO 端口无法正常工作。

  3. 复位 GPIOB 引脚输出状态:使用 LL_GPIO_ResetOutputPin 函数将 GPIOB 的 8、5、3 号引脚的输出状态复位(即输出低电平)。这通常是在初始化时保证引脚状态是已知的,防止出现不确定的信号。

  4. 配置 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; }

主要功能

  1. 更新状态计数器:函数开始时,更新了多个计数器,如 tenkhzcounterledcounterone_khz_loop_counter,这些计数器用于控制不同频率下的操作。

  2. 电机解锁过程:函数检查是否电机已解锁(armed 标志),如果未解锁则执行一系列检查和条件以决定是否可以解锁。这包括电池电压检测、输入状态、超时计数等。

  3. 遥测功能:根据定时器计算是否需要发送遥测数据,如果需要则

3. 总结

通代码分析,可以看到目前RGB和WS2812主要是对ESC进行一个状态更新。

同时,在分析了tenKhzRoutine过程中,我们了解到ESC的主要控制逻辑,后续我们结合算法再做深入介绍。

4. 参考资料

【1】BLDC ESC 无刷直流电子调速器简介
【2】BLDC ESC 无刷直流电子调速器工作原理
【3】BLDC ESC 无刷直流电子调速器工作过程
【4】BLDC ESC 无刷直流电子调速器驱动方式
【5】AM32开源代码之工程结构

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值