【分享】 STM32 DS18B20 程序

admin 2017-5-24 4460


论坛好像没有STM32 驱动DS18B20 的程序,分享一个找到的程序。

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

假如 返回值为 0x1504 那么温度即 21.4。 0x15=16+5=21  0x04=4    21.4 ℃。 

程序调用方法:
1
2
3
4
5
6
7
8
9
int main(void)
{
        unsigned int value;
                ds18b20_init();
        while(1)
        {        
                value = ds18b20_read();
                }
}

DS18B20.C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#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为正负位
}

DS18B20.H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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



最新回复 [0]
返回