读ADC和测温度.
;用STC的MCU的IO方式控制74HC595驱动8位数码管。
;用户可以修改宏来选择时钟频率.
;用户可以在"用户定义宏"中选择共阴或共阳. 推荐尽量使用共阴数码管.
;使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.
;左边4位数码管显示ADC2接的电压基准TL431的读数, 右边4位数码管显示温度值, 分辨率0.1度.
;NTC使用1%精度的MF52 10K@25度C.
;测温度时, 为了通用, 使用12位的ADC值, 使用对分查找表格来计算, 小数点后一位数是用线性插补来计算的.
;所以, 测温度的ADC3进行4次ADC连续采样, 变成12位的ADC来计算温度.
Fosc_KHZ EQU 22118 ;22118KHZ
STACK_POIRTER EQU 0D0H ;堆栈开始地址
Timer0_Reload EQU (65536 - Fosc_KHZ) ; Timer 0 中断频率, 1000次/秒
DIS_DOT EQU 020H
DIS_BLACK EQU 010H
DIS_ EQU 011H
AUXR DATA 08EH
P4 DATA 0C0H
P5 DATA 0C8H
ADC_CONTR DATA 0BCH ;带AD系列
ADC_RES DATA 0BDH ;带AD系列
ADC_RESL DATA 0BEH ;带AD系列
P1ASF DATA 09DH
PCON2 DATA 097H
P0M1 DATA 0x93 ;
P0M0 DATA 0x94 ;
P1M1 DATA 0x91 ;
P1M0 DATA 0x92 ;
P2M1 DATA 0x95 ;
P2M0 DATA 0x96 ;
P3M1 DATA 0xB1 ;
P3M0 DATA 0xB2 ;
P4M1 DATA 0xB3 ;
P4M0 DATA 0xB4 ;
P5M1 DATA 0xC9 ;
P5M0 DATA 0xCA ;
P6M1 DATA 0xCB ;
P6M0 DATA 0xCC ;
P7M1 DATA 0xE1 ;
P7M0 DATA 0xE2 ;
P_HC595_SER BIT P4.0 ; //pin 14 SER data input
P_HC595_RCLK BIT P5.4 ; //pin 12 RCLk store (latch) clock
P_HC595_SRCLK BIT P4.3 ; //pin 11 SRCLK Shift data clock
Flag0 DATA 20H
B_1ms BIT Flag0.0 ; 1ms标志
LED8 DATA 30H ; 显示缓冲 30H ~ 37H
display_index DATA 38H ; 显示位索引
msecond_H DATA 39H ;
msecond_L DATA 3AH ;
min DATA 3BH
max DATA 3CH
ORG 0000H ;reset
LJMP F_Main
ORG 0003H ;0 INT0 interrupt
RETI
LJMP F_INT0_Interrupt
ORG 000BH ;1 Timer0 interrupt
LJMP F_Timer0_Interrupt
ORG 0013H ;2 INT1 interrupt
LJMP F_INT1_Interrupt
ORG 001BH ;3 Timer1 interrupt
LJMP F_Timer1_Interrupt
ORG 0023H ;4 UART1 interrupt
LJMP F_UART1_Interrupt
ORG 002BH ;5 ADC and SPI interrupt
LJMP F_ADC_Interrupt
ORG 0033H ;6 Low Voltage Detect interrupt
LJMP F_LVD_Interrupt
ORG 003BH ;7 PCA interrupt
LJMP F_PCA_Interrupt
ORG 0043H ;8 UART2 interrupt
LJMP F_UART2_Interrupt
ORG 004BH ;9 SPI interrupt
LJMP F_SPI_Interrupt
ORG 0053H ;10 INT2 interrupt
LJMP F_INT2_Interrupt
ORG 005BH ;11 INT3 interrupt
LJMP F_INT3_Interrupt
ORG 0063H ;12 Timer2 interrupt
LJMP F_Timer2_Interrupt
ORG 0083H ;16 INT4 interrupt
LJMP F_INT4_Interrupt
ORG 0100H ;reset
F_Main:
CLR A
MOV P0M1, A ;设置为准双向口
MOV P0M0, A
MOV P1M1, A ;设置为准双向口
MOV P1M0, A
MOV P2M1, A ;设置为准双向口
MOV P2M0, A
MOV P3M1, A ;设置为准双向口
MOV P3M0, A
MOV P4M1, A ;设置为准双向口
MOV P4M0, A
MOV P5M1, A ;设置为准双向口
MOV P5M0, A
MOV P6M1, A ;设置为准双向口
MOV P6M0, A
MOV P7M1, A ;设置为准双向口
MOV P7M0, A
MOV SP, #STACK_POIRTER
MOV PSW, #0
USING 0 ;选择第0组R0~R7
;用户初始化程序
MOV display_index, #0
MOV R0, #LED8
MOV R2, #8
L_ClearLoop:
MOV @R0, #DIS_BLACK ;上电消隐
INC R0
DJNZ R2, L_ClearLoop
CLR TR0
ORL AUXR, #(1 SHL 7) ; Timer0_1T();
ANL TMOD, #NOT 04H ; Timer0_AsTimer();
ANL TMOD, #NOT 03H ; Timer0_16bitAutoReload();
MOV TH0, #Timer0_Reload / 256 ;Timer0_Load(Timer0_Reload);
MOV TL0, #Timer0_Reload MOD 256
SETB ET0 ; Timer0_InterruptEnable();
SETB TR0 ; Timer0_Run();
SETB EA ; 打开总中断
LCALL F_ADC_config ; ADC初始化
L_Main_Loop:
JNB B_1ms, L_Main_Loop ;1ms未到
CLR B_1ms
;检测300ms是否到
INC msecond_L ;msecond + 1
MOV A, msecond_L
JNZ $+4
INC msecond_H
CLR C
MOV A, msecond_L ;msecond - 300
SUBB A, #LOW 300
MOV A, msecond_H
SUBB A, #HIGH 300
JC L_Main_Loop ;if(msecond < 300), jmp
;300ms到
MOV msecond_L, #0 ;if(msecond >= 1000)
MOV msecond_H, #0
MOV A, #2
LCALL F_Get_ADC10bitResult ;ACC - 通道0~7, 查询方式做一次ADC, 返回值(R6 R7)就是ADC结果, == 1024 为错误
MOV A, R6
ANL A, #0FCH
JNZ L_Read_431_ADC_Err ; adc >= 1024, 错误
LCALL F_HEX2_DEC ;(R6 R7) HEX Change to DEC ---> (R3 R4 R5), use (R2~R7)
MOV A, R4
SWAP A
ANL A, #0x0F
MOV LED8, A ;显示Vref的ADC值
MOV A, R4
ANL A, #0x0F
MOV LED8+1, A
MOV A, R5
SWAP A
ANL A, #0x0F
MOV LED8+2, A
MOV A, R5
ANL A, #0x0F
MOV LED8+3, A
MOV A, LED8
JNZ L_QuitRead_431_ADC
MOV LED8, #DIS_BLACK ;千位为0则消隐
SJMP L_QuitRead_431_ADC
L_Read_431_ADC_Err: ;错误, 显示 ----
MOV LED8, #DIS_
MOV LED8+1, #DIS_
MOV LED8+2, #DIS_
MOV LED8+3, #DIS_
L_QuitRead_431_ADC:
MOV R2, #4
MOV R4, #0
MOV R5, #0
L_NTC_ADC_Loop:
MOV A, #3
LCALL F_Get_ADC10bitResult ;ACC - 通道0~7, 查询方式做一次ADC, 返回值(R6 R7)就是ADC结果, == 1024 为错误
MOV A, R7
ADD A, R5
MOV R5, A
MOV A, R6
ADDC A, R4
MOV R4, A
DJNZ R2, L_NTC_ADC_Loop ;连续做4次ADC, 加起来获得12位的ADC, 计算NTC温度需要12位的ADC.
MOV A, R4
ANL A, #0F0H
JNZ L_Read_NTC_ADC_Err ; (adc * 4) >= 4096, 错误
MOV AR6, R4
MOV AR7, R5
LCALL F_get_temperature ;计算温度值, (R6 R7)为12位ADC,
;返回温度为(R6 R7), 0对应-40.0度, 400对应0度, 625对应25.0度, 最大1600对应120.0度.
MOV A, R6
ANL A, #0xC0
JNZ L_Read_NTC_ADC_Err ; >= 16384, 错误
MOV A, R7
CLR C
SUBB A, #LOW 400
MOV A, R6
SUBB A, #HIGH 400
JC L_Temp_LowThan_0 ; (R6 R7) < 400, jmp
CLR F0 ; 温度 >= 0度
MOV R6, A ; (R6 R7) = (R6 R7) - 400
MOV A, R7
CLR C
SUBB A, #LOW 400
MOV R7, A
SJMP L_DisplayTemp
L_Temp_LowThan_0:
SETB F0 ; 温度 < 0度
MOV A, #LOW 400 ; (R6 R7) = 400 - (R6 R7)
CLR C
SUBB A, R7
MOV R7, A
MOV A, #HIGH 400
SUBB A, R6
MOV R6, A
L_DisplayTemp:
LCALL F_HEX2_DEC ;(R6 R7) HEX Change to DEC ---> (R3 R4 R5), use (R2~R7)
MOV A, R4
SWAP A
ANL A, #0x0F
MOV LED8+4, A ;显示温度值
MOV A, R4
ANL A, #0x0F
MOV LED8+5, A
MOV A, R5
SWAP A
ANL A, #0x0F
ADD A, #DIS_DOT
MOV LED8+6, A
MOV A, R5
ANL A, #0x0F
MOV LED8+7, A
MOV A, LED8+4
JNZ L_LED8_4_Not_0
MOV LED8+4, #DIS_BLACK ;千位为0则消隐
L_LED8_4_Not_0:
JNB F0, L_QuitRead_NTC_ADC
MOV LED8+4, #DIS_ ;负温度, 显示-
SJMP L_QuitRead_NTC_ADC
L_Read_NTC_ADC_Err: ;错误, 显示 ----
MOV LED8+4, #DIS_
MOV LED8+5, #DIS_