开源BLHELI-S 代码详细解读(二)

2024-02-04 20:28

本文主要是介绍开源BLHELI-S 代码详细解读(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们继续,上篇跳到init_start, 把所有的moset关掉,把Adc_Conversion_Cnt ,Flags0,Flags1,Demag_Detected_Metric(Metric used to gauge demag event frequency)这几个变量清零。

init_start:clr	IE_EAcall switch_power_offclr	Asetb	IE_EAclr	Amov	Adc_Conversion_Cnt, Amov	Flags0, A				; Clear flags0mov	Flags1, A				; Clear flags1mov	Demag_Detected_Metric, A	; Clear demag metric

等1ms, 然后开始adc转换,通不停的判断ADC0CN0_ADINT
直至读取到温度,然后检查温度,供电电压, 限制输出功率的函数,调用前会设置power, Adc_Conversion_Cnt=8, 这个会在check_temp_voltage_and_limit_power判断,要是小8会进行电压的检查,要是大于等于8,就只有做温度的检查, efm8bb2自带一个温度探测。但是目前看代码,电压也没有检查,只是要是Adc_Conversion_Cnt < 8 ,调用一次Pwm_Limit会增加16, 直到 Pwm_Limit == 255.

温度这里读平均值来,会和Temp_Prot_Limit(就是blsuite界面的温度保护设置)比较,要是大于这个温度就对Pwm_Limit进行限制,一旦超了,Pwm_Limit就限制到 192,再看看有超了多个TEMP_LIMIT_STEP/2,  最多会把 Pwm_Limit限制成0. TEMP_LIMIT_STEP在blheli-s基本都是10度,个别是5度。

;**** **** **** **** ****; Motor start beginning;**** **** **** **** **** mov	Adc_Conversion_Cnt, #8				; Make sure a temp reading is donecall wait1mscall start_adc_conversion
read_initial_temp:jnb	ADC0CN0_ADINT, read_initial_tempRead_Adc_Result						; Read initial temperaturemov	A, Temp2jnz	($+3)							; Is reading below 256?mov	Temp1, A							; Yes - set average temperature value to zeromov	Current_Average_Temp, Temp1			; Set initial average temperaturecall check_temp_voltage_and_limit_powermov	Adc_Conversion_Cnt, #8				; Make sure a temp reading is done next time
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Check temperature, power supply voltage and limit power
;
; No assumptions
;
; Used to limit main motor power in order to maintain the required voltage
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
check_temp_voltage_and_limit_power:inc	Adc_Conversion_Cnt			; Increment conversion counterclr	Cmov	A, Adc_Conversion_Cnt		; Is conversion count equal to temp rate?subb	A, #8jc	check_voltage_start			; No - check voltage   , Adc_Conversion_Cnt < 8, jump to check voltage start.; Wait for ADC conversion to completejnb	ADC0CN0_ADINT, check_temp_voltage_and_limit_power; Read ADC resultRead_Adc_Result; Stop ADCStop_Adcmov	Adc_Conversion_Cnt, #0		; Yes - temperature check. Reset countermov	A, Temp2					; Move ADC MSB to Temp3mov	Temp3, Amov	Temp2, #Pgm_Enable_Temp_Prot	; Is temp protection enabled?mov	A, @Temp2jz	temp_check_exit			; No - branchmov	A, Temp3					; Is temperature reading below 256?jnz	temp_average_inc_dec		; No - proceedmov	A, Current_Average_Temp		; Yes -  decrement averagejz	temp_average_updated		; Already zero - no changejmp	temp_average_dec			; Decrement temp_average_inc_dec:clr	Cmov	A, Temp1					; Check if current temperature is above or below averagesubb	A, Current_Average_Tempjz	temp_average_updated_load_acc	; Equal - no changemov	A, Current_Average_Temp		; Above - increment averagejnc	temp_average_inc				jz	temp_average_updated		; Below - decrement average if average is not already zero
temp_average_dec:dec	A						; Decrement averagejmp	temp_average_updatedtemp_average_inc:inc	A						; Increment averagejz	temp_average_decjmp	temp_average_updatedtemp_average_updated_load_acc:mov	A, Current_Average_Temp
temp_average_updated:mov	Current_Average_Temp, Aclr	Csubb	A, Temp_Prot_Limit			; Is temperature below first limit?jc	temp_check_exit			; Yes - exitmov  Pwm_Limit, #192			; No - limit pwmclr	Csubb	A, #(TEMP_LIMIT_STEP/2)		; Is temperature below second limitjc	temp_check_exit			; Yes - exitmov  Pwm_Limit, #128			; No - limit pwmclr	Csubb	A, #(TEMP_LIMIT_STEP/2)		; Is temperature below third limitjc	temp_check_exit			; Yes - exitmov  Pwm_Limit, #64				; No - limit pwmclr	Csubb	A, #(TEMP_LIMIT_STEP/2)		; Is temperature below final limitjc	temp_check_exit			; Yes - exitmov  Pwm_Limit, #0				; No - limit pwmtemp_check_exit:retcheck_voltage_start:; Increase pwm limitmov  A, Pwm_Limitadd	A, #16			jnc	($+4)					; If not max - branch, not overflow to 255mov	A, #255                 ; max is 255mov	Pwm_Limit, A				; Increment limit ret

然后设置启动pwm, set_startup_pwm, 这里等于设置界面的值的50倍

	; Set up start operating conditionsclr	IE_EA				; Disable interruptscall set_startup_pwmmov	Pwm_Limit, Pwm_Limit_Begmov	Pwm_Limit_By_Rpm, Pwm_Limit_Begsetb	IE_EA

开始启动序列,这里有判断是不是双向。设置       Flags1.STARTUP_PHASE , 把Startup_Cnt清零。然后开启换相操作(commutation), 先是5转6(comm5comm6), 再是comm6comm1. 跟着初始化timing(这里就是调置一下Comm_Period4x_L/H为一个指定的值, 它是最近四次换相,timer3的计数), timing是时机的意思,然后跟关计算下一次换相的时机(timing), 第一次是一个虚拟的时机,这个时间是无感的电机,也不知道当前的位置,应该是计算不出来的。        

; Begin startup sequence
IF MCU_48MHZ >= 1Set_MCU_Clk_48MHz
ENDIFjnb	Flags3.PGM_BIDIR, init_start_bidir_done	; Check if bidirectional operationclr	Flags3.PGM_DIR_REV			; Set spinning direction. Default fwdjnb	Flags2.RCP_DIR_REV, ($+5)	; Check force directionsetb	Flags3.PGM_DIR_REV			; Set spinning directioninit_start_bidir_done:setb	Flags1.STARTUP_PHASE		; Set startup phase flagmov	Startup_Cnt, #0			; Reset countercall comm5comm6				; Initialize commutationcall comm6comm1				call initialize_timing			; Initialize timingcall	calc_next_comm_timing		; Set virtual commutation pointcall initialize_timing			; Initialize timingcall	calc_next_comm_timing		call	initialize_timing			; Initialize timing

计算下次换相时间calc_next_comm_timing这个很重要,迟些要详细看,先还是走主流程

下面来到run1, 这里是B 相打开,然后C相使用pwm控制,然后去检测A的比较器,应该就是检测A的反向电动势, A的电压是会从低到高。 

先是等待A的compare输出为高

然后等待zero cross过零信号

操作换相comm1comm2

计算下次换相时间


;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Run entry point
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****; Run 1 = B(p-on) + C(n-pwm) - comparator A evaluated
; Out_cA changes from low to high
run1:call wait_for_comp_out_high	; Wait for high
;		setup_comm_wait		; Setup wait time from zero cross to commutation
;		evaluate_comparator_integrity	; Check whether comparator reading has been normalcall wait_for_comm			; Wait from zero cross to commutationcall comm1comm2			; Commutatecall calc_next_comm_timing	; Calculate next timing and wait advance timing wait
;		wait_advance_timing		; Wait advance timing and start zero cross wait
;		calc_new_wait_times
;		wait_before_zc_scan		; Wait zero cross wait and start zero cross timeout

跟着是run2, 和run1基本上是一样的,A p打开, C是n-pwm控制,然后评估B的比较器. 这时B的电动势是会从高到低。 多了一个set_pwm_limit_high_rpm和set_pwm_limit_low_rpm的判断,这个是判断Flags.HIGH_RPM这个是上一次计算换相timing(时机)的时候设置的。操作换相comm2comm3


; Run 2 = A(p-on) + C(n-pwm) - comparator B evaluated
; Out_cB changes from high to low
run2:call wait_for_comp_out_low
;		setup_comm_wait
;		evaluate_comparator_integrityjb	Flags1.HIGH_RPM, ($+6)	; Skip if high rpmlcall set_pwm_limit_low_rpmjnb	Flags1.HIGH_RPM, ($+6)	; Do if high rpmlcall set_pwm_limit_high_rpmcall wait_for_commcall comm2comm3call calc_next_comm_timing
;		wait_advance_timing
;		calc_new_wait_times
;		wait_before_zc_scan

跟着是run3, 也是差不多了, 这里打开A p,B是n-pwm, 然后评估C的电压。C会从low变成high。操作互相comm3comm4

; Run 3 = A(p-on) + B(n-pwm) - comparator C evaluated
; Out_cC changes from low to high
run3:call wait_for_comp_out_high
;	 	setup_comm_wait	
;	 	evaluate_comparator_integrity	jnb	Flags1.GOV_ACTIVE, ($+6)lcall calc_governor_int_errorcall wait_for_commcall comm3comm4call calc_next_comm_timing
;	 	wait_advance_timing
;	 	calc_new_wait_times
;	 	wait_before_zc_scan	

跟着是run4, 打开C p, B是n-pwm, 评估A的电压,A会从高变到低,等到之后,操作换相comm4comm5

; Run 4 = C(p-on) + B(n-pwm) - comparator A evaluated
; Out_cA changes from high to low
run4:call wait_for_comp_out_low
;		setup_comm_wait
;		evaluate_comparator_integritycall wait_for_commcall comm4comm5call calc_next_comm_timing
;		wait_advance_timing
;		calc_new_wait_times
;		wait_before_zc_scan

跟着是run5, 打开C p, A是n-pwm, 评估B的电压,B会从low变到high,等到之后,操作换相comm5comm6

; Run 5 = C(p-on) + A(n-pwm) - comparator B evaluated
; Out_cB changes from low to high
run5:call wait_for_comp_out_high
;		setup_comm_wait
;		evaluate_comparator_integritycall wait_for_commcall comm5comm6call calc_next_comm_timing
;		wait_advance_timing
;		calc_new_wait_times
;		wait_before_zc_scan

跟着run6, 打开B p, A是n-pwm, 评估C的电压,C会从high变到low,等到之后,操作换相comm6comm1. run60这里会先打开温度的adc, 然后互相之后,计算下次换相操作时机前调用check_temp_voltage_and_limit_power,检查温度,然后限制功率。


; Run 6 = B(p-on) + A(n-pwm) - comparator C evaluated
; Out_cC changes from high to low
run6:call start_adc_conversioncall wait_for_comp_out_low
;		setup_comm_wait
;		evaluate_comparator_integritycall wait_for_commcall comm6comm1call check_temp_voltage_and_limit_powercall calc_next_comm_timing
;		wait_advance_timing
;		calc_new_wait_times
;		wait_before_zc_scan

检查是不是在启动阶段(Flags1.STARTUP_PHASE),不是的话跳到正常的各种检查(normal_run_checks),  否则Pwm_Limit=Pwm_Limit_Beg

      然后检查启动的计数(Startup_Cnt, 它开始是0,在上面的每个run的检测电压时wait_for_comp_out_low或wait_for_comp_out_high, 会有机会增加1)。 

       要是这个计数大于等于24, 那么会清空启动阶段标志(Flags1.STARTUP_PHASE),然后设置初始化运行阶段标志(Flags1.INITIAL_RUN_PHASE),把初始化运行旋转计算(Initial_Run_Rot_Cntd)设置为12,设置Pwm_Limit=Pwm_Limit_Beg, Pwm_Limit_By_Rpm=Pwm_Limit_Beg, 跟着跳到(normal_run_checks). 

      要是启动的计数(Startup_Cnt)还是小于24的话,那么检查油门输入(New_Rcp),要是油门是大于零的,那么跳回run1, 要是油门零,跳到run_to_wait_for_power_on

	; Check if it is direct startupjnb	Flags1.STARTUP_PHASE, normal_run_checks; Set spoolup power variablesmov	Pwm_Limit, Pwm_Limit_Beg		; Set initial max power; Check startup countermov	Temp2, #24				; Set nominal startup parametersmov	Temp3, #12clr	Cmov	A, Startup_Cnt				; Load countersubb	A, Temp2					; Is counter above requirement?jc	direct_start_check_rcp		; No - proceedclr	Flags1.STARTUP_PHASE		; Clear startup phase flagsetb	Flags1.INITIAL_RUN_PHASE		; Set initial run phase flagmov	Initial_Run_Rot_Cntd, Temp3	; Set initial run rotation countmov	Pwm_Limit, Pwm_Limit_Begmov	Pwm_Limit_By_Rpm, Pwm_Limit_Begjmp	normal_run_checksdirect_start_check_rcp:clr	Cmov	A, New_Rcp				; Load new pulse valuesubb	A, #1					; Check if pulse is below stop valuejc	($+5)ljmp	run1						; Continue to run jmp	run_to_wait_for_power_on

我们接着代码的布局看normal_run_checks,这里就是启动阶段结束后就会来到了,先是检查 不是运行的初始阶段(INITIAL_RUN_PHASE), 要是没设置Flags1.INITIAL_RUN_PHASE,跳到initial_run_phase_done.  否则检查要是换向的刹车阶段跳到DIR_CHANGE_BRAKE也跳到initial_run_phase_done。上面两个条件不成立,那么就递减一下Initial_Run_Rot_Cntd(初始化是12),检查它是不是0.

           要是0的话,就结束这个运行初始化阶段, 把状态设置成电机已启动阶段(Flags1.MOTOR_STARTED),跳回run1. 

           不是0的话,跳到initial_run_check_startup_rot,要是双向跳到initial_run_continue_run,否则检查油门是不是大于零; 油门不是0的话,跳回run1, 要是零就跳到 run_to_wait_for_power_on。


normal_run_checks:; Check if it is initial run phasejnb	Flags1.INITIAL_RUN_PHASE, initial_run_phase_done	; If not initial run phase - branchjb	Flags1.DIR_CHANGE_BRAKE, initial_run_phase_done	; If a direction change - branch; Decrement startup rotaton countmov	A, Initial_Run_Rot_Cntddec	A; Check number of initial rotationsjnz 	initial_run_check_startup_rot	; Branch if counter is not zeroclr	Flags1.INITIAL_RUN_PHASE		; Clear initial run phase flagsetb	Flags1.MOTOR_STARTED		; Set motor startedjmp run1						; Continue with normal runinitial_run_check_startup_rot:mov	Initial_Run_Rot_Cntd, A		; Not zero - store counterjb	Flags3.PGM_BIDIR, initial_run_continue_run	; Check if bidirectional operationclr	Cmov	A, New_Rcp				; Load new pulse valuesubb	A, #1					; Check if pulse is below stop valuejc	($+5)initial_run_continue_run:ljmp	run1						; Continue to run jmp	run_to_wait_for_power_on

我们按代码的布局来读一下initial_run_phase_done这个位置,这个位置其实就是电机已启动阶段来的,即正常运行时。 先是把Stall_Cnt清零(这个Stall_Cnt会在run_to_wait_for_power_on_fail时增加1),如果PGM_BIDIR设置了,就跳去run6_check_timeout    , 判断Rcp_Stop_Cnt是不是大于预设值(Temp1),要是的话跳去run_to_wait_for_power_on。

             Rcp_Stop_Cnt会有Timer2(每32ms)的中断里检查到油门时自增。要是配置了Pgm_Brake_On_Stop那么,这个Temp1是3(100ms), 否则是250(8秒).   Rcp_Stop_Cnt要是比Temp1大的话,那么认为是没有油门了,跳到run_wait_for_power_on.

initial_run_phase_done:; Reset stall countmov	Stall_Cnt, #0; Exit run loop after a given timejb	Flags3.PGM_BIDIR, run6_check_timeout	; Check if bidirectional operationmov	Temp1, #250mov	Temp2, #Pgm_Brake_On_Stopmov	A, @Temp2jz	($+4)mov	Temp1, #3					; About 100ms before stopping when brake is setclr	Cmov	A, Rcp_Stop_Cnt			; Load stop RC pulse counter low byte valuesubb	A, Temp1					; Is number of stop RC pulses above limit?jnc	run_to_wait_for_power_on		; Yes, go back to wait for poweron

没有跳走,就检查 Rcp_Timeout_Cnt是不是超时,它是倒计时的,上一篇有说,初始是10的,每超时一次减1。要是这里看到是零,那么就认为这个也没有油门了,跳到run_to_wait_for_power_on。

run6_check_timeout:mov	A, Rcp_Timeout_Cntd			; Load RC pulse timeout counter valuejz	run_to_wait_for_power_on		; If it is zero - go back to wait for poweron

没跳走,就继续往下走,不是双向的话,就是跳到run6_check_speed, 要是双向倒转PGM_DIR_REV,跳run6_check_dir_rev,不行再看看是不是RCP_DIR_REV,是的话,跳到run6_check_dir_change,说是保证转向匹配力的方向。都不满足就跳到run6_check_speed.

在run6_check_dir_change里,会跳回到run4, 这样顺序变了,就会改变方向。

run6_check_dir:jnb	Flags3.PGM_BIDIR, run6_check_speed		; Check if bidirectional operationjb	Flags3.PGM_DIR_REV, run6_check_dir_rev		; Check if actual rotation directionjb	Flags2.RCP_DIR_REV, run6_check_dir_change	; Matches force directionjmp	run6_check_speedrun6_check_dir_rev:jnb	Flags2.RCP_DIR_REV, run6_check_dir_changejmp	run6_check_speedrun6_check_dir_change:jb	Flags1.DIR_CHANGE_BRAKE, run6_check_speedsetb	Flags1.DIR_CHANGE_BRAKE		; Set brake flagmov	Pwm_Limit, Pwm_Limit_Beg		; Set max power while brakingjmp	run4						; Go back to run 4, thereby changing force direction

来到run6_check_speed, temp1默认是240, 要有DIR_CHANGE_BRAKE, 修改一下Pwm_Limit为Pwm_Limit_Beg     , temp1改为32。 temp1这个是一个时间长短值,跟着temp1会和Comm_Period4x_H    比较大小,要是Comm_Period4x_H   比它小,跳回run1. 否则,看看要是

DIR_CHANGE_BRAKE没有设置的话,就跳到run_to_wait_for_power_on,不是的话,清除DIR_CHANGE_BRAKE的标志,清除PGM_DIR_REV标志,要是RCP_DIR_REV有设置,那么设置PGM_DIR_REV,然后把当前的阶段设置回INITIAL_RUN_PHASE。初始化Initial_Run_Rot_Cntd为18,设置Pwm_Limit = Pwm_Limit_Beg。然后跳加run1.


run6_check_speed:mov	Temp1, #0F0h				; Default minimum speedjnb	Flags1.DIR_CHANGE_BRAKE, run6_brake_done; Is it a direction change?mov	Pwm_Limit, Pwm_Limit_Beg 	; Set max power while brakingmov	Temp1, #20h 				; Bidirectional braking termination speedrun6_brake_done:clr	Cmov	A, Comm_Period4x_H			; Is Comm_Period4x more than 32ms (~1220 eRPM)?subb	A, Temp1jnc	($+5)					; Yes - stop or turn direction ljmp	run1						; No - go back to run 1jnb	Flags1.DIR_CHANGE_BRAKE, run_to_wait_for_power_on	; If it is not a direction change - stopclr	Flags1.DIR_CHANGE_BRAKE		; Clear brake flagclr	Flags3.PGM_DIR_REV			; Set spinning direction. Default fwdjnb	Flags2.RCP_DIR_REV, ($+5)	; Check force directionsetb	Flags3.PGM_DIR_REV			; Set spinning directionsetb	Flags1.INITIAL_RUN_PHASEmov	Initial_Run_Rot_Cntd, #18mov	Pwm_Limit, Pwm_Limit_Beg		; Set initial max powerjmp	run1						; Go back to run 1 

到这里主流程就结束了,运行其实就是在run1-run6这里不断重复,中间会做一些判断和分支处理。

后面就是关于失败的一些处理,run_to_wait_for_power_on_fail这里Stall_Cnt会自增1,要是油门是零,那么跳去run_to_wait_for_power_on,

run_to_wait_for_power_on会重置Stall_Cnt为0。

不是的话,就跳去run_to_wait_for_power_on_stall_done, 就会关闭所有中断, 等100ms,然后调用switch_power_off。

要是设置了brake_on_stop那么,会把a,b和c的comFet 打开。

跟着检查Stall_Cnt, 要是它小于4那么跳回wait_for_power_on, 否则跳到init_no_signal。


run_to_wait_for_power_on_fail:	inc	Stall_Cnt					; Increment stall countmov	A, New_Rcp				; Check if RCP is zero, then it is a normal stop			jz	run_to_wait_for_power_onajmp	run_to_wait_for_power_on_stall_donerun_to_wait_for_power_on:	mov	Stall_Cnt, #0run_to_wait_for_power_on_stall_done:clr	IE_EAcall switch_power_offmov	Flags0, #0				; Clear flags0mov	Flags1, #0				; Clear flags1
IF MCU_48MHZ >= 1Set_MCU_Clk_24MHz
ENDIFsetb	IE_EAcall	wait100ms					; Wait for pwm to be stoppedcall switch_power_offmov	Temp1, #Pgm_Brake_On_Stopmov	A, @Temp1jz	run_to_wait_for_power_on_brake_doneAcomFET_onBcomFET_onCcomFET_onrun_to_wait_for_power_on_brake_done:clr	Cmov	A, Stall_Cntsubb	A, #4jc	jmp_wait_for_power_onjmp	init_no_signaljmp_wait_for_power_on:jmp	wait_for_power_on			; Go back to wait for power on


run_to_wait_for_power_on_fail是由前面的wait_for_comp_out_low和wait_for_comp_out_high的异常读取触发的。 既然主流程结束了,那么我们回去细细读一下wait_for_comp_out_low和wait_for_comp_out_high。

未完待续。。。。

我们下一篇继续详细读一下这个函数,还有计算换相时间,还有各个计时器,比较器相关的一些代码的阅读。 

这篇关于开源BLHELI-S 代码详细解读(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/678708

相关文章

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

金融业开源技术 术语

金融业开源技术  术语 1  范围 本文件界定了金融业开源技术的常用术语。 本文件适用于金融业中涉及开源技术的相关标准及规范性文件制定和信息沟通等活动。

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

MCU7.keil中build产生的hex文件解读

1.hex文件大致解读 闲来无事,查看了MCU6.用keil新建项目的hex文件 用FlexHex打开 给我的第一印象是:经过软件的解释之后,发现这些数据排列地十分整齐 :02000F0080FE71:03000000020003F8:0C000300787FE4F6D8FD75810702000F3D:00000001FF 把解释后的数据当作十六进制来观察 1.每一行数据

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d