单片机
返回首页

STM32驱动DS18B20温度传感器例程(OLED显示)

2025-02-07 来源:jianshu

DS18B20温度显示效果


第一部分:DS18B20温度模块驱动代码[头文件](DS18B20.h)

#ifndef __DS18B20_H__

#define __DS18B20_H__

 

#include'stm32f10x.h'

 

 

#define  SkipROM    0xCC     //跳过ROM

#define  SearchROM  0xF0  //搜索ROM

#define  ReadROM    0x33  //读ROM

#define  MatchROM   0x55  //匹配ROM

#define  AlarmROM   0xEC  //告警ROM

 

#define  StartConvert    0x44  //开始温度转换,在温度转换期间总线上输出0,转换结束后输出1

#define  ReadScratchpad  0xBE  //读暂存器的9个字节

#define  WriteScratchpad 0x4E  //写暂存器的温度告警TH和TL

#define  CopyScratchpad  0x48  //将暂存器的温度告警复制到EEPROM,在复制期间总线上输出0,复制完后输出1

#define  RecallEEPROM    0xB8    //将EEPROM的温度告警复制到暂存器中,复制期间输出0,复制完成后输出1

#define  ReadPower       0xB4    //读电源的供电方式:0为寄生电源供电;1为外部电源供电

 

 

void ds18b20_init(void);

unsigned short ds18b20_read(void);

 

 

#endif


第二部分:DS18B20温度模块驱动代文件(DS18B20.c)


#include 'ds18b20.h'

 

#define EnableINT()  

#define DisableINT()

 

#define DS_PORT   GPIOA

#define DS_DQIO   GPIO_Pin_1

 

#define DS_RCC_PORT  RCC_APB2Periph_GPIOA

 

#define DS_PRECISION 0x7f   //精度配置寄存器 1f=9位; 3f=10位; 5f=11位; 7f=12位;

#define DS_AlarmTH  0x64

#define DS_AlarmTL  0x8a

#define DS_CONVERT_TICK 1000

 

#define ResetDQ() GPIO_ResetBits(DS_PORT,DS_DQIO)

#define SetDQ()  GPIO_SetBits(DS_PORT,DS_DQIO)

#define GetDQ()  GPIO_ReadInputDataBit(DS_PORT,DS_DQIO)

 

 

static unsigned char TempX_TAB[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};

 

 

void Delay_us(u32 Nus) 

{  

 SysTick->LOAD=Nus*9;          //时间加载       

 SysTick->CTRL|=0x01;             //开始倒数     

 while(!(SysTick->CTRL&(1<<16))); //等待时间到达  

 SysTick->CTRL=0X00000000;        //关闭计数器 

 SysTick->VAL=0X00000000;         //清空计数器      

 

 

 

unsigned char ResetDS18B20(void)

{

 unsigned char resport;

 SetDQ();

 Delay_us(50);

 

 ResetDQ();

 Delay_us(500);  //500us (该时间的时间范围可以从480到960微秒)

 SetDQ();

 Delay_us(40);  //40us

 //resport = GetDQ();

 while(GetDQ());

 Delay_us(500);  //500us

 SetDQ();

 return resport;

}

 

void DS18B20WriteByte(unsigned char Dat)

{

 unsigned char i;

 for(i=8;i>0;i--)

 {

   ResetDQ();     //在15u内送数到数据线上,DS18B20在15-60u读数

  Delay_us(5);    //5us

  if(Dat & 0x01)

   SetDQ();

  else

   ResetDQ();

  Delay_us(65);    //65us

  SetDQ();

  Delay_us(2);    //连续两位间应大于1us

  Dat >>= 1; 

 } 

}

 

 

unsigned char DS18B20ReadByte(void)

{

 unsigned char i,Dat;

 SetDQ();

 Delay_us(5);

 for(i=8;i>0;i--)

 {

   Dat >>= 1;

    ResetDQ();     //从读时序开始到采样信号线必须在15u内,且采样尽量安排在15u的最后

  Delay_us(5);   //5us

  SetDQ();

  Delay_us(5);   //5us

  if(GetDQ())

    Dat|=0x80;

  else

   Dat&=0x7f;  

  Delay_us(65);   //65us

  SetDQ();

 }

 return Dat;

}

 

 

void ReadRom(unsigned char *Read_Addr)

{

 unsigned char i;

 

 DS18B20WriteByte(ReadROM);

  

 for(i=8;i>0;i--)

 {

  *Read_Addr=DS18B20ReadByte();

  Read_Addr++;

 }

}

 

 

void DS18B20Init(unsigned char Precision,unsigned char AlarmTH,unsigned char AlarmTL)

{

 DisableINT();

 ResetDS18B20();

 DS18B20WriteByte(SkipROM); 

 DS18B20WriteByte(WriteScratchpad);

 DS18B20WriteByte(AlarmTL);

 DS18B20WriteByte(AlarmTH);

 DS18B20WriteByte(Precision);

 

 ResetDS18B20();

 DS18B20WriteByte(SkipROM); 

 DS18B20WriteByte(CopyScratchpad);

 EnableINT();

 

 while(!GetDQ());  //等待复制完成 ///

}

 

 

void DS18B20StartConvert(void)

{

 DisableINT();

 ResetDS18B20();

 DS18B20WriteByte(SkipROM); 

 DS18B20WriteByte(StartConvert); 

 EnableINT();

}

 

void DS18B20_Configuration(void)

{

 GPIO_InitTypeDef GPIO_InitStructure;

 

 RCC_APB2PeriphClockCmd(DS_RCC_PORT, ENABLE);

 

 GPIO_InitStructure.GPIO_Pin = DS_DQIO;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //2M时钟速度

 GPIO_Init(DS_PORT, &GPIO_InitStructure);

}

 

 

void ds18b20_init(void)

{

 DS18B20_Configuration();

 DS18B20Init(DS_PRECISION, DS_AlarmTH, DS_AlarmTL);

 DS18B20StartConvert();

}

 

 

unsigned short ds18b20_read(void)

{

 unsigned char TemperatureL,TemperatureH;

 unsigned int  Temperature;

 

 DisableINT();

  ResetDS18B20();

 DS18B20WriteByte(SkipROM); 

 DS18B20WriteByte(ReadScratchpad);

 TemperatureL=DS18B20ReadByte();

 TemperatureH=DS18B20ReadByte(); 

 ResetDS18B20();

 EnableINT();

 

 if(TemperatureH & 0x80)

  {

  TemperatureH=(~TemperatureH) | 0x08;

  TemperatureL=~TemperatureL+1;

  if(TemperatureL==0)

   TemperatureH+=1;

  }

 

 TemperatureH=(TemperatureH<<4)+((TemperatureL&0xf0)>>4);

 TemperatureL=TempX_TAB[TemperatureL&0x0f];

 

 //bit0-bit7为小数位,bit8-bit14为整数位,bit15为正负位

 Temperature=TemperatureH;

 Temperature=(Temperature<<8) | TemperatureL; 

 

 DS18B20StartConvert();

 

 return  Temperature;

 //返回16位数据  bit0-bit7为小数位,bit8-bit14为整数位,bit15为正负位

}


经过测试,通讯正常,温度读取正确。。 注意程序的读取函数,返回值的说明喔。 我之前没仔细分析,把返回值乘以0.0625....结果不对。后来发现,返回的值,已经是温度的16进制形式。


假如 返回值为 0x1504 那么温度即 21.4。 0x15=16+5=21  0x04=4    21.4 ℃。
程序调用方法:


int main(void)

{

        unsigned int value;

                ds18b20_init();

        while(1)

        {       

                value = ds18b20_read();

                }

}


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 1瓦四级调频发射机

  • 500W MOS场效应管电源逆变器,12V转110V/220V

  • 红外开关

  • LM317过压保护

  • 0-30V/20A 大功率稳压电源(采用LM338)

    相关电子头条文章