#include <stc15.h>
#include <intrins.h>
#include <stdio.h>

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

//函数声明
void delay1ms();	//@11.0592MHz
void delayms(int nms);		//@11.0592MHz
//位函数
u8 bitSet(u8 x,u8 pos);
u8 bitReset(u8 x,u8 pos);
u8 bitRead(u8 x,u8 pos);
u8 bitToggle(u8 x,u8 pos);
//选择573函数
#define LEDY    0
#define SMGABCY 1
#define SMGCOMY 2
#define ULNY    3
#define NONE    4
void choose573(u8 x);

//LED驱动函数,
#define L1 0
#define L2 1
#define L3 2
#define  LEDON   0
#define  LEDOFF  1
u8 u8LED=0xff;
void LEDONx(u8 x);
void LEDOFFx(u8 x);
u8   LEDReadx(u8 x);
void LEDTOGx(u8 x);
void LEDdis(u8 x);
//继电器和蜂鸣器
u8 u8ULN=0x00;
void ULNdis(u8 x)
{
	choose573(NONE);
	u8ULN=x;
	P0=u8ULN;
	choose573(ULNY);
	choose573(NONE);
}
void JDQON()
{
	u8ULN=bitSet(u8ULN,4);
}
void JDQOFF()
{
	u8ULN=bitReset(u8ULN,4);
}
void FMQON()
{
	u8ULN=bitSet(u8ULN,6);
}
void FMQOFF()
{
	u8ULN=bitReset(u8ULN,6);
}

//******************数码管
u8 SMGbuf[8];//显示缓冲
u8  display_index;  //显示位索引
//位选择,和上面的数组倒过来,这样SMGbuf[0]对应位T_COM[0]数码管
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
//u8 code T_COM[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //位码
char SMGtemp[20];//数码管转换中间变量,sprintf函数打印到这个缓冲区中。
//段码表,字库表
/*************  本地常量声明    **************/
u8 code t_display[]={                       //标准字库,共阴极,记得取反就可以了。
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

//*********************************************复制stc-ISP里面试验箱的HC595驱动数码管的代码
/********************** 显示扫描函数 ************************/
void DisplayScan(void)
{   
			//位选
			choose573(NONE);//关闭所有的通道
			P0=T_COM[display_index];//选择位码
			choose573(SMGCOMY);//选择位选COM通道,输出位码
			choose573(NONE);//关闭通道
			//消隐
			P0=0xff;//段码0xFF,关闭段码熄灭数码管,消隐
			choose573(SMGABCY);//选择段码通道,输出段码
			//段码
			P0=SMGbuf[display_index];//设置段码到P0口,
			choose573(SMGABCY);//输出段码
			choose573(NONE);//关闭所有的通道
	   //8个数码管
    if(++display_index >= 8)    display_index = 0;  //8位结束回0
}
		
void SMGconv(void)
{
	char i=0,j=0,temp;
	while(SMGtemp[i]!=0) //缓冲区每次都会填入8个字符的sprintf,因此如果没数据会等于0x00;
	{
		switch(SMGtemp[i])
		{
			case '0':temp=~t_display[0];break;
			case '1':temp=~t_display[1];break;
			case '2':temp=~t_display[2];break;
			case '3':temp=~t_display[3];break;
			case '4':temp=~t_display[4];break;
			case '5':temp=~t_display[5];break;
			case '6':temp=~t_display[6];break;
			case '7':temp=~t_display[7];break;
			case '8':temp=~t_display[8];break;
			case '9':temp=~t_display[9];break;
			case 'A':temp=~t_display[10];break;
			case 'B':temp=~t_display[11];break;
			case 'P':temp=~0x73;break;
			case 'U':temp=~0x3E;break;
			case '-':temp=~0x40;break;
			default:temp=0xFF;break;
		}
		if(SMGtemp[i+1]=='.')//下一个等于小数点
		{
			temp&=0x7f;//将小数点
			i++;//跳过一个小数点字符
		}
		i++;//不管有没有小数点,都加一个位置
		
		SMGbuf[j]=temp;//将转换的数据,放到数码管段码缓冲区中;
		j++;//记得这个加一
	}
}	

//**********************定时器的设置
#define FOSC 11059200L
//#define T1MS (65536-FOSC/1000)      //1T模式
#define T1MS (65536-FOSC/12/1000) //12T模式
//-----------------------------------------------
u8 flag1s=0;
int cnt1ms=0;
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
	static u8 i=0;
	TL0 = T1MS;   //初始化计时值
  TH0 = T1MS >> 8;
	cnt1ms++;
	if(cnt1ms==1000)
	{
		cnt1ms=0;
		flag1s=1;
	}
	//是2的倍数,cnt1ms%2==0,相当于2ms执行一次,这里是3个数码管,每个2ms那么就是6ms刷新率
	//如果是8个数码管,那么可以cnt1ms%1==0,每8ms刷新一帧数据
	if(cnt1ms%2==0)	
	{
		DisplayScan();//2ms刷新一个字符,也可以%1==0,一个字符显示一个函数
	}
}

//****************************8
void main()
{
	
	float xx=2.54;
	int yy=87;
	int sec=20;  //9999 9999
	int ge,shi,bai;
	u8 jiemian=0;
	u8 i=0;
	
	
	LEDdis(0xFF);//开机关闭LED
	ULNdis(0x00);//开机关闭蜂鸣器和继电器
	
	jiemian=3;
	
	 EA = 1;//单片机总中断EA打开
   AUXR &= 0x7f;                   //定时器0为12T模式
	
    //TMOD &= 0xF0;                //设置定时器为模式0(16位自动重装载)
	//TMOD &= 0xF1;//1111 0001
		TMOD = 0x01;//1111 0001
		TL0 = T1MS;                     //初始化计时值
    TH0 = T1MS >> 8;

    ET0 = 1;                        //使能定时器0中断
	  TR0 =1;                        //定时器0开始计时
	while(1)
	{
		//*******************显示整数,注意%3u和%03u的区别
		sprintf(SMGtemp,"A-B-P%03u",(unsigned int)yy);//不够3个字符宽度,用0代替
		//sprintf(SMGtemp,"A-B--%3u",(unsigned int)yy);
		SMGconv();
		delayms(5000);
		yy=yy+1;
		if(yy==345)yy=65;
	//*********************************************
		
//*******************显示
		sprintf(SMGtemp,"B----%3.2f",xx);3个字符宽度,2个小数点
		SMGconv();//转换到数码管显示缓冲区
		delayms(5000);
		xx=xx+0.01;
		if(xx>=5)xx=2.57;
		//*********************************************	
	}
	
}


//延时89s52,传统的
void delay1ms()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}
void delayms(int nms)		//@11.0592MHz
{
	unsigned char i, j;
	int m;
	for(m=0;m<nms;m++)
	{
			_nop_();
			i = 2;
			j = 199;
			do
			{
				while (--j);
			} while (--i);
	}
}
//位操作
u8 bitSet(u8 x,u8 pos)
{
	x=x|(1<<pos);
	return x;
}
u8 bitReset(u8 x,u8 pos)
{
	x=x&(~(1<<pos));
	return x;
}
u8 bitRead(u8 x,u8 pos)
{
	u8 y;
	y=(x>>pos)&0x01;
	return y;
}
u8 bitToggle(u8 x,u8 pos)
{
	x=x^(1<<pos);
	return x;
}
//选择573
//#define LEDY    0
//#define SMGABCY 1
//#define SMGCOMY 2
//#define ULNY    3
//#define NONE    4
void choose573(u8 x)
{	
	switch(x)
	{
		case LEDY:P2=P2&0x1F |0x80;break;  //1000 0000
		case SMGABCY:P2=P2&0x1F |0xe0;break;  //1110 0000
		case SMGCOMY:P2=P2&0x1F |0xc0;break;  //1100 0000
		case ULNY:P2=P2&0x1F |0xa0;break;  //1010 0000
		case NONE:P2=P2&0x1F;break;  //0000 0000
	}
}
//LED驱动
//u8 bitSet(u8 x,u8 pos);
//u8 bitReset(u8 x,u8 pos);
//u8 bitRead(u8 x,u8 pos);
//u8 bitToggle(u8 x,u8 pos);
void LEDONx(u8 x)
{
	u8LED=bitReset(u8LED,x);
}
void LEDOFFx(u8 x)
{
	u8LED=bitSet(u8LED,x);
}
u8 LEDReadx(u8 x)
{
  return bitRead(u8LED,x);
}
void LEDTOGx(u8 x)
{
   u8LED=bitToggle(u8LED,x);
}
void LEDdis(u8 x)
{
	choose573(NONE);
	u8LED= x;
	P0=u8LED;
	choose573(LEDY);
	//delay1ms();
	choose573(NONE);
}