;***********************************************************
;单    位:苏州华芯微电子有限公司                           
;                                                          
;文件名称:	HS23P2721_ADC							       
;摘    要:	ADC-例程						   					   
;当期版本:	V1.0                                           
;作    者:	Design-Digit	                                   
;开始日期:  2022-09-07                                     
;完成日期:                                                 
;                                                          
;先前版本:                                                 
;作    者:                                                 
;创始日期:                                                 
;***********************************************************
;RAM: 96*8bit
;ROM: 2K×16
;STACK: 5-level
;***********************************************************


;***********************************************************
;files include
#include "HS23P2721.inc"
;=========================================
;管脚定义
;#define 	LED_RED 	P0.3    ;红灯



;=============================================
;user general reg define
;=============================================
.data
DELAY_1			EQU		00H
DELAY_2			EQU		01H
ACC_PROTECT		EQU		02H
BANK_PROTECT	EQU		03H

AD_ADD_L                EQU     04H
AD_ADD_H                EQU     05H
ADC_MAX_L               EQU   	09H
ADC_MAX_H               EQU     010H
ADC_LITTLE_L			EQU     011H
ADC_LITTLE_H			EQU     012H
ADC_SAMP_L              EQU     013H
ADC_SAMP_H              EQU     014H
BUF0_TEMP               EQU		015H
BUF1_TEMP               EQU		016H


ADC_CNT					EQU		017H
F_ADC_TIME				EQU		018H
SEND_BUF				EQU		019H
SEND_NUM				EQU		020H
TEMP0					EQU		021H

;中间 001H~05CH的RAM使用省略

FLAG			EQU     05EH
S_REG			EQU     05FH
;-------------------------------------------      
;    标志位                    
;-------------------------------------------
#define F_KEY_ONCE              FLAG.0


;***************************************************
;    常量定义 
;***************************************************
CONST_RESET			EQU		0
CONST_SET			EQU		1


;=============================================
;程序开始
;=============================================
.code
	ORG		00H
	JMP		MAIN

	ORG		08H
	JMP		INT_PRO

INT_PRO:
	PUSH
	SWAP	PFLAG			;Bit0:Z-零标志位	
								;0-无进位/有借位
								;1-有进位/无借位
							;Bit1:DC-半进位/半借位（加减法指令）	
								;0-无低 4 位进位/有低 4 位借位
								;1-有低 4 位进位/无低 4 位借位
							;Bit2:C-进位/借位（加减法指令）		
								;0-无进位/有借位
								;1-有进位/无借位
							;Bit4：LVDF24-电压检测位
								;0-电源电压大于 2.4V
								;1-电源电压小于 2.4V
							;Bit5：LVDF36-电压检测位
								;0-电源电压大于 3.6V
								;1-电源电压小于 3.6V
							;Bit6:/PD-复位状态标志位
							;Bit7:/T0-复位状态标志位
								;/T0	/PD    	复位状态
								;0		0		看门狗复位
								;0		1		保留
								;1		0		上电或 LVD
								;1		1		外部复位
	MOV		S_REG,A	
	NOP
	
	BTS0	FTC0IF
	JMP		TC0_INT				;/TC1中断	
	JMP		INT_END
	
TC0_INT:
	;TC0IF：TC0 中断请求标志
	BCLR	FTC0IF				;/清中断	
AD_TIME_JUDGE:              	;/AD采样基准 4MS      
	BSET	F_ADC_TIME,0
	
	JMP		INT_END

	
;---------------------------------------------
INT_END:
;-------中断结束------------------------------	
	SWAP	S_REG 			
	MOV		PFLAG,A			;Bit0:Z-零标志位	
								;0-无进位/有借位
								;1-有进位/无借位
							;Bit1:DC-半进位/半借位（加减法指令）	
								;0-无低 4 位进位/有低 4 位借位
								;1-有低 4 位进位/无低 4 位借位
							;Bit2:C-进位/借位（加减法指令）		
								;0-无进位/有借位
								;1-有进位/无借位
							;Bit4：LVDF24-电压检测位
								;0-电源电压大于 2.4V
								;1-电源电压小于 2.4V
							;Bit5：LVDF36-电压检测位
								;0-电源电压大于 3.6V
								;1-电源电压小于 3.6V
							;Bit6:/PD-复位状态标志位
							;Bit7:/T0-复位状态标志位
								;/T0	/PD    	复位状态
								;0		0		看门狗复位
								;0		1		保留
								;1		0		上电或 LVD
								;1		1		外部复位
	POP
	RETI
	

;***********************************************************
;函数名：GPIO_Init
;***********************************************************
GPIO_Init:
	;P0:P0端口寄存器
	MOV		A,#00H			;---0 0000
	B0MOV	P0,A			;0-L , 1-H	
	;P0UR:P0端口上拉寄存器
	MOV		A,#00H			;---0 0000
	B0MOV	P0UR,A			;0-DIS, 1-EN		
	;P0M:P0端口模式控制寄存器
	MOV		A,#0FFH			;---1 1111
	B0MOV	P0M,A			;0-IN,1-OUT
	
	;P4:P4端口寄存器
	MOV		A,#00H			;---0 0000
	B0MOV	P4,A			;0-L , 1-H	
	;P4UR:P4端口上拉寄存器
	MOV		A,#00H			;---0 0000
	B0MOV	P4UR,A			;0-DIS, 1-EN	
	;P4M:P4端口模式控制寄存器
	MOV		A,#0FEH		;---1 1110
	B0MOV	P4M,A			;0-IN,1-OUT
	
	;P5:P5端口寄存器
	MOV		A,#00H			;---0 0---
	B0MOV	P5,A			;0-L , 1-H	
	;P5UR:P5端口上拉寄存器
	MOV		A,#00H			;---0 0---
	B0MOV	P5UR,A			;0-DIS, 1-EN	
	;P5M:P5端口模式控制寄存器
	MOV		A,#0FFH			;---1 1---
	B0MOV	P5M,A			;0-IN,1-OUT
	
	RET

;***********************************************************
;函数名：RAM_CLR
;***********************************************************
RAM_CLR:
	B0MOV 	Y, #0
	B0MOV	Z, #5FH
CLR_RAM:
	CLR		@YZ
	DECMS	Z
	JMP		CLR_RAM
	CLR		@YZ
	RET
	
;***********************************************************
;函数名：MAIN
;***********************************************************	
MAIN:
	CALL	RAM_CLR
	CALL	GPIO_Init
	CALL	TC0_INIT
	
MAIN_LOOP:
	;WDTR:看门狗定时器
	MOV		A,#5AH	
	B0MOV	WDTR,A			;清看门狗定时器	
	
	CALL	ADC_VDD_JUDGE
	JMP		MAIN_LOOP
	
ADC_VDD_JUDGE:
	BTS1	F_ADC_TIME,0
	RET
    BCLR   	F_ADC_TIME,0

	CLR     ADB
    CLR     ADR
    
    ;ADM:ADC 模式寄存器
   	MOV		A,#0x90			;0000 -000		;1101 0000
	MOV		ADM,A			;Bit0~Bit2:CHS[2:0]:ADC输入通道选择位
	   							;000--AIN0		;001--AIN1
	   							;010--AIN2		;011--AIN3
	   							;100--AIN4		;101--AIN5
   							;Bit4:GCHS:通道选择位
   								;0-DIS,1-EN
   							;Bit5:EOC:ADC状态控制位
   								;0-转换过程中
   								;1-转换结束，ADS复位
   							;Bit6:ADS:ADC启动位。ADC处理完成后，ADS位自动清零
   								;0-停止
   								;1-开始
   							;Bit7:ADENB:ADC控制位。睡眠模式下，禁止ADC以省电
   								;0-DIS,1-EN
   															
   	MOV		A,#00H
   	B0MOV	ADR,A

	;VREFH:ADC 参考电压寄存器
	MOV		A,#00H			;0--- --00
	B0MOV	VREFH,A			;Bit0~Bit1:
								;VHS[1:0]：ADC 内部参考电压选择位
								;VHS1		VHS0		内部 VREFH 电压
								; 1			 1				VDD
								; 1			 0				4.0V
								; 0			 1				3.0V
								; 0			 1				2.0V
							;Bit7:EVHENB:ADC 内部参考电压控制位
								;0-允许 ADC 内部 VREFH 功能，VREFH 引脚是 P4.0/AIN0 引脚
								;1-禁止 ADC 内部 VREFH 功能，P4.0/AIN0/VREFH 引脚来自外部 VREFH 输入引脚

	;ADT:ADC 结果微调寄存器
	MOV		A,#00H			;-1-- -111
	B0MOV	ADT,A			;Bit0~Bit2:
								;ADT<2:0>：ADT修调位
								;000-修调0mv
								;001-修调2.1mv
								;010-修调4.3mv
								;011-修调6.5mv
								;100-修调8.6mv
								;101-修调10.7mv
								;110-修调12.9mv
								;111-修调15.1mv
							;Bit6:ADTS<0>：修调方向控制
								;0-负方向(ADB转换制变小)
								;1-正方向(ADB转换制变大)

	;P4CON:P4 口的配置寄存器
	MOV		A,#01H			;---0 0001	
	B0MOV	P4CON,A			;Bit0~Bit4:
							;P4CON[4:0]：P4.n 配置控制位
							;0-P4.n 可以作为模拟输入（ADC 输入）引脚或者 GPIO 引脚
							;1-P4.n 只能作为模拟输入引脚，不能作为 GPIO 引脚
							
	
	;FADENB:ADC控制位
	B0BSET	FADENB
	
	CALL	DELAY
	
	;FGCHS:通道选择位
	B0BSET  FGCHS	    	;使能AIN通道
							;0-DIS,1-EN
							
	;FADCIF:ADC中断请求标志					
    B0BCLR	FADCIF			;清ADC中断请求
        					;0-ADC 无中断请求
        					;1-ADC 有中断请求
        
    ;FADCIEN:ADC中断控制位	
	B0BCLR	FADCIEN			;关闭中断使能
							;0-DIS,1-EN
							
	;FEOC:ADC状态控制位					
	BCLR    FEOC			;0-转换过程中
							;1-转换结束，ADS复位
		
	;FADS:ADC启动位 
	BSET	FADS        	;0-停止
							;1-开始
	NOP
	AND		A,ADR
	
WAIT_ADC:	
	;FEOC:ADC状态控制位		
	BTS1	FEOC			;0-转换过程中
							;1-转换结束，ADS复位
	
	JMP		WAIT_ADC
	;ADB:ADC 数据寄存器
	MOV		A,ADB	
	
	MOV		BUF1_TEMP,A 	;高8位->BUF1_TEMP
	MOV		A,ADR
	MOV		BUF0_TEMP,A		;低4位->BUF0_TEMP
	
	BCLR	FEOC
	
	CLR		ADM				;关闭ADC
	MOV     A,#0FH
	AND     BUF0_TEMP,A     ;BUF0_TEMP=(0000,ADB3~ADB0)
	    
	SWAP	BUF1_TEMP        ;A=(ADB7~ADB4,ADB12~ADB8)
	MOV		TEMP0,A          ;TEMP0=(ADB7~ADB4,ADB12~ADB8)
			
	MOV		A,#0FH
	AND		A,TEMP0          ;A=(0000,ADB12~ADB8)
	MOV     BUF1_TEMP,A     ;BUF1_TEMP=(0000,ADB12~ADB8)
	        
	MOV     A,#0F0H
	AND     A,TEMP0         ;A=(ADB7~ADB4,0000)
	OR      BUF0_TEMP,A     ;BUF0_TEMP=(ADB7~ADB4,ADB3~ADB0)	
	
	INCMS	ADC_CNT		;采样一次数据加一
	NOP
;------------------------------------------------------------------  
;10次采样数据求和
;------------------------------------------------------------------  
	MOV		A,BUF0_TEMP
	ADD		AD_ADD_L,A
	MOV		A,BUF1_TEMP
	ADC		AD_ADD_H,A
	
;------------------------------------------------------------------  
ADC_COUNT_BIG:					;最大值ADC_MAX
	MOV		A,BUF1_TEMP			;BUF1_TEMP-ADC_MAX_H->A
	SBC		A,ADC_MAX_H
	
	BTS1	FC					;C=0->BUF1_TEMP<ADC_MAX_H
	JMP		ADC_COUNT_LITTLE	;C=1->BUF1_TEMP>=ADC_MAX_H
	
	BTS1	PFLAG,0				;Z=0->BUF1_TEMP>ADC_MAX_H
	JMP		ADC_MAX_Update		;Z=1->BUF1_TEMP=ADC_MAX_H
	
	MOV		A,BUF0_TEMP
	SBC		A,ADC_MAX_L
	
	BTS1	FC					;C=0->BUF0_TEMP<ADC_MAX_L
	JMP		ADC_COUNT_LITTLE	;C=1->BUF0_TEMP>=ADC_MAX_L
	JMP		ADC_MAX_Update
	
ADC_MAX_Update:
	MOV		A,BUF0_TEMP
	MOV		ADC_MAX_L,A
	MOV		A,BUF1_TEMP
	MOV		ADC_MAX_H,A
	
ADC_COUNT_LITTLE:				;最小值ADC_CNT
	BTS1	ADC_Cnt,0
	JMP		$+5
	MOV		A,BUF0_TEMP
	MOV		ADC_LITTLE_L,A
	MOV		A,BUF1_TEMP
	MOV		ADC_LITTLE_H,A
	
	MOV		A,BUF1_TEMP
	SBC		A,ADC_LITTLE_H
	
	BTS1	FC					;C=0->BUF1_TEMP<ADC_LITTLE_H
	JMP		ADC_LITTLE_Update	;C=1->BUF1_TEMP>=ADC_LITTLE_H
		
	BTS1	FZ					;Z=0->BUF1_TEMP>ADC_LITTLE_H
	JMP		ADC_COUNT_END		;Z=1->BUF1_TEMP=ADC_LITTLE_H
	
	MOV		A,BUF0_TEMP
	SBC		A,ADC_LITTLE_L
	
	BTS1	FC					;C=0,BUF0_TEMP < ADC_LITTLE_L
	JMP		ADC_LITTLE_Update	;C=0,BUF0_TEMP>=ADC_LITTLE_L
	JMP		ADC_COUNT_END

ADC_LITTLE_Update:
	MOV		A,BUF0_TEMP
	MOV		ADC_LITTLE_L,A
	MOV		A,BUF1_TEMP
	MOV		ADC_LITTLE_H,A
ADC_COUNT_END:
	MOV		A,#0AH
	SUB		A,ADC_CNT
	
	BTS1	FZ
	RET
	CLR		ADC_CNT
;---------------------------------------------------------
;采样值求平均值
;--------------------------------------------------------
SEND_DATE_GET:
	MOV		A,ADC_MAX_H			;10次采样和减去最大值
	SUB		AD_ADD_H,A
	MOV		A,ADC_MAX_L
	SBC		AD_ADD_L,A

	MOV		A,ADC_LITTLE_H			;10次采样和减去最小值
	SUB		AD_ADD_H,A
	MOV		A,ADC_LITTLE_L
	SBC		AD_ADD_L,A
	
	BCLR	FC					;求平均值
	RRCM	AD_ADD_H
	RRCM	AD_ADD_L
	
	BCLR	FC					;求平均值
	RRCM	AD_ADD_H
	RRCM	AD_ADD_L
	
	BCLR	FC					;求平均值
	RRCM	AD_ADD_H
	RRCM	AD_ADD_L

    MOV		A,AD_ADD_L
	MOV		ADC_SAMP_L,A	;上一次保留平均值低位
	MOV		A,AD_ADD_H
	MOV		ADC_SAMP_H,A	;上一次保留平均值高位
	NOP
	CALL	SEND_DATA
	CALL	RAM_CLR
	RET
   
;--------------------------------------------------------
;--------------------------------------------------------
TC0_INIT:
	;TC0C:定时/计数器 0 的 8 位数据
	MOV		A,#00H
	B0MOV	TC0C,A
	
	;TC0R:定时/计数器 0 自动装载位
	MOV		A,#00H
	B0MOV	TC0R,A
	
	MOV		A,#00H			;---- 0000
	B0MOV	PWMS,A			;Bit0:PWMS0：PWM0输出端口选择
								;0-P54输出PWM0（前提PWMS1=0）
								;1-P41输出PWM0
							;Bit1:PWMS2：PWM2输出端口选择
								;0-P01输出PWM2
								;1-P40输出PWM2(前提PWMS3=0)
							;Bit2&Bit3:PWM3输出端口选择
								;00：P44输出PWM3 
								;01：P40输出PWM3 
								;10：P54输出PWM3 
								;11：P54和P40同时输出PWM3
								
	;T0M:TC0、TC1 和 TC2 的时钟源选择及绿色模式唤醒寄存器 
	MOV		A,#00H			;---0 000-
	B0MOV	T0M,A			;Bit1:TC0GN-TC0 绿色模式功能唤醒控制
								;0-DIS，1-EN
							;Bit2:TC0X8-TC0 内部时钟选择控制位
								;0-TC0 内部时钟来至 FCPU，TC0RATE=FCPU/2~FCPU/256
								;1-TC0 内部时钟来至 FHOSC，TC0RATE=FOSC/1~FOSC/128
							;Bit3:TC1X8-TC1 内部时钟选择控制位
								;0-TC1 内部时钟来至 FCPU，TC0RATE=FCPU/2~FCPU/256
								;1-TC1 内部时钟来至 FHOSC，TC0RATE=FOSC/1~FOSC/128
							;Bit4:TC2X8-TC2 内部时钟选择控制位
								;0-TC2 内部时钟来至 FCPU，TC0RATE=FCPU/2~FCPU/256
								;1-TC2 内部时钟来至 FHOSC，TC0RATE=FOSC/1~FOSC/128
	
	;TC0M:定时/计数器 0 模式控制位
	MOV		A,#94H			;1001 0100
	B0MOV	TC0M,A			;Bit0:PWMEN：PWM 输出控制
								;0-禁止 PWM 输出
								;1-使能 PWM 输出，PWM 输出占空比由 TC0OUT 和 ALOAD0 控制
							;Bit1:TCOUT：TC 超时输出信号控制。仅当 PWMEN = 0 时有效
								;0-禁止，P5.4 或者 P5.3 或者 P0.1 作为输入/输出口
								;1-使能，P5.4 或者 P5.3 或者 P0.1 输出 TCOUT 信号。可用作驱动 Buzzer
							;Bit2:ALOAD:自动装载控制。仅当 PWMEN = 0 时有效
								;0-DIS,1-EN
							;Bit3:TnCKS:TC 时钟信号控制位
								;0-内部时钟（Fcpu 或 Fosc）
								;1-外部时钟，T0CK 或 T1CK 或 T2CK 输入
							;Bit4~Bit6:TPS[2:0]:TC 分频选择位
								;TPS[2:0]    	TCnX8=0    		 TCnX8=1
								;	000			Fcpu / 256		Fosc / 128
								;	001			Fcpu / 128		Fosc / 64
								;	010			Fcpu / 64		Fosc / 32
								;	011			Fcpu / 32		Fosc / 16
								;	100			Fcpu / 16		Fosc / 8
								;	101			Fcpu / 8		Fosc / 4
								;	110			Fcpu / 4		Fosc / 2
								;	111			Fcpu / 2		Fosc / 1
							;Bit7:TR：TC 启动控制位
								;0-DIS,1-EN

	;TC0IF:TC0 中断请求标志
	BCLR	FTC0IF			;0-DIS,1-EN
	
	;TC0IEN:TC0 中断控制位
	BSET	FTC0IEN			;0-DIS,1-EN

	;FGIE:全局中断控制位
	BSET	FGIE			;0-DIS,1-EN

	RET



;***********************************************************
;函数名：DELAY
;传参：循环体调用次数
;返回值：
;功能：延时10个指令周期
;引脚：
;备注：
;***********************************************************
DELAY:
	MOV		A,#015H				
	MOV		DELAY_1,A
DELAY1_LOOP:
	MOV		A,#05H				
	MOV		DELAY_2,A
DELAY2_LOOP:	
	DECMS	DELAY_2      	
	JMP		DELAY2_LOOP
	DECMS	DELAY_1
	JMP		DELAY1_LOOP
	RET
	

;***********************************************************
;函数名：SEND_DATA
;传参：
;返回值：无
;功能：发送数据
;引脚：无
;***********************************************************
SEND_DATA:
	MOV		A,#027H					;发送头码  27
	MOV		SEND_BUF,A
	CALL	DATA_SEND_LOOP
	CALL	DELAY
	
	MOV		A,#021H					;发送头码  21
	MOV		SEND_BUF,A
	CALL	DATA_SEND_LOOP
	CALL	DELAY
	
	BTS0	ADC_SAMP_H,4
	JMP		$+10
	MOV		A,ADC_SAMP_H			;发送数据高位
	MOV		SEND_BUF,A
	CALL	DATA_SEND_LOOP
	CALL	DELAY

	MOV		A,ADC_SAMP_L			;发送数据低位
	MOV		SEND_BUF,A
	CALL	DATA_SEND_LOOP
	CALL	DELAY
	RET
	
	MOV		A,#0FH
	MOV		SEND_BUF,A
	CALL	DATA_SEND_LOOP
	CALL	DELAY
	
	MOV		A,#0FFH
	MOV		SEND_BUF,A
	CALL	DATA_SEND_LOOP
	CALL	DELAY
	
	RET
	
DATA_SEND_LOOP:
	MOV		A,#08H
	MOV		SEND_NUM,A
	
	B0BCLR	P0.4
	CALL	DELAY
	;JMP		SEND_CON
	
SEND_CON:
	B0BTS1	SEND_BUF,0
	JMP		DELAY_0_LOOP
	;JMP		DELAY_1_LOOP
	
DELAY_1_LOOP:
	B0BSET	P0.4
	CALL	DELAY
	JMP		SEND_DATA_NEXT
	
DELAY_0_LOOP:
	B0BCLR	P0.4
	CALL	DELAY
	;JMP		SEND_DATA_NEXT
		
SEND_DATA_NEXT:
	RRCM	SEND_BUF
	DECMS	SEND_NUM
	JMP		SEND_CON
	;JMP		SEND_END
	
SEND_END:
	B0BSET	P0.4
	CALL	DELAY
	RET

