Este ejemplo obtiene la temperatura de un sensor DS18B20 y la envía por UART
Las primitivas para la comunicación 1-wire son prácticamente las que brinda la «Application Note 126 – 1-Wire® Communication through Software» de Dallas Semiconductor
– Se asume fBus de 8 MHz; para otros valores eventualmente habrá que cambiar las funciones:
wait(), Write1() y Readx()
#include <hidef.h> /* for EnableInterrupts macro */ #include "derivative.h" /* include peripheral declarations */ /* -- | VCC | Rpu (4.7 Kohm) | MCU B3 | ---- | DQ 18B20 | ---- | GND - El pin del MCU se cambia en los define más abajo */ #define OUT 1 #define IN 0 #define HI 1 #define LOW 0 /* Pin de comunicación 1-Wire */ #define DIO PTBD_PTBD3 #define _DIO PTBDD_PTBDD3 #define T_INTERVALO_SERIE 500 /* Prototipos funciones 1-Wire */ void wait(unsigned int microsec); int Reset(void); void Write1(void); void Write0(void); int Readx(void); void WriteByte(unsigned char Data); unsigned char ReadByte(void); /* Prototipo funciones 18B20 */ long darTemperatura(void); void dec_to_str(char str[], long valor){ int uni; int i = 0; int largo = 0; long aux = valor; if (valor == 0) largo = 1; else { while(aux != 0){ aux /= 10; largo++; } } for(i = 0; i < largo; i++) { uni = valor % 10; str[largo - i - 1] = uni + 0x30; valor = valor / 10; } str[i] = '\0'; } void send_str(char vect[], int lon){ int i; for (i = 0; i < lon; i++) { while (SCIS1_TDRE == 0); SCID = vect[i]; } while (SCIS1_TDRE == 0); SCID = '\n'; } unsigned int tiempo = 500; void main(void) { long temperatura; char numstr[10]; SOPT1 &= 0x3F; ICSTRM = NVICSTRM; ICSSC |= NVFTRIM_FTRIM; while (!ICSSC_IREFST); TPM1SC = 0b01001011; TPM1MOD = 999; EnableInterrupts SCIBD = 52; // divisor = 52 baudrate = 8MHz / 52 / 16 = 9615,38 → 9600 SCIC1 = 0b00000000; // sin paridad SCIC2 = 0b00001000; // tx & rx encendidos SCIC3 = 0; for (;;) { if (tiempo == 0) { temperatura = darTemperatura(); dec_to_str(numstr, temperatura); send_str(numstr, 8); tiempo = T_INTERVALO_SERIE; } } } /* * Lee temperatura de 18B20 */ long darTemperatura(){ unsigned char valor_hi, valor_lo; long temp; unsigned int i; if (Reset()) return 255; WriteByte(0xCC); WriteByte(0xB8); WriteByte(0x01); (void)Reset(); WriteByte(0xCC); WriteByte(0x44); for(i = 0; i<10;i++){ wait(50000); } (void)Reset(); WriteByte(0xCC); WriteByte(0xBE); valor_lo = ReadByte(); valor_hi = ReadByte(); (void)Reset(); temp = valor_hi; temp = temp << 8; temp = temp | valor_lo; temp = ((temp * 10000) >> 4); return temp; // devuelve solo parte entera // la parte decimal hacela vos 🙂 } /* * Funciones genericas 1-Wire */ void wait(unsigned int microsec) { asm { LDHX microsec _seguir: AIX #-1 CPHX #0 BNE _seguir } } int Reset(void) { unsigned char result; _DIO = OUT; DIO = LOW; //Drives DQ low wait(480); DIO = HI; wait(120); _DIO = IN; result = DIO & 0x01; wait(360); return result; } void Write1(void) { _DIO = OUT; DIO = LOW; asm{ nop nop nop nop nop nop nop nop nop nop } DIO = HI; wait(59); } void Write0(void) { _DIO = OUT; DIO = LOW; wait(55); DIO = HI; wait(5); } int Readx(void) { unsigned char result; _DIO = OUT; DIO = LOW; asm{ nop nop nop nop nop nop nop nop nop nop } DIO = HI; wait(15); _DIO = IN; result = DIO & 0x01; wait(45); return result; } void WriteByte(unsigned char Data) { unsigned char loop; for (loop = 0; loop < 8; loop++) { if (Data & (0x01 << loop)) Write1(); else Write0(); } } unsigned char ReadByte(void) { unsigned char loop; unsigned char result = 0; for (loop = 0; loop < 8; loop++) { result = result + (Readx() << loop); } return result; } __interrupt VectorNumber_Vtpm1ovf void tpm1ovf(){ TPM1SC_TOF = 0; if (tiempo > 0){ tiempo--; } }