凌云物联网实验室ISKBoard(IoT Starter Kits Board)开发板项目源码
guowenxue
2023-04-03 32806da6f5647ac637fa7d48aa9c221b091ab35e
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
 * ds18b20.c
 *
 *  Created on: 2021年8月17日
 *      Author: Think
 */
#include "main.h"
#include "miscdev.h"
 
typedef struct w1_gpio_s
{
    GPIO_TypeDef        *group;
    uint16_t             pin;
} w1_gpio_t;
 
static w1_gpio_t   W1Dat =  /* IO pin connected to PA12 */
{
        .group = GPIOA,
        .pin   = GPIO_PIN_12,
};
 
#define W1DQ_Input()           \
{    \
        GPIO_InitTypeDef GPIO_InitStruct = {0}; \
        GPIO_InitStruct.Pin = W1Dat.pin; \
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
        GPIO_InitStruct.Pull = GPIO_PULLUP; \
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \
        HAL_GPIO_Init(W1Dat.group, &GPIO_InitStruct); \
}
 
#define W1DQ_Output()           \
{    \
        GPIO_InitTypeDef GPIO_InitStruct = {0}; \
        GPIO_InitStruct.Pin = W1Dat.pin; \
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
        GPIO_InitStruct.Pull = GPIO_NOPULL; \
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \
        HAL_GPIO_Init(W1Dat.group, &GPIO_InitStruct); \
}
 
#define W1DQ_Write(x)    HAL_GPIO_WritePin(W1Dat.group, W1Dat.pin, \
                        (x==1)?GPIO_PIN_SET:GPIO_PIN_RESET)
 
#define W1DQ_Read()     HAL_GPIO_ReadPin(W1Dat.group,  W1Dat.pin)
 
 
/* Master issues reset pulse and DS18B20s respond with presence pulse */
uint8_t ds18b20_reset(void)
{
    uint8_t            rv = 0;
    uint8_t            retry;
 
    /* Setup W1 DQ pin as output and high level*/
    W1DQ_Output();
    W1DQ_Write(1);
    delay_us(2);
 
    /* Reset pulse by pulling the DQ pin low >=480us */
    W1DQ_Write(0);
    delay_us(480);
 
    /* Master releases bus to high. When DS18B20 detects this rising edge, it waits 15µs to 60µs */
    W1DQ_Write(1);
    delay_us(60);
 
    /* Then DS18B20 transmits a presence pulse by pulling the W1 bus low for 60µs to 240µs */
    while( W1DQ_Read() && retry <240)
    {
        retry++;
        delay_us(1);
    }
 
    if(retry >= 240)
        rv = 1;
 
    delay_us(240);
 
    /* Master Rx time must >= 480us */
    W1DQ_Output();
    W1DQ_Write(1);
    delay_us(240);
 
    return rv;
}
 
void ds18b20_write(uint8_t byte)
{
    uint8_t            i = 0;
 
    W1DQ_Output();
 
    for(i=0; i<8; i++)
    {
        /* Write 1: pull low <= 15us, Write 0: pull low 15~60us*/
        W1DQ_Write(0);
        delay_us(10);
 
        /* DS18B20 bit sent by LSB (lower bit first) */
        if( byte & 0x1 )
            W1DQ_Write(1);
        else
            W1DQ_Write(0);
 
        /* Write 1/0 slot both >= 60us, hold the level for 60us */
        delay_us(60);
 
        /* Release W1 bus to high */
        W1DQ_Write(1);
        delay_us(2);
 
        /* Prepare for next bit */
        byte >>= 1;
    }
}
 
 
uint8_t ds18b20_read(void)
{
    uint8_t            i = 0;
    uint8_t            byte = 0;
 
    for(i=0; i<8; i++)
    {
        /* Read time slot is initiated by master pulling the W1 bus
         * low for minimum of 1µs and then releasing the bus */
        W1DQ_Output();
        W1DQ_Write(0);
        delay_us(2);
        W1DQ_Write(1);
        delay_us(2);
 
        /* After master initiates read time slot, DS18B20 will begin
         * transmitting a 1 or 0 on bus */
        W1DQ_Input();
 
        /* DS18B20 bit sent by LSB (lower bit first) */
        if( W1DQ_Read() )
        {
            byte |= 1<<i;
        }
 
        /* Read slot for >= 60us */
        delay_us(60);
 
        /* Release W1 bus to high */
        W1DQ_Output();
        W1DQ_Write(1);
        delay_us(2);
    }
 
    return byte;
}
 
static inline int ds18b20_start_convert(void)
{
    /* Master issues reset pulse and DS18B20s respond with presence pulse */
    if( 0 != ds18b20_reset() )
        return -1;
 
    /* Master issues Skip ROM command */
    ds18b20_write(0xCC);
 
    /* Master issues Convert T command. */
    ds18b20_write(0x44);
 
    return 0;
}
 
static inline int ds18b20_start_read(uint8_t *buf, int bytes)
{
    /* Master issues reset pulse and DS18B20s respond with presence pulse */
    if( 0 != ds18b20_reset() )
        return -1;
 
    /* Master issues Skip ROM command */
    ds18b20_write(0xCC);
 
    /* Master issues Read Scratchpad command. */
    ds18b20_write(0xBE);
 
    buf[0] = ds18b20_read();   /* Temperature LSB */
    buf[1] = ds18b20_read();   /* Temperature MSB */
 
    /*Don't care followed 7 bytes data */
 
    return 0;
}
 
int ds18b20_sample(float *temperature)
{
    uint8_t               byte[2];
    uint8_t               sign;
    uint16_t              temp;
    static uint8_t        firstin = 1;
 
    if( !temperature )
        return -1;
 
    if( 0 != ds18b20_start_convert() )
        return -2;
 
    /* First sample need 750ms delay */
    if( firstin )
    {
        HAL_Delay(750);
        firstin = 0;
    }
 
    if( 0 != ds18b20_start_read(byte, 2) )
        return -3;
 
    /* Temperature byte[0] is LSB, byte[1] is MSB, total 16 bit:
     * Byte[0]:  bit[3:0]: decimal bits,  bit[7:4]: integer bits
     * bYTE[1]:  bit[2:0]: integer bits,  bit[7:3]: sign bits
     */
    if( byte[1]> 0x7 ) /* bit[7:3] is 1 */
    {
        temp = ~(byte[1]<<8|byte[0]) + 1;  //补码
        sign=0; //温度为负
    }
    else
    {
        sign=1;//温度为正
        temp = byte[1]<<8 | byte[0];
    }
 
   /* byte[1]的低三位和byte[0]的高四位组成温度值的整数部分,
    * 而byte[0]的低四位为小数精度部分,且精度系数为0.0625 */
    *temperature = (temp>>4) + (temp&0xF)*0.0625 ;
    if( !sign )
    {
        *temperature = -*temperature;
    }
 
    return 0;
}