开源BLHELI-S 代码详细解读(一)
Pgm_Beacon_Delay会和Power_On_Wait_Cnt_H相减,要是借位,就会开始beep f4, beep一次Power_On_Wait_Cnt_H会减1,就是Power_On_Wait_Cnt_L是255的时候beep一次了。如果有信号(Rcp_Timeout_Cntd不是零),同时New_Rcp(油门)不是零跳到 wait_for_power_on_nonzero, 再检查一
代码是使用51汇编写的,读之前,先打开汇编指令文档和EFM8BB2 Reference Manual这两个文档备查。 这个有点干涩,也没有其它人做这样的详细解读,一起一行一行读一下吧。
BLHELI主要是由 一堆.inc文件和 BLHeli_S.asm两个组成。 *.inc主要是定义针脚的布局,然后如何开关各个fet等,这个和主逻辑关系不大,我们先不解读*.inc.
BLHeli_S.asm 是从pgm_start 开始的, 我们按正常的流程一行一行来读,先走主的流程。
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Main program start
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;**** **** **** **** **** **** **** **** **** **** **** **** ****
pgm_start:
; Initialize flash keys to invalid values
mov Flash_Key_1, #0
mov Flash_Key_2, #0
; Disable the WDT.
mov WDTCN, #0DEh ; Disable watchdog
mov WDTCN, #0ADh
; Initialize stack
mov SP, #0c0h ; Stack = 64 upper bytes of RAM
; Initialize VDD monitor
IF MCU_48MHZ < 2
orl VDM0CN, #080h ; Enable the VDD monitor
ENDIF
mov RSTSRC, #06h ; Set missing clock and VDD monitor as a reset source if not 1S capable
; Set clock frequency
mov CLKSEL, #00h ; Set clock divider to 1
; Switch power off
call switch_power_off
; Ports initialization
mov P0, #P0_INIT
mov P0MDIN, #P0_DIGITAL
mov P0MDOUT, #P0_PUSHPULL
mov P0, #P0_INIT
mov P0SKIP, #P0_SKIP
mov P1, #P1_INIT
mov P1MDIN, #P1_DIGITAL
mov P1MDOUT, #P1_PUSHPULL
mov P1, #P1_INIT
mov P1SKIP, #P1_SKIP
mov P2MDOUT, #P2_PUSHPULL
; Initialize the XBAR and related functionality
Initialize_Xbar
; Switch power off again, after initializing ports
call switch_power_off
; Clear RAM
clr A ; Clear accumulator
mov Temp1, A ; Clear Temp1
clear_ram:
mov @Temp1, A ; Clear RAM
djnz Temp1, clear_ram ; Is A not zero? - jump
; Set default programmed parameters
call set_default_parameters
; Read all programmed parameters
call read_all_eeprom_parameters
; Set beep strength
mov Temp1, #Pgm_Beep_Strength
mov Beep_Strength, @Temp1
; Set initial arm variable
mov Initial_Arm, #1
; Initializing beep
clr IE_EA ; Disable interrupts explicitly
call wait200ms
call beep_f1
call wait30ms
call beep_f2
call wait30ms
call beep_f3
call wait30ms
call led_control
这里先做一些初始化, 特别一点这里会操作VDM0CN和RSTSRC,打开VDD电压监控,要是电压变化超过一定的范围,会软重启。
初始化时钟CLKSEL=0, 表示div 1, 这里先是选择HFOSC0(24.5 MHz), 即1tick是 1/24.5 ns秒,后面到运行阶段要是48Mhz的MCU就会选择HFOSC1(49 MHz).
跟着读取配置等等 然后驱动电机响三声,输出一个do re mi 的声音。表示初始化完成。
一共会有四个声调输出,f1, f2,f3,f4, 我们认为是do re mi fa吧。 即do re mi就是f1 f2 f3.
接着检查输入的rc_in, 就是电调的信线连着那个针脚的电平,检查它有没有15ms持续都是高电平,如果是的话,那么跳到bootloader, 就是进入和电脑blsuite设置的功能里。因为如 pwm是20ms一个周期,高电平最多2-3ms, dshot, ppm 等都不可能这么多时间高电平,所以这个15ms是一个很合理的值。
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; No signal entry point
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
init_no_signal:
; Disable interrupts explicitly
clr IE_EA
; Initialize flash keys to invalid values
mov Flash_Key_1, #0
mov Flash_Key_2, #0
; Check if input signal is high for more than 15ms
mov Temp1, #250
input_high_check_1:
mov Temp2, #250
input_high_check_2:
jnb RTX_PORT.RTX_PIN, bootloader_done ; Look for low
djnz Temp2, input_high_check_2
djnz Temp1, input_high_check_1
IF MCU_48MHZ == 2
ljmp 0F000h ; Jump to bootloader
ELSE
ljmp 1C00h ; Jump to bootloader
ENDIF
我们先不看bootloader, 先看正常流程,正常流程是跳到bootloader_done,跳到这里,就是解码之前读出的配置, 然后调用 find_throttle_gains 去找油门补偿,就是根据最大最小测试,还有死区,计算一个油门的补偿,结果放在 Throttle_Gain: ( ; Gain to be applied to RCP value)和
Throttle_Gain_M: ( 倍数, Gain to be applied to RCP value (multiplier 0=1x, 1=2x, 2=4x etc)) )
bootloader_done:
; Decode settings
call decode_settings
; Find throttle gain from stored min and max settings
call find_throttle_gains
; Set beep strength
mov Temp1, #Pgm_Beep_Strength
mov Beep_Strength, @Temp1
; Switch power off
call switch_power_off
; Set clock frequency
IF MCU_48MHZ >= 1
Set_MCU_Clk_24MHz
ENDIF
开启油门输入的中断,开启timer等等
; Setup timers for pwm input
mov IT01CF, #RTX_PIN ; Route RCP input to INT0
mov TCON, #11h ; Timer 0 run and INT0 edge triggered
mov CKCON0, #04h ; Timer 0 clock is system clock
mov TMOD, #09h ; Timer 0 set to 16bits and gated by INT0
mov TMR2CN0, #04h ; Timer 2 enabled
mov TMR3CN0, #04h ; Timer 3 enabled
Initialize_PCA ; Initialize PCA
Set_Pwm_Polarity ; Set pwm polarity
Enable_Power_Pwm_Module ; Enable power pwm module
Enable_Damp_Pwm_Module ; Enable damping pwm module
; Enable interrupts
IF MCU_48MHZ == 0
mov IE, #21h ; Enable timer 2 interrupts and INT0 interrupts
ELSE
mov IE, #23h ; Enable timer 0, timer 2 interrupts and INT0 interrupts
ENDIF
mov EIE1, #90h ; Enable timer 3 and PCA0 interrupts
mov IP, #01h ; High priority to INT0 interrupts
初始化比较器和ADC,并打开所有的中断
; Initialize comparator
Initialize_Comparator ; Initialize comparator
; Initialize ADC
Initialize_Adc ; Initialize ADC operation
call wait1ms
setb IE_EA ; Enable all interrupts
重置一些和dshot输入信号相关的变量:
; Reset stall count
mov Stall_Cnt, #0
; Initialize RC pulse
clr Flags2.RCP_UPDATED ; Clear updated flag
call wait200ms
; Clear all shot flags
clr Flags2.RCP_ONESHOT125 ; Clear OneShot125 flag
clr Flags2.RCP_ONESHOT42 ; Clear OneShot42 flag
clr Flags2.RCP_MULTISHOT ; Clear Multishot flag
clr Flags2.RCP_DSHOT ; Clear DShot flag
mov Dshot_Cmd, #0 ; Clear Dshot command
mov Dshot_Cmd_Cnt, #0 ; Clear Dshot command count
测试信号是不是常规的pwm, 直接等100ms ,是如果Rcp_Outside_Range_Cnt小于10,那么就是常规的pwm。 否则去检查是不是OneShot125,mulitshot. 检查之前会上面几行已经清空Flags2.RCP_ONESHOT125, Flags2.RCP_ONESHOT42,clr Flags2.RCP_MULTISHOT
和clr Flags2.RCP_DSHOT。
Rcp_Outside_Range的是在输入信号的中断里,检查到高电水大于2235us就会增加一次计数。pwm是20ms一个周期,最多5次,正常一般正电平也不会超2235us。
; Test whether signal is regular pwm
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
call wait100ms ; Wait for new RC pulse
clr C
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
subb A, #10
jnc ($+4) ;jump to Test whether signal is OneShot125
ajmp validate_rcp_start
检查输入出信号是不是dshot, 检查之前设置 Flags2.RCP_ONESHOT125
; Test whether signal is OneShot125
setb Flags2.RCP_ONESHOT125 ; Set OneShot125 flag
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
call wait100ms ; Wait for new RC pulse
clr C
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
subb A, #10
jnc ($+4)
ajmp validate_rcp_start
检查其它信号,这里如下,这里不详细看了, 相关资料
Standard PWM :1000us – 2000us
Oneshot125:125us – 250us
Oneshot 42:2us – 84us
Multishot:5us – 25us
Dshot150 :106.8us
Dshot300 :53.4us
Dshot600 :26.7us
DShot1200:13.4us
; Test whether signal is OneShot42
clr Flags2.RCP_ONESHOT125
setb Flags2.RCP_ONESHOT42 ; Set OneShot42 flag
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
call wait100ms ; Wait for new RC pulse
clr C
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
subb A, #10
jnc ($+4)
ajmp validate_rcp_start
; Setup timers for DShot
mov IT01CF, #(80h+(RTX_PIN SHL 4)+(RTX_PIN)) ; Route RCP input to INT0/1, with INT1 inverted
mov TCON, #51h ; Timer 0/1 run and INT0 edge triggered
mov CKCON0, #01h ; Timer 0/1 clock is system clock divided by 4 (for DShot150)
mov TMOD, #0AAh ; Timer 0/1 set to 8bits auto reload and gated by INT0
mov TH0, #0 ; Auto reload value zero
mov TH1, #0
; Setup interrupts for DShot
clr IE_ET0 ; Disable timer 0 interrupts
setb IE_ET1 ; Enable timer 1 interrupts
setb IE_EX1 ; Enable int1 interrupts
; Setup variables for DSshot150
IF MCU_48MHZ >= 1
mov DShot_Timer_Preset, #128 ; Load DShot sync timer preset (for DShot150)
ELSE
mov DShot_Timer_Preset, #192
ENDIF
mov DShot_Pwm_Thr, #20 ; Load DShot qualification pwm threshold (for DShot150)
mov DShot_Frame_Length_Thr, #80 ; Load DShot frame length criteria
; Test whether signal is DShot150
clr Flags2.RCP_ONESHOT42
setb Flags2.RCP_DSHOT
mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
call wait100ms ; Wait for new RC pulse
mov DShot_Pwm_Thr, #16 ; Load DShot regular pwm threshold
clr C
mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
subb A, #10
mov Dshot_Cmd, #0
mov Dshot_Cmd_Cnt, #0
jc validate_rcp_start
; Setup variables for DShot300
mov CKCON0, #0Ch ; Timer 0/1 clock is system clock (for DShot300)
IF MCU_48MHZ >= 1
mov DShot_Timer_Preset, #0 ; Load DShot sync timer preset (for DShot300)
ELSE
mov DShot_Timer_Preset, #128
ENDIF
mov DShot_Pwm_Thr, #40 ; Load DShot qualification pwm threshold (for DShot300)
mov DShot_Frame_Length_Thr, #40 ; Load DShot frame length criteria
; Test whether signal is DShot300
mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
call wait100ms ; Wait for new RC pulse
mov DShot_Pwm_Thr, #32 ; Load DShot regular pwm threshold
clr C
mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
subb A, #10
mov Dshot_Cmd, #0
mov Dshot_Cmd_Cnt, #0
jc validate_rcp_start
; Setup variables for DShot600
mov CKCON0, #0Ch ; Timer 0/1 clock is system clock (for DShot600)
IF MCU_48MHZ >= 1
mov DShot_Timer_Preset, #128 ; Load DShot sync timer preset (for DShot600)
ELSE
mov DShot_Timer_Preset, #192
ENDIF
mov DShot_Pwm_Thr, #20 ; Load DShot qualification pwm threshold (for DShot600)
mov DShot_Frame_Length_Thr, #20 ; Load DShot frame length criteria
; Test whether signal is DShot600
mov Rcp_Outside_Range_Cnt, #10 ; Set out of range counter
call wait100ms ; Wait for new RC pulse
mov DShot_Pwm_Thr, #16 ; Load DShot regular pwm threshold
clr C
mov A, Rcp_Outside_Range_Cnt ; Check if pulses were accepted
subb A, #10
mov Dshot_Cmd, #0
mov Dshot_Cmd_Cnt, #0
jc validate_rcp_start
; Setup timers for Multishot
mov IT01CF, #RTX_PIN ; Route RCP input to INT0
mov TCON, #11h ; Timer 0 run and INT0 edge triggered
mov CKCON0, #04h ; Timer 0 clock is system clock
mov TMOD, #09h ; Timer 0 set to 16bits and gated by INT0
; Setup interrupts for Multishot
setb IE_ET0 ; Enable timer 0 interrupts
clr IE_ET1 ; Disable timer 1 interrupts
clr IE_EX1 ; Disable int1 interrupts
; Test whether signal is Multishot
clr Flags2.RCP_DSHOT
setb Flags2.RCP_MULTISHOT ; Set Multishot flag
mov Rcp_Outside_Range_Cnt, #0 ; Reset out of range counter
call wait100ms ; Wait for new RC pulse
clr C
mov A, Rcp_Outside_Range_Cnt ; Check how many pulses were outside normal range ("900-2235us")
subb A, #10
jc validate_rcp_start
如果都不满足,那么跳回no signal,继续检查。
ajmp init_no_signal
要是检测到上述任一个信号,那么再等3 ms, 看看jb Flags2.RCP_UPDATED,是不是有设置,应该就是说再去读一个输入值了吧。就是没有设置,那么跳回init_no_signal, 继续检查。
validate_rcp_start:
; Validate RC pulse
call wait3ms ; Wait for new RC pulse
jb Flags2.RCP_UPDATED, ($+6) ; Is there an updated RC pulse available - proceed
ljmp init_no_signal ; Go back to detect input signal
信号ok了,那么开始一个长beep f1了 , 这里没有wait30ms, 其实就是do加长三倍。
; Beep arm sequence start signal
clr IE_EA ; Disable all interrupts
call beep_f1 ; Signal that RC pulse is ready
call beep_f1
call beep_f1
setb IE_EA ; Enable all interrupts
call wait200ms
开启arming序列, 要是dshot协议, 或者是双向打开,那么不会进行油门校准,直接跳到program_by_tx_checked, 如果设置没有打开tx program这里也会跳到program_by_tx_checked。
; Arming sequence start
arming_start:
jb Flags2.RCP_DSHOT, ($+6) ; Disable tx programming for DShot
jnb Flags3.PGM_BIDIR, ($+6) ; Disable tx programming for bidir
ljmp program_by_tx_checked ; Disable tx programming if bidirectional operation
call wait3ms
mov Temp1, #Pgm_Enable_TX_Program; Start programming mode entry if enabled
mov A, @Temp1
clr C
subb A, #1 ; Is TX programming enabled?
jnc arming_initial_arm_check ; Yes - proceed
jmp program_by_tx_checked ; No - branch
进行arming_initial_arm_check,Initial_Arm(这个变量在开始是1, 在arming完成之后会置0)是不是1, 要是零,也跳到program_by_tx_checked
arming_initial_arm_check:
mov A, Initial_Arm ; Yes - check if it is initial arm sequence
clr C
subb A, #1 ; Is it the initial arm sequence?
jnc arming_check ; Yes - proceed
jmp program_by_tx_checked ; No - branch
开始arming_check, 找出补偿,然后等100ms, 看看New_Rcp是不是超过中位(255/2),如果不是的话,那么也跳到program_by_tx_checked。否则等1ms, 然后beep_f4, 上面这个循环两次(throttle_high_cal开始)。
就是说你的油门要是一直在高位,你听到两个f4的beep.
两声beep之后,开计算平均油门。然后等200ms, 开始响成功beep,这个是f1,f2,f3,f4等10ms, 重复三次。 这个代码在inc里。
保存这个油门值在 Pgm_Max_Throttle
arming_check:
; Initialize flash keys to valid values
mov Flash_Key_1, #0A5h
mov Flash_Key_2, #0F1h
; Throttle calibration and tx program entry
mov Temp8, #2 ; Set 1 seconds wait time
throttle_high_cal:
setb Flags2.RCP_FULL_RANGE ; Set range to 1000-2020us
call find_throttle_gains ; Set throttle gains
call wait100ms ; Wait for new throttle value
clr IE_EA ; Disable interrupts (freeze New_Rcp value)
clr Flags2.RCP_FULL_RANGE ; Set programmed range
call find_throttle_gains ; Set throttle gains
clr C
mov A, New_Rcp ; Load new RC pulse value
subb A, #(255/2) ; Is RC pulse above midstick?
setb IE_EA ; Enable interrupts
jc program_by_tx_checked ; No - branch
call wait1ms
clr IE_EA ; Disable all interrupts
call beep_f4
setb IE_EA ; Enable all interrupts
djnz Temp8, throttle_high_cal ; Continue to wait
call average_throttle
clr C
mov A, Temp8
mov Temp1, #Pgm_Max_Throttle ; Store
mov @Temp1, A
call wait200ms
call success_beep
然后等用户打遥杆输入低油门, 找出补偿,然后等100ms, 看看New_Rcp是不是低于 中位(255/2),不是的话,在跳回throttle_low_cal循环续等。
等到小于中位的油门,就响beep_f1两次。
比较当前油门(new_Rcp)值是不是 Pgm_Max_Throttle 小 140us(35),如果太小,就是会把Pgm_Max_Throttle设置为当前的最小值+140us(35),然后等200ms.
响成功的声音 success_beep_inverted, 这个和高油门的反过来了,就是f4, f3, f2, f1这样响三次,也是在inc文件里,这里为会了不打断主流程也不列贴出来了。
throttle_low_cal_start:
mov Temp8, #10 ; Set 3 seconds wait time
throttle_low_cal:
setb Flags2.RCP_FULL_RANGE ; Set range to 1000-2020us
call find_throttle_gains ; Set throttle gains
call wait100ms
clr IE_EA ; Disable interrupts (freeze New_Rcp value)
clr Flags2.RCP_FULL_RANGE ; Set programmed range
call find_throttle_gains ; Set throttle gains
clr C
mov A, New_Rcp ; Load new RC pulse value
subb A, #(255/2) ; Below midstick?
setb IE_EA ; Enable interrupts
jnc throttle_low_cal_start ; No - start over
call wait1ms
clr IE_EA ; Disable all interrupts
call beep_f1
call wait10ms
call beep_f1
setb IE_EA ; Enable all interrupts
djnz Temp8, throttle_low_cal ; Continue to wait
call average_throttle
mov A, Temp8
add A, #3 ; Add about 1%
mov Temp1, #Pgm_Min_Throttle ; Store
mov @Temp1, A
mov Temp1, A ; Min throttle in Temp1
mov Temp2, #Pgm_Max_Throttle
mov A, @Temp2
clr C
subb A, #35 ; Subtract 35 (140us) from max throttle
jc program_by_tx_entry_limit
subb A, Temp1 ; Subtract min from max
jnc program_by_tx_entry_store
program_by_tx_entry_limit:
mov A, Temp1 ; Load min
add A, #35 ; Make max 140us higher than min
mov Temp1, #Pgm_Max_Throttle ; Store new max
mov @Temp1, A
program_by_tx_entry_store:
call wait200ms
call erase_and_store_all_in_eeprom
call success_beep_inverted
然后来到tx编程的等待,这里又会跳回去init_no_signal,这里又会走一次上面的设置代码,但是到了校准高位油门时,因为New_Rcp这时是小于255/2的,所以你听到一声长响的beep_f1(do) 后,就直接会跳到了program_by_tx_checked.
program_by_tx_entry_wait:
call wait100ms
call find_throttle_gains ; Set throttle gains
ljmp init_no_signal ; Go back
检查油门是不是低于stop, 是的话,arming结束, 开始长响一个三拍的beep_f4(没有wait,所以连起来了), 保存 Initial_Arm为0.
program_by_tx_checked:
; Initialize flash keys to invalid values
mov Flash_Key_1, #0
mov Flash_Key_2, #0
call wait100ms ; Wait for new throttle value
clr C
mov A, New_Rcp ; Load new RC pulse value
subb A, #1 ; Below stop?
jc arm_end_beep ; Yes - proceed
jmp arming_start ; No - start over
arm_end_beep:
; Beep arm sequence end signal
clr IE_EA ; Disable all interrupts
call beep_f4 ; Signal that rcpulse is ready
call beep_f4
call beep_f4
setb IE_EA ; Enable all interrupts
call wait200ms
; Clear initial arm variable
mov Initial_Arm, #0
检查信号, 这个其实就是看看 Rcp_Timeout_Cnt是不是零,Rcp_Timeout_Cntd在开始赋值1或10,要是超时这个减少1,要是零表示,有一段时间没有收到油门信号变化了,Timer2(t2), 每32ms会去减一下Rcp_Timeout_Cnt直至到零。Pgm_Beacon_Delay会和Power_On_Wait_Cnt_H相减,要是借位,就会开始beep f4, beep一次Power_On_Wait_Cnt_H会减1,就是Power_On_Wait_Cnt_L是255的时候beep一次了。 这个是用来发出声音来寻机用的。很多地方会跳回wait_for_power_on。
; Armed and waiting for power on
wait_for_power_on:
clr A
mov Power_On_Wait_Cnt_L, A ; Clear wait counter
mov Power_On_Wait_Cnt_H, A
wait_for_power_on_loop:
inc Power_On_Wait_Cnt_L ; Increment low wait counter
mov A, Power_On_Wait_Cnt_L
cpl A
jnz wait_for_power_on_no_beep; Counter wrapping (about 3 sec) , jump if A nozero, cpl first, actually jmp if A is not 255
inc Power_On_Wait_Cnt_H ; Increment high wait counter
mov Temp1, #Pgm_Beacon_Delay
mov A, @Temp1
mov Temp1, #25 ; Approximately 1 min
dec A
jz beep_delay_set
mov Temp1, #50 ; Approximately 2 min
dec A
jz beep_delay_set
mov Temp1, #125 ; Approximately 5 min
dec A
jz beep_delay_set
mov Temp1, #250 ; Approximately 10 min
dec A
jz beep_delay_set
mov Power_On_Wait_Cnt_H, #0 ; Reset counter for infinite delay
beep_delay_set:
clr C
mov A, Power_On_Wait_Cnt_H
subb A, Temp1 ; Check against chosen delay
jc wait_for_power_on_no_beep; Has delay elapsed?
call switch_power_off ; Switch power off in case braking is set
call wait1ms
dec Power_On_Wait_Cnt_H ; Decrement high wait counter
mov Power_On_Wait_Cnt_L, #0 ; Set low wait counter
mov Temp1, #Pgm_Beacon_Strength
mov Beep_Strength, @Temp1
clr IE_EA ; Disable all interrupts
call beep_f4 ; Signal that there is no signal
setb IE_EA ; Enable all interrupts
mov Temp1, #Pgm_Beep_Strength
mov Beep_Strength, @Temp1
call wait100ms ; Wait for new RC pulse to be measured
wait_for_power_on_no_beep:
call wait10ms
mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
jnz wait_for_power_on_not_missing ; If it is not zero - proceed
jmp init_no_signal ; If pulses missing - go back to detect input signal
如果有信号(Rcp_Timeout_Cntd不是零),同时New_Rcp(油门)不是零跳到 wait_for_power_on_nonzero, 再检查一次Rcp_Timeout_Cntd是不是零,要是不是零,那就跳到init_start
wait_for_power_on_not_missing:
clr C
mov A, New_Rcp ; Load new RC pulse value
subb A, #1 ; Higher than stop
jnc wait_for_power_on_nonzero ; Yes - proceed
clr C
mov A, Dshot_Cmd
subb A, #1 ; 1 or higher
jnc check_dshot_cmd ; Check Dshot command
ljmp wait_for_power_on_loop ; If not Dshot command - start over
wait_for_power_on_nonzero:
lcall wait100ms ; Wait to see if start pulse was only a glitch
mov A, Rcp_Timeout_Cntd ; Load RC pulse timeout counter value
jnz ($+5) ; If it is not zero - proceed
ljmp init_no_signal ; If it is zero (pulses missing) - go back to detect input signal
mov Dshot_Cmd, #0
mov Dshot_Cmd_Cnt, #0
ljmp init_start
上面基本上是准备阶段,下一篇 我们继续读init_start , 开始驱动电机去工作了。 未完待续!
更多推荐
所有评论(0)