一、初始化
1.逻辑
1.主机(控制器STM32,下同)拉低电平,持续480us-960us,然后释放(拉高电平,下同)
2.等待15us-60us(在程序中给了30)//第一和第二步均为输出,但是第二部后要切换为输入模式
3.从机(DS18B20 传感器,下同)会低电平,持续时间60us-240us,//这一步是检测传感器在不在的关键一步,加上第二步释放后的时间,所以我们要在90us(30+60)-270us(30+240)内检测电平高低来判断传感器是否存在。在此时应为输入模式。
4.主机接收至少480us,所以我们检测完后还需等待时序结束,时间=480us-释放后到检测时时间
返回数值。
代码:
1.初始化代码- #include "stm32f10x.h" // Device header
- #include "main.h" //这里面没什么(除了delay函数)
-
- #define DS18B20 GPIO_Pin_15 //如果复制使用,只需改这行Pin口和下行通道还开启有时钟
- #define DS18B20_PROT GPIOB //其他代码不用更改,只需补全delay和显示函数就行
- #define DS18B20_LOW GPIO_ResetBits(DS18B20_PROT,DS18B20)
- #define DS18B20_HIGH GPIO_SetBits(DS18B20_PROT,DS18B20)
-
- void DS18B20_Init(void) //初始化函数
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启对应通道时钟
-
- GPIO_InitTypeDef GPIO_InitStruct;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStruct.GPIO_Pin = DS18B20;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(DS18B20_PROT,&GPIO_InitStruct);
- }
复制代码
2.模式切换函数,1为写/输出模式,0为读/输入模式- void DS18B20_Output_Input(u8 cmd) //输入输出模式切换,1输出,0输入/读取
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- if(cmd) //为1 是输出模式
- {
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStruct.GPIO_Pin = DS18B20;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
-
- }
- else //为0,输入模式
- {
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStruct.GPIO_Pin = DS18B20;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
-
- }
- GPIO_Init(DS18B20_PROT,&GPIO_InitStruct);
- }
复制代码
3. 初始化代码
- u8 DS18B20_Starup(void) //判断DS18B20 是否存在的一个函数
- {
- u8 data;
-
- DS18B20_Output_Input(1); //为输出模式
- DS18B20_LOW; //拉低电平
- Delay_us(480); //delay函数,需要自己写,网上资料很多,保证时间准确就行
- DS18B20_HIGH; //拉高电平,也是 释放总线
- Delay_us(100);
-
- DS18B20_Output_Input(0); //为输入模式
- data = GPIO_ReadInputDataBit(DS18B20_PROT,DS18B20); //根据时序存在返回0,不存在是1
- Delay_us(380);
-
- return data;
- }
复制代码
4.此时我们需要验证下,在main函数里进行数据显示- int main(void)
- {
- OLED_Init();
- DS18B20_Init();
-
- while (1)
- {
- OLED_ShowNum(2, 5, DS18B20_Starup(), 1);//用自己的方式验证,存在为0,否则为1
- }
- }
复制代码
如果显示0,在拔下传感器的数据线后显示为1,插入后为0.则以上代码和传感器没有问题
二、写数据和读数据
1.写时序函数
DS18B20对时序要求非常高,所以delay函数一定要精准
代码- void DS18B20_Write_Byte(u8 data) //写数据
- {
- for(u8 i=0;i<8;i++)
- {
- DS18B20_Output_Input(1);
- DS18B20_LOW;
- Delay_us(2); //拉低2us进入书写时序
- (data&0x01) ? DS18B20_HIGH:DS18B20_LOW;//从低位往高位写移位7次后将是最高位
- Delay_us(45); //延时45us
- DS18B20_HIGH; //释放总线
-
- data >>=1;
- }
- }
复制代码
2.读函数
代码:
- u8 DS18B20_Read_Byte(void) //读程序
- {
- u8 data=0;
- for(u8 i=0;i<8;i++)
- {
- data >>=1;
- DS18B20_Output_Input(1); //写时序,拉低2us后释放
- DS18B20_LOW;
- Delay_us(2); //拉低2us进入读时序
- DS18B20_HIGH;
-
- DS18B20_Output_Input(0); //进入读时序
- if((GPIO_ReadInputDataBit(DS18B20_PROT,DS18B20)) == SET)
- {
- data |= 0x80;
- }
- Delay_us(45);
- }
- return data;
- }
复制代码
三 、读取温度
逻辑:1.初始化
跳过匹配命令(0XCC)
温度转换命令(0X44)
delay750ms //注意时间单位毫秒
初始化
跳过匹配命令(0XCC)
温度读取命令(0XBE)
先读取的低8位
再读取的高8位
数据转换,二进制转换成10进制
代码:最后的代码*10,为方便显示小数- void DS18B20_Read_Temp(u16 *data)
- {
- u8 LSB=0,HSB=0;u16 Temp=0; //LSB 低位的8位数据
-
- DS18B20_Starup();
- DS18B20_Write_Byte(0xCC); //跳过匹配步骤
- DS18B20_Write_Byte(0x44); //温度转换,12位时间为750ms,注意时间单位
- Delay_ms(750);
- DS18B20_Starup();
- DS18B20_Write_Byte(0xCC);
- DS18B20_Write_Byte(0xBE); //进行数据读写
-
- LSB = DS18B20_Read_Byte(); //先读取的低8位
- HSB = DS18B20_Read_Byte(); //再读取的高8位
-
- Temp = (HSB<<8) | LSB;
-
- if((Temp&0xF800)==0xF800) //S=1为真否则位0
- {
- *data = (((~Temp + 0x01)*-0.0625))*10;//为负温度
-
- }
- else
- {
- *data = (Temp*0.0625)*10; //正温度
- }
- }
复制代码
四 ,显示数据
在main里进行显示,需要取地址操作
代码:- u16 Temp=0; //u16 类型值
-
- int main(void)
- {
- OLED_Init();
- DS18B20_Init();
-
- while (1)
- {
- DS18B20_Read_Temp(&Temp); //取值
- OLED_ShowSignedNum(2, 1, (Temp/10), 2); //整数位
- OLED_ShowString(2, 4, ".");
- OLED_ShowNum(2, 5, (Temp%10), 1);//小数位一位
- }
- }
复制代码
转载自:钜锋智联
如有侵权请联系删除
|