📄 battery.asm
字号:
;----------------------------------
; 智能充电器实例
;功能:通过定时器定时从AD上读取数据,根据不同的电压选择不同的控制
; 充电方案,使用PWM控制输出脉宽来控制电流
;-----------------------------------
ORG 0000H
LJMP START
ORG 0003H
LJMP EXTERN_INT ; 外中断入口
ORG 000BH
LJMP TIMER0_INT ; 定时器中断入口
;-----------------------
; 程序开始,初始化各个寄存器以及标志位
;-----------------------
START:
MOV SP,#050H ; 设置堆栈
MOV R0,#030H ; 设置AD存储单元初始地址
MOV IE,#0FFH ; 打开所有中断
MOV DPTR,#78FFH ; 采集通道首地址,只使用一路AD就可以
MOV R0,#40H
MOV @R0,#00H ; 清除方案选择位
MOV R0,#40H
MOV @R0,#00H ; 清除方案选择触发位
MOV R1,#042H
MOV @R0,#00H ; 清除定时器计数器
LCALL TIMER1_INIT
;-----------------------
; 进入循环,查询标志位,采取不同的方案
;-----------------------
LOOP:
MOV R0,#30H ; 30H是AD转换的地址,将数据和几个值进行比较,确定方案
MOV A,@R0
SUBB A,#30H ; 当电压很小的时候,采用第一种方案,向引脚PWM发送占空比为10%的信号
JC PROCESS_01
MOV A,@R0
SUBB A,#90H
JC PROCESS_02 ; 当电压较小的时候,采用第二种方案,向引脚PWM发送占空比为20%的信号
MOV A,@R0
SUBB A,#90H
JZ PROCESS_03 ; 当电压正好的时候,采用第三种方案,向引脚PWM发送占空比为50%的信号
MOV A,#04H ; 当电压超出的时候,采用第四种方案,向引脚PWM发送占空比为0%的信号
LJMP PROCESS_04
CLEAR_FLAG:
MOV R0,#40H ; 清除方案选择位
MOV @R0,#00H
MOV R0,#41H ; 清除触发位
MOV @R0,#00H
LJMP LOOP
PROCESS_01:
MOV R1,#040H
MOV @R1,#01H ; 选择方案1
PROCESS_01_NEXT:
SETB P2.0 ; 将和PWM连接的管脚置高
MOV R1,#0F0H
MOV R0,#00H
PROCESS_01_01:
DJNZ R1,PROCESS_01_01
DJNZ R0,PROCESS_01_01 ; 空跑16*256*2个周期
CLR P2.0 ; 将和PWM连接的管脚置低
MOV R1,#070H
MOV R0,#00H
PROCESS_01_02:
DJNZ R1,PROCESS_01_02
DJNZ R0,PROCESS_01_02 ; 空跑16*256*2*9个周期
MOV R1,#041H ; 当方案改变标志位到来的时候,清除标志并且重新进行判断
CJNE @R1,#00H,CLEAR_FLAG
SJMP PROCESS_01_NEXT
PROCESS_02:
MOV R1,#040H
MOV @R1,#02H ; 选择方案2
PROCESS_02_NEXT:
SETB P2.0 ; 将和PWM连接的管脚置高
MOV R1,#0E0H
MOV R0,#00H
PROCESS_02_01:
DJNZ R1,PROCESS_02_01
DJNZ R0,PROCESS_02_01 ; 空跑16*256*2个周期
CLR P2.0 ; 将和PWM连接的管脚置低
MOV R1,#080H
MOV R0,#00H
PROCESS_02_02:
DJNZ R1,PROCESS_02_02
DJNZ R0,PROCESS_02_02 ; 空跑16*256*2*8个周期
MOV R1,#041H ; 当方案改变标志位到来的时候,清除标志并且重新进行判断
CJNE @R1,#00H,CLEAR_FLAG
SJMP PROCESS_02_NEXT
PROCESS_03:
MOV R1,#040H
MOV @R1,#03H ; 选择方案3
PROCESS_03_NEXT:
SETB P2.0 ; 将和PWM连接的管脚置高
MOV R1,#0B0H
MOV R0,#00H
PROCESS_03_01:
DJNZ R1,PROCESS_03_01
DJNZ R0,PROCESS_03_01 ; 空跑16*256*2*2个周期
CLR P2.0 ; 将和PWM连接的管脚置低
MOV R1,#0B0H
MOV R0,#00H
PROCESS_03_02:
DJNZ R1,PROCESS_03_02
DJNZ R0,PROCESS_03_02 ; 空跑16*256*2*7个周期
MOV R1,#041H ; 当方案改变标志位到来的时候,清除标志并且重新进行判断
CJNE @R1,#00H,CLEAR_FLAG
SJMP PROCESS_03_NEXT
PROCESS_04:
CLR P2.0
MOV R1,#040H
MOV @R1,#04H ; 选择方案4
MOV R1,#041H
CJNE @R1,#00H,CLEAR_FLAG
SJMP PROCESS_04
TIMER1_INIT:
ANL TMOD,#0FH ; 设置定时器1为方式2
ORL TMOD,#10H
MOV TMOD,#21H ; 定时器0工作在方式1
MOV PCON,#080H
CLR TR1 ; 禁止定时器1
SETB EA
SETB ET1
SETB ET0
SETB PT0 ; 定时器0中断优于串口中断
CLR TF1
MOV TL0,#00H
MOV TH0,#01FH ; 定时器0中断发生时间为62.5毫秒
SETB TR0 ; 使能定时器0
CLR TF0
RET;
;-----------------------
; 进入定时器中断,每500毫秒设置一次标志位
;-----------------------
TIMER0_INT:
PUSH ACC ; 累加器入栈
PUSH PSW ; 程序状态字入栈
MOV PSW,#18H ; 切换寄存器区域
CLR TF0 ; 清除定时器中断TF0
CLR TR0 ; 禁止定时器0
MOV TL0,#00H
MOV TH0,#01FH ; 定时器0中断发生时间为6
CLR TF0 ; 清除溢出中断位
MOV R1,#042H
INC @R1 ; 增加计数器的值,到8为止,这样达到500毫秒
CJNE @R1,#08H,TIMER0_READY
MOV @R1,#00H ; 清除计数器的值
MOV R1,#041H ; 设置标志位,每500毫秒重新选择方案
MOV @R1,#01H
TIMER0_READY:
SETB TR0 ; 使能定时器0
POP PSW ; 程序状态字出栈
POP ACC ; 累加器出栈
RETI
;-----------------------
; 进入外部中断,每进入一次读取ADC的值
;-----------------------
EXTERN_INT:
PUSH ACC ; 累加器压栈
PUSH PSW ; 程序状态字压栈
MOV PSW,#010H ; 切换寄存器区域
MOV DPTR,#78FFH ; AD转换器首地址
MOVX A,@DPTR ; 读入AD的值
MOV R1,#030H ; 存储AD转换器的数据的地址
MOV @R1,A ; 将AD的值读入该地址
POP PSW ; 程序状态字出栈
POP ACC ; 累加器出栈
RETI
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -