程序分主程序和PCA定时器。写入器件(STC8G1K08A):按启动开关(P3.3),PCA运行正常有输出,而主程序有时有输出,有时没有输出。且没有输出时,按启动开关(P3.3)不起作用也不能关闭PCA。经判断程序在(32位除16位 即程序:第2步算:双字节无符号除法)处于死循环!但关闭PCA定时器,主程序输出又正常,程序仿真也正常!这是为什么?用T0,T1 定时器也是这情况!
未开启看门狗
程序用汇编写的- ;器件STC8G1K08A
- ORG 0000H
- LJMP MAIN1
- ORG 003BH ;PCA中断
- LJMP PCAISR
- ORG 0100H
- //************************IO口*************************
- P5 EQU 0C8H
- P5M1 EQU 0C9H
- P5M0 EQU 0CAH
- P3M1 EQU 0B1H
- P3M0 EQU 0B2H
- //************************ADC*************************
- AUXR EQU 8EH ;辅助寄存器
- ADC_CONTR EQU 0BCH ;ADC控制寄存器
- ADC_RES EQU 0BDH ;ADC高2位结果
- ADC_RESL EQU 0BEH ;ADC低8位结果
- ADCCFG EQU 0DEH //ADC 配置寄存器
- P_SW2 DATA 0BAH
- ADCTIM XDATA 0FEA8H //ADC速度控制器
- //************************PCA*************************
- CCON DATA 0D8H //PCA控制寄存器
- CF BIT CCON.7 //PCA控制寄存器B7位, 计数器溢出中断标志
- CR BIT CCON.6 //PCA控制寄存器B6位. 计数器启动控制位
- CCF2 BIT CCON.2 //PCA控制寄存器B2位, 模块2中断标志,需软件清零
- CCF1 BIT CCON.1 //PCA控制寄存器B1位, 模块1中断标志,需软件清零
- CCF0 BIT CCON.0 //PCA控制寄存器B0位, 模块0中断标志,需软件清零
- CMOD DATA 0D9H //PCA模式寄存器, 空闲时是否继续计数及时钟设定
- CL DATA 0E9H //PCA计数器低字节
- CH DATA 0F9H //PCA计数器高字节
- CCAPM0 DATA 0DAH //PCA模块0模式控制寄存器
- CCAP0L DATA 0EAH //PCA模块0低字节
- CCAP0H DATA 0FAH //PCA模块0高字节
- PCA_PWM0 DATA 0F2H //PCA0的PWM模式寄存器
- CCAPM1 DATA 0DBH //PCA模块1模式控制寄存器
- CCAP1L DATA 0EBH //PCA模块1低字节
- CCAP1H DATA 0FBH //PCA模块1高字节
- PCA_PWM1 DATA 0F3H //PCA1的PWM模式寄存器
- CCAPM2 DATA 0DCH //PCA模块2模式控制寄存器
- CCAP2L DATA 0ECH //PCA模块2低字节
- CCAP2H DATA 0FCH //PCA模块2高字节
- PCA_PWM2 DATA 0F4H //PCA2的PWM模式寄存器
- T50HZ EQU 0029H //此调频率 0030H为10K
- //************************常用*************************
- E_DATAS_L EQU 34H ;有效定时器值L
- E_DATAS_H EQU 35H ;有效定时器值H
- E_DUTY_L EQU 37H //有效占空L
- E_DUTY_H EQU 38H //有效占空H
- I_DUTY_L EQU 39H //无效占空L
- I_DUTY_H EQU 3AH //无效占空H
- I_DATAS_L EQU 3DH ;无效定时器值L
- I_DATAS_H EQU 3EH ;无效定时器值H
- BUTTON EQU 3FH ;ADC按钮控制
- IPH EQU 0B7H //高中断优先级控制寄存器
- MAIN1: MOV SP, #5FH //设置堆栈指针为5FH
- SETB EA //开中断
- MOV IP,#080H //PCA中断最高级,T1中断最低级
- MOV IPH,#080H //PCA中断最高级,T1中断最低级
- MOV P3M1,#00000100B
- MOV P3M0,#00000000B
- MOV P5M1,#00100000B
- MOV P5M0,#00000000B
- SETB P5.4
- CLR P3.0
- CLR P3.1
- MOV CCON ,#00H //PCA配置
- MOV CMOD ,#00H //PCA配置
- ANL AUXR,#0BFH ;定时器1时钟12T模式
- ANL TMOD,#0FH ;设置定时器模式
- ORL TMOD,#10H ;设置定时器模式
- CALL GET_ADC //初始化,开ADC电源,
- ;.....................................................准备
- JSM06: SETB P5.4
- CLR TR1
- CLR CR
- CLR P3.0
- CLR P3.1
- CALL DELAY100MS
- JB P3.3,JSM06
- ;...................................................主程序
- JSM01: JNB P3.3,JSM01 ;防止开关抖动
- CALL DELAY100MS ;防止开关抖动
- JNB P3.3,JSM01
- LCALL PCA_ON //开PCA定时器
- CALL AUT_DUTY //占空计算
- CALL FREQUENCY //频率计算
- MOV TH1,I_DATAS_H
- MOV TL1 ,I_DATAS_L
- SETB TR1
- SETB P5.4 ;关后级
-
- JSM04: JNB P3.3,JSM06 ;开关是否放开
- JNB TF1,JSM04
- CLR TR1
- CLR TF1
- JB P5.4,LLLL
- MOV TH1, I_DATAS_H
- MOV TL1, I_DATAS_L
- SETB TR1
- SETB P5.4
- ACALL AUT_DUTY //占空计算
- ACALL FREQUENCY //频率计算
- AJMP JSM04
- RET
-
- LLLL:
- MOV TH1,E_DATAS_H
- MOV TL1,E_DATAS_L
- SETB TR1
- CLR P5.4 ;开后级
- AJMP JSM04
- RET
- //****************PCA启动********************
- PCA_ON:
- MOV CL ,#00H
- MOV CH ,# 00H
- MOV CCAPM0,#49H
- MOV CCAP0L,#LOW T50HZ
- MOV CCAP0H,# HIGH T50HZ
- SETB CR
- SETB P3.0
- RET
- ;********************************************************************ADC初始化
- GET_ADC: //初始化
- MOV P_SW2,#80H
- MOV DPTR,#ADCTIM ;设置 ADC 内部时序
- MOV A,#3FH
- MOVX @DPTR,A
- MOV P_SW2,#00H
- MOV ADCCFG,#02FH ;设置 ADC 时钟为系统时钟/2/16/16, 结果右对齐
- MOV ADC_CONTR,#080H ;开启 ADC 模块电源,
- RET
- ;****************************************占空计算************************************
- AUT_DUTY:
- ;********************************************************************ADC2转换
- GET_ADC2:
- MOV ADC_CONTR,#082H ;使能 ADC 模块,设P3.2为ADC2
- ORL ADC_CONTR,#40H ;启动 AD 转换"ORL或运算=逢1等于1"
- NOP
- NOP
- MOV A,ADC_CONTR ;查询 ADC 完成标志
- JNB ACC.5,$-2 ;ACC.5是否为‘1’,不为‘1’原址等待
- ANL ADC_CONTR,#NOT 20H ;清完成标志
- //单字节无符号数乘法
- MOV R3,ADC_RES
- MOV R4,ADC_RESL
- MOV R7,#00AH
- NMUL21 : MOV A,R4
- MOV B,R7
- MUL AB
- MOV R4,A
- MOV A,B
- XCH A,R3
- MOV B,R7
- MUL AB
- ADD A,R3
- MOV R3,A
- CLR A
- ADDC A,B
- MOV R2,A
- CLR OV
- //单字节无符号除法程序
- MOV R7,#066H
- NDIV31 : MOV A,R2
- MOV B,R7
- DIV AB
- PUSH ACC
- MOV R2,B
- MOV B,#10H
- NDV311 : CLR C
- MOV A,R4
- RLC A
- MOV R4,A
- MOV A,R3
- RLC A
- MOV R3,A
- MOV A,R2
- RLC A
- MOV R2,A
- MOV F0,C
- CLR C
- SUBB A,R7
- JB F0,NDV312
- JC NDV313
- NDV312 : MOV R2,A
- INC R4
- NDV313 : DJNZ B,NDV311
- POP ACC
- CLR OV
- JZ NDV314
- SETB OV
- NDV314 : XCH A,R2
- MOV R7,A
- MOV E_DUTY_L,R4
- MOV E_DUTY_H,R3
- //双字节无符号数减法
- MOV R3,#03H
- MOV R4,#0E8H
- MOV R6,E_DUTY_H
- MOV R7,E_DUTY_L
- NSUB : MOV A,R4
- CLR C
- SUBB A,R7
- MOV R4,A
- MOV A,R3
- SUBB A,R6
- MOV R3,A
- MOV I_DUTY_L,R4
- MOV I_DUTY_H,R3
- RET
- //*********************************频率计算***********************************
- FREQUENCY:
- ;**************************************ADC5转换
- GET_ADC5:
- MOV ADC_CONTR,#085H ;使能 ADC 模块,设P5.5为ADC5
- ORL ADC_CONTR,#40H ;启动 AD 转换"ORL或运算=逢1等于1"
- NOP
- NOP
- MOV A,ADC_CONTR ;查询 ADC 完成标志
- JNB ACC.5,$-2 ;ACC.5是否为‘1’,不为‘1’原址等待
- ANL ADC_CONTR,#NOT 20H ;清完成标志
- ;计算有效定时器值。。。。。。。
- MOV R3,#01BH
- MOV R4,#058H
- MOV R6,E_DUTY_H
- MOV R7,E_DUTY_L
- ACALL STEP_1 //第1步算
- MOV R6,ADC_RES
- MOV R7,ADC_RESL
- ACALL STEP_2 //第2步算
- MOV A,R3
- MOV R6,A
- MOV A,R4
- MOV R7,A
- MOV R3,#0FFH
- MOV R4,#0FFH
- ACALL STEP_3 //第3步算
- MOV E_DATAS_L,R4
- MOV E_DATAS_H,R3
- ;计算无效定时器值。。。。。。。
- MOV R3,#01BH
- MOV R4,#058H
- MOV R6,I_DUTY_H
- MOV R7,I_DUTY_L
- ACALL STEP_1 //;第1步算
- MOV R6,ADC_RES
- MOV R7,ADC_RESL
- ACALL STEP_2 //第2步算
- MOV A,R3
- MOV R6,A
- MOV A,R4
- MOV R7,A
- MOV R3,#0FFH
- MOV R4,#0FFH
- ACALL STEP_3 //第3步算
- MOV I_DATAS_L,R4
- MOV I_DATAS_H,R3
- RET
- //第1步算:双字节无符号数乘法
- STEP_1:
- NMUL22 : MOV A,R4
- MOV B,R7
- MUL AB
- XCH A,R4
- MOV R5,B
- MOV B,R6
- MUL AB
- ADD A,R5
- MOV R5,A
- CLR A
- ADDC A,B
- MOV R2,A
- MOV A,R3
- MOV B,R7
- MUL AB
- ADD A,R5
- MOV R5,A
- MOV A,B
- ADDC A,R2
- MOV R2,A
- CLR A
- ADDC A,#00H
- XCH A,R3
- MOV B,R6
- MUL AB
- ADD A,R2
- MOV R2,A
- MOV A,B
- ADDC A,R3
- XCH A,R5
- MOV R3,A
- CLR OV
- RET
- //第2步算:双字节无符号除法
- STEP_2:
- NDIV42 : MOV A,R1
- PUSH ACC
- MOV B,#00H
- NDV421 : MOV A,R2
- CLR C
- SUBB A,R7
- MOV R1,A
- MOV A,R5
- SUBB A,R6
- JC NDV422
- MOV R5,A
- MOV A,R1
- MOV R2,A
- INC B
- SJMP NDV421
- NDV422 : PUSH B
- MOV B,#10H
- NDV423 : CLR C
- MOV A,R4
- RLC A
- MOV R4,A
- MOV A,R3
- RLC A
- MOV R3,A
- MOV A,R2
- RLC A
- MOV R2,A
- XCH A,R5
- RLC A
- XCH A,R5
- MOV F0,C
- CLR C
- SUBB A,R7
- MOV R1,A
- MOV A,R5
- SUBB A,R6
- JB F0,NCV424
- JC NDV425
- NCV424 : MOV R5,A
- MOV A,R1
- MOV R2,A
- INC R4
- NDV425 : DJNZ B,NDV423
- POP ACC
- CLR OV
- JNZ NDV426
- SETB OV
- NDV426 : XCH A,R2
- MOV R7,A
- MOV A,R5
- MOV R6,A
- POP ACC
- MOV R1,A
- RET
- //第3步算:双字节无符号数减法程序
- STEP_3:
- MOV A,R4
- CLR C
- SUBB A,R7
- MOV R4,A
- MOV A,R3
- SUBB A,R6
- MOV R3,A
- RET
- //**************************PCA中断***************************
- PCAISR : PUSH ACC //进堆栈
- PUSH PSW //进堆栈
- CLR CR //关PCA
- CLR CCF0 //模块0中断标志清零
- JB P3.0,JSMJSM
- CLR P3.1
- MOV CL ,#00H
- MOV CH ,# 00H
- MOV CCAPM0,#49H
- MOV CCAP0L,#LOW T50HZ
- MOV CCAP0H,# HIGH T50HZ
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- SETB CR
- SETB P3.0
- POP PSW //出堆栈
- POP ACC //出堆栈 ;恢复现场
- RETI
- JSMJSM:
- CLR P3.0
- MOV CL ,#00H
- MOV CH ,# 00H
- MOV CCAPM0,#49H
- MOV CCAP0L,#LOW T50HZ
- MOV CCAP0H,# HIGH T50HZ
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- NOP
- SETB CR
- SETB P3.1
- POP PSW //出堆栈
- POP ACC //出堆栈 ;恢复现场
- RETI
- ;软件延时
- DELAY100MS: ;@12.000MHz
- NOP
- PUSH 30H
- PUSH 31H
- PUSH 32H
- MOV 30H,#7
- MOV 31H,#23
- MOV 32H,#103
- NEXT:
- DJNZ 32H,NEXT
- DJNZ 31H,NEXT
- DJNZ 30H,NEXT
- POP 32H
- POP 31H
- POP 30H
- RET
- END
复制代码
|