⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shiyan4.c

📁 添加按键功能
💻 C
字号:
/**********************************************/
//
//        单个DS18B20数字温度计测温C程序
//    (测温范围-30~110℃,误差在±0.0625℃)
//             2008.5.2通过调试
/**********************************************/
#include<math.h>       /*数学函数库*/
#include<absacc.h>     /*绝对地址访问函数*/
#include<intrins.h>    /*内部函数*/
#include"C8051F040.h"  /*C8051F040头文件*/

#define Decoding 0x09     /*译码模式*/
#define Brightness 0x0A   /*亮度*/
#define BoundaryScan 0x0B /*扫描界限*/
#define Brownout 0x0C     /*掉电模式*/
#define DisplayTest 0x0F  /*显示测试*/
//#define tempp 0x00
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;

//显示部分
uchar xdata dispbuff[7];
//uchar xdata pbuff[7];
uchar bit_sym=0,bit_int,bit_dec,bit_all;    /*符号位,整数位,小数位及全部位数*/
float xdata part_dec;             /*小数部分*/
ulong xdata part_int,part_dec_int;/*整数部分和小数部分取整*/
uchar num[13]={0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B,0x00,0xFF,0x01};/*从0~9及全灭,全亮和"-"*/
sbit dis_LOAD=P3^2; /*MAX7219 Load-Data Input: rising edge*/
sbit dis_DIN=P3^0;  /*MAX7219 Serial-Data Input: rising edge*/
sbit dis_CLK=P3^3;  /*MAX7219 Serial-Clock Input: maximum 10MHz*/

//DS18B20数据输入端定义
sbit DQ=P6^7;
sbit k1=P3^4;
sbit k2=P3^5;
sbit k3=P3^6;
uchar key=0;
bit enflash=0;
uchar n=0;
uchar tempp=20;
uchar h;
uchar l;
//uchar code tempp;

//延时纳秒
void delayns(void) 
{
   	  _nop_();
      _nop_();
      _nop_();
      _nop_();
}

//传送1字节(8位)
void SendChar (uchar ch)
{
    uchar i,temp;
    dis_CLK=0;
    for (i=0;i<8;i++)
    {
        temp=ch&0x80;
        ch=ch<<1;
        if(temp)
        {
            dis_DIN=1;
            delayns();
            dis_CLK=1;
            delayns();
            dis_CLK=0;
        }
        else
        {
            dis_DIN=0;
            delayns();
            dis_CLK=1;
            delayns();
            dis_CLK=0;
        }
    }
}

//向MAX7219写入字(16位)
void WriteWord (uchar addr,uchar num)
{
    dis_LOAD=0;
    delayns();
    SendChar(addr);
    delayns();
    SendChar(num);
    delayns();
    dis_LOAD=1;
    delayns();
}

//数值显示
void dis_result()
{
    WriteWord(0x01,dispbuff[5]);
    WriteWord(0x02,dispbuff[4]);
    WriteWord(0x03,dispbuff[3]);
    WriteWord(0x04,dispbuff[2]);
    WriteWord(0x05,dispbuff[1]);
    WriteWord(0x06,dispbuff[0]);
}

//利用递归法实现指数运算
ulong power(ulong number,uint index)reentrant
{                                        
     ulong result;
     if(index==0) result=1;
     else result=number*power(number,index-1);
     return(result);
}

//数值计算
void disp(float f)
{
    int i,j;
    if(f<0.0)
    {
     bit_sym=1;
     f=-f;
    }
    part_int=(long)f;
    part_dec=f-(float)part_int;
    part_dec_int=(long)(part_dec*100000);/*小数部分取整*/
    bit_dec=5;/*小数部分的最多位数*/
    bit_int=1;/*整数部分的最少位数*/
    bit_all=1;/*总显示的最少位数*/
    //计算小数位数
    for(i=1;i<=5;i++)
    {
     if(part_dec_int%(power(10,i))==0)
     bit_dec=bit_dec-1;
    }
    //计算整数位数
    for(i=0;i<=5;i++)
    {
     if(part_int>=power(10,i))
     bit_int=i+1;
    }
   //总的显示位数最多为6
    if(bit_dec+bit_int+bit_sym>6) 
    bit_dec=6-bit_int-bit_sym;
   //总的有效显示位数
    bit_all=bit_sym+bit_int+bit_dec;
   //不足位小数位后添零
    if(6-bit_all>0)
    bit_dec=6-bit_int-bit_sym;
   //总的显示位数
    bit_all=bit_sym+bit_int+bit_dec;
   //显示小数位
    if(bit_dec>0)
    {
     for(i=bit_dec-1,j=5;i>=0,j>=1;i--,j--)
     {
      dispbuff[i]=num[(part_dec_int%(power(10,j)))/(power(10,j-1))];
	  //dispbuff[i]=num[pbuff[i]];
/*该语句实现对各位的求取*/
     }
    }
   //显示整数位
   for(i=bit_all-bit_sym-1,j=bit_int;i>=bit_dec,j>=1;i--,j--)
   {
    dispbuff[i]=num[(part_int%(power(10,j)))/(power(10,j-1))];
	//dispbuff[i]=num[pbuff[i]];
   }
  //显示符号位
   if(bit_sym==1)
   dispbuff[bit_all-1]=12;
  //小数点位置
   if(bit_dec>0)     
   dispbuff[bit_dec]=dispbuff[bit_dec]+0x80;
}

//延时
void Delay1us(uchar us)
{
     while(us)
     {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        --us;
      }
}

//延时15uS
void Delay15us(void)   
{
      Delay1us(15);
}

void Delay10us(void)
{
      Delay1us(10);
}

//返回0,有设备连接;返回1,无设备连接
bit RstDS18B20(void)
{
     uchar i;
     bit RstFlag=1;
     DQ=0;
     for(i=0;i<40;i++)   /*延时480us*/
     {
         Delay15us();
     }
     DQ=1;
     for(i=0;i<4;i++)    /*延时15~60us*/
     {
         Delay15us();
     }
     for(i=0;i<16;i++)   /*延时60~240us*/
     {
         Delay15us();
         if(DQ==0) RstFlag=0;
     }
     for(i=0;i<16;i++)   /*240us*/
     {
         Delay15us();
     }
     return RstFlag;
}

void WriteDS18B20(uchar val)
{
     uchar i;
     DQ=1;
     Delay1us(1);
     for(i=0;i<8;i++)
     {
        DQ=0;
        Delay15us();
        DQ=val&0x01;
        Delay15us();Delay15us();Delay15us();
        DQ=1;
        val=val/2;
        Delay1us(1);
     }
}

uchar ReadDS18B20(void)
{
     uchar i,value=0;
     DQ=1;
     Delay1us(1);
     for(i=0;i<8;i++)
     {
        DQ=0;
        Delay1us(4);
        DQ=1;
        Delay10us();
        value>>=1;
        if(DQ==1)
        {
         value|=0x80;
        }
        Delay15us();Delay15us();Delay15us();
     }
     return(value);
}

//主机发送跳过读序列号的操作命令:0xCC
void SkipROMCode(void)
{
    RstDS18B20();
    WriteDS18B20(0xCC);
}

void StartADC(void)
{
     RstDS18B20();            /*复位*/
     WriteDS18B20(0xCC);      /*skip ROM*/
     WriteDS18B20(0x44);      /*启动温度转换12位700ms*/
}

//读取温度值的程序
float GetTempValue(void)    
{
    uchar i,j;
    float T;
    SkipROMCode();
    WriteDS18B20(0xBE);     /*发布读取温度值的命令(0xBE)*/
    i=ReadDS18B20();
    j=ReadDS18B20();
    StartADC();
    T=i+j*256;
    if(T==0xFFFF) return 0xFFFF;
    if(T>0x8000)                 /*温度为负号*/
       return((T-65536)/16.0);  /*计算温度值*/
    else                         /*温度为正*/
       return(T/16);             /*计算温度值*/
}

void InitDS18B20(void)
{
     SkipROMCode();
     WriteDS18B20(0x44);
}

void sleep_ms(uint count)
{
     int ii,jj;
     for(ii=0;ii<count;ii++)
     {
        for(jj=0;jj<250;jj++)
        _nop_();
     }
}

void ConfigC8051F040()
{
    int i;       /*延时计数器*/
//看门狗禁止
	WDTCN=0x07;  /*设置看门狗超时间隔*/	
    WDTCN=0xDE;   
    WDTCN=0xAD;
//交叉开关使能配置,使得P0~P3口能输出
	SFRPAGE=0x0F;
    XBR0=0x00;	
	XBR1=0x00;	
	XBR2=0x40;
 	XBR3=0x00;   
//管脚输出配置
 	SFRPAGE=0x0F;
    P3MDOUT=0x0F; /*P3[3:0]推挽输出,用以显示部分*/ 
//晶振配置
    SFRPAGE=0x0F;
    OSCXCN=0x77;  
 /*配置为外部石英晶振2分频模式,且配置相应频率的驱动电流*/
	for(i=0;i<256;i++);   /*等待外部晶振稳定*/
	while(!(OSCXCN & 0x80)); 
/*查询XTLVLD是否为1,若为1,表明外部晶振稳定,可切换到外部时钟*/
    CLKSEL=0x01;    /*选择外部晶振*/
    OSCICN=0x00;    /*将内部晶振关闭,也可不关闭,不关闭时MCU耗能高*/
    
}
//MAX7219初始化
void InitDis (void)
{
	WriteWord(Brownout,0x00);     /*设置电源工作模式*/
	WriteWord(BoundaryScan,0x06); /*设置扫描界限*/
	WriteWord(Brightness,0x05);    /*设置亮度*/
	WriteWord(Decoding,0x00);     /*设置译码模式*/
    WriteWord(DisplayTest,0x00);   /*设置非测试模式*/
	WriteWord(Brownout,0x01);    /*设置电源工作模式*/
}
void flashtempp(uchar input_date)
{
    uchar xdata *pDate=0x00;
	//pDate=0x00;
	FLSCL=0x01;
	PSCTL|=0x07;             
	*pDate=0x01;
    PSCTL=0x05;
	*pDate=input_date;
    PSCTL=0x04;
    FLSCL=0x00;

}
uchar flash_read(void)
{
    uchar xdata *pDate=0x00;
	uchar t;
//    PSCTL=0x04;
	t=*pDate;
    PSCTL=0x00;
	return t;
}

void KeyScan(void)
{
    bit k;
	k=k1&k2&k3;
	if(!k)
	{
	   if(k1==0)
	   {
	      sleep_ms(100);
		  if(k1==0)do{}while(!k1);

		  key=1;
		  return;	   
	   }
	   if(k2==0)
	   {
	      sleep_ms(100);
	      if(k2==0)do{}while(!k2);
		  key=2;
		  return;
	   }
	   if(k3==0)
	   {
	      sleep_ms(100);
		  if(k3==0)do{}while(!k3);
		  key=3;
		  return;
	   }	
	}
}

void eflash(void)
{
    
	if(enflash)
	{
	   switch(n)
	   {
	      case 1:WriteWord(1,num[h]);
	             sleep_ms(400);
	             WriteWord(1,0x00);
				 sleep_ms(400);
				 break;
          case 2:WriteWord(2,num[l]);
	             sleep_ms(400);
	             WriteWord(2,0x00);
				 sleep_ms(400);
				 break;
		}
	}
}
void k1_handle(void)
{
	n++;
    key=0;
	if(n==3)enflash=0;
	else enflash=1;
}
void k2_handle(void)
{
    key=0;
	switch(n)
	{
	    case 1:h++;
		       if(h==0x0a)h=0x00;
			   //tempp+=10;
			   break;
        case 2:l++;
		       if(l==0x0a)l=0x00;
			   //tempp+=1;
	           break;
	 }
}
void k3_handle(void)
{
    key=0;
	switch(n)
	{
	    case 1:if(h==0)h=9;
		       else h--;			   
			   break;
	    case 2:if(l==0)l=9;
		       else l--;			   
			   break;
	}
}
void KeyProcess(void)
{
    KeyScan();
	if(key==1)
	{	
	   disp(tempp);
	   dis_result();   
	      do
		  {
		     tempp=h*10+l;
             
		     WriteWord(0x01,num[h]);
			 WriteWord(0x02,num[l]);     
			 k1_handle();
			 if(n==3)	
			 {
			    n=0;
				break;
			 } 			 	 			 			 			 			    						    			  		
             do
		     {              		     			 			    
				eflash();
				KeyScan();			  
				switch(key)
				{
				    case 1:break;
					case 2:k2_handle();
					       do
						   {
						      eflash();
							  KeyScan();
						   }while(key==0);
						   break;
                    case 3:k3_handle();
					       do
						   {
						      eflash();
							  KeyScan();
						   }while(key==0);
						   break;								
				 }
				}while(key!=1);		  	   
	      }while(n!=3);
		  return;	       	
   	   
	}

}

main()
{
    float temp;
    ConfigC8051F040();
    WriteWord(0x07,0x04);/*LED灯显示*/
    InitDis();
    InitDS18B20();
    //flashtempp(20);
    for(;;)            
    {
       tempp=flash_read();
	   h=tempp/10;
	   l=tempp%10;
	   sleep_ms(250);
	   sleep_ms(250);
	   sleep_ms(250);
       temp=GetTempValue();
       disp(temp);
       dis_result();
	   KeyProcess();
       flashtempp(tempp);
       sleep_ms(250);
       sleep_ms(250);
       _nop_();
       sleep_ms(250);
       sleep_ms(250);
    }
}
//***************************结束*******************************//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -