Temperatura con DS18B20

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

– La fBus en este caso es 8 MHz, si habrá que cambiar la función

wait(), Write1() y Readx()

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

/*
MCU         18B20
       -- | VCC
       |
      Rpu
       |       
B3 | ---- | DQ
   | ---- | 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--;
	}
}

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *