蓝桥杯CT107D之ds18b20

单总线协议简介

  1. 单总线延时函数
//单总线延时函数,此处延时函数很重要,根据自己的时钟频率而定
void Delay_OneWire(unsigned int t)  //Y5指令集,FOSC:11059200L,软件延时15us(t=1)
{
	unsigned char i;
	for(;t>0;t--)
	{
		i = 39;
		while(--i);
	}	
}
  1. 单总线写时序
    蓝桥杯CT107D之ds18b20
    蓝桥杯CT107D之ds18b20
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(2);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(2);
}
  1. 单总线读时序
    蓝桥杯CT107D之ds18b20
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(2);
	}
	return dat;
}

ds18b20初始化

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(2);
  	DQ = 0;
  	Delay_OneWire(36);
  	DQ = 1;
  	Delay_OneWire(2); 
    initflag = DQ;     
  	Delay_OneWire(6);
  
  	return initflag;
}

ds18b20读取温度函数

//读取温度
float rd_temperature(void)
{
	unsigned int temp;
	float temperature;
	unsigned char low,high;
	
	init_ds18b20();
	Write_DS18B20(0xCC);   //忽略ROM指令
	Write_DS18B20(0x44);   //启动温度转换
	Delay_OneWire(100);	   //1ms->等待温度转换  ---MAX(750ms)
	
	init_ds18b20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0xBE);   //读取寄存器

	low = Read_DS18B20();
	high = Read_DS18B20();
	/**精度为0.0625摄氏度**/
	temp = high;
	temp <<= 8;
	temp |= low;
	temperature	= (float)temp*0.0625;
	return temperature;			
}

主函数部分

  • 此处有些杂乱
#include "reg52.h"
#include "ds18b20.h"


#define FOSC 11059200L
#define T1MS (65536-FOSC/1000)      //1T模式
#define N 10

sfr AUXR = 0x8e;

sbit N_RELAY = P0^4;
sbit N_BUZZ = P0^6;
sbit LED_1 = P0^0;
sbit LED_2 = P0^1;

unsigned char code Duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极段选0~9
unsigned char code Wei[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //共阴极位选 1--8
unsigned char c[N];

unsigned char SMG_chai(unsigned int t);


float temperature = 0;
unsigned int t = 58;
unsigned char s=0,i1=0;

void T0Init()
{
	AUXR |= 0x80;                   //定时器0为1T模式
//  AUXR &= 0x7f;                   //定时器0为12T模式

    TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
    TL0 = T1MS;                     //初始化计时值
    TH0 = T1MS >> 8;
    TR0 = 1;                        //定时器0开始计时
    ET0 = 1;                        //使能定时器0中断
    EA = 1;
}

void main()
{
	
	
	T0Init();
	P2 = 0xa0; N_BUZZ=0; N_RELAY=0; P2 = 0x00;
	P2 = 0x80; P0=0xff;  P2 = 0x00;
	while(1)
	{
		if(temperature < 28)
		{
			P2 = 0x80; P0=0xff; LED_1=0; LED_2=0; P2 = 0x00;
		}
		else
		{
			P2 = 0x80; P0=0xff; LED_2=0; P2 = 0x00;
		}

		i1 = SMG_chai(temperature);
		
		//注释:锁存器真麻烦
//		P0=0x00;	P2 = 0xc0;		 P2 = 0x00;			//关闭下位选,达到消隐的目的。
		P0=0xff;    									//关闭下段选,达到消隐的目的。
		P2 = 0xe0;	P0=~Duan[c[s]];  P2 = 0x00; 
		P0=0x00;							    		//进入位选前先把P0清零,禁止选通数码管。	  
		P2 = 0xc0;	P0=~Wei[7-s];	 P2 = 0x00;
		P0=0xff;	  			
	}
}

/* Timer0 interrupt routine */
void tm0_isr() interrupt 1 
{
	static int count = 1000;

	if(s<i1)
	{
		s++;
	}
	else
	s=0;	

	
	if(count-- == 0)
	{
		count = 1000;
		temperature = rd_temperature();
	}		
}


unsigned char SMG_chai(unsigned int t)
{
	unsigned char i=0;
 	if(t<10)
	c[i]=t;
	else
	{
		while(1)
	    {
		  	c[i]=t%10;
		    t=t/10;
		    i++;
		    if(t<10)
		    break; 
	    }
	    c[i]=t;
	}
	return i;	
}


小结

  1. 程序还有许多可改进之处,欢迎各路大神批评指正。

  2. 单总线协议对时序要求严格,一定按照datasheet给的时序一步一步写;读取到错误值4095或者没有值,一定先检查时序。

  3. CT107D开发板的锁存器可能有其独到之处,首先节省了IO口,其次作为驱动使用,但是在使用之时注意何时开何时关。

  4. 写程序逻辑和时序很重要。

  5. 溜了溜了~~~

上一篇:Arduino点灯玩成这样,也是没谁了


下一篇:Python 控制220V ??? 老板,你没看错!