单片机的ds18b20程序

ds18b20对时序要求很高,所以一定要注意延时

下面是32单片机的程序

//复位DS18B20
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); 	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 	//拉低DQ
    delay_us(750);    	//延时750us
    DS18B20_DQ_OUT=1; 	//DQ=1 
	delay_us(15);     	//15US
}

//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();	//SET PG11 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}

//从DS18B20读取一位
//返回1/0
u8 DS18B20_Read_Bit(void) 	 
{
    u8 data;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 
	delay_us(2);
    DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();	//SET PG11 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)data=1;
    else data=0;	 
    delay_us(50);           
    return data;
}

//从DS18B20读取一个字节
u8 DS18B20_Read_Byte(void)     
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}

//写一个字节到DS18B20
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;	// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;	// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}

//开始温度转换
void DS18B20_Start(void) 
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0x44);	// convert
} 

//初始化DS18B20的DQ 同时检测DS18B20的存在
//返回1:不存在
//返回0:存在   	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;		
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOC, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOC,GPIO_Pin_10);    //拉高

	DS18B20_Rst();

	return DS18B20_Check();
}  

//从ds18b20得到温度值
//精度0.1C
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();  			// ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0xbe);	// convert	    
    TL=DS18B20_Read_Byte(); 	// LSB 
    TH=DS18B20_Read_Byte(); 	// MSB  
		USART_SendData(USART1, TL);
		delay_ms(10);
		USART_SendData(USART1, TH);
	   	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;					//温度为负
    }else temp=1;				//温度为正  	  
    tem=TH; 					
    tem<<=8;    
    tem+=TL;					
    tem=(float)tem*0.625;		
	if(temp)return tem; 	
	else return -tem;    
}

然后这里是51单片机的程序

这里我用的是12M晶振,延时程序如下

/*us延时,参数为1时约延时7us
			  10时约延时50us
			 100时约延时205us
			 250时约延时480us	
*/
void delay(uchar us) {
	while(us--);
}

然后下面就是对DQ信号线操作的程序

//复位ds18b20
void Init_ds18b20(void) {
	DQ = 1; 
	delay(1); 
	DQ = 0; 
	delay(250); 
	DQ = 1; 
	delay(100);
}

//读一个字节
uchar ReadoneByte() {
	uchar i;
	uchar dat = 0;
	for(i=8; i>0; i--) {
		DQ = 0;
		_nop_();
		dat >>= 1;
		DQ = 1;
		delay(1);
		if(DQ) dat |= 0x80;
		delay(10);
	}
	return dat;
}

//写一个字节
void WriteoneByte(uchar dat) {
	uchar i;
	for(i=8; i>0; i--) {
		DQ = 0;
		_nop_();
		DQ = dat & 0x01;
		delay(10);
		DQ = 1;
		dat >>= 1;
		delay(1);
	}
}

//获取温度值
int GetTempe() {
	int temp;
	uchar teml, temh;
	Init_ds18b20();
	WriteoneByte(0xcc);
	WriteoneByte(0x44);
	Init_ds18b20();
	WriteoneByte(0xcc);
	WriteoneByte(0xbe);
	teml = ReadoneByte();//先读低四位
	temh = ReadoneByte();//再读高四位
	
	temp = teml/16+temh*16;//这里只保留了整数,去掉了小数
	//temp <<= 8;
	//temp += teml;
	//t = temp * 0.625;
	return temp;
}

你可能感兴趣的:(C)