summaryrefslogtreecommitdiffstats
path: root/fw/ds18b20.c
diff options
context:
space:
mode:
authorVäinö Kauppila <vaino@vke.fi>2026-04-19 19:02:42 +0300
committerVäinö Kauppila <vaino@vke.fi>2026-04-19 19:02:42 +0300
commit46e1210381106707c2df7f07c56023eb6b760763 (patch)
tree6740a17199f76e2965a511dafcbc7ffb61ceafeb /fw/ds18b20.c
parenteb8643ddbef43547eb7bfe58789a3908926c7258 (diff)
downloadvhdl_pic-46e1210381106707c2df7f07c56023eb6b760763.tar.gz
vhdl_pic-46e1210381106707c2df7f07c56023eb6b760763.zip
BSRAM progmem. fix Makefile memory command that does not work. add interrupts, bank 1, timer0. Timer0 not tested.
Diffstat (limited to 'fw/ds18b20.c')
-rw-r--r--fw/ds18b20.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/fw/ds18b20.c b/fw/ds18b20.c
new file mode 100644
index 0000000..0b57732
--- /dev/null
+++ b/fw/ds18b20.c
@@ -0,0 +1,156 @@
+#include <pic16f84a.h>
+
+typedef unsigned char uint8_t;
+
+__sfr __at(0x70) UART_TX;
+__sfr __at(0x72) UART_STATUS;
+
+__sfr __at(0x73) OW_DATA;
+__sfr __at(0x74) OW_CMD;
+__sfr __at(0x75) OW_STATUS;
+
+#define OW_RESET 0x00
+#define OW_WRITE 0x01
+#define OW_READ 0x02
+
+#define OW_BUSY 0x01
+#define OW_PRESENCE 0x02
+
+#define CMD_SKIP_ROM 0xCC
+#define CMD_CONVERT_T 0x44
+#define CMD_READ_SCRATCH 0xBE
+
+/*
+ * Fractional nibble lookup: each step is 0.0625 deg C.
+ * Tables give the two decimal digits (tenths, hundredths) truncated.
+ * e.g. frac=1 -> 0.0625 -> prints ".06"
+ * frac=8 -> 0.5000 -> prints ".50"
+ */
+static const uint8_t frac_tens[16] = {0,0,1,1,2,3,3,4,5,5,6,6,7,8,8,9};
+static const uint8_t frac_hund[16] = {0,6,2,8,5,1,7,4,0,6,2,8,5,1,7,3};
+
+/*
+ * Timer0 delay. OPTION_REG 0x07: T0CS=0 (Fosc/4), PSA=0, PS=111 (1:256).
+ * At 50 MHz: overflow every 256*256 / (50M/4) = 5.24 ms.
+ * 143 overflows ≈ 750 ms.
+ */
+#define STATUS_RP0 0x20
+#define T0IF 0x04
+
+static void wait_overflows(uint8_t n) {
+ INTCON &= ~T0IF;
+ while (n--) {
+ while (!(INTCON & T0IF));
+ INTCON &= ~T0IF;
+ }
+}
+
+static void delay_750ms(void) { wait_overflows(143); }
+
+static void uart_send(uint8_t b) {
+ while (UART_STATUS & 0x01);
+ UART_TX = b;
+}
+
+static void uart_puts(const char *s) {
+ while (*s) uart_send((uint8_t)*s++);
+}
+
+static void ow_wait(void) {
+ while (OW_STATUS & OW_BUSY);
+}
+
+static void ow_write_byte(uint8_t b) {
+ OW_DATA = b;
+ OW_CMD = OW_WRITE;
+ ow_wait();
+}
+
+static uint8_t ow_read_byte(void) {
+ OW_CMD = OW_READ;
+ ow_wait();
+ return OW_DATA;
+}
+
+static void print_uint8(uint8_t v) {
+ uint8_t started = 0;
+ if (v >= 200) { uart_send('2'); v -= 200; started = 1; }
+ else if (v >= 100) { uart_send('1'); v -= 100; started = 1; }
+ {
+ uint8_t t = '0';
+ while (v >= 10) { v -= 10; t++; }
+ if (started || t != '0') uart_send(t);
+ }
+ uart_send(v + '0');
+}
+
+void main(void) {
+ uint8_t lo, hi, sign, temp_int, frac;
+ uint8_t i;
+
+ /* Configure Timer0: bank 1, OPTION_REG = 0x07 (Fosc/4, prescaler 1:256) */
+ STATUS |= STATUS_RP0;
+ TMR0 = 0x07;
+ STATUS &= ~STATUS_RP0;
+
+ uart_puts("\x1B[2J\x1B[H");
+ uart_puts("DS18B20 Temperature\r\n");
+ uart_puts("-------------------\r\n");
+
+ while (1) {
+ /* Reset */
+ OW_CMD = OW_RESET;
+ ow_wait();
+ if (!(OW_STATUS & OW_PRESENCE)) {
+ uart_puts("No sensor\r\n");
+ delay_750ms();
+ continue;
+ }
+
+ /* Start temperature conversion */
+ ow_write_byte(CMD_SKIP_ROM);
+ ow_write_byte(CMD_CONVERT_T);
+ delay_750ms();
+
+ /* Reset and read scratchpad */
+ OW_CMD = OW_RESET;
+ ow_wait();
+ if (!(OW_STATUS & OW_PRESENCE)) {
+ uart_puts("Lost sensor\r\n");
+ continue;
+ }
+ ow_write_byte(CMD_SKIP_ROM);
+ ow_write_byte(CMD_READ_SCRATCH);
+
+ lo = ow_read_byte(); /* scratchpad byte 0: temp LSB */
+ hi = ow_read_byte(); /* scratchpad byte 1: temp MSB */
+ for (i = 0; i < 7; i++) ow_read_byte(); /* discard remaining bytes */
+
+ /*
+ * DS18B20 12-bit format:
+ * sign = hi bit 7 (and sign-extended through hi[7:4])
+ * integer part = hi[3:0]:lo[7:4]
+ * fractional nibble = lo[3:0] (each bit = 0.0625 deg C)
+ *
+ * Negative values are two's complement of the 16-bit word.
+ */
+ sign = hi & 0x80;
+ if (sign) {
+ lo = ~lo;
+ hi = ~hi;
+ if (lo == 0xFF) { lo = 0; hi++; }
+ else { lo++; }
+ }
+
+ temp_int = ((hi & 0x0F) << 4) | (lo >> 4);
+ frac = lo & 0x0F;
+
+ uart_puts("\rTemp: ");
+ if (sign) uart_send('-');
+ print_uint8(temp_int);
+ uart_send('.');
+ uart_send('0' + frac_tens[frac]);
+ uart_send('0' + frac_hund[frac]);
+ uart_puts(" C\r\n");
+ }
+}