【驱动】DS18B20
前言
DS18B20,单总线,它已经有定义好的初始化、写数据、读数据的时序图和一些需要使用的指令。驱动的关键,是writebit和readbit两个函数的时序。
1、初始化
说明:在初始化单片机的IO的输入输出、时钟等,把DQ引脚拉低480us后,DS18B20就会自动完成复位,之后单片机拉高DQ引脚15~60us后,检测DQ引脚,如果存在60~240us的低电平,则表示DS18B20在线并能正常工作。
2、读、写数据
说明: 读取的数据,低位在前,例如12345678,按位读出来的顺序8,7,6,5,4,3,2,1
写入的数据,也是低位在前,例如12345678,写入的顺序8,7,6,5,4,3,2,1
3、功能指令
每次进行功能指令操作前,都必须重新对DS18B20进行复位操作。
转换温度 44h
忽略ROM CCh
读取寄存器 BEh
4、驱动代码
#include "ds18b20.h" #include "stm32f10x_gpio.h" #include "delay.h" #include "lcd.h" #define GPIO_x GPIOA #define GPIO_Pin_x GPIO_Pin_0 #define DS18B20_IO_IN() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;} #define DS18B20_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;} static void Init_DQ(void); static void ds18b20_Rst(void); int ds12820_init(void); static int ds18b20_Readbit(void); static unsigned char ds18b20_Readbyte(void); static void ds18b20_Writebyte(unsigned char cmd); short ds18b20_GetTemp(void); static int ds18b20_Check(void); /* ds18b20 has 3 configs :10bits/11bits/12bits,user can ingnor the high 2 bits because they has no use except impacting its thransmission speed. Every time when you want use function command you must follow the steps below: step1: Initialization step2: ROM Command(if only 1 18b20,can skip this step) step3: ds18b20 Function Command 每一次操作均需要满足以上步骤。 例如:进行温度转换的function command后,需要再次复位,再进行读取温度的function command */ /* @brief init IO_DQ and init its value */ static void Init_DQ(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PORTA0 推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_0); //输出1 } /* step1: 拉低DQ 1us step2: 等待30us step3: 采样 */ static int ds18b20_Readbit(void){ unsigned char data=0; DS18B20_IO_OUT(); GPIO_ResetBits(GPIO_x,GPIO_Pin_x); delay_us(2); GPIO_SetBits(GPIO_x,GPIO_Pin_x); DS18B20_IO_IN(); delay_us(20); if(GPIO_ReadInputDataBit(GPIO_x,GPIO_Pin_x)) data=1; else data=0; delay_us(50);//must be return data; } /* step1:拉低1us step2:延时15us step3:读取BitVal 从低位到高位读出 */ static unsigned char ds18b20_Readbyte(void){ unsigned char i=0; unsigned char BitVal=0; unsigned char data=0; for (i=0;i<8;i++) { BitVal=ds18b20_Readbit(); data |= (BitVal<<i); } return data; } /* @brief: step1:拉低1us step2:写BitVal step3:持续60us 从低位到高位写入 */ static void ds18b20_Writebyte(unsigned char cmd){ unsigned char i=0; unsigned char BitVal=0; DS18B20_IO_OUT(); for (i=0;i<8;i++){ BitVal=cmd&0x01; cmd =cmd>>1; if(BitVal){ GPIO_ResetBits(GPIO_x,GPIO_Pin_x); delay_us(2); GPIO_SetBits(GPIO_x,GPIO_Pin_x); delay_us(60); } else{ GPIO_ResetBits(GPIO_x,GPIO_Pin_x); delay_us(60); GPIO_SetBits(GPIO_x,GPIO_Pin_x); delay_us(2); } } } /* step1: 高电平750us step2: 低电平15us */ static void ds18b20_Rst(void){ DS18B20_IO_OUT(); GPIO_ResetBits(GPIO_x,GPIO_Pin_x); delay_us(750); GPIO_SetBits(GPIO_x,GPIO_Pin_x); delay_us(15); } //@brief 低电平480us~960us,等待15~60us,DQ会变成低电平60~240us static int ds18b20_Check(void){ int i=0; int cnt=0; //检查应答 while(GPIO_ReadInputDataBit(GPIO_x,GPIO_Pin_x)!=0){ delay_us(1); } for(i=0;i<150;i++){//多次读取,防止时序抖动 if(GPIO_ReadInputDataBit(GPIO_x,GPIO_Pin_x)) cnt++; delay_us(1); } if(cnt > 60) return 1; else return 0; } //@brief init ds18b20 before get its tempreture int ds12820_init(void){ ds18b20_Rst(); if(ds18b20_Check() == 1) return 1; else return -1; } /* step1:init step2:ROM Command(skip) step3:ds18b20 Function Command */ short ds18b20_GetTemp(void){ unsigned char TL=0; unsigned char TH=0; short temp=0; Init_DQ(); ds12820_init(); ds18b20_Writebyte(0xCC);// skip rom ds18b20_Writebyte(0x44);// convert delay_ms(800); ds12820_init(); ds18b20_Writebyte(0xCC);// skip ROM ds18b20_Writebyte(0xBE);//read RAM TL=ds18b20_Readbyte(); // LSB TH=ds18b20_Readbyte(); // MSB if(TH>7){ TH=~TH; TL=~TL; temp=-(float)((TH<<8)+TL+1)*0.625; } else temp=(float)((TH<<8)+TL)*0.625; return temp; } //end