单片机
原理图怎么画啊?I/O接口怎么连接?
普通电风扇电机一般用调相法调速,对于象电加热器之类热惯量较大的,还可用调功 法来调温,即控制每秒内正弦波形个数.
调功 法当每秒内完整波形少于25个时,平均电压波动较大,负载的热惯性会起一个平衡作用,一般不低于10个.但用于惯量较小的风扇,就会有明显的抖晃了.
调相法调速缺点是不能过零触发,因此干扰毛刺较大.而调**可过零触发,干扰很小.
下面是俺以前做过的一个小产品,可参考一下.
lc.sch → http://bbs.21ic.com/upfiles/img/200711/2007112282813673.rar
lc.asm → http://bbs.21ic.com/upfiles/img/200711/200711228352463.rar
;
; ┏━━━━━━━━━━━┓
; ┃┏━━━━━━━━━┓┃
; ┃┃无线遥控开关接收器┃┃
; ┃┃ 源程序 ┃┃
; ┃┃ V1.0 01.03.18 ┃┃
; ┃┗━━━━━━━━━┛┃
; ┗━━━━━━━━━━━┛
;
ORG 0000H
AJMP CSH ;主程序进入点
ORG 0003H
LJMP WT0 ;外部中断WT0入口
ORG 000BH
AJMP TI0 ;定时中断T0入口
ORG 001BH
AJMP TI1 ;定时中断T1入口
;
;**********
;* 初始化 *
;**********
;
ORG 0020H
CSH: MOV R0,#7FH ;内部RAM(00H~7FH)清零
CSH1: MOV @R0,#00H
DJNZ R0,CSH1
MOV SP,#60H ;堆栈60H~7FH,【使用89C2051】
MOV TMOD,#00010010B ;T0作8位计数器 (自动装入),T1作16位计数器
MOV TH0,#155 ;FFH-9BH=100D,12M/12/100D=10000HZ(100us)
MOV TH1,#0ECH ;FFFFH-1388H=EC77H
MOV TL1,#77H ;T1频率为12M/12/5000D=200HZ(5ms)
;
SETB TCON.4 ;T0开始动作
SETB IE.1 ;T0允许中断
SETB TCON.6 ;T1开始动作
SETB IE.3 ;T1开始中断
SETB IE.0 ;INT0允许中断
SETB TCON.0 ;INT0低电平触发
SETB PT0 ;T0中断优先
SETB IE.7 ;系统允许中断
;
MOV 46H,#03
LCALL BEL
;
CLR 24H ;24.4H←"0"开一短键标志复位(关)
CLR 26H ;24.6H←"0"开一短键标志复位(关)
MOV 30H,#85 ;调相上电初始亮度(最暗)
MOV 31H,#02 ;调功上电初始亮度(最暗)
;
;**********
;* 主程序 *
;**********
;
MAIN: NOP
LCALL JS ;调用PT2272解码信号接收子程序
LCALL DTCL ;调用PT2272解码信号处理子程序
LJMP MAIN
;
;**********************
;* PT2272解码信号接收 *
;**********************
;
JS: JNB P1.2,JS5 ;P1.2="0",解码信号无效,转JS5
;
JNB P1.4,JS2 ;不是调相键,转JS2继续
SETB 0AH ;调相键有效标志置位
JS2: JNB P1.5,JS3 ;不是调功键,转JS3继续
SETB 0BH ;调功键有效标志置位
JS3: JNB P1.6,JS4 ;不是开一键,转JS4继续
SETB 0CH ;开一键有效标志置位
JS4: JNB P1.7,JS0 ;不是开二键,转JS0出口
SETB 0DH ;开二键有效标志置位
JS0: RET
;
JS5: CLR 0AH ;调相键有效标志复位
CLR 0BH ;调功键有效标志复位
CLR 0CH ;开一键有效标志复位
CLR 0DH ;开二键有效标志复位
RET
;
;*************************************
;* 解码信号处理 *
;*-----------------------------------*
;* 【调相键】 P14H="1"键按下 *
;* 【调功键】 P15H="1"键按下 *
;* 【开一键】 P16H="1"键按下 *
;* 【开二键】 P17H="1"键按下 *
;*-----------------------------------*
;* 短键作开、关用 *
;* 长键作控制用(="0"减低,="1"增高) *
;*************************************
;
DTCL: JB 06H,TXK3 ;转TXK3,检查调相长键有否放开?
JB 11H,TXK2 ;正在作调相短键定时,转TXK2
JNB 0AH,DTL1 ;不是调相键,转DTL1继续
;**************
;* 调相键处理 *
;**************
JB 10H,TXK1 ;正在作调相键按下消抖动延时,转TXK1
SETB 10H ;22.0H←"1",调相键消抖动延时标志置位
MOV 54H,#10 ;设置30ms键按下消抖动延时
TXK1: MOV A,54H
CJNE A,#00,TXK0 ;30ms定时未到,转TXK0出口
CLR 10H ;10H←"0",调相键消抖动延时标志复位
JNB 0AH,TXK0 ;无效键入,转TXK0出口
LCALL BEL1 ;蜂鸣一次
SETB 11H ;11H←"1",调相长键定时已设置标志置位
MOV 54H,#80 ;设置400ms长键定时
TXK2: MOV A,54H
CJNE A,#00,TXK4 ;400ms长键定时未到,转TXK4检查有否放键
JB 20H,TXK5 ;20H="1",调相短键已打开
SETB 20H ;打开调相短键
MOV A,30H
SETB 21H ;30H<"50",蛮亮了,设置调暗方向
CJNE A,#50,TXK6
TXK6: JC TXK5
CLR 21H ;30H≥"50",蛮暗了,设置调亮方向
TXK5: CPL 21H ;21H←"X"调相长键标志取反
SETB 06H ;06H←"1",调相长键标志置位
MOV 46H,#01 ;长键蜂鸣
LCALL BEL
TXK3: JB 0AH,TXK0 ;>400ms,键未放,保持长键,转TXK0
CLR 11H ;11H←"1",调相长键定时已设置标志复位
CLR 06H ;06H←"0",调相长键标志复位
TXK0: RET
;
TXK4: JB 0AH,TXK0 ;调相键未放,转TXK0
;************************
;* <400ms就放键,是短键 *
;************************
CPL 20H ;20H←"X"调相短键标志取反
CLR 11H ;11H←"1",调相长键定时已设置标志复位
RET
;
DTL1: JB 07H,TGK3 ;转TGK3,检查调功长键有否放开?
JB 13H,TGK2 ;正在作调功短键定时,转TGK2
JNB 0BH,DTL2 ;不是调功键,转DTL2继续
;**************
;* 调功键处理 *
;**************
JB 12H,TGK1 ;正在作调功键按下消抖动延时,转TGK1
SETB 12H ;12H←"1",调功键消抖动延时标志置位
MOV 54H,#10 ;设置10ms键按下消抖动延时
TGK1: MOV A,54H
CJNE A,#00,TGK0 ;10ms定时未到,转TGK0出口
CLR 12H ;12H←"0",调功键消抖动延时标志复位
JNB 0BH,TGK0 ;无效键入,转TGK0出口
SETB 13H ;13H←"1",调功长键定时已设置标志置位
LCALL BEL1 ;蜂鸣一次
MOV 54H,#80 ;设置400ms长键定时
TGK2: MOV A,54H
CJNE A,#00,TGK4 ;400ms长键定时未到,转TGK4检查有否放键
JB 22H,TGX5
SETB 22H ;打开调功短键
MOV A,31H
CLR 23H ;31H≥"25",蛮暗了,设置调亮方向
CJNE A,#12,TGX6
TGX6: JC TGX5
SETB 23H ;31H<"25",蛮亮了,设置调暗方向
TGX5: CPL 23H ;23H←"X"调功长键标志取反
SETB 07H ;07H←"1",调功长键标志置位
MOV 46H,#01 ;蜂鸣二次
LCALL BEL
TGK3: JB 0BH,TGK0 ;>400ms,键未放,保持长键,转TGK0
CLR 13H ;13H←"1",调功长键定时已设置标志复位
CLR 07H ;07H←"0",调功长键标志复位
TGK0: RET
;
TGK4: JB 0BH,TGK0 ;调功键未放,转TGK0
;************************
;* <400ms就放键,是短键 *
;************************
CPL 22H ;22H←"X"调功短键标志取反
CLR 13H ;13H←"0",调功长键定时已设置标志复位
RET
;
DTL2: JB 08H,K1C2
JNB 0CH,DTL3 ;不是开一键,转DTL3继续
;**************
;* 开一键处理 *
;**************
JB 14H,K1C1 ;正在作开一键按下消抖动延时,转K1C1
SETB 14H ;22.4H←"1",开一键消抖动延时标志置位
MOV 54H,#10 ;设置30ms键按下消抖动延时
K1C1: MOV A,54H
CJNE A,#00,K1C0 ;30ms定时未到,转K1C0出口
CLR 14H ;22.4H←"0",开一键消抖动延时标志复位
JNB 0CH,K1C0 ;无效键入,转K1C0出口
LCALL BEL1 ;蜂鸣一次
SETB 08H ;禁止开一键连续蜂鸣
CPL 24H ;24.4H←"X"开一短键标志取反
K1C2: JB 0CH,K1C0 ;键未放,转K1C0
CLR 08H ;允许开一键蜂鸣
K1C0: RET
;
DTL3: JB 09H,K2C2
JNB 0DH,K2C0 ;不是开二键,转K2C0出口
;**************
;* 开二键处理 *
;**************
JB 16H,K2C1 ;正在作开二键按下消抖动延时,转K2C1
SETB 16H ;22.6H←"1",开二键消抖动延时标志置位
MOV 54H,#10 ;设置30ms键按下消抖动延时
K2C1: MOV A,54H
CJNE A,#00,K2C0 ;30ms定时未到,转K2C0出口
CLR 16H ;22.6H←"0",开二键消抖动延时标志复位
JNB 0DH,K2C0 ;无效键入,转K2C0出口
SETB 09H ;禁止开二键连续蜂鸣
LCALL BEL1 ;蜂鸣一次
CPL 26H ;24.6H←"X"开二短键标志取反
K2C2: JB 0DH,K2C0 ;键未放,转K2C0
CLR 09H ;允许开二键蜂鸣
K2C0: RET
;
;********
;* 蜂鸣 *
;********
;
BEL1: MOV 46H,#01
BEL: SETB 01H ;允许蜂鸣
MOV 38H,#30 ;150ms蜂鸣定时
RET
;
;***************************
;* 100us时标T0定时中断处理 *
;***************************
;
TI0: PUSH PSW ;PSW进栈
SETB PSW.3 ;RS0←"1"
CLR PSW.4 ;RS1←"0",选工作寄存区1(R08H ̄R0FH)
PUSH ACC
CPL P3.1
MOV R1,#04 ;需延时计数器字节
MOV R0,#50H ;延时计数器R50H~R53H
DY2: MOV A,@R0 ;读计数值
JZ DY1 ;=0?是转DY1处理下一位
DEC @R0 ;计数器减一
DY1: INC R0 ;计数器指针加一
DJNZ R1,DY2 ;3字节到?
;*************************************
;* 调相滞后触发处理 (脉宽0.1ms) *
;* 40H装载当前调相触发滞后时间值 *
;* 40H每0.1ms减一,(40H最大为100) *
;* 40H="01"时P3.7←"0",触发脉冲前沿 *
;* 40H="00"时P3.7←"1",触发脉冲后沿 *
;*************************************
JNB 20H,TCL0 ;20H="0",调相输出关
JNB 30H,TCL0 ;30H="0",电压未过零,禁止调相触发定时
JB 04H,TCL1
MOV 40H,30H ;取出30H当前调相触发滞后时间值
SETB 04H ;20.4H←"1",滞后触发已置初值
TCL1: DEC 40H ;当前调相触发滞后时间值减0.1ms
MOV A,40H
CJNE A,#01,TCL2
CLR P3.7 ;P3.7←"0",调相触发脉冲前沿(脉宽0.1ms)
TCL0: POP ACC ;ACC出栈
POP PSW ;PSW出栈【恢复进栈前寄存器区】
RETI ;中断返回
;
TCL2: CJNE A,#00,TCL0
CLR 04H ;04H←"0",触发定时器允许重置初值
CLR 30H ;30H←"0",禁止调相触发定时
SETB P3.7 ;P3.7←"1",调相触发脉冲后沿
SJMP TCL0 ;出中断
;
;*************************
;* 5ms时标T1定时中断处理 *
;*************************
;
TI1: MOV TH1,#0ECH ;FFFFH-1388H=EC77H
MOV TL1,#77H ;T0频率为12M/12/5000D=1388H=200HZ(5ms)
PUSH PSW ;PSW进栈
CLR PSW.3 ;RS0←"0"
SETB PSW.4 ;RS1←"1",选工作寄存区2(R10H ̄R17H)
PUSH ACC
;
CPL P3.0 ;看门狗定时100Hz(10ms)
;
MOV R1,#02 ;需延时计数器字节
MOV R0,#54H ;延时计数器R54H~R55H
DY4: MOV A,@R0 ;读计数值
JZ DY3 ;=0?是转DY1处理下一位
DEC @R0 ;计数器减一
DY3: INC R0 ;计数器指针加一
DJNZ R1,DY4 ;3字节到?
;****************
;* 蜂鸣定时处理 *
;****************
JB 05H,TT9 ;05H="1",正在作关蜂鸣定时,转TT9
JB 02H,TT9K ;02H="1",正在作开蜂鸣定时,转TT9K
JNB 01H,TT8 ;01H="0",禁止蜂鸣处理,转TT8继续
CLR P1.3 ;开蜂鸣
SETB 02H ;02H←"1",开蜂鸣定时
TT9K: DEC 38H ;蜂鸣10ms计数器减一
MOV A,38H ;取出蜂鸣10ms计数器
CJNE A,#10,TT8 ;开蜂鸣100ms未到,转TT8继续
SETB 05H ;05H←"1",关蜂鸣定时
SETB P1.3 ;关蜂鸣
TT9: DEC 38H ;蜂鸣10ms计数器减一
MOV A,38H ;取出蜂鸣10ms计数器
CJNE A,#00,TT8 ;关蜂鸣50ms未到,转TT8继续
CLR 05H ;05H←"0",关蜂鸣定时标志复位
CLR 02H ;02H←"0",开蜂鸣定时标志复位
MOV 38H,#30 ;重置蜂鸣定时150ms常数
DJNZ 46H,TT8 ;蜂鸣次数未到,转TT8继续
CLR 01H ;01H←"0",禁止蜂鸣处理
;**********************************
;* 调相触发滞后时间调整 *
;*--------------------------------*
;* 每20ms调整一档,每档0.1ms *
;* 半周期共调整10ms÷0.1ms=100档 *
;* 20msX100=2s调完半程,4s调完全程 *
;**********************************
TT8: JNB 20H,DY5 ;20H="0",调相关,转DY5不调整
INC 56H ;5ms计数器加一
MOV A,56H ;取出5ms计数器值
CJNE A,#12,DY5 ;20ms未到,转DY5出口
MOV 56H,#00
JNB 06H,DY5 ;06H="0",禁止调相,转DY5不调整
JNB 21H,DY6 ;21H="0",转DY6电压调低
MOV A,30H ;取出当前调相触发滞后时间值
CJNE A,#08,DY7 ;30H="02",电压最高值
SJMP DY5 ;30H="0",电压已调到最高了,转DY5出口
;
DY7: DEC 30H ;每20ms调相触发延时减一档(每档0.1ms),电压调高
SJMP DY5
;
DY6: MOV A,30H ;取出当前调相触发滞后时间值
INC 30H ;每20ms调相触发延时加一档(每档0.1ms),电压调低
CJNE A,#85,DY5 ;100usX100=10ms未到,转DY5出口
MOV 30H,#85 ;30H="97",电压已调到最低了,不再增加
;
DY5: POP ACC ;ACC出栈
POP PSW ;PSW出栈【恢复进栈前寄存器区】
RETI ;定时中断返回
;
;****************
;* 外部中断处理 *
;****************
;
WT0: PUSH PSW ;PSW进栈
PUSH ACC ;ACC进栈
SETB PSW.3 ;RS0←"1"
SETB PSW.4 ;RS1←"1",选工作寄存区3(R18H ̄R1FH)
;*************************
;* 电压过零,允许调相触发 *
;*************************
JNB 20H,TOFF1 ;20H="0",调相关,转TOFF1
SETB 30H ;30H←"1",电压过零,允许调相触发定时
;********************
;* 调功周期触发处理 *
;********************
TOFF1: JNB 22H,TOFF2 ;22H="0",调功关,转TOFF2
INC 33H ;21H="0",当前周期触发步进定时计数器加一
MOV A,33H ;读取当前周期触发步进定时计数器
CJNE A,#50,TF13 ;未到250ms设定数
MOV 33H,#01 ;周期触发脉冲计数器清"0"
;**************************
;* 周期触发脉冲数调整环节 *
;**************************
JNB 07H,TF13 ;07H="0",禁止调功,转TF13直接触发
MOV A,31H ;读取开周期计数器
JB 23H,TF12 ;23H="1",递增
DEC 31H ;开周期计数器减一
CJNE A,#02,TF13 ;未到开周期设定数下限(20%)
MOV 31H,#02 ;到设定数下限,不再减少
SJMP TF13
TF12: INC 31H ;开周期计数器加一
CJNE A,#20,TF13 ;未到开周期设定数上限(100%)
MOV 31H,#20 ;到设定数上限,不再增加
;****************
;* 周期脉冲触发 *
;****************
TF13: MOV A,32H ;读取周期触发脉冲计数器
INC 32H ;21H="0",调功触发计数器加一
JB 29H,TF10
CLR 29H ;29H←"0",当前周期触发开
CJNE A,31H,TF10 ;未到开周期设定数
SETB 29H ;29H←"1",当前周期触发关
TF10: CJNE A,#20,TF11 ;未到周期
MOV 32H,#00 ;加载周期触发脉冲计数器
CLR 29H ;29H←"0",当前周期触发开
;
TF11: JB 29H,TOFF2 ;29H="1",调功间隙,禁止触发
CLR P3.3 ;P3.3←"0",调功触发脉冲前沿
;
TOFF2: JNB 24H,TOFF3 ;24H="0",开1关,转TOFF3
CLR P3.4 ;P3.4←"0",开1触发脉冲前沿
;
TOFF3: JNB 26H,TOFF4 ;26H="0",开2关,转TOFF4
CLR P3.5 ;P3.5←"0",开2触发脉冲前沿
;
TOFF4: MOV R7,#50 ;设置100us触发脉宽软件延时
WAIT: DJNZ R7,WAIT ;产生100us触发脉宽
SETB P3.3 ;P3.3←"1",调功触发脉冲后沿
SETB P3.4 ;P3.4←"1",开1触发脉冲后沿
SETB P3.5 ;P3.5←"1",开2触发脉冲后沿
;
POP ACC ;ACC出栈
POP PSW ;PSW出栈=【恢复进栈前寄存器区】
RETI ;外部中断返回
;
END