cursada_mc2
Base de control de temperatura para EDU-CIAA-NXP
Loading...
Searching...
No Matches
ds18b20_driver.c
Go to the documentation of this file.
1
6#include "ds18b20_driver.h"
7
8#include "delay_driver.h"
9
10#include <string.h>
11
12#define DS18B20_CMD_CONVERT_T 0x44U
13#define DS18B20_CMD_READ_SCRATCHPAD 0xBEU
14
15static uint8_t ds18b20_crc8(const uint8_t* data, uint8_t length)
16{
17 uint8_t index = 0U;
18 uint8_t crc = 0U;
19
20 for (index = 0U; index < length; ++index) {
21 uint8_t current_byte = data[index];
22 for (uint8_t bit_index = 0U; bit_index < 8U; ++bit_index) {
23 const uint8_t mix = (uint8_t) ((crc ^ current_byte) & 0x01U);
24 crc >>= 1U;
25 if (mix != 0U) {
26 crc ^= 0x8CU;
27 }
28 current_byte >>= 1U;
29 }
30 }
31
32 return crc;
33}
34
35static bool ds18b20_crc8_is_valid(const uint8_t* data, uint8_t length)
36{
37 return (ds18b20_crc8(data, length) == 0U);
38}
39
41{
42 driver->sample_valid = false;
43 driver->last_raw_temperature = 0;
44 driver->conversion_elapsed_ms = 0U;
45 driver->state = DS18B20_STATE_IDLE;
46}
47
48static bool ds18b20_begin_command(ds18b20_driver_t* driver, uint8_t command)
49{
50 if ((driver == 0) || !driver->initialized) {
51 return false;
52 }
53
54 if (!onewire_reset(&driver->bus)) {
55 return false;
56 }
57
58 if (driver->use_match_rom) {
59 onewire_match_rom(&driver->bus, driver->rom_code);
60 } else {
61 onewire_skip_rom(&driver->bus);
62 }
63 onewire_write_byte(&driver->bus, command);
64 return true;
65}
66
68 const uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE],
69 uint8_t command)
70{
71 if ((bus == 0) || !bus->initialized) {
72 return false;
73 }
74
75 if (!onewire_reset(bus)) {
76 return false;
77 }
78
79 if (rom_code != 0) {
80 onewire_match_rom(bus, rom_code);
81 } else {
83 }
84
85 onewire_write_byte(bus, command);
86 return true;
87}
88
90{
91 uint8_t scratchpad[DS18B20_SCRATCHPAD_SIZE];
92
93 if (!ds18b20_read_scratchpad(driver, scratchpad)) {
94 driver->state = DS18B20_STATE_ERROR;
95 driver->sample_valid = false;
96 return false;
97 }
98
99 driver->last_raw_temperature = (int16_t) (((uint16_t) scratchpad[1] << 8U) | scratchpad[0]);
100 driver->sample_valid = true;
102 return true;
103}
104
106 const uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE],
107 int16_t* raw_temperature)
108{
109 uint8_t scratchpad[DS18B20_SCRATCHPAD_SIZE];
110 uint8_t index = 0U;
111
112 if ((bus == 0) || (raw_temperature == 0) || (rom_code == 0) || !bus->initialized) {
113 return false;
114 }
115
117 return false;
118 }
119
120 for (index = 0U; index < DS18B20_SCRATCHPAD_SIZE; ++index) {
121 scratchpad[index] = onewire_read_byte(bus);
122 }
123
125 return false;
126 }
127
128 *raw_temperature = (int16_t) (((uint16_t) scratchpad[1] << 8U) | scratchpad[0]);
129 return true;
130}
131
132bool ds18b20_init(ds18b20_driver_t* driver, const onewire_pin_config_t* pin_config)
133{
134 if ((driver == 0) || (pin_config == 0)) {
135 return false;
136 }
137
138 if (!onewire_init(&driver->bus, pin_config)) {
139 return false;
140 }
141
142 driver->use_match_rom = false;
143 (void) memset(driver->rom_code, 0, sizeof(driver->rom_code));
144 ds18b20_reset_state(driver);
145 driver->initialized = ds18b20_is_present(driver);
146 return driver->initialized;
147}
148
150 const onewire_pin_config_t* pin_config,
151 const uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE])
152{
153 if ((driver == 0) || (pin_config == 0) || (rom_code == 0)) {
154 return false;
155 }
156
157 if ((rom_code[0] != DS18B20_FAMILY_CODE)
159 return false;
160 }
161
162 if (!onewire_init(&driver->bus, pin_config)) {
163 return false;
164 }
165
166 driver->use_match_rom = true;
167 (void) memcpy(driver->rom_code, rom_code, sizeof(driver->rom_code));
168 ds18b20_reset_state(driver);
169 driver->initialized = ds18b20_is_present(driver);
170 return driver->initialized;
171}
172
173uint8_t ds18b20_discover(const onewire_pin_config_t* pin_config,
174 uint8_t rom_codes[][ONEWIRE_ROM_CODE_SIZE],
175 uint8_t max_devices)
176{
178 uint8_t raw_rom_codes[16U][ONEWIRE_ROM_CODE_SIZE];
179 uint8_t raw_count = 0U;
180 uint8_t valid_count = 0U;
181 uint8_t index = 0U;
182
183 if ((pin_config == 0) || (rom_codes == 0) || (max_devices == 0U)) {
184 return 0U;
185 }
186
187 if (max_devices > 16U) {
188 max_devices = 16U;
189 }
190
191 if (!onewire_init(&bus, pin_config)) {
192 return 0U;
193 }
194
195 raw_count = onewire_search_roms(&bus, raw_rom_codes, max_devices);
196
197 for (index = 0U; index < raw_count; ++index) {
198 if ((raw_rom_codes[index][0] == DS18B20_FAMILY_CODE)
199 && ds18b20_crc8_is_valid(raw_rom_codes[index], ONEWIRE_ROM_CODE_SIZE)) {
200 (void) memcpy(rom_codes[valid_count], raw_rom_codes[index], ONEWIRE_ROM_CODE_SIZE);
201 valid_count++;
202 }
203 }
204
205 return valid_count;
206}
207
209{
210 if ((driver == 0) || !driver->bus.initialized) {
211 return false;
212 }
213
214 return onewire_reset(&driver->bus);
215}
216
218{
220 driver->state = DS18B20_STATE_ERROR;
221 return false;
222 }
223
224 driver->conversion_elapsed_ms = 0U;
226 return true;
227}
228
229void ds18b20_process(ds18b20_driver_t* driver, uint16_t elapsed_ms)
230{
231 if ((driver == 0) || !driver->initialized) {
232 return;
233 }
234
235 if (driver->state != DS18B20_STATE_CONVERTING) {
236 return;
237 }
238
239 if ((uint32_t) driver->conversion_elapsed_ms + elapsed_ms >= DS18B20_CONVERSION_TIME_MS) {
241 (void) ds18b20_finish_conversion(driver);
242 } else {
243 driver->conversion_elapsed_ms = (uint16_t) (driver->conversion_elapsed_ms + elapsed_ms);
244 }
245}
246
248{
249 if ((driver == 0) || !driver->initialized) {
250 return false;
251 }
252
253 return (driver->state == DS18B20_STATE_CONVERTING);
254}
255
257{
258 if ((driver == 0) || !driver->initialized) {
259 return false;
260 }
261
262 return driver->sample_valid;
263}
264
265bool ds18b20_get_latest_raw(const ds18b20_driver_t* driver, int16_t* raw_temperature)
266{
267 if ((driver == 0) || (raw_temperature == 0) || !driver->initialized || !driver->sample_valid) {
268 return false;
269 }
270
271 *raw_temperature = driver->last_raw_temperature;
272 return true;
273}
274
276 float* temperature_celsius)
277{
278 if ((temperature_celsius == 0) || !ds18b20_has_valid_sample(driver)) {
279 return false;
280 }
281
282 *temperature_celsius = (float) driver->last_raw_temperature / 16.0f;
283 return true;
284}
285
287{
288 uint8_t index = 0U;
289
290 if ((driver == 0) || (scratchpad == 0)) {
291 return false;
292 }
293
295 return false;
296 }
297
298 for (index = 0U; index < DS18B20_SCRATCHPAD_SIZE; ++index) {
299 scratchpad[index] = onewire_read_byte(&driver->bus);
300 }
301
303}
304
305bool ds18b20_read_raw(ds18b20_driver_t* driver, int16_t* raw_temperature)
306{
307 if ((driver == 0) || (raw_temperature == 0)) {
308 return false;
309 }
310
311 if (!ds18b20_start_conversion(driver)) {
312 return false;
313 }
314
316
317 if (!ds18b20_finish_conversion(driver)) {
318 return false;
319 }
320
321 return ds18b20_get_latest_raw(driver, raw_temperature);
322}
323
324bool ds18b20_read_temperature_celsius(ds18b20_driver_t* driver, float* temperature_celsius)
325{
326 int16_t raw_temperature = 0;
327
328 if ((driver == 0) || (temperature_celsius == 0)) {
329 return false;
330 }
331
332 if (!ds18b20_read_raw(driver, &raw_temperature)) {
333 return false;
334 }
335
336 *temperature_celsius = (float) raw_temperature / 16.0f;
337 return true;
338}
339
341{
342 if ((driver == 0) || (pin_config == 0)) {
343 return false;
344 }
345
346 if (!onewire_init(&driver->bus, pin_config)) {
347 return false;
348 }
349
350 driver->initialized = true;
351 driver->device_count = 0U;
352 driver->current_index = 0U;
353 driver->conversion_elapsed_ms = 0U;
355 (void) memset(driver->devices, 0, sizeof(driver->devices));
356 return true;
357}
358
360{
361 uint8_t raw_rom_codes[DS18B20_MAX_DEVICES][ONEWIRE_ROM_CODE_SIZE];
362 uint8_t raw_count = 0U;
363 uint8_t valid_count = 0U;
364 uint8_t index = 0U;
365
366 if ((driver == 0) || !driver->initialized) {
367 return 0U;
368 }
369
370 raw_count = onewire_search_roms(&driver->bus, raw_rom_codes, DS18B20_MAX_DEVICES);
371 (void) memset(driver->devices, 0, sizeof(driver->devices));
372
373 for (index = 0U; index < raw_count; ++index) {
374 if ((raw_rom_codes[index][0] == DS18B20_FAMILY_CODE)
375 && ds18b20_crc8_is_valid(raw_rom_codes[index], ONEWIRE_ROM_CODE_SIZE)) {
376 (void) memcpy(driver->devices[valid_count].rom_code,
377 raw_rom_codes[index],
379 driver->devices[valid_count].sample_valid = false;
380 driver->devices[valid_count].last_raw_temperature = 0;
381 valid_count++;
382 }
383 }
384
385 driver->device_count = valid_count;
386 driver->current_index = 0U;
387 driver->conversion_elapsed_ms = 0U;
389 return driver->device_count;
390}
391
393{
394 if ((driver == 0) || !driver->initialized || (driver->device_count == 0U)) {
395 return false;
396 }
397
400 return false;
401 }
402
403 driver->current_index = 0U;
404 driver->conversion_elapsed_ms = 0U;
406 return true;
407}
408
409void ds18b20_bus_process(ds18b20_bus_driver_t* driver, uint16_t elapsed_ms)
410{
411 if ((driver == 0) || !driver->initialized || (driver->device_count == 0U)) {
412 return;
413 }
414
415 switch (driver->state) {
417 if ((uint32_t) driver->conversion_elapsed_ms + elapsed_ms >= DS18B20_CONVERSION_TIME_MS) {
419 driver->current_index = 0U;
421 } else {
422 driver->conversion_elapsed_ms = (uint16_t) (driver->conversion_elapsed_ms + elapsed_ms);
423 }
424 break;
425
427 if (driver->current_index < driver->device_count) {
428 int16_t raw_temperature = 0;
429 ds18b20_device_t* device = &driver->devices[driver->current_index];
430
431 if (ds18b20_bus_read_raw(&driver->bus, device->rom_code, &raw_temperature)) {
432 device->last_raw_temperature = raw_temperature;
433 device->sample_valid = true;
434 } else {
435 device->sample_valid = false;
437 }
438
439 driver->current_index++;
440 if (driver->current_index >= driver->device_count) {
441 if (driver->state != DS18B20_BUS_STATE_ERROR) {
443 }
444 }
445 } else {
447 }
448 break;
449
452 default:
453 break;
454 }
455}
456
458{
459 if ((driver == 0) || !driver->initialized) {
460 return false;
461 }
462
463 return (driver->state == DS18B20_BUS_STATE_CONVERTING)
464 || (driver->state == DS18B20_BUS_STATE_READING);
465}
466
468{
469 if ((driver == 0) || !driver->initialized) {
470 return 0U;
471 }
472
473 return driver->device_count;
474}
475
476bool ds18b20_bus_has_valid_sample(const ds18b20_bus_driver_t* driver, uint8_t index)
477{
478 if ((driver == 0) || !driver->initialized || (index >= driver->device_count)) {
479 return false;
480 }
481
482 return driver->devices[index].sample_valid;
483}
484
486 uint8_t index,
487 int16_t* raw_temperature)
488{
489 if ((driver == 0) || (raw_temperature == 0) || !driver->initialized
490 || (index >= driver->device_count) || !driver->devices[index].sample_valid) {
491 return false;
492 }
493
494 *raw_temperature = driver->devices[index].last_raw_temperature;
495 return true;
496}
497
499 uint8_t index,
500 float* temperature_celsius)
501{
502 if ((temperature_celsius == 0) || !ds18b20_bus_has_valid_sample(driver, index)) {
503 return false;
504 }
505
506 *temperature_celsius = (float) driver->devices[index].last_raw_temperature / 16.0f;
507 return true;
508}
509
511 uint8_t index,
512 uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE])
513{
514 if ((driver == 0) || (rom_code == 0) || !driver->initialized || (index >= driver->device_count)) {
515 return false;
516 }
517
518 (void) memcpy(rom_code, driver->devices[index].rom_code, ONEWIRE_ROM_CODE_SIZE);
519 return true;
520}
void driver_delay_ms(uint32_t milliseconds)
Realiza una espera bloqueante expresada en milisegundos.
Interfaz comun de delays bloqueantes basada en stopwatch de LPCOpen.
uint8_t ds18b20_bus_get_device_count(const ds18b20_bus_driver_t *driver)
Devuelve la cantidad de sensores actualmente descubiertos.
bool ds18b20_init(ds18b20_driver_t *driver, const onewire_pin_config_t *pin_config)
Inicializa el driver DS18B20 sobre el pin indicado.
static uint8_t ds18b20_crc8(const uint8_t *data, uint8_t length)
uint8_t ds18b20_bus_discover(ds18b20_bus_driver_t *driver)
Descubre sensores DS18B20 y actualiza la tabla interna del bus.
bool ds18b20_bus_get_latest_raw(const ds18b20_bus_driver_t *driver, uint8_t index, int16_t *raw_temperature)
Obtiene la ultima temperatura cruda cacheada de un sensor del bus.
bool ds18b20_is_present(ds18b20_driver_t *driver)
Verifica si hay un dispositivo presente en el bus del sensor.
bool ds18b20_init_with_rom(ds18b20_driver_t *driver, const onewire_pin_config_t *pin_config, const uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE])
Inicializa un sensor DS18B20 concreto identificado por su ROM.
bool ds18b20_bus_get_rom_code(const ds18b20_bus_driver_t *driver, uint8_t index, uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE])
Copia el codigo ROM de un sensor descubierto en el bus.
bool ds18b20_read_raw(ds18b20_driver_t *driver, int16_t *raw_temperature)
Lee la temperatura cruda del sensor en forma bloqueante.
#define DS18B20_CMD_READ_SCRATCHPAD
static bool ds18b20_finish_conversion(ds18b20_driver_t *driver)
void ds18b20_bus_process(ds18b20_bus_driver_t *driver, uint16_t elapsed_ms)
Avanza la maquina de estados multi-sensor del bus.
void ds18b20_process(ds18b20_driver_t *driver, uint16_t elapsed_ms)
Avanza la maquina de estados no bloqueante del sensor.
bool ds18b20_is_busy(const ds18b20_driver_t *driver)
Indica si hay una conversion en curso.
static void ds18b20_reset_state(ds18b20_driver_t *driver)
static bool ds18b20_crc8_is_valid(const uint8_t *data, uint8_t length)
bool ds18b20_bus_is_busy(const ds18b20_bus_driver_t *driver)
Indica si el bus esta ocupado convirtiendo o leyendo sensores.
bool ds18b20_bus_init(ds18b20_bus_driver_t *driver, const onewire_pin_config_t *pin_config)
Inicializa un bus compartido para varios sensores DS18B20.
bool ds18b20_bus_has_valid_sample(const ds18b20_bus_driver_t *driver, uint8_t index)
Indica si un sensor del bus tiene una muestra valida disponible.
uint8_t ds18b20_discover(const onewire_pin_config_t *pin_config, uint8_t rom_codes[][ONEWIRE_ROM_CODE_SIZE], uint8_t max_devices)
Busca sensores DS18B20 presentes en el bus indicado.
bool ds18b20_start_conversion(ds18b20_driver_t *driver)
Inicia una conversion de temperatura.
static bool ds18b20_begin_command(ds18b20_driver_t *driver, uint8_t command)
bool ds18b20_read_scratchpad(ds18b20_driver_t *driver, uint8_t scratchpad[DS18B20_SCRATCHPAD_SIZE])
Lee el scratchpad completo del sensor.
bool ds18b20_has_valid_sample(const ds18b20_driver_t *driver)
Indica si el driver dispone de una ultima muestra valida.
#define DS18B20_CMD_CONVERT_T
static bool ds18b20_bus_read_raw(const onewire_driver_t *bus, const uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE], int16_t *raw_temperature)
bool ds18b20_get_latest_temperature_celsius(const ds18b20_driver_t *driver, float *temperature_celsius)
Obtiene la ultima temperatura valida en grados Celsius.
bool ds18b20_read_temperature_celsius(ds18b20_driver_t *driver, float *temperature_celsius)
Lee la temperatura del sensor en grados Celsius en forma bloqueante.
bool ds18b20_bus_get_latest_temperature_celsius(const ds18b20_bus_driver_t *driver, uint8_t index, float *temperature_celsius)
Obtiene la ultima temperatura cacheada de un sensor del bus en Celsius.
bool ds18b20_bus_start_conversion(ds18b20_bus_driver_t *driver)
Inicia una conversion global para todos los sensores del bus.
bool ds18b20_get_latest_raw(const ds18b20_driver_t *driver, int16_t *raw_temperature)
Obtiene la ultima temperatura cruda ya convertida.
static bool ds18b20_bus_begin_command(const onewire_driver_t *bus, const uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE], uint8_t command)
Interfaz del driver para sensor de temperatura DS18B20.
#define DS18B20_FAMILY_CODE
Codigo de familia 1-Wire del DS18B20.
@ DS18B20_BUS_STATE_IDLE
@ DS18B20_BUS_STATE_READING
@ DS18B20_BUS_STATE_ERROR
@ DS18B20_BUS_STATE_CONVERTING
@ DS18B20_STATE_IDLE
@ DS18B20_STATE_CONVERTING
@ DS18B20_STATE_DATA_READY
@ DS18B20_STATE_ERROR
#define DS18B20_CONVERSION_TIME_MS
Tiempo maximo de conversion del DS18B20 a 12 bits.
#define DS18B20_MAX_DEVICES
Cantidad maxima de sensores DS18B20 por bus en esta implementacion.
#define DS18B20_SCRATCHPAD_SIZE
Tamano del scratchpad del DS18B20.
bool onewire_init(onewire_driver_t *driver, const onewire_pin_config_t *pin_config)
Inicializa un bus 1-Wire sobre el pin indicado.
void onewire_write_byte(const onewire_driver_t *driver, uint8_t value)
Escribe un byte en el bus 1-Wire.
bool onewire_reset(const onewire_driver_t *driver)
Emite un reset 1-Wire y detecta presencia de dispositivos.
uint8_t onewire_search_roms(const onewire_driver_t *driver, uint8_t rom_codes[][ONEWIRE_ROM_CODE_SIZE], uint8_t max_devices)
Busca dispositivos presentes en el bus mediante el comando Search ROM.
uint8_t onewire_read_byte(const onewire_driver_t *driver)
Lee un byte desde el bus 1-Wire.
void onewire_skip_rom(const onewire_driver_t *driver)
Emite el comando Skip ROM sobre el bus.
void onewire_match_rom(const onewire_driver_t *driver, const uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE])
Selecciona un dispositivo concreto por su codigo ROM.
#define ONEWIRE_ROM_CODE_SIZE
Tamano del codigo ROM de un dispositivo 1-Wire.
Estado del driver para multiples sensores DS18B20 sobre un mismo bus.
ds18b20_bus_state_t state
ds18b20_device_t devices[DS18B20_MAX_DEVICES]
onewire_driver_t bus
Datos cacheados de un sensor DS18B20 descubierto en un bus compartido.
uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE]
int16_t last_raw_temperature
Estado del driver DS18B20 para un sensor individual.
ds18b20_state_t state
int16_t last_raw_temperature
uint16_t conversion_elapsed_ms
uint8_t rom_code[ONEWIRE_ROM_CODE_SIZE]
onewire_driver_t bus
Estado del driver 1-Wire para un bus individual.
Configuracion fisica del pin usado por el bus 1-Wire.