STC实验箱4
IAP15W4K58S4
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0


库函数

比较器的库函数仅在官方例程中发现,未与其他库函数放在一起,笔者也未对其进行测试,请谨慎使用。

compare.c

/*---------------------------------------------------------------------*/
/* --- STC MCU International Limited ----------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
/*---------------------------------------------------------------------*/

#include "compare.h"


//========================================================================
// 函数:void	CMP_Inilize(CMP_InitDefine *CMPx)
// 描述: 比较器初始化程序.
// 参数: CMPx: 结构参数,请参考compare.h里的定义.
// 返回: 成功返回0, 空操作返回1,错误返回2.
// 版本: V1.0, 2012-10-22
//========================================================================
void	CMP_Inilize(CMP_InitDefine *CMPx)
{
	CMPCR1 = 0;
	CMPCR2 = CMPx->CMP_OutDelayDuty & 0x3f;						//比较结果变化延时周期数, 0~63
	if(CMPx->CMP_EN == ENABLE)				CMPCR1 |= CMPEN;	//允许比较器		ENABLE,DISABLE
	if(CMPx->CMP_RiseInterruptEn == ENABLE)	CMPCR1 |= PIE;		//允许上升沿中断	ENABLE,DISABLE
	if(CMPx->CMP_FallInterruptEn == ENABLE)	CMPCR1 |= NIE;		//允许下降沿中断	ENABLE,DISABLE
	if(CMPx->CMP_P_Select  == CMP_P_ADCIS)	CMPCR1 |= PIS;		//比较器输入正极性选择, CMP_P_P55: 选择内部P5.5做正输入, CMP_P_ADCIS: 由ADCIS[2:0]所选择的ADC输入端做正输入.
	if(CMPx->CMP_N_Select  == CMP_N_P54)	CMPCR1 |= NIS;		//比较器输入负极性选择, CMP_N_BGv: 选择内部BandGap电压BGv做负输入, CMP_N_P54: 选择外部P5.4做输入.
	if(CMPx->CMP_OutptP12_En == ENABLE)		CMPCR1 |= CMPOE;	//允许比较结果输出到P1.2,   ENABLE,DISABLE
	if(CMPx->CMP_InvCMPO     == ENABLE)		CMPCR2 |= INVCMPO;	//比较器输出取反, 	ENABLE,DISABLE
	if(CMPx->CMP_100nsFilter == DISABLE)	CMPCR2 |= DISFLT;	//内部0.1uF滤波,  	ENABLE,DISABLE
//	u8	CMP_Polity;			//中断优先级,     PolityLow,PolityHigh
}



/********************* 比较器中断函数************************/
void CMP_int (void) interrupt CMP_VECTOR
{
	P13 = ~P13;
	if((CMPCR1 & CMPRES) > 0)	P14 = ~P14;
	else						P15 = ~P15;
	CMPCR1 &= ~CMPIF;	//清除中断标志
}

compare.h

  1. /*---------------------------------------------------------------------*/
    /* --- STC MCU International Limited ----------------------------------*/
    /* --- STC 1T Series MCU Demo Programme -------------------------------*/
    /* --- Mobile: (86)13922805190 ----------------------------------------*/
    /* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
    /* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
    /* --- Web: www.GXWMCU.com --------------------------------------------*/
    /* --- QQ:  800003751 -------------------------------------------------*/
    /* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
    /*---------------------------------------------------------------------*/
    
    #ifndef	__COMPARE_H
    #define	__COMPARE_H
    
    #include	"config.h"
    
    //CMPCR1
    #define	CMPEN	0x80	//1: 允许比较器, 0: 禁止,关闭比较器电源
    #define	CMPIF	0x40	//比较器中断标志, 包括上升沿或下降沿中断, 软件清0
    #define	PIE		0x20	//1: 比较结果由0变1, 产生上升沿中断
    #define	NIE		0x10	//1: 比较结果由1变0, 产生下降沿中断
    #define	PIS		0x08	//输入正极性选择, 0: 选择内部P5.5做正输入,           1: 由ADCIS[2:0]所选择的ADC输入端做正输入.
    #define	NIS		0x04	//输入负极性选择, 0: 选择内部BandGap电压BGv做负输入, 1: 选择外部P5.4做输入.
    #define	CMPOE	0x02	//1: 允许比较结果输出到P1.2, 0: 禁止.
    #define	CMPRES	0x01	//比较结果, 1: CMP+电平高于CMP-,  0: CMP+电平低于CMP-,  只读
    
    //CMPCR2
    #define	INVCMPO	0x80	//1: 比较器输出取反,  0: 不取反
    #define	DISFLT	0x40	//1: 关闭0.1uF滤波,   0: 允许
    #define	LCDTY	0x00	//0~63, 比较结果变化延时周期数
    
    #define	CMP_P_P55		0
    #define	CMP_P_ADCIS		1
    #define	CMP_N_P54		1
    #define	CMP_N_BGv		0
    
    typedef struct
    { 
    	u8	CMP_EN;				//比较器允许或禁止, 			ENABLE,DISABLE
    	u8	CMP_Interrupt;		//比较器中断允许或禁止, 		ENABLE,DISABLE
    	u8	CMP_RiseInterruptEn;	//比较器上升沿中断允许或禁止, 	ENABLE,DISABLE       
    	u8	CMP_FallInterruptEn;	//比较器下降沿中断允许或禁止, 	ENABLE,DISABLE
    	u8	CMP_P_Select;		//比较器输入正极性选择, CMP_P_P55: 选择内部P5.5做正输入, CMP_P_ADCIS: 由ADCIS[2:0]所选择的ADC输入端做正输入.
    	u8	CMP_N_Select;		//比较器输入负极性选择, CMP_N_BGv: 选择内部BandGap电压BGv做负输入, CMP_N_P54: 选择外部P5.4做输入.
    	u8	CMP_OutptP12_En;	//允许比较结果输出到P1.2,   ENABLE,DISABLE
    	u8	CMP_Polity;			//中断优先级,     PolityLow,PolityHigh
    	u8	CMP_InvCMPO;		//比较器输出取反, ENABLE,DISABLE
    	u8	CMP_100nsFilter;	//内部0.1uF滤波,  ENABLE,DISABLE
    	u8	CMP_OutDelayDuty;	//0~63, 比较结果变化延时周期数
    
    } CMP_InitDefine; 
    
    void	CMP_Inilize(CMP_InitDefine *CMPx);
    
    #endif
    

STC15Fxxxx.H

该头文件版本补充了比较器的寄存器。

/*---------------------------------------------------------------------*/
/* --- STC MCU International Limited ----------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
/*---------------------------------------------------------------------*/


#ifndef	_STC15Fxxxx_H
#define	_STC15Fxxxx_H

#include <intrins.h>

/*  BYTE Registers  */
sfr P0   = 0x80;
sfr SP   = 0x81;
sfr DPL  = 0x82;
sfr DPH  = 0x83;
sfr	S4CON = 0x84;
sfr	S4BUF = 0x85;
sfr PCON = 0x87;

sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0  = 0x8A;
sfr TL1  = 0x8B;
sfr TH0  = 0x8C;
sfr TH1  = 0x8D;
sfr	AUXR = 0x8E;
sfr WAKE_CLKO = 0x8F;
sfr INT_CLKO = 0x8F;
sfr	AUXR2    = 0x8F;

sfr RL_TL0  = 0x8A;
sfr RL_TL1  = 0x8B;
sfr RL_TH0  = 0x8C;
sfr RL_TH1  = 0x8D;


sfr P1   = 0x90;
sfr P1M1 = 0x91;	//P1M1.n,P1M0.n 	=00--->Standard,	01--->push-pull		实际上1T的都一样
sfr P1M0 = 0x92;	//					=10--->pure input,	11--->open drain
sfr P0M1 = 0x93;	//P0M1.n,P0M0.n 	=00--->Standard,	01--->push-pull
sfr P0M0 = 0x94;	//					=10--->pure input,	11--->open drain
sfr P2M1 = 0x95;	//P2M1.n,P2M0.n 	=00--->Standard,	01--->push-pull
sfr P2M0 = 0x96;	//					=10--->pure input,	11--->open drain
sfr CLK_DIV = 0x97;
sfr PCON2   = 0x97;

sfr SCON  = 0x98;
sfr SBUF  = 0x99;
sfr S2CON = 0x9A;	//
sfr S2BUF = 0x9B;	//
sfr P1ASF = 0x9D;	//只写,模拟输入(AD或LVD)选择

sfr P2    = 0xA0;
sfr BUS_SPEED = 0xA1;
sfr AUXR1 = 0xA2;
sfr P_SW1 = 0xA2;

sfr IE    = 0xA8;
sfr SADDR = 0xA9;
sfr WKTCL = 0xAA;	//唤醒定时器低字节
sfr WKTCH = 0xAB;	//唤醒定时器高字节
sfr	S3CON = 0xAC;
sfr S3BUF = 0xAD;
sfr IE2   = 0xAF;	//STC12C5A60S2系列

sfr P3    = 0xB0;
sfr P3M1  = 0xB1;	//P3M1.n,P3M0.n 	=00--->Standard,	01--->push-pull
sfr P3M0  = 0xB2;	//					=10--->pure input,	11--->open drain
sfr P4M1  = 0xB3;	//P4M1.n,P4M0.n 	=00--->Standard,	01--->push-pull
sfr P4M0  = 0xB4;	//					=10--->pure input,	11--->open drain
sfr IP2   = 0xB5;	//STC12C5A60S2系列
sfr IPH2  = 0xB6;	//STC12C5A60S2系列
sfr IPH   = 0xB7;

sfr IP        = 0xB8;
sfr SADEN     = 0xB9;
sfr	P_SW2     = 0xBA;
sfr ADC_CONTR = 0xBC;	//带AD系列
sfr ADC_RES   = 0xBD;	//带AD系列
sfr ADC_RESL  = 0xBE;	//带AD系列

sfr P4        = 0xC0;
sfr WDT_CONTR = 0xC1;
sfr IAP_DATA  = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD   = 0xC5;
sfr IAP_TRIG  = 0xC6;
sfr IAP_CONTR = 0xC7;

sfr ISP_DATA  = 0xC2;
sfr ISP_ADDRH = 0xC3;
sfr ISP_ADDRL = 0xC4;
sfr ISP_CMD   = 0xC5;
sfr ISP_TRIG  = 0xC6;
sfr ISP_CONTR = 0xC7;

sfr P5     = 0xC8;	//
sfr P5M1   = 0xC9;	//	P5M1.n,P5M0.n 	=00--->Standard,	01--->push-pull
sfr P5M0   = 0xCA;	//					=10--->pure input,	11--->open drain
sfr P6M1   = 0xCB;	//	P5M1.n,P5M0.n 	=00--->Standard,	01--->push-pull
sfr P6M0   = 0xCC;	//					=10--->pure input,	11--->open drain
sfr SPSTAT = 0xCD;	//
sfr SPCTL  = 0xCE;	//
sfr SPDAT  = 0xCF;	//

sfr PSW  = 0xD0;
sfr	T4T3M = 0xD1;
sfr	T4H  = 0xD2;
sfr	T4L  = 0xD3;
sfr	T3H  = 0xD4;
sfr	T3L  = 0xD5;
sfr	T2H  = 0xD6;
sfr	T2L  = 0xD7;

sfr	TH4  = 0xD2;
sfr	TL4  = 0xD3;
sfr	TH3  = 0xD4;
sfr	TL3  = 0xD5;
sfr	TH2  = 0xD6;
sfr	TL2  = 0xD7;

sfr	RL_T4H  = 0xD2;
sfr	RL_T4L  = 0xD3;
sfr	RL_T3H  = 0xD4;
sfr	RL_T3L  = 0xD5;
sfr	RL_T2H  = 0xD6;
sfr	RL_T2L  = 0xD7;

sfr CCON = 0xD8;	//
sfr CMOD = 0xD9;	//
sfr CCAPM0 = 0xDA;	//PCA模块0的工作模式寄存器。
sfr CCAPM1 = 0xDB;	//PCA模块1的工作模式寄存器。
sfr CCAPM2 = 0xDC;	//PCA模块2的工作模式寄存器。

sfr ACC    = 0xE0;
sfr	P7M1   = 0xE1;
sfr	P7M0   = 0xE2;
sfr	CMPCR1 = 0xE6;
sfr	CMPCR2 = 0xE7;


sfr	P6     = 0xE8;
sfr CL     = 0xE9;	//
sfr CCAP0L = 0xEA;	//PCA模块0的捕捉/比较寄存器低8位。
sfr CCAP1L = 0xEB;	//PCA模块1的捕捉/比较寄存器低8位。
sfr CCAP2L = 0xEC;	//PCA模块2的捕捉/比较寄存器低8位。

sfr B      = 0xF0;
sfr PCA_PWM0 = 0xF2;	//PCA模块0 PWM寄存器。
sfr PCA_PWM1 = 0xF3;	//PCA模块1 PWM寄存器。
sfr PCA_PWM2 = 0xF4;	//PCA模块2 PWM寄存器。

sfr	P7     = 0xF8;
sfr CH     = 0xF9;
sfr CCAP0H = 0xFA;		//PCA模块0的捕捉/比较寄存器高8位。
sfr CCAP1H = 0xFB;		//PCA模块1的捕捉/比较寄存器高8位。
sfr CCAP2H = 0xFC;		//PCA模块2的捕捉/比较寄存器高8位。


/*  BIT Registers  */
/*  PSW   */
sbit CY   = PSW^7;
sbit AC   = PSW^6;
sbit F0   = PSW^5;
sbit RS1  = PSW^4;
sbit RS0  = PSW^3;
sbit OV   = PSW^2;
sbit F1   = PSW^1;
sbit P    = PSW^0;

/*  TCON  */
sbit TF1  = TCON^7;	//定时器1溢出中断标志位
sbit TR1  = TCON^6;	//定时器1运行控制位
sbit TF0  = TCON^5;	//定时器0溢出中断标志位
sbit TR0  = TCON^4;	//定时器0运行控制位
sbit IE1  = TCON^3;	//外中断1标志位
sbit IT1  = TCON^2;	//外中断1信号方式控制位,1:下降沿中断,0:上升下降均中断。
sbit IE0  = TCON^1;	//外中断0标志位
sbit IT0  = TCON^0;	//外中断0信号方式控制位,1:下降沿中断,0:上升下降均中断。

/*  P0  */
sbit  P00 = P0^0;
sbit  P01 = P0^1;
sbit  P02 = P0^2;
sbit  P03 = P0^3;
sbit  P04 = P0^4;
sbit  P05 = P0^5;
sbit  P06 = P0^6;
sbit  P07 = P0^7;

/*  P1  */
sbit  P10 = P1^0;
sbit  P11 = P1^1;
sbit  P12 = P1^2;
sbit  P13 = P1^3;
sbit  P14 = P1^4;
sbit  P15 = P1^5;
sbit  P16 = P1^6;
sbit  P17 = P1^7;

sbit  RXD2      = P1^0;
sbit  TXD2      = P1^1;
sbit  CCP1      = P1^0;
sbit  CCP0      = P1^1;
sbit  SPI_SS    = P1^2;
sbit  SPI_MOSI  = P1^3;
sbit  SPI_MISO  = P1^4;
sbit  SPI_SCLK  = P1^5;

/*  P2  */
sbit  P20 = P2^0;
sbit  P21 = P2^1;
sbit  P22 = P2^2;
sbit  P23 = P2^3;
sbit  P24 = P2^4;
sbit  P25 = P2^5;
sbit  P26 = P2^6;
sbit  P27 = P2^7;

/*  P3  */
sbit  P30 = P3^0;
sbit  P31 = P3^1;
sbit  P32 = P3^2;
sbit  P33 = P3^3;
sbit  P34 = P3^4;
sbit  P35 = P3^5;
sbit  P36 = P3^6;
sbit  P37 = P3^7;

sbit RXD  = P3^0;
sbit TXD  = P3^1;
sbit INT0 = P3^2;
sbit INT1 = P3^3;
sbit T0   = P3^4;
sbit T1   = P3^5;
sbit WR   = P3^6;
sbit RD   = P3^7;
sbit CCP2  = P3^7;

sbit CLKOUT0   = P3^5;
sbit CLKOUT1   = P3^4;

/*  P4  */
sbit  P40 = P4^0;
sbit  P41 = P4^1;
sbit  P42 = P4^2;
sbit  P43 = P4^3;
sbit  P44 = P4^4;
sbit  P45 = P4^5;
sbit  P46 = P4^6;
sbit  P47 = P4^7;

/*  P5  */
sbit  P50 = P5^0;
sbit  P51 = P5^1;
sbit  P52 = P5^2;
sbit  P53 = P5^3;
sbit  P54 = P5^4;
sbit  P55 = P5^5;
sbit  P56 = P5^6;
sbit  P57 = P5^7;

/*  SCON  */
sbit SM0  = SCON^7;	//SM0/FE		SM0 SM1 = 00 ~ 11: 方式0~3
sbit SM1  = SCON^6;	//
sbit SM2  = SCON^5;	//多机通讯
sbit REN  = SCON^4;	//接收允许
sbit TB8  = SCON^3;	//发送数据第8位
sbit RB8  = SCON^2;	//接收数据第8位
sbit TI   = SCON^1;	//发送中断标志位
sbit RI   = SCON^0;	//接收中断标志位

/*  IE   */
sbit EA   = IE^7;	//中断允许总控制位
sbit ELVD = IE^6;	//低压监测中断允许位
sbit EADC = IE^5;	//ADC 中断 允许位
sbit ES   = IE^4;	//串行中断 允许控制位
sbit ET1  = IE^3;	//定时中断1允许控制位
sbit EX1  = IE^2;	//外部中断1允许控制位
sbit ET0  = IE^1;	//定时中断0允许控制位
sbit EX0  = IE^0;	//外部中断0允许控制位


/*  IP   */ 
/*
sbit PPCA = IP^7;	//PCA 中断 优先级设定位
sbit PLVD = IP^6; 	//低压中断 优先级设定位
sbit PADC = IP^5; 	//ADC 中断 优先级设定位
sbit PS   = IP^4;	//串行中断0优先级设定位
sbit PT1  = IP^3;	//定时中断1优先级设定位
sbit PX1  = IP^2;	//外部中断1优先级设定位
sbit PT0  = IP^1;	//定时中断0优先级设定位
sbit PX0  = IP^0;	//外部中断0优先级设定位
*/

sbit ACC0 = ACC^0;
sbit ACC1 = ACC^1;
sbit ACC2 = ACC^2;
sbit ACC3 = ACC^3;
sbit ACC4 = ACC^4;
sbit ACC5 = ACC^5;
sbit ACC6 = ACC^6;
sbit ACC7 = ACC^7;

sbit B0 = B^0;
sbit B1 = B^1;
sbit B2 = B^2;
sbit B3 = B^3;
sbit B4 = B^4;
sbit B5 = B^5;
sbit B6 = B^6;
sbit B7 = B^7;


//							7     6     5    4    3    2    1     0    Reset Value
//sfr IE2       = 0xAF;		-     -     -    -    -    -   ESPI  ES2   0000,0000B	//Auxiliary Interrupt   
#define		SPI_INT_ENABLE()		IE2 |=  2	//允许SPI中断
#define		SPI_INT_DISABLE()		IE2 &= ~2	//允许SPI中断
#define		UART2_INT_ENABLE()		IE2 |=  1	//允许串口2中断
#define		UART2_INT_DISABLE()		IE2 &= ~1	//允许串口2中断

//                                          7     6     5    4    3    2    1    0    Reset Value
//sfr IP      = 0xB8; //中断优先级低位      PPCA  PLVD  PADC  PS   PT1  PX1  PT0  PX0   0000,0000
//--------
sbit PPCA	= IP^7;	//PCA 模块中断优先级
sbit PLVD	= IP^6;	//低压监测中断优先级
sbit PADC	= IP^5;	//ADC 中断优先级
sbit PS   	= IP^4;	//串行中断0优先级设定位
sbit PT1	= IP^3;	//定时中断1优先级设定位
sbit PX1	= IP^2;	//外部中断1优先级设定位
sbit PT0	= IP^1;	//定时中断0优先级设定位
sbit PX0	= IP^0;	//外部中断0优先级设定位

//                                           7      6      5     4     3     2    1     0        Reset Value
//sfr IPH   = 0xB7; //中断优先级高位       PPCAH  PLVDH  PADCH  PSH  PT1H  PX1H  PT0H  PX0H   0000,0000
//sfr IP2   = 0xB5; //                       -      -      -     -     -     -   PSPI   PS2   xxxx,xx00
//sfr IPH2  = 0xB6; //                       -      -      -     -     -     -   PSPIH  PS2H  xxxx,xx00
#define		PPCAH	0x80
#define		PLVDH	0x40
#define		PADCH	0x20
#define		PSH		0x10
#define		PT1H	0x08
#define		PX1H	0x04
#define		PT0H	0x02
#define		PX0H	0x01

#define		PCA_InterruptFirst()	PPCA = 1
#define		LVD_InterruptFirst()	PLVD = 1
#define		ADC_InterruptFirst()	PADC = 1
#define		UART1_InterruptFirst()	PS   = 1
#define		Timer1_InterruptFirst()	PT1  = 1
#define		INT1_InterruptFirst()	PX1  = 1
#define		Timer0_InterruptFirst()	PT0  = 1
#define		INT0_InterruptFirst()	PX0  = 1


/*************************************************************************************************/



/*************************************************************************************************/
#define		S1_DoubleRate()		PCON |= 0x80
#define		S1_SHIFT()			SCON &= 0x3f
#define		S1_8bit()			SCON  = (SCON & 0x3f) | 0x40
#define		S1_9bit()			SCON  = (SCON & 0x3f) | 0xc0
#define		S1_RX_Enable()		SCON |= 0x10
#define		S1_USE_P30P31()		P_SW1 &= ~0xc0					//UART1 使用P30 P31口	默认
#define		S1_USE_P36P37()		P_SW1 = (P_SW1 & ~0xc0) | 0x40	//UART1 使用P36 P37口
#define		S1_USE_P16P17()		P_SW1 = (P_SW1 & ~0xc0) | 0x80	//UART1 使用P16 P17口
#define		S1_TXD_RXD_SHORT()	PCON2 |=  (1<<4)	//将TXD与RXD连接中继输出
#define		S1_TXD_RXD_OPEN()	PCON2 &= ~(1<<4)	//将TXD与RXD连接中继断开	默认
#define 	S1_BRT_UseTimer2()	AUXR |=  1
#define 	S1_BRT_UseTimer1()	AUXR &= ~1

//						  7      6      5      4      3      2     1     0        Reset Value
//sfr S2CON = 0x9A;		S2SM0    -    S2SM2  S2REN  S2TB8  S2RB8  S2TI  S2RI      00000000B		 //S2 Control

#define		S2_8bit()			S2CON &= ~(1<<7)		//串口2模式0,8位UART,波特率 = 定时器2的溢出率 / 4
#define		S2_9bit()			S2CON |=  (1<<7)		//串口2模式1,9位UART,波特率 = 定时器2的溢出率 / 4
#define		S2_RX_Enable()		S2CON |=  (1<<4)		//允许串2接收

#define		S2_MODE0()			S2CON &= ~(1<<7)		//串口2模式0,8位UART,波特率 = 定时器2的溢出率 / 4
#define		S2_MODE1()			S2CON |=  (1<<7)		//串口2模式1,9位UART,波特率 = 定时器2的溢出率 / 4
#define		S2_RX_EN()			S2CON |=  (1<<4)							//允许串2接收
#define		S2_RX_Disable()		S2CON &= ~(1<<4)							//禁止串2接收
#define		TI2					(S2CON & 2) != 0
#define		RI2					(S2CON & 1) != 0
#define		SET_TI2()			S2CON |=  2
#define		CLR_TI2()			S2CON &= ~2
#define		CLR_RI2()			S2CON &= ~1
#define		S2TB8_SET()			S2CON |=  8
#define		S2TB8_CLR()			S2CON &= ~8
#define		S2_Int_en()			IE2   |=  1		//串口2允许中断
#define		S2_USE_P10P11()		P_SW2 &= ~1		//UART2 使用P1口	默认
#define		S2_USE_P46P47()		P_SW2 |=  1		//UART2 使用P4口

#define		S3_USE_P00P01()		P_SW2 &= ~2		//UART3 使用P0口	默认
#define		S3_USE_P50P51()		P_SW2 |=  2		//UART3 使用P5口
#define		S4_USE_P02P03()		P_SW2 &= ~4		//UART4 使用P0口	默认
#define		S4_USE_P52P53()		P_SW2 |=  4		//UART4 使用P5口


/**********************************************************/

#define		Timer0_16bitAutoReload()	TMOD &= ~0x03					//16位自动重装
#define		Timer0_16bit()				TMOD  = (TMOD & ~0x03) | 0x01	//16位
#define		Timer0_8bitAutoReload()		TMOD  = (TMOD & ~0x03) | 0x02	//8位自动重装
#define		Timer0_16bitAutoRL_NoMask()	TMOD |=  0x03		//16位自动重装不可屏蔽中断
#define		Timer0_AsCounterP32()		TMOD |=  4		//时器0用做计数器
#define		Timer0_AsTimer()			TMOD &= ~4		//时器0用做定时器
#define		Timer0_ExtControlP34()		TMOD |=  4		//时器0由外部INT0高电平允许定时计数
#define 	Timer0_Run()	 			TR0 = 1				//允许定时器0计数
#define 	Timer0_Stop()	 			TR0 = 0				//禁止定时器0计数
#define 	Timer0_InterruptEnable()	ET0 = 1				//允许Timer1中断.
#define 	Timer0_InterruptDisable()	ET0 = 0				//禁止Timer1中断.

#define		Timer1_16bitAutoReload()	TMOD &= ~0x30					//16位自动重装
#define		Timer1_16bit()				TMOD  = (TMOD & ~0x30) | 0x10	//16位
#define		Timer1_8bitAutoReload()		TMOD  = (TMOD & ~0x30) | 0x20	//8位自动重装
#define		Timer1_16bitAutoRL_NoMask()	TMOD |=  0x30		//16位自动重装不可屏蔽中断
#define		Timer1_AsCounterP33()		TMOD |=  (1<<6)		//时器1用做计数器
#define		Timer1_AsTimer()			TMOD &= ~(1<<6)		//时器1用做定时器
#define		Timer1_ExtControlP35()		TMOD |=  (1<<7)		//时器1由外部INT1高电平允许定时计数
#define 	Timer1_Run()	 			TR1 = 1				//允许定时器1计数
#define 	Timer1_Stop()	 			TR1 = 0				//禁止定时器1计数
#define 	Timer1_InterruptEnable()	ET1 = 1				//允许Timer1中断.
#define 	Timer1_InterruptDisable()	ET1 = 0				//禁止Timer1中断.


//						   7     6       5      4     3      2      1      0    Reset Value
//sfr AUXR  = 0x8E;		T0x12 T1x12 UART_M0x6  T2R  T2_C/T T2x12 EXTRAM  S1ST2  0000,0000	//Auxiliary Register 

#define 	Timer0_1T()					AUXR |=  (1<<7)	//Timer0 clodk = fo
#define 	Timer0_12T()				AUXR &= ~(1<<7)	//Timer0 clodk = fo/12	12分频,	default
#define 	Timer1_1T()					AUXR |=  (1<<6)	//Timer1 clodk = fo
#define 	Timer1_12T()				AUXR &= ~(1<<6)	//Timer1 clodk = fo/12	12分频,	default
#define		S1_M0x6()					AUXR |=  (1<<5)	//UART Mode0 Speed is 6x Standard
#define		S1_M0x1()					AUXR &= ~(1<<5)	//default,	UART Mode0 Speed is Standard
#define 	Timer2_Run()	 			AUXR |=  (1<<4)	//允许定时器2计数
#define 	Timer2_Stop()	 			AUXR &= ~(1<<4)	//禁止定时器2计数
#define		Timer2_AsCounterP31()		AUXR |=  (1<<3)	//时器2用做计数器
#define		Timer2_AsTimer()			AUXR &= ~(1<<3)	//时器2用做定时器
#define 	Timer2_1T()					AUXR |=  (1<<2)	//Timer0 clodk = fo
#define 	Timer2_12T()				AUXR &= ~(1<<2)	//Timer0 clodk = fo/12	12分频,	default
#define 	Timer2_InterruptEnable()	IE2  |=  (1<<2)	//允许Timer2中断.
#define 	Timer2_InterruptDisable()	IE2  &= ~(1<<2)	//禁止Timer2中断.

#define 	ExternalRAM_enable()		AUXR |=  2		//允许外部XRAM,禁止使用内部1024RAM
#define 	InternalRAM_enable()		AUXR &= ~2		//禁止外部XRAM,允许使用内部1024RAM

#define		T0_pulseP34_enable()		AUXR2 |=  1		//允许 T0 溢出脉冲在T0(P3.5)脚输出,Fck0 = 1/2 T0 溢出率,T0可以1T或12T。
#define		T0_pulseP34_disable()		AUXR2 &= ~1
#define		T1_pulseP35_enable()		AUXR2 |=  2		//允许 T1 溢出脉冲在T1(P3.4)脚输出,Fck1 = 1/2 T1 溢出率,T1可以1T或12T。
#define		T1_pulseP35_disable()		AUXR2 &= ~2
#define		T2_pulseP30_enable()		AUXR2 |=  4		//允许 T2 溢出脉冲在T1(P3.0)脚输出,Fck2 = 1/2 T2 溢出率,T2可以1T或12T。
#define		T2_pulseP30_disable()		AUXR2 &= ~4

#define		T0_pulseP35(n)		ET0=0,Timer0_AsTimer(),Timer0_1T(),Timer0_16bitAutoReload(),TH0=(65536-(n/2+MAIN_Fosc/2)/(n))/256,TL0=(65536-(n/2+MAIN_Fosc/2)/(n))%256,AUXR2 |= bit0,TR0=1		//fx=fosc/(2*M)/n,  M=1 or M=12
#define		T1_pulseP34(n)		ET1=0,Timer1_AsTimer(),Timer1_1T(),Timer1_16bitAutoReload(),TH1=(65536-(n/2+MAIN_Fosc/2)/(n))/256,TL1=(65536-(n/2+MAIN_Fosc/2)/(n))%256,AUXR2 |= bit1,TR1=1		//fx=fosc/(2*M)/n,  M=1 or M=12
#define		T2_pulseP30(n)		Timer2_InterruptDisable(),Timer2_AsTimer(),Timer2_1T(),TH2=(65536-(n/2+MAIN_Fosc/2)/(n))/256,TL2=(65536-(n/2+MAIN_Fosc/2)/(n))%256,AUXR2 |= bit2,Timer2_Run()	//fx=fosc/(2*M)/n,  M=1 or M=12

#define		Timer0_Load(n)		TH0 = (n) / 256,	TL0 = (n) % 256
#define		Timer1_Load(n)		TH1 = (n) / 256,	TL1 = (n) % 256
#define		Timer2_Load(n)		TH2 = (n) / 256,	TL2 = (n) % 256

#define		Timer0_Load_us(n)	TH0=(65536-MainFosc_KHZ*(n)/1000)/256,TL0=(65536-MainFosc_KHZ*(n)/1000)%256
#define		Timer1_Load_us(n)	TH1=(65536-MainFosc_KHZ*(n)/1000)/256,TL1=(65536-MainFosc_KHZ*(n)/1000)%256
#define		Timer2_Load_us(n)	TH2=(65536-MainFosc_KHZ*(n)/1000)/256,TL2=(65536-MainFosc_KHZ*(n)/1000)%256


//sfr WDT_CONTR = 0xC1; //Watch-Dog-Timer Control register
//                                      7     6     5      4       3      2   1   0     Reset Value
//                                  WDT_FLAG  -  EN_WDT CLR_WDT IDLE_WDT PS2 PS1 PS0    xx00,0000
#define D_WDT_FLAG			(1<<7)
#define D_EN_WDT			(1<<5)
#define D_CLR_WDT			(1<<4)	//auto clear
#define D_IDLE_WDT			(1<<3)	//WDT counter when Idle
#define D_WDT_SCALE_2		0
#define D_WDT_SCALE_4		1
#define D_WDT_SCALE_8		2		//T=393216*N/fo
#define D_WDT_SCALE_16		3
#define D_WDT_SCALE_32		4
#define D_WDT_SCALE_64		5
#define D_WDT_SCALE_128		6
#define D_WDT_SCALE_256		7

#define	WDT_reset(n)	WDT_CONTR = D_EN_WDT + D_CLR_WDT + D_IDLE_WDT + (n)		//初始化WDT,喂狗


//						  7     6      5    4     3      2    1     0     Reset Value
//sfr PCON   = 0x87;	SMOD  SMOD0  LVDF  POF   GF1    GF0   PD   IDL    0001,0000	 //Power Control 
//SMOD		//串口双倍速
//SMOD0
#define		LVDF		(1<<5)	//P4.6低压检测标志
//POF
//GF1
//GF0
//#define 	D_PD		2		//set 1, power down mode
//#define 	D_IDLE		1		//set 1, idle mode
#define		MCU_IDLE()			PCON |= 1	//MCU 进入 IDLE 模式
#define		MCU_POWER_DOWN()	PCON |= 2	//MCU 进入 睡眠 模式


//sfr ISP_CMD   = 0xC5;
#define		ISP_STANDBY()	ISP_CMD = 0		//ISP空闲命令(禁止)
#define		ISP_READ()		ISP_CMD = 1		//ISP读出命令
#define		ISP_WRITE()		ISP_CMD = 2		//ISP写入命令
#define		ISP_ERASE()		ISP_CMD = 3		//ISP擦除命令

//sfr ISP_TRIG  = 0xC6;
#define 	ISP_TRIG()	ISP_TRIG = 0x5A,	ISP_TRIG = 0xA5		//ISP触发命令

//							  7    6    5      4    3    2    1     0    Reset Value
//sfr IAP_CONTR = 0xC7;		IAPEN SWBS SWRST CFAIL  -   WT2  WT1   WT0   0000,x000	//IAP Control Register
#define ISP_EN			(1<<7)
#define ISP_SWBS		(1<<6)
#define ISP_SWRST		(1<<5)
#define ISP_CMD_FAIL	(1<<4)
#define ISP_WAIT_1MHZ	7
#define ISP_WAIT_2MHZ	6
#define ISP_WAIT_3MHZ	5
#define ISP_WAIT_6MHZ	4
#define ISP_WAIT_12MHZ	3
#define ISP_WAIT_20MHZ	2
#define ISP_WAIT_24MHZ	1
#define ISP_WAIT_30MHZ	0

#if (MAIN_Fosc >= 24000000L)
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_30MHZ
#elif (MAIN_Fosc >= 20000000L)
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_24MHZ
#elif (MAIN_Fosc >= 12000000L)
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_20MHZ
#elif (MAIN_Fosc >= 6000000L)
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_12MHZ
#elif (MAIN_Fosc >= 3000000L)
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_6MHZ
#elif (MAIN_Fosc >= 2000000L)
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_3MHZ
#elif (MAIN_Fosc >= 1000000L)
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_2MHZ
#else
	#define		ISP_WAIT_FREQUENCY	ISP_WAIT_1MHZ
#endif



/* ADC Register */
//								7       6      5       4         3      2    1    0   Reset Value
//sfr ADC_CONTR = 0xBC;		ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 0000,0000	//AD 转换控制寄存器 
//sfr ADC_RES  = 0xBD;		ADCV.9 ADCV.8 ADCV.7 ADCV.6 ADCV.5 ADCV.4 ADCV.3 ADCV.2	  0000,0000	//A/D 转换结果高8位 
//sfr ADC_RESL = 0xBE;												  ADCV.1 ADCV.0	  0000,0000	//A/D 转换结果低2位
//sfr ADC_CONTR  = 0xBC;	//直接用MOV操作,不要用与或


//sfr SPCTL  = 0xCE;	SPI控制寄存器
//   7       6       5       4       3       2       1       0    	Reset Value
//	SSIG	SPEN	DORD	MSTR	CPOL	CPHA	SPR1	SPR0		0x00

#define	SPI_SSIG_None()		SPCTL |=  (1<<7)		//1: 忽略SS脚
#define	SPI_SSIG_Enable()	SPCTL &= ~(1<<7)		//0: SS脚用于决定主从机
#define	SPI_Enable()		SPCTL |=  (1<<6)		//1: 允许SPI
#define	SPI_Disable()		SPCTL &= ~(1<<6)		//0: 禁止SPI
#define	SPI_LSB_First()		SPCTL |=  (1<<5)		//1: LSB先发
#define	SPI_MSB_First()		SPCTL &= ~(1<<5)		//0: MSB先发
#define	SPI_Master()		SPCTL |=  (1<<4)		//1: 设为主机
#define	SPI_Slave()			SPCTL &= ~(1<<4)		//0: 设为从机
#define	SPI_SCLK_NormalH()	SPCTL |=  (1<<3)		//1: 空闲时SCLK为高电平
#define	SPI_SCLK_NormalL()	SPCTL &= ~(1<<3)		//0: 空闲时SCLK为低电平
#define	SPI_PhaseH()		SPCTL |=  (1<<2)		//1: 
#define	SPI_PhaseL()		SPCTL &= ~(1<<2)		//0: 
#define	SPI_Speed(n)		SPCTL = (SPCTL & ~3) | (n)	//设置速度, 0 -- fosc/4, 1 -- fosc/16, 2 -- fosc/64, 3 -- fosc/128

//sfr SPDAT  = 0xCF; //SPI Data Register                                                     0000,0000
//sfr SPSTAT  = 0xCD;	//SPI状态寄存器
//   7       6      5   4   3   2   1   0    	Reset Value
//	SPIF	WCOL	-	-	-	-	-	-
#define	SPIF	0x80		//SPI传输完成标志。写入1清0。
#define	WCOL	0x40		//SPI写冲突标志。写入1清0。

#define		SPI_USE_P12P13P14P15()	AUXR1 &= ~0x0c	//将SPI切换到P12(SS) P13(MOSI) P14(MISO) P15(SCLK)(上电默认)。
#define		SPI_USE_P24P23P22P21()	AUXR1 = (AUXR1 & ~0x0c) | 0x04	//将SPI切换到P24(SS) P23(MOSI) P22(MISO) P21(SCLK)。
#define		SPI_USE_P54P40P41P43()	AUXR1 = (AUXR1 & ~0x0c) | 0x08	//将SPI切换到P54(SS) P40(MOSI) P41(MISO) P43(SCLK)。


/*
;PCA_PWMn:    7       6     5   4   3   2     1       0
;			EBSn_1	EBSn_0	-	-	-	-	EPCnH	EPCnL
;B5-B2:		保留
;B1(EPCnH):	在PWM模式下,与CCAPnH组成9位数。
;B0(EPCnL):	在PWM模式下,与CCAPnL组成9位数。
*/
#define		PWM0_NORMAL()	PCA_PWM0 &= ~3				//PWM0正常输出(默认)
#define		PWM0_OUT_0()	PCA_PWM0 |=  3				//PWM0一直输出0
#define		PWM0_OUT_1()	PCA_PWM0 &= ~3, CCAP0H = 0	//PWM0一直输出1

#define		PWM1_NORMAL()	PCA_PWM1 &= ~3				//PWM0正常输出(默认)
#define		PWM1_OUT_0()	PCA_PWM1 |=  3				//PWM0一直输出0
#define		PWM1_OUT_1()	PCA_PWM1 &= ~3, CCAP1H = 0	//PWM1一直输出1

#define		PWM2_NORMAL()	PCA_PWM2 &= ~3				//PWM1正常输出(默认)
#define		PWM2_OUT_0()	PCA_PWM2 |=  3				//PWM2一直输出0
#define		PWM2_OUT_1()	PCA_PWM2 &= ~3, CCAP2H = 0	//PWM2一直输出1


//						7     6     5     4     3     2     1     0     Reset Value
//sfr CCON   = 0xD8;	CF    CR    -     -     -    CCF2  CCF1  CCF0   00xx,xx00	//PCA 控制寄存器。
sbit CCF0  = CCON^0;	//PCA 模块0中断标志,由硬件置位,必须由软件清0。
sbit CCF1  = CCON^1;	//PCA 模块1中断标志,由硬件置位,必须由软件清0。
sbit CCF2  = CCON^2;	//PCA 模块2中断标志,由硬件置位,必须由软件清0。
sbit CR    = CCON^6;	//1: 允许PCA计数器计数,必须由软件清0。
sbit CF    = CCON^7;	//PCA计数器溢出(CH,CL由FFFFH变为0000H)标志。PCA计数器溢出后由硬件置位,必须由软件清0。

//					 7     6     5     4     3     2     1     0    Reset Value
//sfr CMOD  = 0xD9;	CIDL   -     -     -   CPS2   CPS1  CPS0  ECF   0xxx,0000	//PCA 工作模式寄存器。
#define PCA_IDLE_OFF()		CMOD |=  (1<<7)				//IDLE状态PCA停止计数。
#define PCA_IDLE_ON()		CMOD &= ~(1<<7)				//IDLE状态PCA继续计数。
#define PCA_CLK_12T()		CMOD &= ~0x0E				//PCA计数脉冲选择外部晶振/12。	fosc/12
#define PCA_CLK_2T()		CMOD = (CMOD & ~0x0E) + 2	//PCA计数脉冲选择外部晶振/2。	fosc/2
#define PCA_CLK_T0()		CMOD = (CMOD & ~0x0E) + 4	//PCA计数脉冲选择Timer0中断,Timer0可通过AUXR寄存器设置成工作在12T或1T模式。
#define PCA_CLK_ECI()		CMOD = (CMOD & ~0x0E) + 6	//PCA计数脉冲选择从ECI/P3.4脚输入的外部时钟,最大 fosc/2。
#define PCA_CLK_1T()		CMOD = (CMOD & ~0x0E) + 8	//PCA计数脉冲选择外部晶振。		Fosc/1
#define PCA_CLK_4T()		CMOD = (CMOD & ~0x0E) + 10	//PCA计数脉冲选择外部晶振/4。	Fosc/4
#define PCA_CLK_6T()		CMOD = (CMOD & ~0x0E) + 12	//PCA计数脉冲选择外部晶振/6。	Fosc/6
#define PCA_CLK_8T()		CMOD = (CMOD & ~0x0E) + 14	//PCA计数脉冲选择外部晶振/8。	Fosc/8
#define PCA_INT_ENABLE()	CMOD |=  1					//PCA计数器溢出中断允许位,1---允许CF(CCON.7)产生中断。
#define PCA_INT_DISABLE()	CMOD &= ~1					//PCA计数器溢出中断禁止。

//					    7      6       5        4       3       2       1      0    Reset Value
//sfr AUXR1 = 0xA2;	  S1_S1  S1_S0  CCP_S1   CCP_S0  SPI_S1   SPI_S0    -     DPS   0100,0000	//Auxiliary Register 1

#define		PCA_USE_P12P11P10P37()	AUXR1 &= ~0x30		//将PCA/PWM切换到P12(ECI) P11(CCP0) P10(CCP1) P37(CCP2)(上电默认)。
#define		PCA_USE_P34P35P36P37()	AUXR1 = (AUXR1 & ~0x30) | 0x10	//将PCA/PWM切换到P34(ECI) P35(CCP0) P36(CCP1) P37(CCP2)。
#define		PCA_USE_P24P25P26P27()	AUXR1 = (AUXR1 & ~0x30) | 0x20	//将PCA/PWM切换到P24(ECI) P25(CCP0) P26(CCP1) P27(CCP2)。

#define		DPS_SEL1()		AUXR1 |=  1		//1:选择DPTR1。
#define		DPS_SEL0()		AUXR1 &= ~1		//0:选择DPTR0(上电默认)。


/*									7     6      5      4     3     2     1     0     Reset Value
//sfr CCAPM0 = 0xDA;	PWM 寄存器  -   ECOM0  CAPP0  CAPN0  MAT0  TOG0  PWM0  ECCF0   x000,0000	//PCA 模块0 
//sfr CCAPM1 = 0xDB;	PWM 寄存器  -   ECOM1  CAPP1  CAPN1  MAT1  TOG1  PWM1  ECCF1   x000,0000	//PCA 模块1
//sfr CCAPM2 = 0xDC;	PWM 寄存器  -   ECOM2  CAPP2  CAPN2  MAT2  TOG2  PWM2  ECCF2   x000,0000	//PCA 模块2
;ECOMn = 1:	允许比较功能。
;CAPPn = 1:	允许上升沿触发捕捉功能。
;CAPNn = 1:	允许下降沿触发捕捉功能。
;MATn  = 1:	当匹配情况发生时,允许CCON中的CCFn置位。
;TOGn  = 1:	当匹配情况发生时,CEXn将翻转。(CEX0/PCA0/PWM0/P3.7,CEX1/PCA1/PWM1/P3.5)
;PWMn  = 1:	将CEXn设置为PWM输出。
;ECCFn = 1:	允许CCON中的CCFn触发中断。
;ECOMn CAPPn CAPNn MATn TOGn PWMn ECCFn
;  0     0     0    0    0    0     0		00H	未启用任何功能。
;  x     1     0    0    0    0     x	 	20H	16位CEXn上升沿触发捕捉功能。
;  x     0     1    0    0    0     x	 	10H	16位CEXn下降沿触发捕捉功能。
;  x     1     1    0    0    0     x	 	30H	16位CEXn/PCAn边沿(上、下沿)触发捕捉功能。
;  1     0     0    1    0    0     x	 	48H	16位软件定时器。
;  1     0     0    1    1    0     x	 	4CH	16位高速脉冲输出。
;  1     0     0    0    0    1     0		42H	8位PWM。无中断
;  1     1     0    0    0    1     1		63H	8位PWM。低变高可产生中断
;  1     0     1    0    0    1     1		53H	8位PWM。高变低可产生中断
;  1     1     1    0    0    1     1		73H	8位PWM。低变高或高变低均可产生中断
;*******************************************************************
;*******************************************************************/
#define		PCA0_none()				CCAPM0 = 0
#define		PCA0_PWM(nbit)			CCAPM0 = 0x42,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)
#define		PCA0_PWM_rise_int(nbit) CCAPM0 = 0x63,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)
#define		PCA0_PWM_fall_int(nbit) CCAPM0 = 0x53,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)
#define		PCA0_PWM_edge_int(nbit) CCAPM0 = 0x73,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)
#define		PCA0_capture_rise()		CCAPM0 = (0x20 + 1)
#define		PCA0_capture_fall()		CCAPM0 = (0x10 + 1)
#define		PCA0_capture_edge()		CCAPM0 = (0x30 + 1)
#define		PCA0_16bit_Timer()		CCAPM0 = (0x48 + 1)
#define		PCA0_High_Pulse()		CCAPM0 = (0x4C + 1)

#define		PCA1_none()				CCAPM1 = 0
#define		PCA1_PWM(nbit)			CCAPM1 = 0x42,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)
#define		PCA1_PWM_rise_int(nbit) CCAPM1 = 0x63,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)
#define		PCA1_PWM_fall_int(nbit) CCAPM1 = 0x53,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)
#define		PCA1_PWM_edge_int(nbit) CCAPM1 = 0x73,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)
#define		PCA1_capture_rise()		CCAPM1 = (0x20 + 1)
#define		PCA1_capture_fall()		CCAPM1 = (0x10 + 1)
#define		PCA1_capture_edge()		CCAPM1 = (0x30 + 1)
#define		PCA1_16bit_Timer()		CCAPM1 = (0x48 + 1)
#define		PCA1_High_Pulse()		CCAPM1 = (0x4C + 1)

#define		PCA2_none()				CCAPM2 = 0
#define		PCA2_PWM(nbit)			CCAPM2 = 0x42,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)
#define		PCA2_PWM_rise_int(nbit) CCAPM2 = 0x63,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)
#define		PCA2_PWM_fall_int(nbit) CCAPM2 = 0x53,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)
#define		PCA2_PWM_edge_int(nbit) CCAPM2 = 0x73,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)
#define		PCA2_capture_rise()		CCAPM2 = (0x20 + 1)
#define		PCA2_capture_fall()		CCAPM2 = (0x10 + 1)
#define		PCA2_capture_edge()		CCAPM2 = (0x30 + 1)
#define		PCA2_16bit_Timer()		CCAPM2 = (0x48 + 1)
#define		PCA2_High_Pulse()		CCAPM2 = (0x4C + 1)

/* Above is STC additional SFR or change */




/**********************************************************/
typedef 	unsigned char	u8;
typedef 	unsigned int	u16;
typedef 	unsigned long	u32;

/**********************************************************/
#define NOP1()  _nop_()
#define NOP2()  NOP1(),NOP1()
#define NOP3()  NOP2(),NOP1()
#define NOP4()  NOP3(),NOP1()
#define NOP5()  NOP4(),NOP1()
#define NOP6()  NOP5(),NOP1()
#define NOP7()  NOP6(),NOP1()
#define NOP8()  NOP7(),NOP1()
#define NOP9()  NOP8(),NOP1()
#define NOP10() NOP9(),NOP1()
#define NOP11() NOP10(),NOP1()
#define NOP12() NOP11(),NOP1()
#define NOP13() NOP12(),NOP1()
#define NOP14() NOP13(),NOP1()
#define NOP15() NOP14(),NOP1()
#define NOP16() NOP15(),NOP1()
#define NOP17() NOP16(),NOP1()
#define NOP18() NOP17(),NOP1()
#define NOP19() NOP18(),NOP1()
#define NOP20() NOP19(),NOP1()
#define NOP21() NOP20(),NOP1()
#define NOP22() NOP21(),NOP1()
#define NOP23() NOP22(),NOP1()
#define NOP24() NOP23(),NOP1()
#define NOP25() NOP24(),NOP1()
#define NOP26() NOP25(),NOP1()
#define NOP27() NOP26(),NOP1()
#define NOP28() NOP27(),NOP1()
#define NOP29() NOP28(),NOP1()
#define NOP30() NOP29(),NOP1()
#define NOP31() NOP30(),NOP1()
#define NOP32() NOP31(),NOP1()
#define NOP33() NOP32(),NOP1()
#define NOP34() NOP33(),NOP1()
#define NOP35() NOP34(),NOP1()
#define NOP36() NOP35(),NOP1()
#define NOP37() NOP36(),NOP1()
#define NOP38() NOP37(),NOP1()
#define NOP39() NOP38(),NOP1()
#define NOP40() NOP39(),NOP1()
#define NOP(N)  NOP##N()


/**********************************************/


/****************************************************************/


//sfr INT_CLKO = 0x8F;	//附加的 SFR WAKE_CLKO (地址:0x8F)
/*
    7   6    5    4   3     2        1       0         Reset Value
    -  EX4  EX3  EX2  -   T2CLKO   T1CLKO  T0CLKO      0000,0000B
b6 -  EX4      : 外中断INT4允许
b5 -  EX3      : 外中断INT3允许
b4 -  EX2      : 外中断INT2允许
b2 - T1CLKO    : 允许 T2 溢出脉冲在P3.0脚输出,Fck1 = 1/2 T1 溢出率
b1 - T1CLKO    : 允许 T1 溢出脉冲在P3.4脚输出,Fck1 = 1/2 T1 溢出率
b0 - T0CLKO    : 允许 T0 溢出脉冲在P3.5脚输出,Fck0 = 1/2 T0 溢出率
*/

#define		LVD_InterruptEnable()		ELVD = 1
#define		LVD_InterruptDisable()		ELVD = 0


//sfr WKTCL = 0xAA;	//STC11F\10和STC15系列 唤醒定时器低字节
//sfr WKTCH = 0xAB;	//STC11F\10和STC15系列 唤醒定时器高字节
//	B7		B6	B5	B4	B3	B2	B1	B0		B7	B6	B5	B4	B3	B2	B1	B0
//	WKTEN				S11	S10	S9	S8		S7	S6	S5	S4	S3	S2	S1	S0	n * 560us
#define		WakeTimerDisable()		WKTCH &= 0x7f	//WKTEN = 0		禁止睡眠唤醒定时器
#define		WakeTimerSet(scale)		WKTCL = (scale) % 256,WKTCH = (scale) / 256 | 0x80	//WKTEN = 1	允许睡眠唤醒定时器


//sfr CLK_DIV = 0x97; //Clock Divder 系统时钟分频  -     -      -       -     -  CLKS2 CLKS1 CLKS0 xxxx,x000
#define		SYSTEM_CLK_1T()		CLK_DIV &= ~0x07	//default
#define		SYSTEM_CLK_2T()		CLK_DIV = (CLK_DIV & ~0x07) | 1
#define		SYSTEM_CLK_4T()		CLK_DIV = (CLK_DIV & ~0x07) | 2
#define		SYSTEM_CLK_8T()		CLK_DIV = (CLK_DIV & ~0x07) | 3
#define		SYSTEM_CLK_16T()	CLK_DIV = (CLK_DIV & ~0x07) | 4
#define		SYSTEM_CLK_32T()	CLK_DIV = (CLK_DIV & ~0x07) | 5
#define		SYSTEM_CLK_64T()	CLK_DIV = (CLK_DIV & ~0x07) | 6
#define		SYSTEM_CLK_128T()	CLK_DIV =  CLK_DIV          | 7

#define		MCLKO_P54_None()	CLK_DIV &= ~0xc0					//主时钟不输出
#define		MCLKO_P54_DIV1()	CLK_DIV  = (CLK_DIV & ~0xc0) | 0x40	//主时钟不分频输出
#define		MCLKO_P54_DIV2()	CLK_DIV  = (CLK_DIV & ~0xc0) | 0x80	//主时钟2分频输出
#define		MCLKO_P54_DIV4()	CLK_DIV  =  CLK_DIV | 0xc0			//主时钟4分频输出

#define		MCLKO_P34_None()	CLK_DIV &= ~0xc0					//主时钟不输出
#define		MCLKO_P34_DIV1()	CLK_DIV  = (CLK_DIV & ~0xc0) | 0x40	//主时钟不分频输出
#define		MCLKO_P34_DIV2()	CLK_DIV  = (CLK_DIV & ~0xc0) | 0x80	//主时钟2分频输出
#define		MCLKO_P34_DIV4()	CLK_DIV  =  CLK_DIV | 0xc0			//主时钟4分频输出

//sfr BUS_SPEED = 0xA1; //Stretch register      -   -  -  -   -   -  EXRTS1  EXRTSS0 xxxx,xx10
#define		BUS_SPEED_1T()	BUS_SPEED = 0
#define		BUS_SPEED_2T()	BUS_SPEED = 1
#define		BUS_SPEED_4T()	BUS_SPEED = 2
#define		BUS_SPEED_8T()	BUS_SPEED = 3

/*   interrupt vector */
#define		INT0_VECTOR		0
#define		TIMER0_VECTOR	1
#define		INT1_VECTOR		2
#define		TIMER1_VECTOR	3
#define		UART1_VECTOR	4
#define		ADC_VECTOR		5
#define		LVD_VECTOR		6
#define		PCA_VECTOR		7
#define		UART2_VECTOR	8
#define		SPI_VECTOR		9
#define		INT2_VECTOR		10
#define		INT3_VECTOR		11
#define		TIMER2_VECTOR	12
#define		INT4_VECTOR		16
#define		UART3_VECTOR	17
#define		UART4_VECTOR	18
#define		TIMER3_VECTOR	19
#define		TIMER4_VECTOR	20
#define		CMP_VECTOR		21


#define	TRUE	1
#define	FALSE	0

//=============================================================

//========================================

#define	PolityLow			0	//低优先级中断
#define	PolityHigh			1	//高优先级中断

//========================================

#define		MCLKO_None	0
#define		MCLKO_DIV1	1
#define		MCLKO_DIV2	2
#define		MCLKO_DIV4	3

#define		ENABLE		1
#define		DISABLE		0

#define		STC15F_L2K08S2	8
#define		STC15F_L2K16S2	16
#define		STC15F_L2K24S2	24
#define		STC15F_L2K32S2	32
#define		STC15F_L2K40S2	40
#define		STC15F_L2K48S2	48
#define		STC15F_L2K56S2	56
#define		STC15F_L2K60S2	60
#define		IAP15F_L2K61S2	61

#endif

测试程序

修改timer.c文件的timer0_int函数,添加如下内容:

#include 	"compare.h"
#define	ADC_SCALE	50000		//ADC满量程, 根据需要设置
sbit	P_ADC	= P1^2;			//P1.2 比较器转IO输出端
u16		adc;					//ADC中间值, 用户层不可见
u16		adc_duty;				//ADC计数周期, 用户层不可见
u16		adc_value;				//ADC值, 用户层使用
bit		adc_ok;					//ADC结束标志, 为1则adc_value的值可用. 此标志给用户层查询,并且清0

/********************* Timer0中断函数************************/
void timer0_int (void) interrupt TIMER0_VECTOR
{
	if((CMPCR1 & CMPRES) == 0)	//比较器输出低电平
		P_ADC = 0;				//P_ADC输出低电平, 给负输入端做反馈. 
	else						//比较器输出高电平. 
	{
		P_ADC = 1;				//P_ADC输出高电平, 给负输入端做反馈. 
		adc ++;					//ADC计数+1
	}

	if(--adc_duty == 0)			//ADC周期-1, 到0则ADC结束
	{
		adc_duty = ADC_SCALE;	//周期计数赋初值
		adc_value = adc;		//保存ADC值
		adc = 0;				//清除ADC值
		adc_ok = 1;				//标志ADC已结束
	}
}

main.c

/*---------------------------------------------------------------------*/
/* --- STC MCU International Limited ----------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
/*---------------------------------------------------------------------*/



/****************************
本示例在Keil开发环境下请选择Intel的8052芯片型号进行编译

本例程MCU的工作频率为22.1184MHz.

使用MCU自带的比较器进行ADC转换, 并通过串口输出结果. 用定时器0产生10us中断查询比较器的状态.

使用比较器做ADC, 原理图如下.
做ADC的原理是基于电荷平衡的计数式ADC.
电压从Vin输入, 通过100K+104滤波, 进入比较器的P5.5正输入端, 经过比较器的比较, 将结果输出到P1.5再通过100K+104滤波后送比较器P5.4负输入端,跟输入电压平衡.
设置两个变量: 计数周期(量程)adc_duty 和 比较结果高电平的计数值 adc, adc严格比例于输入电压.
ADC的基准就是P1.5的高电平. 如果高电平准确,比较器的放大倍数足够大,则ADC结果会很准确.
当比较结果为高电平,则P1.5输出1, 并且adc+1.
当比较结果为低电平,则P1.5输出0.
每一次比较都判断计数周期是否完成,完成则adc里的值就是ADC结果.
电荷平衡计数式ADC的性能类似数字万用表用的双积分ADC, 当计数周期为20ms的倍数时,具有很强的抗工频干扰能力,很好的线性和精度.
原理可以参考ADD3501(3 1/2位数字万用表)或ADD3701(3 3/4位数字万用表), 也可以参考AD7740 VFC电路.

例: 比较一次的时间间隔为10us, 量程为10000, 则做1次ADC的时间为100ms. 比较器的响应时间越短, 则完成ADC就越快.

由于要求每次比较时间间隔都要相等,所以用C编程最好在定时器中断里进行, 定时器设置为自动重装, 高优先级中断, 其它中断均低优先级.
用汇编的话, 保证比较输出电平处理的时间要相等.


                                         100K
                            /| P5.5       ___
                    P1.2   /+|---------o-|___|- ------- Vin
                     .----<  | P5.4    |
                     |     \-|---.     |
                     |      \|   |     |
                     |           |     |
                     |    ___    |     |
                     '---|___|---o     |
                        100K     |     |
                                ---   ---
                                ---   ---
                            104  |     |  104
                                 |     |
                                ===   ===
                                GND   GND



******************************/


#include "./Drivers/config.h"
#include "./Drivers/delay.h"

#include "./Drivers/timer.h"
#include "./Drivers/GPIO.h"
#include "./Drivers/soft_UART.h"
#include <stdio.h>

#include "./Drivers/compare.h"

/*************	本地常量声明	**************/


/*************	本地变量声明	**************/


/*************	本地函数声明	**************/
char putchar(char Char)
{
	TxSend(Char);
    return Char;
}

/*************  外部函数和变量声明 *****************/
extern	bit	B_Timer0;
extern	u16		adc_value;		//ADC值, 用户层使用
extern	bit		adc_ok;			//ADC结束标志, 为1则adc_value的值可用. 此标志给用户层查询,并且清0

/************************ 比较器配置 ****************************/
void	CMP_config(void)
{
	CMP_InitDefine CMP_InitStructure;					//结构定义
	CMP_InitStructure.CMP_EN = ENABLE;					//允许比较器		ENABLE,DISABLE
	CMP_InitStructure.CMP_RiseInterruptEn = DISABLE;	//允许上升沿中断	ENABLE,DISABLE
	CMP_InitStructure.CMP_FallInterruptEn = DISABLE;	//允许下降沿中断	ENABLE,DISABLE
	CMP_InitStructure.CMP_P_Select     = CMP_P_P55;		//比较器输入正极性选择, CMP_P_P55: 选择内部P5.5做正输入, CMP_P_ADCIS: 由ADCIS[2:0]所选择的ADC输入端做正输入.
	CMP_InitStructure.CMP_N_Select     = CMP_N_P54;		//比较器输入负极性选择, CMP_N_BGv: 选择内部BandGap电压BGv做负输入, CMP_N_P54: 选择外部P5.4做输入.
	CMP_InitStructure.CMP_OutptP12_En  = DISABLE;		//允许比较结果输出到P1.2,   ENABLE,DISABLE
	CMP_InitStructure.CMP_InvCMPO      = DISABLE;		//比较器输出取反, 	ENABLE,DISABLE
	CMP_InitStructure.CMP_100nsFilter  = ENABLE;		//内部0.1uF滤波,  	ENABLE,DISABLE
	CMP_InitStructure.CMP_OutDelayDuty = 20;			//比较结果变化延时周期数, 0~63
//	CMP_InitStructure.CMP_Polity	   = PolityHigh;	//中断优先级,     PolityLow,PolityHigh
	CMP_Inilize(&CMP_InitStructure);				//初始化Timer2	  Timer0,Timer1,Timer2
}


/************************ IO口配置 ****************************/
void	GPIO_config(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure;				//结构定义
	GPIO_InitStructure.Pin  = GPIO_Pin_4 | GPIO_Pin_5;	//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_HighZ;				//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P5,&GPIO_InitStructure);			//初始化

	GPIO_InitStructure.Pin  = GPIO_Pin_2;				//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_OUT_PP;				//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);			//初始化
}

/************************ 定时器配置 ****************************/

void	Timer_config(void)
{
	TIM_InitTypeDef		TIM_InitStructure;					//结构定义
	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	//指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
	TIM_InitStructure.TIM_Polity    = PolityHigh;			//指定中断优先级, PolityHigh,PolityLow
	TIM_InitStructure.TIM_Interrupt = ENABLE;				//中断是否允许,   ENABLE或DISABLE
	TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;			//指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
	TIM_InitStructure.TIM_ClkOut    = ENABLE;				//是否输出高速脉冲, ENABLE或DISABLE
	TIM_InitStructure.TIM_Value     = 65536 - MAIN_Fosc / 100000UL;	//初值,
	TIM_InitStructure.TIM_Run       = ENABLE;				//是否初始化后启动定时器, ENABLE或DISABLE
	Timer_Inilize(Timer0,&TIM_InitStructure);				//初始化Timer0	  Timer0,Timer1,Timer2
}

/******************** task A **************************/
void main(void)
{
	GPIO_config();
	Timer_config();
	CMP_config();

	EA = 1;

	printf("\r\n使用比较器做ADC例子\r\n");	//发送一个字符串

	while (1)
	{
		if(adc_ok)		//等待ADC结束
		{
			adc_ok = 0;				//清除ADC已结束标志
			printf("ADC = %ld\r\n", (long)adc_value);
		}
	}
}