|
# 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
所以时钟配置程序如下 :
- ;****************************** 设置系统时钟为24M *****************************
- ;
- ; 1:时钟源为 HFOSC1 (48M) ,然后配置为 2分频
- ; 2
- ;
- ;*****************************************************************************
- Set_MCU_Clk_24MHz MACRO
- mov CLKSEL, #13h; Set clock to 24MHz
- mov SFRPAGE, #10h
- mov PFE0CN, #00h; Set flash timing for 24MHz
- mov SFRPAGE, #00h
- mov Clock_Set_At_48MHz, #0
- ENDM
复制代码
- ;****************************** 设置系统时钟为48M *****************************
- ;
- ; 1:时钟源为 HFOSC1 (48M) SYSCLK 为 clock source(原时钟的1分频)
- ; 1:
- ;
- ;*****************************************************************************
- Set_MCU_Clk_48MHz MACRO
- mov SFRPAGE, #10h
- mov PFE0CN, #30h; Set flash timing for 48MHz
- mov SFRPAGE, #00h
- mov CLKSEL, #03h; Set clock to 48MHz
- mov Clock_Set_At_48MHz, #1
- ENDM
复制代码
## 1.1页寄存器使用说明 ##
你所用的每个寄存器都有个寄存地址,而寄存器页的页码就是指向你的寄存地址的。当你需要使用某个寄存器时,就必须把SFRPAGE指向你所要用的寄存器页上面去
举例如下:
- void Init_ADC0()
- {
- char SFRPAGE_SAVE = SFRPAGE; // 保存当前的SFR页
- SFRPAGE = ADC0_PAGE; //把页码改到以下几个寄存器所在的页码
- ADC0CN = 0x00; // 每次向AD0BUSY 写1 时启动ADC0 转换
- REF0CN = 0x03; // ADC0电压基准取自VREF0引脚,内部电压基准缓冲器工作
- AMX0CF = 0x00; // AIN inputs are single-ended (default)
- AMX0SL = 0x00; // 选择ADC 输入为AIN0.0
- // ADC0CF = (SYSCLK/SAR_CLK) << 3; // ADC 转换时钟 = 2.5MHz
- ADC0CF |= 0x00; // PGA 增益 = 1 (默认)
- // EIE2 |= 0x02; // 允许ADC0 转换结束中断
- SFRPAGE = SFRPAGE_SAVE; //回复寄存器页
- }
复制代码
这个程序中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模式
代码如下 :
- Enable_Power_Pwm_Module MACRO
- IF FETON_DELAY == 0
- mov PCA0CPM0, #4Ah ; Enable comparator of module, enable match, set pwm mode
- ELSE
- mov PCA0CPM0, #42h ; Enable comparator of module, set pwm mode
- ENDIF
- 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
- ;**** **** **** **** **** **** **** **** **** **** **** **** ****
- ;
- ; Wait xms ~(x*4*250) (Different entry points)
- ;
- ; No assumptions
- ;
- ;**** **** **** **** **** **** **** **** **** **** **** **** ****
- wait1ms:
- mov Temp2, #1
- jmp waitxms_o
- wait3ms:
- mov Temp2, #3
- jmp waitxms_o
- wait10ms:
- mov Temp2, #10
- jmp waitxms_o
- wait30ms:
- mov Temp2, #30
- jmp waitxms_o
- wait100ms:
- mov Temp2, #100
- jmp waitxms_o
- wait200ms:
- mov Temp2, #200
- jmp waitxms_o
- waitxms_o: ; Outer loop
- mov Temp1, #23
- waitxms_m: ; Middle loop
- clr A
- djnz ACC, [ DISCUZ_CODE_0 ]nbsp; ; Inner loop (42.7us - 1024 cycles)
- djnz Temp1, waitxms_m
- djnz Temp2, waitxms_o
- 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控制
代码如下 :
- 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
- orl VDM0CN, #080h ; Enable the VDD monitor
- IF ONE_S_CAPABLE == 0
- mov RSTSRC, #06h ; Set missing clock and VDD monitor as a reset source if not 1S capable
- ELSE
- mov RSTSRC, #04h ; Do not set VDD monitor as a reset source for 1S ESCSs, in order to avoid resets due to it
- ENDIF
- ; 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
复制代码
最后奉上BLHeli_s 电调最小电调系统原理图,支持BLHeli_S F_H_40固件,后面还需用户自行添加驱动电路,电调电流大小,取决于驱动电路的MOS型号,和最小系统无关,所以后面的驱动电路需要用户自行设计,(驱动电路都长那个样子,一般都是差不多)
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|