TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: kenniata en 08 de Septiembre de 2009, 10:19:03
-
Buenas a todos,
Estoy haciendo una tarjeta para un amigo para controlar una especie de invernadero. La temperatura y la humedad la captura con un SHT75. Tengo puesto un reloj DS1307 y una eeprom 24LC256 para guardar unos parametros. La idea es activar y desactivar unos relés en función de la hora, temperatura y humedad detectada. El problema es que el código no me arranca de ninguna manera. Antes, cuando quitaba la interrupción de RDA, en protoboard me funcionaba. Esta tarjeta a funcionado, este fin de semana me pase horas con ella, y cambie algo en el código que dejó de funcionar. Espero que alguien me pueda ayudar.
Muchas gracias de antemano
#include <16F877.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP
#use delay(clock=4000000)
#define num 10
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, stream=pc)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)
#include <DS1307.C> //Driver reloj
#include <LCD420.C> //driver lcd 4x20
#include <sht75.c> //sensor temp & hum
#include <24256.c> //driver eeprom 256
float restemp, truehumid;
char C_Ints=0;
char Flag=0;
char k, keys[num];
int hora_inicio, hora_final,i;
byte const NInts=15;
#int_RTCC
void RTCC_isr(void)
{
if(C_Ints > NInts) // Si las ints ocurridas > ints para 0.5 Seg.
{
if(Flag==0){
Flag=1;
}
else{
Flag=0;
}
C_Ints=0; // Reinicializo Contador de Ints
}
++C_Ints;
}
#int_RDA
void RDA_isr(void)
{
if(kbhit(pc))
{
gets(keys);
switch (keys[0])
{
case 'H':
ds1307_set_date_time(keys[3],keys[4],keys[5],1,keys[1],keys[2],0);
break;
case 'L':
hora_inicio=keys[1];
hora_final=keys[2];
fprintf(pc,"%d-%d",hora_inicio,hora_final);
break;
default:
break;
}
}
}
void main()
{
int aux;
BYTE sec;
BYTE min;
BYTE hrs;
BYTE day;
BYTE month;
BYTE yr;
BYTE dow;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
// INICIALIZACIÓN DE LOS DISPOSITIVOS
lcd_init();
ds1307_init();
sht_init();
enable_interrupts(INT_RTCC);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
init_ext_eeprom();
if (read_ext_eeprom(0)!=2)
{
ds1307_set_date_time(8,9,9,5,9,54,0);
write_ext_eeprom(0,2);
}
while(1)
{
if(Flag==K){}
else
{
sht_rd (restemp, truehumid);
delay_ms(1);
ds1307_get_date(day,month,yr,dow);
delay_ms(1);
ds1307_get_time(hrs,min,sec);
delay_ms(1);
lcd_gotoxy(1,1);
printf(lcd_putc, "Temp : %3.1f %cC ", restemp, 223);
lcd_gotoxy(1,2);
printf(lcd_putc, "RH : %3.1f %% ", truehumid);
lcd_gotoxy(1,3);
printf(lcd_putc,"\%02d/\%02d/\%02d",day,month,yr);
lcd_gotoxy(1,4);
printf(lcd_putc,"\%02d:\%02d:\%02d", hrs,min,sec);
k=Flag; // Guardo estado anterior de Flag
}
}
}
///////////////////////////////////////////////////////////////////////////////
// //
// Driver file for SHT75 Temperature & Humidity Sensor //
// //
// ***** To initialise SHT75 sensor upon power up ***** //
// //
// Function : sht_init() //
// Return : none //
// //
// //
// ***** To measure and caluculate SHT75 temp & real RH ***** //
// //
// Function : sht_rd (temp, truehumid) //
// Return : temperature & true humidity in float values //
// //
///////////////////////////////////////////////////////////////////////////////
#define sht_data_pin PIN_D3
#define sht_clk_pin PIN_C4
//***** Function to alert SHT75 *****
void comstart (void)
{
output_float(sht_data_pin); //data high
output_bit(sht_clk_pin, 0); //clk low
delay_us(1);
output_bit(sht_clk_pin, 1); //clk high
delay_us(1);
output_bit(sht_data_pin, 0); //data low
delay_us(1);
output_bit(sht_clk_pin, 0); //clk low
delay_us(2);
output_bit(sht_clk_pin, 1); //clk high
delay_us(1);
output_float(sht_data_pin); //data high
delay_us(1);
output_bit(sht_clk_pin, 0); //clk low
}
//***** Function to write data to SHT75 *****
int1 comwrite (int8 iobyte)
{
int8 i, mask = 0x80;
int1 ack;
//Shift out command
delay_us(4);
for(i=0; i<8; i++)
{
output_bit(sht_clk_pin, 0); //clk low
if((iobyte & mask) > 0) output_float(sht_data_pin); //data high if MSB high
else output_bit(sht_data_pin, 0); //data low if MSB low
delay_us(1);
output_bit(sht_clk_pin, 1); //clk high
delay_us(1);
mask = mask >> 1; //shift to next bit
}
//Shift in ack
output_bit(sht_clk_pin, 0); //clk low
delay_us(1);
ack = input(sht_data_pin); //get ack bit
output_bit(sht_clk_pin, 1); //clk high
delay_us(1);
output_bit(sht_clk_pin, 0); //clk low
return(ack);
}
//***** Function to read data from SHT75 *****
int16 comread (void)
{
int8 i;
int16 iobyte = 0;
const int16 mask0 = 0x0000;
const int16 mask1 = 0x0001;
//shift in MSB data
for(i=0; i<8; i++)
{
iobyte = iobyte << 1;
output_bit(sht_clk_pin, 1); //clk high
delay_us(1);
if (input(sht_data_pin)) iobyte |= mask1; //shift in data bit
else iobyte |= mask0;
output_bit(sht_clk_pin, 0); //clk low
delay_us(1);
}
//send ack 0 bit
output_bit(sht_data_pin, 0); //data low
delay_us(1);
output_bit(sht_clk_pin, 1); //clk high
delay_us(2);
output_bit(sht_clk_pin, 0); //clk low
delay_us(1);
output_float(sht_data_pin); //data high
//shift in LSB data
for(i=0; i<8; i++)
{
iobyte = iobyte << 1;
output_bit(sht_clk_pin, 1); //clk high
delay_us(1);
if (input(sht_data_pin)) iobyte |= mask1; //shift in data bit
else iobyte |= mask0;
output_bit(sht_clk_pin, 0); //clk low
delay_us(1);
}
//send ack 1 bit
output_float(sht_data_pin); //data high
delay_us(1);
output_bit(sht_clk_pin, 1); //clk high
delay_us(2);
output_bit(sht_clk_pin, 0); //clk low
return(iobyte);
}
//***** Function to wait for SHT75 reading *****
void comwait (void)
{
int16 sht_delay;
output_float(sht_data_pin); //data high
output_bit(sht_clk_pin, 0); //clk low
delay_us(1);
for(sht_delay=0; sht_delay<30000; sht_delay++) // wait for max 300ms
{
if (!input(sht_data_pin)) break; //if sht_data_pin low, SHT75 ready
delay_us(10);
}
}
//***** Function to reset SHT75 communication *****
void comreset (void)
{
int8 i;
output_float(sht_data_pin); //data high
output_bit(sht_clk_pin, 0); //clk low
delay_us(2);
for(i=0; i<9; i++)
{
output_bit(sht_clk_pin, 1); //toggle clk 9 times
delay_us(2);
output_bit(sht_clk_pin, 0);
delay_us(2);
}
comstart();
}
//***** Function to soft reset SHT75 *****
void sht_soft_reset (void)
{
comreset(); //SHT75 communication reset
comwrite(0x1e); //send SHT75 reset command
delay_ms(15); //pause 15 ms
}
//***** Function to measure SHT75 temperature *****
int16 measuretemp (void)
{
int1 ack;
int16 iobyte;
comstart(); //alert SHT75
ack = comwrite(0x03); //send measure temp command and read ack status
if(ack == 1) return;
comwait(); //wait for SHT75 measurement to complete
iobyte = comread(); //read SHT75 temp data
return(iobyte);
}
//***** Function to measure SHT75 RH *****
int16 measurehumid (void)
{
int1 ack;
int16 iobyte;
comstart(); //alert SHT75
ack = comwrite(0x05); //send measure RH command and read ack status
if(ack == 1) return;
comwait(); //wait for SHT75 measurement to complete
iobyte = comread(); //read SHT75 temp data
return(iobyte);
}
//***** Function to calculate SHT75 temp & RH *****
void calculate_data (int16 temp, int16 humid, float & tc, float & rhlin, float & rhtrue)
{
float truehumid1, rh;
//calculate temperature reading
tc = ((float) temp * 0.01) - 40.0;
//calculate Real RH reading
rh = (float) humid;
rhlin = (rh * 0.0405) - (rh * rh * 0.0000028) - 4.0;
//calculate True RH reading
rhtrue = ((tc - 25.0) * (0.01 + (0.00008 * rh))) + rhlin;
}
//***** Function to measure & calculate SHT75 temp & RH *****
void sht_rd (float & temp, float & truehumid)
{
int16 restemp, reshumid;
float realhumid;
restemp = 0; truehumid = 0;
restemp = measuretemp(); //measure temp
reshumid = measurehumid(); //measure RH
calculate_data (restemp, reshumid, temp, realhumid, truehumid); //calculate temp & RH
}
//***** Function to initialise SHT75 on power-up *****
void sht_init (void)
{
comreset(); //reset SHT75
delay_ms(20); //delay for power-up
}
[code]
////////////////////////////////////////////////////////////////////////////////
/// DS1307.C ///
/// Driver for Real Time Clock ///
/// ///
/// ds1307_init() - Enable oscillator without clearing the seconds register -///
/// used when PIC loses power and DS1307 run from 3V BAT ///
/// - Disable squarewave output ///
/// ///
/// ds1307_set_date_time(day,mth,year,dow,hour,min,sec) Set the date/time ///
/// ///
/// ds1307_get_date(day,mth,year,dow) Get the date ///
/// ///
/// ds1307_get_time(hr,min,sec) Get the time ///
/// ///
////////////////////////////////////////////////////////////////////////////////
#define RTC_SDA PIN_C4
#define RTC_SCL PIN_C3
#use i2c(slave, sda=RTC_SDA, scl=RTC_SCL)
BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);
void ds1307_init(void)
{
BYTE seconds = 0;
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_start();
i2c_write(0xD1); // RD from RTC
seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
i2c_stop();
seconds &= 0x7F;
delay_us(3);
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_write(bin2bcd(seconds)); // Start oscillator with current "seconds value
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x07); // Control Register
i2c_write(0x80); // Disable squarewave output pin
i2c_stop();
}
void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
sec &= 0x7F;
hr &= 0x3F;
i2c_start();
i2c_write(0xD0); // I2C write address
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_write(bin2bcd(sec)); // REG 0
i2c_write(bin2bcd(min)); // REG 1
i2c_write(bin2bcd(hr)); // REG 2
i2c_write(bin2bcd(dow)); // REG 3
i2c_write(bin2bcd(day)); // REG 4
i2c_write(bin2bcd(mth)); // REG 5
i2c_write(bin2bcd(year)); // REG 6
i2c_write(0x80); // REG 7 - Disable squarewave output pin
i2c_stop();
}
void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x03); // Start at REG 3 - Day of week
i2c_start();
i2c_write(0xD1);
dow = bcd2bin(i2c_read() & 0x7f); // REG 3
day = bcd2bin(i2c_read() & 0x3f); // REG 4
mth = bcd2bin(i2c_read() & 0x1f); // REG 5
year = bcd2bin(i2c_read(0)); // REG 6
i2c_stop();
}
void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_start();
i2c_write(0xD1);
sec = bcd2bin(i2c_read() & 0x7f);
min = bcd2bin(i2c_read() & 0x7f);
hr = bcd2bin(i2c_read(0) & 0x3f);
i2c_stop();
}
BYTE bin2bcd(BYTE binary_value)
{
BYTE temp;
BYTE retval;
temp = binary_value;
retval = 0;
while(1)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(temp >= 10)
{
temp -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += temp;
break;
}
}
return(retval);
}
// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
BYTE temp;
temp = bcd_value;
// Shifting upper digit right by 1 is same as multiplying by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;
// Now return: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
[/code]
-
Hola :mrgreen:
Estas lineas no te dan un error al compilar????
printf(lcd_putc,"\%02d/\%02d/\%02d",day,month,yr);
lcd_gotoxy(1,4);
printf(lcd_putc,"\%02d:\%02d:\%02d", hrs,min,sec);
Estas escapando el simbolo %, asi que los parametros day,month e yr, estan demas.
Intenta eliminando la barra invertida asi:
printf(lcd_putc,"%02d/%02d/%02d",day,month,yr);
lcd_gotoxy(1,4);
printf(lcd_putc,"%02d:%02d:%02d", hrs,min,sec);
Saludos!
-
Hola Geronimoo,
Siempre me ha compilado correctamente. Las barras es para hacer la separación de la fecha. Ahora he probado otro código, haciendo uso de uno que publicó J1M en su web. Funciona todo pero cuando activo la interrupción de RDA, entonces se cuelga el pic, no hace nada. Deshabilito la interrupción, vuelve todo a la normalidad. Estoy que me subo por las paredes!
-
Hola.
Creo que el I2C se va -por decirlo de alguna manera- cuando se activa alguna interrupción y se esta en pleno proceso de comunicación. Prueba deshabilitar la int_RDA cuando estes haciendo uso del I2C a ver que sucede.
Saludos
-
O de ultima, no uses interrupciones en RDA y reemplaza el codigo por polling :(
-
Hola MLO_,
Si deshabilito la interrupción de RDA, todo funciona correctamente. He puesto varios leds en la placa para que se activen en función de la linea del código que están. Se cuelga en la de enable RDA. Me tiene loco
Geronimo, cómo podría hacerlo sin que se quedase colgado esperando a la recepción de un caracter? Al PC sólo se conecta de vez en cuando, no está conectado siempre.
Gracias a ambos
-
Hola.
Lo mas recomendable, es que la interrupción no tome mucho tiempo, y veo que tienes un printf(); dentro de la interrupción. Mejor seria, asignar un flag dentro de la int_RDA y hacer todo lo que hace en el main.
Lo de deshabilitar la int_RDA seria momentáneo, solo cuando vas a usar el i2C, luego la podrías volver a activar.
Si solo vas a usar una USAR no es necesario el stream.
Saludos
-
Hola MLO_,
Si deshabilito la interrupción de RDA, todo funciona correctamente. He puesto varios leds en la placa para que se activen en función de la linea del código que están. Se cuelga en la de enable RDA. Me tiene loco
Geronimo, cómo podría hacerlo sin que se quedase colgado esperando a la recepción de un caracter? Al PC sólo se conecta de vez en cuando, no está conectado siempre.
Gracias a ambos
La funcion kbhit te sirve para hacer el poll al buffer del hardware.
En la ayuda de CCS hay un ejemplo, aunque basicamente se usa como la usaste en la rutina de la interrupcion.
kbhit( )
Returns:
0 (or FALSE) if getc() will need to wait for a character to come in, 1 (or TRUE) if a character is ready for getc()
Function:
If the RS232 is under software control this function returns TRUE if the start bit of a character is being sent on the RS232 RCV pin. If the RS232 is hardware this function returns TRUE if a character has been received and is waiting in the hardware buffer for getc() to read. This function may be used to poll for data without stopping and waiting for the data to appear. Note that in the case of software RS232 this function should be called at least 10 times the bit rate to ensure incoming data is not lost.
-
Che loco Soy Mariano, estudio en la UTN de Cordoba - Arg.
Estamos haciendo un trabajo similar, sensor de temperatura y humedad + un real time. y para poder visualizarlo en un LCD 2x16. Buscando en la red , llegue a tu POST. Y te funciono? jeje no se de donde sos prometo que te llega un fernet de litro a tu casa si me pasas el codigo . Saludos! un abrazo!