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

📄 wend.c

📁 单片机控制的数字温度计程序源码
💻 C
字号:
#include<reg52.H>		   //使用1602LCD显示DS18B20转换的温度值,12MHz,程序已经好使
#include<intrins.H>
#include<math.H>

#define uchar unsigned char		//定义无符号字符为 uchar,方便书写
#define uint unsigned int

sbit RS=P3^3; //  数据/命令选择端(H/L)
sbit LCDEN=P3^5;//使能端,RW读写端接地



void delayUs()
{
  _nop_();
}
//写命令:RS=0, RW=0;
//第一行开始地址为0x80, 第二行开始地址为0xc0;
void delayMs(uint a)
{
 uint i,j;
for(i=a;i>0;i--)
  for(j=100;j>0;j--);
}


void writeComm(uchar comm)
{
 RS=0;
 P1=comm;
 LCDEN=1;
delayUs();
 LCDEN=0;
 delayMs(1);
}
// 写数据:RS=1, RW=0;
void writeData(uchar dat)
{
 RS=1;
 P1=dat;
 LCDEN=1;
 delayUs();
 LCDEN=0;
 delayMs(1);
}
//初始化
void init()
{

 writeComm(0x38);  //显示模式,固定指令为00111000=0x38, 16*2显示, 5*7点阵,8位数据接口
 writeComm(0x0c);  //开显示, 关光标,指令1: 00001DCB : D:开显示/关显示(H/L);
				   //C:显示光标/不显示(H/L), B:光标闪烁/不闪烁(H/L)
  writeComm(0x06);  //写字符后地址加1, 光标加1
 writeComm(0x01);  //清屏
}

void writeString(uchar * str,uchar length)
{
 uchar i;
 for(i=0;i<length;i++)
 {
 writeData(str[i]);
 }
}

sbit ds=P3^7;
//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
//初始化DS18B20
void dsInit()
{
 unsigned int i;  //  对于12MHz时钟, unsigned int型的i, 作一个i++操作的时间大约为8us
 ds=0;
 i=100;	 //	拉低约800us, 符合协议要求的480us以上
 while(i>0)i--;	 //产生一个上升沿, 进入等待应答状态
 ds=1;
 i=4;
 while(i>0)i--;
}

void dsWait()
{
 unsigned int i;
 while(ds);
 while(~ds);//检测到应答脉冲
 i=4;
 while(i>0)i--;
}
// 向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
bit readBit()
{
 unsigned int i;
 bit b;
 ds=0;
 i++;	  //延时约8us, 符合协议要求至少保持1us
 ds=1;
 i++;i++;//延时约16us, 符合协议要求的至少延时15us以上
 b=ds;
 i=8;
 while(i>0)i--;	 //延时约64us, 符合读时隙不低于60us要求
 return b;
}
//读取一字节数据, 通过调用readBit()来实现
unsigned char readByte()
{
 unsigned int i;
 unsigned char j,dat;
 dat=0;
 for(i=0;i<8;i++)
 {
  j=readBit();	//最先读出的是最低位数据
  dat=(j<<7)|(dat>>1);
 }
 return dat;
}
//向DS18B20写入一字节数据
void writeByte(unsigned char dat)
{
 unsigned int i;
 unsigned char j;
 bit b;
 for(j=0;j<8;j++)
 {
  b=dat&0x01;
  dat>>=1;	  //写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1
  if(b)
  {
    ds=0;
   i++;i++;		  // 拉低约16us, 符号要求15~60us内
   ds=1;
    i=8;while(i>0)i--;	//延时约64us, 符合写时隙不低于60us要求
   }
   else			//写"0", 将DQ拉低60us~120us
   {
    ds=0;
    i=8;while(i>0)i--; // 拉低约64us, 符号要求
    ds=1;
    i++;i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了
    }
   }
}
// 向DS18B20发送温度转换命令
void sendChangeCmd()
{
 dsInit();			 //	初始化DS18B20, 无论什么命令, 首先都要发起初始化
 dsWait();			 //等待DS18B20应答
 delayMs(1);		 //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号
 writeByte(0xcc);	//写入跳过序列号命令字 Skip Rom
 writeByte(0x44);	// 写入温度转换命令字 Convert T
}
// 向DS18B20发送读取数据命令
void sendReadCmd()
{
 dsInit();
 dsWait();
 delayMs(1);
 writeByte(0xcc);	 //写入跳过序列号命令字 Skip Rom
 writeByte(0xbe);	 //写入读取数据令字 Read Scratchpad
}
//	  获取当前温度值
int getTmpValue()
{
 unsigned int tmpvalue;
 int value;		   //	存放温度数值
 float t;
 unsigned char low,high;
 sendReadCmd();	 //连续读取两个字节数据
 
 low=readByte();
 high=readByte();
 
 tmpvalue=high;	   // 若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value
 tmpvalue<<=8;
 tmpvalue|=low;	   //计算机中对于负数是利用补码来表示的
 value=tmpvalue;   //将高低两个字节合成一个整形变量,将高低两个字节合成一个整形变量
 t=value*0.0625;   //使用DS18B20的默认分辨率12位, 精确度为0.0625度,
				   // 即读回数据的最低位代表0.0625度
 value=t*100+(value>0?0.5:-0.5); //将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入
			       // 如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度
 				   //如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度大于0加0.5, 小于0减0.5
 return value;
}

void display(int v)
{
 unsigned char count;
 unsigned char datas[]={0,1,2,3,4};
 unsigned int tmp=abs(v);
 datas[0]=tmp/10000;		//最高位
 datas[1]=tmp%10000/1000;
 datas[2]=tmp%1000/100;
 datas[3]=tmp%100/10;
 datas[4]=tmp%10;			//最低位


 writeComm(0xc0+1);	   //0xc0=1100 0011	->DDRAM地址设置,两行显示,第二行开始地址,距头1个距离
 if(v<0)					//温度的符号判断
 {
    writeString("- ",2);	//注意符号后有一个空格
 }
 else
 {
  writeString("+ ",2);
 }
 if(datas[0]!=0)
 {
 writeData('0'+datas[0]);	//输入字符0,1,2,3,4,5,6,7,8,9
 }
 for(count=1;count!=5;count++)	//	依次显示由高到低位
 {
   writeData('0'+datas[count]);
   if(count==2)		 //两高位之后小数点
  {
    writeData('.');
   }
  }
 
  }

void main()
{
 uchar table[]="Now Temperature:";
  sendChangeCmd();	 //先放入温度传感指令再液晶驱动,将顺序执行,没有检测到温度传感则无数据输出
 init();
 writeComm(0x80);
 writeString(table,16);

 while(1)
 {
  delayMs(1000);	//温度转换时间需要750ms以上
  writeComm(0xc0);
  display(getTmpValue());
  sendChangeCmd();
  }
} 

⌨️ 快捷键说明

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