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

📄 18b20_1602.c

📁 这是用于1602初始化的程序
💻 C
字号:
#include <at89x52.h>
#include <absacc.h>
#include <intrins.h>
#include <math.h>
#include <stdio.h>

#define  uchar  unsigned char 
#define  uint   unsigned int 

#define  LCD_COMMAND  0	 //1602写命令或数据参数
#define  LCD_DATA     1

#define  RS  P2_0	//1602控制端口
#define  RW  P2_1
#define  EN  P2_2 

#define DBport  P0 //1602数据命令口

#define DO   P1_0  //18b20总线接口


uchar temp_l = 0;  //温度值存储低位字节
uchar temp_h = 0;  //温度值存储高位字节

uchar tempsign = 0;  //温度值符号位
uchar temp_integer[4]; //温度整数存储数组
uchar temp_dicimal[5]; //温度小数存储数组

/*延时以ms为单位的t时间*/
void Delay(uint t)
{
  uint i;
  while(t--)
   {
    for(i=0; i<125; i++)
	 { }
   }
}

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

等待程序

**********************************************************/
uchar LCD_Wait(void)
{
 RS = 0;
 RW = 1;			   _nop_();
 EN = 1;			   _nop_();
 //while(DBport & 0x80); _nop_();
 EN = 0;			   _nop_();

 return DBport;
}

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

写指令/数据

**********************************************************/
LCD_Write(bit style, uchar input)
{
 RW = 0;
 RS = style;
 EN = 0;          _nop_();
 DBport = input;  _nop_();
 EN = 1;		  _nop_();
 EN = 0;		  _nop_();

 LCD_Wait();
}


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

设置屏幕初始模式

**********************************************************/
#define LCD_SHOW			0x0C    //显示开
#define LCD_HIDE			0x08    //显示关	  

#define LCD_CURSOR			0x0A 	//显示光标
#define LCD_NO_CURSOR		0x08    //无光标		     

#define LCD_FLASH			0x09    //光标闪动
#define LCD_NO_FLASH		0x08    //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)
{
  LCD_Write(LCD_COMMAND, DisplayMode);	
}


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

设置写完1byte数据后显示模式(输入每个字符后屏幕变化)

**********************************************************/
#define LCD_CURSOR_LEFT     0x04    //每写完一个字节光标左移,且AC减1
#define LCD_CURSOR_RIGHT    0x06	//每写完一个字节光标右移,且AC加1

#define LCD_CHAR_RIGHT      0x05   //每写完一个字节字符右移
#define LCD_CHAR_LEFT       0x07   //每写完一个字节字符左移

void LCD_Setinput(unsigned char InputMode)
{
 LCD_Write(LCD_COMMAND, InputMode);
}


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

设定显示功能

**********************************************************/
#define  LCD_DISPLAY_FUNCTION   0x38  //8位两行显示,5×7字型

void LCD_Setfunction(unsigned char Display_function)
{
 LCD_Write(LCD_COMMAND, Display_function);
}    

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

做完上面的设置,现在可以初始化LCD了

**********************************************************/
#define LCD_SCREEN_CLEAR    0x01

void Initial_LCD(void)
{
  EN = 0;

  LCD_Setfunction(LCD_DISPLAY_FUNCTION);
  LCD_Setfunction(LCD_DISPLAY_FUNCTION);
  //这几句顺序很重要,我随便改变了一下,竟然就没有显示了
  LCD_SetDisplay(LCD_SHOW | LCD_NO_CURSOR);
  LCD_Write(LCD_COMMAND, LCD_SCREEN_CLEAR);
  LCD_Setinput(LCD_CURSOR_RIGHT);
   
}


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

令字符左移

*********************************************************
#define  SCREEN_RIGHT_MOVE  0x18
#define  SCREEN_LEFT_MOVE   0x1C
void LCD_SCREEN_MOVE(uchar Move_Director)
{
 LCD_Write(LCD_COMMAND, Move_Director);
}*/


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

设定显示位置程序(即字符在什么位置显示出来)

**********************************************************/
void GotoXY(uchar x, uchar y)
{
 if(y == 0)
  {LCD_Write(LCD_COMMAND, 0x80|x);}	       //1602地址为第一行00H~0FH,第二行为40H~4FH,
 if(y == 1)							       //而且写入地址命令格式为1xxx xxxx,
  {LCD_Write(LCD_COMMAND, 0x80|(x-0x40));} //所以这里的0x80|(x-0x40)就是如此得出
}


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

写字符程序

**********************************************************/
void Print(uchar *str, uchar j)
{
 uchar i = 0;
 for(i=0; i<j; i++)
  {
    LCD_Write(LCD_DATA, *str);
	str++;
  }
}


/*us级延时,延时时间约4+2*i*/
void Delayus(uchar i)
 {
  while(--i);
 }

/*产生复位脉冲,等待应答信号*/
bit Resetpaulse()
{

 DO = 0; //拉低约600us
 Delayus(150);
 Delayus(150);

 DO = 1;//产生上升沿,延时约15~60us
 Delayus(30);

 return(~DO); //等待应答信号

} 

/*读取数据一位*/
bit Readbit()
{
 uint i = 0;
 bit b = 0;

 DO = 0; //产生读时隙  
 i++;	 //维持低电平至少1us

 DO = 1; //1us以上后拉高
 Delayus(2); //延时8us,DO下降沿15内ds18b20输出的数据才有效


 b = DO; //读取数据
 Delayus(40);	 //每个读时隙至少持续60us

 return(b);
} 

/*读取一个字节*/
uchar Readbyte()
{
 uchar byte_read = 0;
 uchar i, j;

 for(i=0; i<8; i++)
  {
   j = Readbit();
   byte_read = (j<<i) | byte_read; //低位读起
  }

 return(byte_read);
} 

/*写一个字节*/
void Writebyte(uchar byte_to_write)
{
 uchar i = 0;
 uchar j = 0;
 bit write_bit = 0;

 for(j=0; j<8; j++)
  {
   write_bit = 	(byte_to_write & 0x01);
    if(write_bit == 1) //写1
	 {
	  DO = 0;  //产生写时隙
	  Delayus(3);	   //延时15us
	  
	  DO = 1;  //写1
	  Delayus(40);   //延时,写时隙不得低于60us
	 }
	else
	 {
	  DO = 0;  //产生写时隙
	  Delayus(50);   //延时,保持低约60us~120us 
	  DO = 1;  
	  i++;
	 }
   byte_to_write = byte_to_write >> 1;
  }
}


/*启动温度转换*/
void StartConvert()
{
 Resetpaulse();	  // 发出复位脉冲,每次操作都从复位开始
 Delay(1);
 EA = 0;
 Writebyte(0xcc); //skip room命令
 Writebyte(0x44); //启动温度转换命令
 EA = 1;
}

/*读取温度值*/
void ReadTempreture()
{
 EA = 0;
 Resetpaulse();	  // 发出复位脉冲,每次操作都从复位开始
 Delay(1);
 Writebyte(0xcc); //skip room命令
 Writebyte(0xbe); //读取暂存器命令
 temp_l = Readbyte(); //存储温度低字节值 (整数部分低四位和小数部分)
 temp_h	= Readbyte(); //存储温度高字节值 (其中高五位为符号位)
 EA = 1;
}

/*数据处理程序*/
void Digital_process()
{
 uchar total = 0;
 uchar low = 0;
 uint  dicimal = 0;

 tempsign = (temp_h >> 7) & 0x01; //得出符号位
 total = ((temp_h << 4)&0xf0) | ((temp_l >> 4)&0x0f); //取整数位
 low =  temp_l & 0x0f; //取小数位

 if(tempsign == 0)
  {
   temp_integer[0] = total / 100 + '0'; //计算百、十、个位	 	  
   temp_integer[1] = (total%100)/10 + '0';
   temp_integer[2] = (total%100)%10 + '0'; 
   temp_integer[3] = '\0';
    if(temp_integer[0] == '0')
	 {
	   if(temp_integer[1] != '0')
		{
	     temp_integer[0] = '\0'; //百位零消隐
	     
	     }
	   else if(temp_integer[1] == '0')
	    {
		 temp_integer[0] = '\0';  //百位,十位零都消隐
		 temp_integer[1] = '\0';
		 }
	 }
   dicimal = low * 625;	         //计算小数
   temp_dicimal[0] = dicimal / 1000 + '0';	//十分位
   temp_dicimal[1] = dicimal % 1000 /100 + '0';	 //百分位
   temp_dicimal[2] = dicimal % 100 / 10 + '0';	 //千分位
   temp_dicimal[3] = dicimal % 10 + '0';		//万分位
   temp_dicimal[4] = '\0'; 	  //数组加一个空字符(好像系统也会自动加上的?)
  }

  else if(tempsign == 1)	  //负数处理
  {
   if(low == 0x00)		//负数要取反加一再乘以0.0625就是实际温度值了,我这里没有设那么多int型变量,
     {
	  total = ~total + 1;  //所以就用了这么一个计算方法
	  low &= 0x0f;
	  }				   /*具体一点讲,小树低四位为全零时取反加一要有进位,此时只要整数位取反加一即可,
                         小数位不用理会,其余情况整数位取反,小数位取反加一*/
   else
     {
	  total = ~total ;
	  low = (~low) + 1;
	  low &= 0x0f;	  //注意高四位要变成零
	  }	 	  
   temp_integer[1] = (total%100)/10 + '0'; //计算十、个位
   temp_integer[2] = (total%100)%10 + '0'; 
   temp_integer[3] = '\0';


   if(temp_integer[1] == '0')
    {
	 temp_integer[1] = '\0';
    }
   dicimal = low * 625;
   temp_dicimal[0] = dicimal / 1000 + '0';
   temp_dicimal[1] = dicimal % 1000 /100 + '0';
   temp_dicimal[2] = dicimal % 100 / 10 + '0';
   temp_dicimal[3] = dicimal % 10 + '0';
   temp_dicimal[4] = '\0';
  }
 

}



void main()
{
 bit palse = 0;
 Initial_LCD();

 GotoXY(0,0);
 Print("CHECKING...",12);
 Delay(3000);
 

 palse = Resetpaulse();	  //检测DS18B20是否响应
 if(palse)
  {
   Initial_LCD();
   GotoXY(0,0);
   Print("DS18B20 OK",11);
   }
 else
   {
   Initial_LCD();
   GotoXY(0,0);
   Print("DS18B20 ERROR",13);
   while(1);

   } 
 
 do{
   Delay(1);
   StartConvert();
   Delay(1020);
   ReadTempreture();
   Digital_process();

   if(tempsign == 0)     //显示正值温度
   {
     GotoXY(0,1);
	 Print("TEMP:",5);
	 GotoXY(5,1);
     Print(temp_integer,3);
     GotoXY(8,1);
     Print(".",1);
     GotoXY(9,1);
     Print(temp_dicimal,4);
	}
   else				     //显示负值温度
    {
	 GotoXY(0,1);
	 Print("TEMP:",5);
	 GotoXY(5,1);
	 Print("-",1);
	 GotoXY(6,1);
     Print(temp_integer + 1,2);
     GotoXY(8,1);
     Print(".",1);
     GotoXY(9,1);
     Print(temp_dicimal,4);
	}
   }
 while(1); 
}

⌨️ 快捷键说明

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