

#include <STC8H.H>
#include "intrins.h"

// 定义数据类型别名
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long int u32;

// 定义主时钟频率和波特率
#define MAIN_Fosc     22118400UL         // 主时钟频率
#define Baudrate      115200             // 波特率
#define BRT           (65536 - (MAIN_Fosc/Baudrate + 2)/4)  // 波特率发生器重装值



// 定义P3.4口的控制信号  【P3.4需要设置为推挽输出（蜂鸣器）】

sbit beep = P3^4;                        // 蜂鸣器接口
sbit buz = P3^5;                         // 蜂鸣使能指示灯
sbit mut = P3^6;                         // 静音使能指示灯

//定义DS18B20相关变量及接口
bit MinusFlag;                          // 温度正负标志位（0：正数，1：负数）
sbit DQ = P3^3;                          // DS18B20数据线连接P3.3   【需要设置为准双向口】
sbit key = P3^2; 
sbit btoff = P3^7; 						 // 关蓝牙 1=关
u16 val;                                 // 温度值
u16 alarm;                               // 报警温度值
u8 l;                                    // 仅显示，不读取温度的循环  的计数器
u8 time;								 // 按键计时

/*-- UART 相关变量 --*/
bit busy;                                // 发送忙标志
u8 wptr;                                 // 写指针
u8 rptr;                                 // 读指针
u8 buffer[16];                           // 接收缓冲区
u8 date;                                 // 接收的数据
u8 recFlag;                              // 接收数据标识（0：未接收，1：接收）

u8 receivedChar;	 // 接收到的字符
u8 inputBuffer[32];  // 用户输入缓冲区
u8 inputIndex = 0;   // 用户输入缓冲区索引
bit inputComplete = 0;  // 输入完成标志


/*--------- 函数声明 ----------*/
void GPIO_Init();                        // GPIO初始化
void UartInit();                         // UART初始化
void UartSend(u8 dat);                   // 发送一个字节
void UartSendStr(u8 *p);                 // 发送字符串
void Display();                          // 获取并用串口输出温度
u16 Readtemp();					    	 // 读取温度值
void Delay_ms(u16 ms);                   // 延时函数
void Check();                            // 系统自检
void BeepThreeTimes();					 // 蜂鸣三次
u8 bijiao(u8 *s1, u8 *s2);				 // 比较字符串
void changan();
void liangmiao();
void duanan();
void anjian();


/*----------- 主程序 ---------------*/
void main(void)
{



    P_SW2 |= 0X80; // 使能访问XFR

    GPIO_Init();  // 初始化GPIO
//    UartInit();   // 初始化UART
    val = Readtemp(); // 读取温度值

//    ES = 1;       // 使能串口中断
    EA = 1;       // 使能总中断
    Check();      // 系统自检
    l = 1;
    Display(); // 获取{并用串口}输出温度

	alarm = 385	;


    while (1)
    {


    if (btoff ==1)  //如果蓝牙关闭 
	{
//		 WKTCH = 0x8F;  // 高字节	  // 使能掉电唤醒计时器		 2秒
//		 WKTCL = 0xFE;  // 低字节	  
		 WKTCH = 0xA7;  // 高字节	  // 使能掉电唤醒计时器		 5秒
		 WKTCL = 0x0F;  // 低字节	  

	     IT0 = 1;   //INT0下降沿中断
		 EX0 = 1;   //使能INT0中断
		 
	
	     PCON |= 0x02;     //MCU进入掉电模式
	     _nop_();
	     _nop_();     
		 _nop_();
	     _nop_();    
		 _nop_();
	     _nop_();
	
	}	


    if (btoff ==0)  //如果蓝牙使能 


    {



        Delay_ms(5000);












        if (inputComplete)  // 如果用户输入完成
        {
            inputComplete = 0;  // 清除输入完成标志
            UartSendStr("You entered: ");  // 提示用户输入的内容
            UartSendStr(inputBuffer);      // 发送用户输入的内容
            UartSendStr("\r\nOK\r\n");     // 返回 "OK"
            inputIndex = 0;                // 重置输入缓冲区索引


			 beep = 1;         // 蜂鸣器鸣响
		   	 Delay_ms(100);
		     beep = 0;         // 关闭蜂鸣器


			if (bijiao(inputBuffer, "beep") == 0)
			{

			   BeepThreeTimes(); // 蜂鸣器响三声



			}



	    }

	}

        if (l < 1) // 每1次循环更新一次温度显示
        {
//            Delay_ms(10);
// 		    if (btoff == 0)
//		      	 {


//		     	 }

 

//            Delay_ms(50);
            l++;
        }
        else
        {
            Delay_ms(10);
            Display(); // 获取{并用串口输出}温度


           if (MinusFlag == 0)		 //正温度
			{
			    if(val>395)
//				if(val % 10  == 8)
				{
//				      P1PU = 0xff; // 使能P1上拉电阻，LED全亮
					  P1PU = 0x01; // 使能P1上拉电阻，LED8亮
				}
				else
				{
					if(val>390)
//					if(val % 10  == 7)
					{
//					    P1PU = 0xfe; 
					    P1PU = 0x02; 

					}
					else
				    {
						if(val>385)
//						if(val % 10  == 6)
						{
//						    P1PU = 0xfc;
							P1PU = 0x04; 

						}
				   		else
				  		 {
		
							if(val>380)
//							if(val % 10  == 5)
							{
//							     P1PU = 0xf8;
								 P1PU = 0x08; 

							}
							else
						    {
								if(val>375)
//								if(val % 10  == 4)
								{
//								    P1PU = 0xf0; 
									P1PU = 0x10;

								}
						   		else
						  	    {
								  	
								 	if(val>370)
//									if(val % 10  == 3)
									{
//									     P1PU = 0xe0;
										 P1PU = 0x20; 

									}
									else
								    {
										if(val>365)
//		           						if(val % 10  == 2)
										{
//										    P1PU = 0xc0; 
											P1PU = 0x40; 

										}
								   		else

										{
//										    P1PU = 0x80;
											P1PU = 0x80; 


										}

									}

								}
							}
						 }

					}


				}

//			     Delay_ms(10);
//				 P1PU = 0x00;


			 }
            else	 //负温度
			{	
	        P1PU = 0x80; 	
            }




			if (val>alarm)
			{
				if (buz == 1)
				{
				BeepThreeTimes(); // 蜂鸣器响三声
				}
			}




			l = 1;
        }
    }
}



/*-------------- GPIO初始化 --------------*/
void GPIO_Init()
{
    P1M0 = 0x00; P1M1 = 0xff; // P1口高阻输入，程序控制单片机内部上拉电阻，实现灯亮灭
    P3M0 = 0x10; P3M1 = 0x00; // P3.0、P3.1准双向口
							  // P3.2准双向口（按键）
							  // P3.3准双向口（DS18B20 DQ）
							  // P3.4推挽输出（蜂鸣器）
							  // P3.5、P3.6准双向口，实现灯亮灭
							  // P3.7 准双向口（蓝牙使能）
    RSTCFG |= 0x10;           // 设置P5.4为复位引脚
    P1IE = 0x00; 			  //关P1数字输入
    P3IE = 0xff;              //使能P3口数字输入
}

/*----------- 延时函数 ------------*/
void Delay1us(void) // 1us延时
{
    u8 i;
    _nop_();
    i = 5;
    while (--i);
}

void Delay60us(void) // 60us延时
{
    u8 i, j;
    _nop_();
    _nop_();
    i = 2;
    j = 182;
    do
    {
        while (--j);
    } while (--i);
}

void Delay480us(void) // 480us延时
{
    u8 i, j;
    _nop_();
    i = 14;
    j = 199;
    do
    {
        while (--j);
    } while (--i);
}

void Delay_ms(u16 ms) // 毫秒级延时
{
    u16 i;
    do
    {
        i = MAIN_Fosc / 10000;
        while (--i);
    } while (--ms);
}

/*-------------- UART发送一个字节 --------------*/
void UartSend(u8 dat)
{
    while (busy); // 等待发送完成
    busy = 1;
    SBUF = dat;   // 发送数据
}

/*-------------- UART发送字符串 --------------*/
void UartSendStr(u8 *p)
{
    while (*p)
    {
        UartSend(*p++); // 逐个发送字符
    }
}

/*-------------- UART中断服务程序 --------------*/
void UartIsr() interrupt 4
{
    if (TI)  // 发送中断
    {
        TI = 0;    // 清除发送中断标志
        busy = 0;  // 设置 busy 标志为 0，表示发送完成
    }

    if (RI)  // 接收中断
    {
        RI = 0;  // 清除接收中断标志
        receivedChar = SBUF;  // 读取接收到的字符

        if (receivedChar == '\r' || receivedChar == '\n')  // 如果接收到回车或换行符
        {
            inputBuffer[inputIndex] = '\0';  // 在输入缓冲区末尾添加字符串结束符
            inputComplete = 1;               // 设置输入完成标志
        }
        else
        {
            inputBuffer[inputIndex++] = receivedChar;  // 将接收到的字符存入输入缓冲区
            if (inputIndex >= sizeof(inputBuffer) - 1)  // 防止缓冲区溢出
            {
                inputIndex = sizeof(inputBuffer) - 1;
            }
        }
    }
}

/*-------------- UART初始化 --------------*/
void UartInit()
{
    SCON = 0x50; // 串口模式1，8位数据，1位停止位
    TMOD = 0x00; // 定时器模式0
    TL1 = BRT;   // 波特率发生器低字节
    TH1 = BRT >> 8; // 波特率发生器高字节
    TR1 = 1;     // 启动定时器1
    AUXR = 0x40; // 定时器1为1T模式
    wptr = 0x00; // 初始化写指针
    rptr = 0x00; // 初始化读指针
    busy = 0;    // 初始化忙标志
}

/*----------- DS18B20初始化 --------------*/
void Init_DS18B20()
{
    bit flag = 1;
    while (flag)
    {
        DQ = 0;          // 拉低总线
        Delay480us();    // 延时480us
        DQ = 1;          // 释放总线
        Delay60us();     // 延时60us
        flag = DQ;       // 读取总线状态
        Delay480us();    // 延时480us
    }
}

/*----------- DS18B20写0 --------------*/
void DS18b20_Write_0()
{
    DQ = 0;          // 拉低总线
    Delay60us();     // 延时60us
    DQ = 1;          // 释放总线
    Delay1us();      // 延时1us
}

/*----------- DS18B20写1 --------------*/
void DS18b20_Write_1()
{
    DQ = 0;          // 拉低总线
    Delay1us();      // 延时1us
    DQ = 1;          // 释放总线
    Delay60us();     // 延时60us
}

/*----------- DS18B20读取电平 --------------*/
bit DS18b20_Read()
{
    bit state;
    DQ = 0;          // 拉低总线
    Delay1us();      // 延时1us
    DQ = 1;          // 释放总线
    Delay1us();      // 延时1us
    state = DQ;      // 读取总线状态
    Delay60us();     // 延时60us
    return state;
}

/*----------- DS18B20写一个字节 --------------*/
void WriteOneChar(u8 dat)
{
    u8 i;
    for (i = 0; i < 8; i++) // 循环8次，写入8位数据
    {
        if (dat & 0x01)
            DS18b20_Write_1(); // 写1
        else
            DS18b20_Write_0(); // 写0
        dat >>= 1;             // 右移一位
    }
}

/*----------- DS18B20读一个字节 --------------*/
u8 ReadOneChar()
{
    u8 i = 0;
    u8 dat = 0;
    for (i = 8; i > 0; i--) // 循环8次，读取8位数据
    {
        DQ = 0;          // 拉低总线
        dat >>= 1;       // 右移一位
        DQ = 1;          // 释放总线
        if (DS18b20_Read()) // 读取总线状态
            dat |= 0x80; // 如果为1，设置最高位
    }
    return dat;
}

/*----------- DS18B20启动温度转换 --------------*/
void Start_Convert()
{
    Init_DS18B20(); // 初始化DS18B20
    WriteOneChar(0xcc); // 跳过ROM命令
    WriteOneChar(0x44); // 启动温度转换
}

/*----------- 读取温度值 --------------*/
u16 Readtemp()
{
    u8 Low = 0;
    u8 High = 0;
    u16 Temper = 0; // 温度值
    float Tt = 0;

    Start_Convert(); // 启动温度转换
    while (!DQ);     // 等待转换完成

    Init_DS18B20();  // 初始化DS18B20
    WriteOneChar(0xcc); // 跳过ROM命令
    WriteOneChar(0xbe); // 读取温度寄存器

    Low = ReadOneChar();  // 读取温度低字节
    High = ReadOneChar(); // 读取温度高字节

    if (High & 0xF8) // 判断是否为负数
    {
        MinusFlag = 1; // 设置负温度标志
        Temper = (High << 8) | Low; // 合并高低字节
        Temper = (~Temper) + 1;     // 取反加1，得到补码
        Tt = Temper * 0.0625;       // 转换为实际温度
        Temper = Tt * 10 + 0.5;     // 放大10倍，四舍五入
    }
    else
    {
        MinusFlag = 0; // 设置正温度标志
        Temper = (High << 8) | Low; // 合并高低字节
        Tt = Temper * 0.0625;       // 转换为实际温度
        Temper = Tt * 10 + 0.5;     // 放大10倍，四舍五入
    }
    return Temper;
}

/*----------- 获取{并用串口输出}温度 --------------*/
void Display()
{
    u16 shi, ge, xiaoshu;
    val = Readtemp(); // 读取温度值



	if (btoff == 0)  //如果蓝牙使能
	{

	


		shi = val / 100 % 10 + 48;   // 十位
        ge = val / 10 % 10 + 48;     // 个位
        xiaoshu = val % 10 + 48;     // 小数位
	
	    if (MinusFlag == 1) // 负温度
	    {
	        UartSendStr("Temperature: ");
	        UartSend('-');
	        UartSend(shi);
	        UartSend(ge);
	        UartSend('.');
	        UartSend(xiaoshu);
	        UartSendStr("\r\n");
	    }
	    else // 正温度
	    {
	        UartSendStr("Temperature: ");
	        if (val > 1000) // 温度超过100度
	            UartSend('1');
	        UartSend(shi);
	        UartSend(ge);
	        UartSend('.');
	        UartSend(xiaoshu);
	        UartSendStr("\r\n");
	  
	    }



	}
}

/*----------- 系统自检 --------------*/
void Check()
{
    P1PU = 0xff; // 使能P1上拉电阻，LED全亮
    Delay_ms(600); // 延时600ms

    val = Readtemp(); // 读取温度值

    beep = 1;         // 蜂鸣器鸣响
    Delay_ms(100);
    beep = 0;         // 关闭蜂鸣器

    P1PU = 0x00; // 禁用P1上拉电阻，LED全灭
	buz = 1;
	mut = 0;

}



/*----------- 蜂鸣器响三声 ------------*/
void BeepThreeTimes()
{
    u8 i;

//	shuma = a[16]; // ---
//    LED_0 = 1;
//    LED_1 = 1;
//    LED_2 = 1;
//    LED_3 = 1;



    for (i = 0; i < 3; i++)
    {
        beep = 1; // 打开蜂鸣器
        Delay_ms(200); // 延时200ms
        beep = 0; // 关闭蜂鸣器
        Delay_ms(200); // 延时200ms
    }

//	LED_0 = 0;
//    LED_1 = 0;
//    LED_2 = 0;
//    LED_3 = 0;


}



/*----------- 长按 ------------*/
void changan()
{
   

 beep = 1;         // 蜂鸣器鸣响
 Delay_ms(500);
 beep = 0;         // 关闭蜂鸣器
 Delay_ms(2000);
 IAP_CONTR = 0x60; //软件复位



}





/*----------- liangmiao ------------*/
void liangmiao()


{
 beep = 1;         // 蜂鸣器鸣响
 Delay_ms(100);
 beep = 0;         // 关闭蜂鸣器
 Delay_ms(100);
 beep = 1;         // 蜂鸣器鸣响
 Delay_ms(100);
 beep = 0;         // 关闭蜂鸣器

 Delay_ms(1000);

 beep = 1;         // 蜂鸣器鸣响
 Delay_ms(100);
 beep = 0;         // 关闭蜂鸣器




 btoff = 1;  // 关蓝牙
 P1PU = 0x00; 	//禁用P1口上拉电阻
 TR1 = 0;     // 关定时器1
 ES = 0;        // 关串口中断
 P1M0 = 0x00; P1M1 = 0xff;  //P1口高阻输入
 P3M0 = 0x00; P3M1 = 0xfb;   //P3口高阻输入	key3.2 准双向口
 P3PU |= 0x04; 
 P1IE = 0x00; 				//关P1数字输入
 P3IE = 0x04; 		  	//关P3口3.2以外的数字输入

//	P3PU |= 0x04; 				//使能3.2上拉电阻



IT0 = 1;   //INT0下降沿中断
EX0 = 1;   //使能INT0中断
EA = 1;       // 使能总中断
WKTCH = 0x00;  // 高字节	  // 禁用掉电唤醒计时器
WKTCL = 0x01;  // 低字节		 
_nop_();
_nop_();    
_nop_();
_nop_();



PCON |= 0x02;     //MCU进入掉电模式
_nop_();
_nop_();     
_nop_();
_nop_();    
_nop_();
_nop_();

GPIO_Init(); 
Check();      // 系统自检

//					ES = 1;        // 开串口中断


}



 
/*----------- duanan ------------*/
void duanan()

{
		beep = 1;         // 蜂鸣器鸣响
		 Delay_ms(100);
		 beep = 0;         // 关闭蜂鸣器
		
		if (buz == 1)
		{
		
		 	buz = 0;  // 开关蜂鸣器
			mut = 1;
		}
		else
		{
			if(btoff == 1)
			{
				btoff=0;
				UartInit();   // 初始化UART
			    ES = 1;       // 使能串口中断
		
			}
			else
			{
				btoff = 1;
		
				TR1 = 0;     // 关定时器1
				ES = 0;        // 关串口中断
		
				buz = 1;
				mut = 0;
		
		
		
			}

       }

}


 
/*----------- anjian ------------*/
void anjian()
{

 
         if (!key) 
		{
			Delay_ms(10);
			time = 0;
		    while (!key) 
			{
				Delay_ms(10);
				if (time < 200) time++;

				if (key)
				{

					if (time == 200)
					{
					 	changan();
					}
	
				
	
					else
					{
		
						if (time > 50)
						 {
						    liangmiao();
		
		
						 }
					 
						 else
						 {
							duanan() ;
			
						 }
					 }
				}

			}
		 time = 0;


        }


}









/*----------- 自定义strcmp函数 ------------*/
u8 bijiao(u8 *s1, u8 *s2)
{
    while (*s1 && *s2 && (*s1 == *s2))
    {
        s1++;
        s2++;
    }
    return (*s1 - *s2); // 返回0表示字符串相等
}




/********************* INT0中断函数 *************************/
void INT0_Isr () interrupt 0      //进中断时已经清除标志
{
anjian();
}

