/**/ /* Bresciani Silvia **/ /* Piccinelli Mario **/ /* programma di controllo sensore di temperatura DS1631 **/ /**/ #include <p18f452.h> #include <math.h> #include <timers.h> #include <i2c.h> /* Configurazione dei fusibili #pragma romdata CONFIG rom const unsigned int config_word1=0xfaff; rom const unsigned int config_word2=0xfefc; rom const unsigned int config_word3=0xffff; rom const unsigned int config_word4=0xfffa; no debug!!! rom const unsigned int config_word4=0xff7a; with debug!!! rom const unsigned int config_word5=0xffff; rom const unsigned int config_word6=0xffff; rom const unsigned int config_word7=0xffff; #pragma romdata /* Prototipi int Sincro(int); void ee_repeatstart(void); void ee_data(int *x); void e_delay(void); void ee_start(void); void ee_byte(int x); void MasterAck(void); void aspetta(void); void setta_display(void); void int_alta(void); void int_bassa(void); int ConfigByteDS1631(int NewConfig); int StartTemperatureConversionDS1631(void); int ReadTemperatureFromDS1631(int *MSByteRead, int *LSByteRead); int ack(void); int segno_temperatura(char msb); int valore_intero_temperatura(char msb); int valore_decimale_temp(char lsb);
/* Gestione della jump table relativa agli interrupt #pragma code intvect=0x08 void isr_jump (void) _asm GOTO int_alta _endasm #pragma code #pragma code lowintvect=0x18 void isrlow_jump (void) _asm GOTO int_bassa _endasm #pragma code /* Routine di interrupt #pragma interrupt int_alta void int_alta(void) INTCONbits.TMR0IF=0; setta_display(); resetta il flag #pragma interruptlow int_bassa void int_bassa(void) /* Costanti pin sensore #define SCL PORTCbits.RC3 #define SCL_DIR TRISCbits.TRISC3 #define SDA PORTCbits.RC4 #define SDA_DIR TRISCbits.TRISC4 pin display #define DISPLAY1 PORTAbits.RA0 #define DISPLAY2 PORTAbits.RA1 #define DISPLAY3 PORTAbits.RA2 #define DISPLAYMENO PORTAbits.RA3 #define DISPLAY PORTD pin led
#define LED_VERDE PORTBbits.RB0 #define LED_ROSSO PORTBbits.RB1 costanti #define ON 1 #define OFF 0 #define IN 1 #define OUT 0 #define TRUE 1 #define FALSE 0 #define TCICLO 2500 #define TCONT 500 comandi sensore e bus 2-wire #define WRITE_CONTROL_BYTE #define READ_CONTROL_BYTE #define ACCESS_CONFIG #define START_TEMP_CONVERT #define READ_TEMPERATURE 0B10010000 0B10010001 0xAC 0x51 0xAA /* Variabili globali variabili sincronizzatore int t0 = 0; int tcont_temp; char newconfig; int status1, status2, status, segno, parte_intera, parte_frazionaria; char msb, lsb; /* Main void main (void) settaggio uscite TRISA = 0x00; TRISB = 0x00; TRISD = 0x00; inizializzazione timer1 per il sincronizzatore OpenTimer1(TIMER_INT_OFF & T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_8 & T1_OSC1EN_OFF); impostazione valore iniziale t0 t0=readtimer1();
inizializzazione timer0 per interrupt display OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_8); INTCON2bits.TMR0IP = 1; alta priorità inizializzazione sensore newconfig = 0b10001110; status1 = ConfigByteDS1631(newconfig); status2 = StartTemperatureConversionDS1631(); controllo condizione di errore if (!status1!status2) parte_intera = 200; segnalazione condizione errore LED_ROSSO = ON; LED_VERDE = ON; attivazione interrupt (necessario per il funzionamento dei display) INTCONbits.GIE = 1; while(1); stop programma LED_VERDE = 1; LED_ROSSO = 0; while (1) INTCONbits.GIE = 0; disattivazione interrupt status = ReadTemperatureFromDS1631(&msb, &lsb); verifica condizione di errore if (!status) parte_intera = 200; LED_ROSSO = ON; LED_VERDE = ON; attivazione interrupt (necessario per il funzionamento dei display) INTCONbits.GIE = 1; while(1); stop programma assegnazione variabili globali segno = segno_temperatura(msb); parte_intera = valore_intero_temperatura(msb); parte_frazionaria = valore_decimale_temp(lsb); lampeggio led LED_VERDE =!LED_VERDE; LED_ROSSO =!LED_ROSSO; INTCONbits.GIE = 1; riattivazione interrupt
sincronizzazione tcont_temp = TCONT; do t0=sincro(t0); tcont_temp--; while (tcont_temp >= 0); /* Routine sincronizzazione "equidistant" int Sincro(int T0c) int T1; do T1=ReadTimer1(); while ((T1-T0c)<TCICLO); return (T0c+TCICLO); int ConfigByteDS1631(int NewConfig) /* ritorna TRUE se l'operazione è andata a buon fine */ ee_start(); /* sequenza di start */ ee_byte(write_control_byte); /* byte di controllo (scrittura) */ ee_byte(access_config); /* comando di accesso al registro */ ee_byte(newconfig); /* scrittura della nuova configurazione */
SDA=0; /* sequenza di stop */ SDA_DIR=OUT; SCL = 1; SDA = 1; return(true); int StartTemperatureConversionDS1631(void) /* ritorna TRUE se l'operazione è andata a buon fine */ ee_start(); /* sequenza di start */ ee_byte(write_control_byte); /* byte di controllo (scrittura) */ ee_byte(start_temp_convert); /* comando di inizio conversione temperatura */ SDA=0; /* sequenza di stop */ SDA_DIR=OUT; SCL = 1; SDA = 1; return(true); void ee_repeatstart() SCL = 0; SDA_DIR=OUT; SCL_DIR=OUT; SDA = 1;
SCL = 1; SDA = 0; int ReadTemperatureFromDS1631(int *MSByteRead, int *LSByteRead) /* ritorna TRUE se l'operazione è andata a buon fine */ ee_start(); /* sequenza di start */ ee_byte(write_control_byte); /* byte di controllo (scrittura) */ ee_byte(read_temperature); /* comando di lettura temperatura */ ee_repeatstart(); /* sequenza di restart della linea */ ee_byte(read_control_byte); /* byte di controllo (lettura) */ ee_data(msbyteread); /* lettura MSB */ MasterAck(); /* invio ACK */ ee_data(lsbyteread); /* lettura LSB */ ack(); /* invio ACK */ /* sequenza di stop */ SDA=0; SDA_DIR = OUT; SCL=1; SDA=1; return(true); tempo di riconoscimento per ogni bit void e_delay() int delay; for(delay=0;delay<10;delay++);
sequeza di start della linea void ee_start(void) SDA_DIR=OUT; SCL_DIR=OUT; SDA = 0; SCL = 1; SDA = 1; stop SDA=0; start scrittura di un byte sulla linea void ee_byte(int x) int i; i=0x80; do SDA_DIR=OUT; if (x&i) SDA=1; else SDA=0; SCL=1; i>>=1; while(i!=0); lettura di un byte dalla linea void ee_data(int *x)
int i; SDA_DIR=IN; *x=0; i=0x80; do SCL=1; if (SDA) *x=(*x) i; i>>=1; while(i!=0); controllo ack int ack(void) SDA_DIR=IN; SCL=1; /* controllo ack */ return(sda); invio ack da parte del master void MasterAck(void) SDA=0; SDA_DIR=OUT; SCL=1;
routines per convertire i byte letti dal sensore in valori decimali (memorizzati in variabili globali) int temp_high, temp_low, segno; int segno_temperatura(char msb) int segno = (msb >> 7) & 0x01; return segno; int valore_intero_temperatura(char msb) int segno = (msb >> 7) & 0x01; if (segno) msb = msb - 0b10000000; temp_high = msb; return temp_high; int valore_decimale_temp(char lsb) lsb = lsb >> 4; temp_low = lsb * 625; return temp_low; simboli per visualizzare i valori sui display a 7 segmenti char display[] = 0b01111110, 0b00110000, 0b01101101, 0b01111001, 0b00110011, 0b01011011, 0b01011111, 0b01110000, 0b01111111, 0b01110011 ; simboli per visualizzare o meno il simbolo "-" sul primo display char segno_simboli[] = 0x00,0b00000001;
refresh dei display void setta_display() int decine, unita, decimi, meno; int intero, decimale; DISPLAY1 = OFF; DISPLAY2 = OFF; DISPLAY3 = OFF; DISPLAYMENO = OFF; intero = parte_intera; decimale = parte_frazionaria; meno = segno; display in caso di condizione di errore indicata imponendo il valore parte_intera = 200 if (parte_intera >= 200) DISPLAY = 0x01; DISPLAYMENO = ON; DISPLAYMENO = OFF; DISPLAY1 = ON; DISPLAY1 = OFF; DISPLAY2 = ON; DISPLAY2 = OFF; DISPLAY3 = ON; DISPLAY3 = OFF; return; si è scelto di non disegnare il valore delle centinaia if (intero > 100) intero -= 100; decine = intero / 10; unita = intero - decine * 10; decimi = decimale / 1000; DISPLAY = segno_simboli[meno]; DISPLAYMENO = ON; DISPLAYMENO = OFF; DISPLAY = display[decine]; DISPLAY1 = ON; DISPLAY1 = OFF;
DISPLAY = display[unita]; DISPLAY2 = ON; DISPLAY2 = OFF; DISPLAY = display[decimi]; DISPLAY3 = ON; DISPLAY3 = OFF; void aspetta() int i; for (i = 0; i < 10; i++) _asm NOP _endasm