搜索
bottom↓
回复: 23

BLHeli_S 源码解析讨论

[复制链接]

出0入0汤圆

发表于 2016-12-24 10:39:05 | 显示全部楼层 |阅读模式
# 1.时钟配置说明 #

对每次 FLASH 读或取指操作,系统为 FLASH存储器提供一个内部 FLASH 读选通信号。FLASH读选通信号持续一或两个系统时钟周期,由 FLRT(PFE0CN.4)决定。如果系统时钟大于 25 MHz,则 FLRT 位必须被设置为逻辑 1,否则,从 FLASH读取的数据或指令不是实际的 FLASH内容。

更新 FLRT步骤如下

- 第一步:设置SFRPAGE地址为 PFE0CN页地址(0X10) 即 mov SFRPAGE, #10h
- 第二步:

         如果系统时钟SYSCLK小于等于25M 则
                         禁止指令预取引擎(PFE0CN寄存器中的 PFEN位清 0),设置  PFE0CN.5 = 0
                         FLASH读选通信号为一个系统时钟                   设置 PFE0CN.4 = 0  即mov SFRPAGE, #10h

         如果系统时钟SYSCLK大于 25 MH 则
                         使能指令预取引擎(PFE0CN寄存器中的 PFEN位清 0),设置  PFE0CN.5 = 1
                         FLASH读选通信号为两个系统时钟                   设置 PFE0CN.4 = 1 即mov PFE0CN, #30h

- 第三步:设置 SFRPAGE页地址为 00H。即 mov SFRPAGE, #00h

所以时钟配置程序如下 :
  1.     ;****************************** 设置系统时钟为24M *****************************
  2.     ;
  3.     ; 1:时钟源为 HFOSC1 (48M)  ,然后配置为 2分频
  4.     ; 2
  5.     ;
  6.     ;*****************************************************************************
  7.     Set_MCU_Clk_24MHz MACRO
  8.     mov CLKSEL, #13h; Set clock to 24MHz
  9.     mov SFRPAGE, #10h
  10.     mov PFE0CN, #00h; Set flash timing for 24MHz
  11.     mov SFRPAGE, #00h
  12.     mov Clock_Set_At_48MHz, #0
  13.     ENDM
复制代码

  1.    ;****************************** 设置系统时钟为48M *****************************
  2.     ;
  3.     ; 1:时钟源为 HFOSC1 (48M) SYSCLK 为  clock source(原时钟的1分频)
  4.     ; 1:
  5.     ;
  6.     ;*****************************************************************************
  7.     Set_MCU_Clk_48MHz MACRO
  8.     mov SFRPAGE, #10h
  9.     mov PFE0CN, #30h; Set flash timing for 48MHz
  10.     mov SFRPAGE, #00h
  11.     mov CLKSEL, #03h; Set clock to 48MHz
  12.     mov Clock_Set_At_48MHz, #1
  13.     ENDM
复制代码


##  1.1页寄存器使用说明  ##

你所用的每个寄存器都有个寄存地址,而寄存器页的页码就是指向你的寄存地址的。当你需要使用某个寄存器时,就必须把SFRPAGE指向你所要用的寄存器页上面去
举例如下:

  1.     void Init_ADC0()

  2.     {

  3.      char SFRPAGE_SAVE = SFRPAGE;  // 保存当前的SFR页

  4.      SFRPAGE = ADC0_PAGE;          //把页码改到以下几个寄存器所在的页码

  5.      ADC0CN = 0x00;                // 每次向AD0BUSY 写1 时启动ADC0 转换

  6.      REF0CN = 0x03;                // ADC0电压基准取自VREF0引脚,内部电压基准缓冲器工作

  7.      AMX0CF = 0x00;                // AIN inputs are single-ended (default)

  8.      AMX0SL = 0x00;                // 选择ADC 输入为AIN0.0   

  9.                                   // ADC0CF = (SYSCLK/SAR_CLK) << 3; // ADC 转换时钟 = 2.5MHz

  10.      ADC0CF |= 0x00;  // PGA 增益 = 1 (默认)

  11.                                   // EIE2 |= 0x02;   // 允许ADC0 转换结束中断

  12.      SFRPAGE = SFRPAGE_SAVE;      //回复寄存器页

  13.     }
复制代码


这个程序中char SFRPAGE_SAVE = SFRPAGE; 和  SFRPAGE = SFRPAGE_SAVE; 是使在调用这个子函数后页码能够回到调用前的页码

----------

# 2.脉冲捕获--获取油门值说明 (Get_Rcp_Capture_Values) #
函数说明

- 1:脉冲捕获使用定时器0,计数周期 41.67ns;
- 2:该函数是在定时器 0中断中执行。

操作步骤如下:

- 1:关闭定时器0
- 2:保存计数值 Temp1 = TL0  Temp2 = TH0  Temp3 = Timer0_X (该值在定时器0中断中被自加)
- 3:如果定时器0和其他的中断同时产生了,那么定时器0会被挂起,如果被挂起则把Temp3++, 否则 Temp3 保持原来的值
- 4:把定时器0 计数器清0 即TL0 =0 TH0 = 0
- 5:把 Timer0_X 清零,即 Timer0_X = 0
- 6:从新使能定时器 0
- 7: 如果48M Temp1 = Temp1 *2  Temp2 = Temp2 *2  Temp3 = Temp3 *2,如果不是 Temp1 Temp2 Temp3 保持原有值

该函数的作用是读取脉冲捕获的计数器值 参数返回放到 Temp1 和 Temp2 中


----------

# 3. PCA初始化函数说明 -- Initialize_PCA #
  说明:

-  1: 使能PCA0
-  2: PCA0时钟选择系统时钟
-  3: 如果延时为0  如果48M,则设置PCA0为11位PWM  ,否则设置为10位模式 ,设置PWM 边沿对齐
-  4: 如果延时不为0 如果48M 则设置PCA0为10位PWM  ,否则设置为9位模式 , 设置PWM 中间对齐

----------

# 4.上电PWM模式设置--Enable_Power_Pwm_Module #

说明:

1. 如果延时为0 使能比较器CPM0,使能匹配功能,  使能PCA为PWM模式
2. 如果延时为0 使能比较器CPM0, 禁能匹配功能, 使能PCA为PWM模式

代码如下 :

  1.   Enable_Power_Pwm_Module MACRO
  2.     IF FETON_DELAY == 0
  3.             mov PCA0CPM0, #4Ah  ; Enable comparator of module, enable match, set pwm mode
  4.     ELSE
  5.             mov PCA0CPM0, #42h  ; Enable comparator of module, set pwm mode
  6.     ENDIF
  7.     ENDM
复制代码


# ADC 初始化函数 -- Initialize_Adc #


说明:设置采样频率为 2M

-  1:设置VDD作为电压基准,使能内部温度传感器
-  2:设置ADC转换clk =  PCLK/(REF0CN >>3 -1) ,所以,

                  如果是48M 则48/ (B9H >>3 -1)= 2.18M
                如果是24M 则24/ (59h >>3 -1)= 2.4M

-  3:设置ADC增益为 1倍

代码如下 :

Initialize_Adc MACRO
            mov REF0CN, #0Ch; Set vdd (3.3V) as reference. Enable temp sensor and bias
    IF MCU_48MHZ == 0
            mov ADC0CF, #59h; ADC clock 2MHz, PGA gain 1
    ELSE
            mov ADC0CF, #0B9h   ; ADC clock 2MHz, PGA gain 1
    ENDIF
            mov ADC0MX, #10h; Select temp sensor input
            mov ADC0CN0, #80h   ; ADC enabled
            mov ADC0CN1, #01h   ; Common mode buffer enabled
    ENDM

定时器资源使用如下 :

1. 定时器 0 : 定时周期41.67ns, 用于RC;
2. 定时器 2 : 定时周期500ns,   用于RC 和换向时间;
3. 定时器 3 : 定时周期500ns,   用于换向时间;
4. PCA0    : 用于硬件PWM ;

# 读取全部eeprom函数: read_all_eeprom_parameters #

执行过程 :

从 Eep_Initialized_L 所代表的地址中读取数据dataL放到 Bit_Access所代表的地址中 ,

  如果 读到数据dataL == 055h

                把 Eep_Initialized_L +1 所代表的地址中的数据读取出来dataH,放到   Bit_Access所代表的地址中,此时
             如果 dataH  ==0AAh 则调用read_eeprom_read函数,读取 eeprom中的数据;
             如果 dataH  != 0AAh 则调用 read_eeprom_store_defaults函数 ,读取默认的eeprom中的数据
  如果 读到数据dataL != 055h

                则调用 read_eeprom_store_defaults函数 ,读取默认的eeprom中的数据

总结 :如果 [Eep_Initialized_L] = 055h 且 [Eep_Initialized_L +1] = 0AAh 才能调用read_eeprom_read函数,读取 eeprom中的数据;否则会调用 read_eeprom_store_defaults函数 ,读取默认的eeprom中的数据,

# 延时函数#

----------
执行一次是 42.7us  内环是 23 * 42.7 us = 982.1us = 1ms
所以 Temp2的值决定着 要延时多少ms eg : wait30ms中 要把 Temp2 = 30

  1. ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  2.     ;
  3.     ; Wait xms ~(x*4*250)  (Different entry points)
  4.     ;
  5.     ; No assumptions
  6.     ;
  7.     ;**** **** **** **** **** **** **** **** **** **** **** **** ****
  8.     wait1ms:
  9.             mov         Temp2, #1
  10.             jmp                 waitxms_o

  11.     wait3ms:
  12.             mov         Temp2, #3
  13.             jmp         waitxms_o

  14.     wait10ms:   
  15.             mov         Temp2, #10
  16.             jmp         waitxms_o

  17.     wait30ms:   
  18.             mov         Temp2, #30
  19.             jmp         waitxms_o

  20.     wait100ms:  
  21.             mov         Temp2, #100
  22.             jmp         waitxms_o

  23.     wait200ms:  
  24.             mov         Temp2, #200
  25.             jmp         waitxms_o

  26.     waitxms_o:  ; Outer loop
  27.             mov         Temp1, #23
  28.     waitxms_m:  ; Middle loop
  29.             clr         A
  30.             djnz        ACC, [        DISCUZ_CODE_0        ]nbsp; ; Inner loop (42.7us - 1024 cycles)
  31.             djnz        Temp1, waitxms_m
  32.             djnz        Temp2, waitxms_o

  33.     ret
复制代码


# pgm_start 函数 #

1. 初始化 Flash_Key_1和Flash_Key_2为 0
2. 禁能看门口
3. 初始化栈大小
4. 使能VDD电压监视器
5. 如果 是1s电池 不把VDD电压监视器设置为系统复位源,否则设置为系统复位源
6. 选择内部震荡器为系统时钟源
7. 关闭所有的MOS管和PWM输出
8. 初始化 所有IO
9. 初始化交叉开关
10. 再次关闭所有的MOS管和PWM输出
11. 清除RAM
12. 执行设置默认参数到内存中
13. 执行从eeprom中读取参数
14. 取出Pgm_Beep_Strength地址中的数据 放到Beep_Strength中
15. 把 Initial_Arm位置1
16. 禁能所有中断,
17. 发声处理
18. 执行led控制

代码如下 :
  1. pgm_start:
  2.             ; Initialize flash keys to invalid values
  3.             mov Flash_Key_1, #0
  4.             mov Flash_Key_2, #0
  5.             ; Disable the WDT.
  6.             mov WDTCN, #0DEh        ; Disable watchdog
  7.             mov WDTCN, #0ADh        
  8.             ; Initialize stack
  9.             mov SP, #0c0h           ; Stack = 64 upper bytes of RAM
  10.             ; Initialize VDD monitor
  11.             orl VDM0CN, #080h       ; Enable the VDD monitor
  12.         IF ONE_S_CAPABLE == 0      
  13.             mov     RSTSRC, #06h    ; Set missing clock and VDD monitor as a reset source if not 1S capable
  14.         ELSE
  15.             mov     RSTSRC, #04h    ; Do not set VDD monitor as a reset source for 1S ESCSs, in order to avoid resets due to it
  16.         ENDIF
  17.             ; Set clock frequency
  18.             mov CLKSEL, #00h        ; Set clock divider to 1
  19.             ; Switch power off
  20.             call    switch_power_off
  21.             ; Ports initialization
  22.             mov P0, #P0_INIT
  23.             mov P0MDIN, #P0_DIGITAL
  24.             mov P0MDOUT, #P0_PUSHPULL
  25.             mov P0, #P0_INIT
  26.             mov P0SKIP, #P0_SKIP               
  27.             mov P1, #P1_INIT
  28.             mov P1MDIN, #P1_DIGITAL
  29.             mov P1MDOUT, #P1_PUSHPULL
  30.             mov P1, #P1_INIT
  31.             mov P1SKIP, #P1_SKIP               
  32.             mov P2MDOUT, #P2_PUSHPULL               
  33.             ; Initialize the XBAR and related functionality
  34.             Initialize_Xbar
  35.             ; Switch power off again, after initializing ports
  36.             call    switch_power_off
  37.             ; Clear RAM
  38.             clr A               ; Clear accumulator
  39.             mov Temp1, A            ; Clear Temp1
  40.             clear_ram:  
  41.             mov @Temp1, A           ; Clear RAM
  42.             djnz Temp1, clear_ram   ; Is A not zero? - jump
  43.             ; Set default programmed parameters
  44.             call    set_default_parameters
  45.             ; Read all programmed parameters
  46.             call read_all_eeprom_parameters
  47.             ; Set beep strength
  48.             mov Temp1, #Pgm_Beep_Strength
  49.             mov Beep_Strength, @Temp1
  50.             ; Set initial arm variable
  51.             mov Initial_Arm, #1
  52.             ; Initializing beep
  53.             clr IE_EA           ; Disable interrupts explicitly
  54.             call wait200ms  
  55.             call beep_f1
  56.             call wait30ms
  57.             call beep_f2
  58.             call wait30ms
  59.             call beep_f3
  60.             call wait30ms
  61.             call    led_control
复制代码


最后奉上BLHeli_s 电调最小电调系统原理图,支持BLHeli_S F_H_40固件,后面还需用户自行添加驱动电路,电调电流大小,取决于驱动电路的MOS型号,和最小系统无关,所以后面的驱动电路需要用户自行设计,(驱动电路都长那个样子,一般都是差不多)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

如果想吃一顿饺子,就得从冰箱里取出肉,剁馅儿,倒面粉、揉面、醒面,擀成皮儿,下锅……
一整个繁琐流程,就是为了出锅时那一嘴滚烫流油的热饺子。

如果这个过程,禁不住饿,零食下肚了,饺子出锅时也就不香了……《非诚勿扰3》

出0入0汤圆

 楼主| 发表于 2016-12-24 11:32:07 | 显示全部楼层
附件是BLHeli_S keil 编译说明,源码结构分析:目录结构如所示,可以看出只有 Atmel/BLHeli_S SiLabs/SiLabs 三个文件夹有用,举例说 明:当你想用 EFM8 系列的 MCU 作为主控,那么你就可以直接拷贝 BLHeli_S SiLabs 文件夹 加入到你的工程,其他的都可以删除,同理也是一样。本教程以 BLHeli_S SiLabs 文件夹为例 说明,因为这个是最新源码,并且长久更新。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入25汤圆

发表于 2016-12-24 12:07:03 | 显示全部楼层
lz  blheli    官方网站多少?  github地址多少?? 研究一下 有什么优势 或者 缺点

出0入0汤圆

 楼主| 发表于 2016-12-24 12:18:18 | 显示全部楼层
rei1984 发表于 2016-12-24 12:07
lz  blheli    官方网站多少?  github地址多少?? 研究一下 有什么优势 或者 缺点 ...

github.com/bitdump/BLHeli

出0入0汤圆

发表于 2016-12-25 20:55:17 | 显示全部楼层
楼主有对应的原理图吗?另外BLHeli_S 用了硬件的PWM,以前版本在检查比较器结果时会判断是PWN_ON还是OFF,不知道这个版本是怎么做判断的?

出0入0汤圆

 楼主| 发表于 2016-12-26 10:07:54 | 显示全部楼层
yuntian 发表于 2016-12-25 20:55
楼主有对应的原理图吗?另外BLHeli_S 用了硬件的PWM,以前版本在检查比较器结果时会判断是PWN_ON还是OFF, ...

1:1楼最后的PDF就是原理图,支持BLHeli_S F_H_40 原生固件;
2:在检测比较器结果的时候,不用管PWM开或者关,作者的处理方式是根据不同的电机状态,决定检测次数,动态调整,如果检测过程中出现错误就再进行检查,直到比较器检测超时为止,如果超时就出错,否则结果是想要的,检测时间正常情况下是过零时间的3/8.

出0入0汤圆

发表于 2016-12-27 13:00:55 | 显示全部楼层
谢谢解答, 另外请教个问题, 硬件PWM是使用互补PWM吗?

出0入0汤圆

 楼主| 发表于 2016-12-27 13:22:21 | 显示全部楼层
yuntian 发表于 2016-12-27 13:00
谢谢解答, 另外请教个问题, 硬件PWM是使用互补PWM吗?

BLHeli_s是硬互补PWM

出0入0汤圆

发表于 2016-12-27 14:14:02 | 显示全部楼层
原来电调也是有程序的,我以为是纯模拟电路呢

出0入0汤圆

 楼主| 发表于 2016-12-27 16:54:56 | 显示全部楼层
grash 发表于 2016-12-27 14:14
原来电调也是有程序的,我以为是纯模拟电路呢

不但有程序,而且电机控制是一个大的学问!平常用的电调是一种简化版的电机控制。

出0入0汤圆

发表于 2016-12-28 17:53:39 | 显示全部楼层
EFM8 keil 5 的device pack 能不能发一下, 在网上没找到, 谢谢! 另外有板子可以买吗? 想直接在板子上调一下

出0入0汤圆

发表于 2017-1-2 20:56:57 | 显示全部楼层
密码不对

出0入0汤圆

 楼主| 发表于 2017-1-4 10:27:17 | 显示全部楼层

What 密码?

出0入0汤圆

发表于 2017-7-3 11:53:58 | 显示全部楼层
楼主的BLHeli的源码能发一份吗?好像官网的只有HEX文件,没有asm的源码了

出0入0汤圆

发表于 2017-7-3 14:08:40 | 显示全部楼层
makeflyeasy 发表于 2017-7-3 11:53
楼主的BLHeli的源码能发一份吗?好像官网的只有HEX文件,没有asm的源码了

https://github.com/bitdump/BLHeli/tree/master/BLHeli_S%20SiLabs

这不是有源码吗?

出0入0汤圆

发表于 2017-7-3 15:42:08 | 显示全部楼层
huangyiting1990 发表于 2017-7-3 14:08
https://github.com/bitdump/BLHeli/tree/master/BLHeli_S%20SiLabs

这不是有源码吗?

谢谢,之前可能找错了吧。已经下载下来了。谢谢哈

出0入0汤圆

发表于 2017-7-28 11:33:52 | 显示全部楼层
您好,请问BLHeli-S  keli 工程 百度网盘的密码是多少

出0入0汤圆

发表于 2017-8-9 11:51:41 | 显示全部楼层
电调水太深

出0入0汤圆

发表于 2018-2-22 23:39:54 | 显示全部楼层
非常想试试做个电调,可自己做好像成本并不划算,也许只是图个乐趣

出0入0汤圆

发表于 2018-4-18 07:36:45 来自手机 | 显示全部楼层
厉害,学习学习

出0入0汤圆

发表于 2019-7-26 09:55:51 | 显示全部楼层
麻烦问一下网盘keil工程的密码多少啊

出0入0汤圆

发表于 2019-7-26 12:56:52 | 显示全部楼层
学习一下

出0入79汤圆

发表于 2019-7-26 19:40:34 来自手机 | 显示全部楼层
做电调开发需要相当知识和经验,拿开源学习很不错,做产品还是三思而行。

出0入4汤圆

发表于 2019-9-18 17:40:32 | 显示全部楼层
谢谢分享
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-28 18:51

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表