From 46e1210381106707c2df7f07c56023eb6b760763 Mon Sep 17 00:00:00 2001 From: Väinö Kauppila Date: Sun, 19 Apr 2026 19:02:42 +0300 Subject: BSRAM progmem. fix Makefile memory command that does not work. add interrupts, bank 1, timer0. Timer0 not tested. --- fw/ds18b20.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 fw/ds18b20.c (limited to 'fw/ds18b20.c') 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 + +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"); + } +} -- cgit v1.3