working, tested original DS1820

master
Ondřej Hruška 6 år sedan
förälder c7b83a9ba4
incheckning 56320f7f26
Signerad av: MightyPork
GPG-nyckel ID: 2C5FD5035250423D
  1. 2
      CMakeLists.txt
  2. 1
      Makefile
  3. 71
      main.c
  4. 248
      onewire.c
  5. 58
      onewire.h

@ -19,6 +19,8 @@ set(SOURCE_FILES
lib/usart.h
lcd.c
lcd.h
onewire.c
onewire.h
)
include_directories(lib

@ -31,6 +31,7 @@ OBJS += lib/iopins.o
OBJS += lib/spi.o
OBJS += lib/adc.o
OBJS += lcd.o
OBJS += onewire.o
# Dirs with header files
INCL_DIRS = . lib/

@ -6,19 +6,24 @@
#include <stdint.h> // C header for int types like uint8_t
#include <stdbool.h> // C header for the bool type
#include <stdlib.h>
#include <stdio.h>
// Include stuff from the library
#include "lib/iopins.h"
#include "lib/usart.h"
#include "lcd.h"
#include "onewire.h"
// Pins
#define LED 13
#define OW_PIN D9
void _lcd_wait_bf();
void _lcd_write_byte(uint8_t bb);
#if 0
// UART receive handler
ISR(USART_RX_vect)
{
@ -26,31 +31,81 @@ ISR(USART_RX_vect)
uint8_t b = usart_rx();
usart_tx(b); // send back
}
#endif
void main()
{
#if 0
usart_init(BAUD_115200);
usart_isr_rx_enable(true); // enable RX interrupt handler
#endif
// configure pins
as_output(LED);
lcd_init();
lcd_clear();
lcd_puts("");
// globally enable interrupts (for the USART_RX handler)
sei();
uint8_t cnt = 0;
uint8_t addr[8];
char charbuf[21];
int dots = 0;
while (1) {
lcd_clear();
bool signal = ow_reset(OW_PIN);
if (!signal) {
lcd_clear();
lcd_puts("No 1-Wire detected...");
dots = 0;
} else {
ow_write(OW_PIN, 0x33);
ow_read_arr(OW_PIN, addr, 8);
lcd_xy(cnt, 0);
lcd_putc('A'+cnt);
lcd_clear();
cnt = (cnt+1)%20;
char *p = charbuf;
for(uint8_t i = 0; i < 4; i++) {
p += sprintf(p, "%02X", addr[i]);
if (i < 3) *p++ = ':';
}
lcd_puts(charbuf);
lcd_xy(0, 1);
pin_toggle(13); // blink the LED
p = charbuf;
for(uint8_t i = 0; i < 4; i++) {
p += sprintf(p, "%02X", addr[4+i]);
if (i < 3) *p++ = ':';
}
lcd_puts(charbuf);
ds1820_single_measure(OW_PIN);
uint16_t cels = ds1820_read_temp_c(OW_PIN);
if (cels == 850) {
lcd_xy(12, 0);
for(uint8_t i = 0; i <= dots; i++) {
lcd_putc('.');
}
dots = (dots+1)%3;
} else {
p = charbuf;
p += sprintf(p, "%d", cels/10);
*p++ = '.';
p += sprintf(p, "%d", cels%10);
*p++ = 0xDF;
*p++ = 'C';
*p++ = 0;
_delay_ms(100);
lcd_xy(12, 0);
lcd_puts(charbuf);
}
}
pin_toggle(13); // blink the LED
_delay_ms(100);
}
}

@ -0,0 +1,248 @@
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <stdbool.h>
#include "iopins.h"
#include "onewire.h"
/** Perform bus reset. Returns true if any device is connected */
bool ow_reset(const uint8_t pin)
{
as_output_n(pin);
pin_down_n(pin);
_delay_us(480);
as_input_pu_n(pin);
_delay_us(70);
const bool a = ! pin_read_n(pin);
_delay_us(410);
return a;
}
/** Send a single bit */
void _ow_tx_bit(const uint8_t pin, const bool bit)
{
as_output_n(pin);
pin_down_n(pin);
if (bit)
{
_delay_us(6);
as_input_pu_n(pin);
_delay_us(64);
}
else
{
_delay_us(60);
as_input_pu_n(pin);
_delay_us(10);
}
}
/** Send a single byte */
void ow_write(const uint8_t pin, const uint8_t byte)
{
for (uint8_t i = 0; i < 8; i++)
{
_ow_tx_bit(pin, (byte >> i) & 0x01);
}
}
/** Read a single bit */
bool _ow_rx_bit(const uint8_t pin)
{
as_output_n(pin);
pin_down_n(pin);
_delay_us(6);
as_input_pu_n(pin);
_delay_us(9);
const bool a = pin_read_n(pin);
_delay_us(55);
return a;
}
/** Read a single byte */
uint8_t ow_read(const uint8_t pin)
{
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++)
{
byte = (byte >> 1) | (_ow_rx_bit(pin) << 7);
}
return byte;
}
/** Wait until the device is ready. Returns false on timeout */
bool ow_wait_ready(const uint8_t pin)
{
uint16_t timeout = 700;
as_input_pu_n(pin);
while (--timeout > 0)
{
if (pin_is_high_n(pin)) return true;
_delay_ms(1);
}
return false;
}
/** Read bytes into an array */
void ow_read_arr(const uint8_t pin, uint8_t* array, const uint8_t count)
{
for (uint8_t i = 0; i < count; i++)
{
array[i] = ow_read(pin);
}
}
// ---------- CRC utils ----------
/*
Dallas 1-wire CRC routines for Arduino with examples of usage.
The 16-bit routine is new.
The 8-bit routine is from http://github.com/paeaetech/paeae/tree/master/Libraries/ds2482/
Copyright (C) 2010 Kairama Inc
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Dallas 1-wire 16-bit CRC calculation. Developed from Maxim Application Note 27.
/** Compute a CRC16 checksum */
uint16_t crc16(uint8_t *data, uint8_t len)
{
uint16_t crc = 0;
for (uint8_t i = 0; i < len; i++)
{
uint8_t inbyte = data[i];
for (uint8_t j = 0; j < 8; j++)
{
uint8_t mix = (crc ^ inbyte) & 0x01;
crc = crc >> 1;
if (mix)
crc = crc ^ 0xA001;
inbyte = inbyte >> 1;
}
}
return crc;
}
// The 1-Wire CRC scheme is described in Maxim Application Note 27:
// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
/** Compute a CRC8 checksum */
uint8_t crc8(uint8_t *addr, uint8_t len)
{
uint8_t crc = 0;
for (uint8_t i = 0; i < len; i++)
{
uint8_t inbyte = addr[i];
for (uint8_t j = 0; j < 8; j++)
{
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix)
crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}
// --- utils for DS1820 ---
/** Read temperature in 0.0625°C, or TEMP_ERROR on error */
int16_t ds1820_read_temp(uint8_t pin)
{
ow_write(pin, READ_SCRATCHPAD);
uint8_t bytes[9];
ow_read_arr(pin, bytes, 9);
uint8_t crc = crc8(bytes, 8);
if (crc != bytes[8])
{
return TEMP_ERROR;
}
else
{
int16_t a = ((bytes[1] << 8) | bytes[0]) >> 1;
a = a << 4;
a += (16 - bytes[6]) & 0x0F;
a -= 0x04;
return a;
}
}
/** Read temperature in 0.1°C, or TEMP_ERROR on error */
int16_t ds1820_read_temp_c(uint8_t pin)
{
int32_t temp = ds1820_read_temp(pin);
if (temp == TEMP_ERROR)
return TEMP_ERROR;
temp *= 625;
uint16_t rem = temp % 1000;
temp /= 1000;
if (rem >= 500) temp++;
return (int16_t) temp;
}
bool ds1820_single_measure(uint8_t pin)
{
ow_reset(pin);
ow_write(pin, SKIP_ROM);
ow_write(pin, CONVERT_T);
if (!ow_wait_ready(pin))
{
return false;
}
ow_reset(pin);
ow_write(pin, SKIP_ROM);
return true;
}

@ -0,0 +1,58 @@
#pragma once
//
// Utils for Dallas OneWire bus (DS1820 etc)
//
#include <stdint.h>
#include <stdbool.h>
#define SKIP_ROM 0xCC
#define CONVERT_T 0x44
#define READ_SCRATCHPAD 0xBE
/** Perform bus reset. Returns true if any device is connected */
bool ow_reset(uint8_t pin);
/** Send a single byte */
void ow_write(const uint8_t pin, const uint8_t byte);
/** Read a single byte */
uint8_t ow_read(uint8_t pin);
/** Wait until the device is ready. Returns false on timeout */
bool ow_wait_ready(uint8_t pin);
/** Read bytes into an array */
void ow_read_arr(uint8_t pin, uint8_t* array, uint8_t count);
/** Compute a CRC16 checksum */
uint16_t crc16(uint8_t *data, uint8_t len);
/** Compute a CRC8 checksum */
uint8_t crc8(uint8_t *addr, uint8_t len);
// --- utils for DS1820 ---
#define TEMP_ERROR (-32768)
/**
* Read temperature in 0.0625°C, or TEMP_ERROR on error
* Use this where you'd normally use READ_SCRATCHPAD
*/
int16_t ds1820_read_temp(uint8_t pin);
/**
* Read temperature in 0.1°C, or TEMP_ERROR on error
* Use this where you'd normally use READ_SCRATCHPAD
*/
int16_t ds1820_read_temp_c(uint8_t pin);
/**
* Perform a temperature measurement with single DS1820 device on the line
* Can be followed by a call to read temperature (READ_SCRATCHPAD).
*
* Returns false on failure (device not connected)
*/
bool ds1820_single_measure(uint8_t pin);
Laddar…
Avbryt
Spara