/* Real time clock using PIC16F887 & DS3231 (DS3232) CCS C code
Read DS3231 RTC datasheet to understand the code!
Internal oscillator used @ 8MHz
http://ccspicc.blogspot.com/
electronnote@gmail.com
*/
////COMANDOS:
///set:22:21 ///pone hour en 22:21
///hour ///muestra la hour
///tiempo muestra el tiempo de activacion grabado en dir 0x00
///ta:10;//ajusta tiempo activacion en eeprom 0x00
////ver ///muestra los programas
///de:1///borra programa 1
//pr1:23:45 ///setea programa en 23:45
///los programas estan en las posiciones:
///t1=0x20, m1=0x21
//t2=0x30, m2=0x31
//t3=0x41, m3=0x041
///t4=0x50, m4=0x51
//t5=0x60; m5=0x61
#include <16F887.h>
#include <stdlib.h>////para poder hacer las conversiones a entero
#include <string.h>
#fuses MCLR NOBROWNOUT NOLVP INTRC_IO PROTECT
#use delay(clock = 4MHz)
#use I2C(master, I2C1, SLOW)
#use rs232(uart1, baud=9600)//usart1 -->ajuste de XMIT y RCV para la USART 1
unsigned int8 i, second, minute, hour, date=1, month=5, year=19,DHora,DMinutos,UHora,UMinutos,TActivacion=10;
int8 t1,t2,t3,t4,t5;
int8 m1,m2,m3,m4,m5;
// CONSTANTES /////////////////////////////////////////////////////////////////
int const lenbuff=32; // Longitud de buffer, Ajustar
// a lo que desees (o te sea posible)
// VARIABLES EN RAM ///////////////////////////////////////////////////////////
int xbuff=0x00; // Índice: siguiente char en cbuff
char cbuff[lenbuff]; // Buffer
char rcvchar=0x00; // último caracter recibido
char strHoras[3];
char strMinutos[3];
char strTa[3];
int1 flagcommand=0; // Flag para indicar comando disponible
int1 EsNumero=0;
int1 EsHora=0;
int8 CantidadNumeros=0;
int1 Activar=0;//me dice si tengo que activar la salida
// Declaración de Funciones ///////////////////////////////////////////////////
void inicbuff(void); // Borra buffer
int addcbuff(char c); // añade caracter recibido al buffer
void echos(char c); // Eco
// Desarrollo de Funciones ////////////////////////////////////////////////////
void inicbuff(void){ // Inicia a cbuff -------------------
int i;
for(i=0;i<lenbuff;i++){ // Bucle que pone a 0 todos los
cbuff[ i ]=0x00; // caracteres en el buffer
}
xbuff=0x00; // Inicializo el indice de siguiente
// caracter
}
int addcbuff(char c)
{ // Añade a cbuff -----------------------
cbuff[xbuff++]=c; // Añade caracter recibido al Buffer
}
// INTERRUPCIONES /////////////////////////////////////////////////////////////
#int_rda
void serial_isr() { // Interrupción recepción serie USART
///restart_wdt();
rcvchar=0x00; // Inicializo caracter recibido
if(kbhit()){ // Si hay algo pendiente de recibir ...
rcvchar=getc(); // lo descargo y ...
addcbuff(rcvchar); // lo añado al buffer y ...
///echos(rcvchar); // hago eco (si procede).
}
}
ImprimirPlantillaReloj(void)
{
printf("%u",DHora);
printf("%u",UHora);
printf(":");
printf("%u",DMinutos);
printf("%u\r\n",UMinutos);//salto de linea
}
ObtenerHoraActual(void)
{
// read current time and date from the RTC chip}
i2c_start(); // Start I2C protocol
i2c_write(0xD0); // DS3231 address
i2c_write(0); // Send register address
i2c_start(); // Restart I2C
i2c_write(0xD1); // Initialize data read
second = i2c_read(1); // Read seconds from register 0
minute = i2c_read(1); // Read minuts from register 1
hour = i2c_read(1); // Read hour from register 2
i2c_read(1); // Read day from register 3 (not used)
date = i2c_read(1); // Read date from register 4
month = i2c_read(1); // Read month from register 5
year = i2c_read(0); // Read year from register 6
i2c_stop();
}
ModificarPrograma(int8 DirHora,DirMin)
{
write_eeprom(DirHora,hour);
delay_ms(5);
write_eeprom(DirMin,minute);
delay_ms(5);
}
int8 LeerTActivacion(void)
{
TActivacion=read_eeprom(0x00);///lee la memoria
if(TActivacion==0xFF)TActivacion=10;///valor por defecto
delay_ms(5);
return(TActivacion);
}
GuardarTActivacion(void)
{
write_eeprom(0x00,TActivacion);///guardo el tiempo de activacion
delay_ms(5);
}
int1 comprobarSiNumero()
{
EsNumero=0;
CantidadNumeros=0;
for (i=4;i<=8;++i)
if((cbuff[i]=='0')||(cbuff[i]=='1')||(cbuff[i]=='2')||(cbuff[i]=='3')||(cbuff[i]=='4')||(cbuff[i]=='5')||(cbuff[i]=='6')||(cbuff[i]=='7')||(cbuff[i]=='8')||(cbuff[i]=='9'))CantidadNumeros=CantidadNumeros+1;
if(CantidadNumeros==4)EsNumero=1;
else EsNumero=0;
return(EsNumero);
}
int1 comprobarTActivacion()
{
CantidadNumeros=0;//inicalizo la cuenta
if((cbuff[4]=='0')||(cbuff[4]=='1')||(cbuff[4]=='2')||(cbuff[4]=='3')||(cbuff[4]=='4')||(cbuff[4]=='5')||(cbuff[4]=='6')||(cbuff[4]=='7')||(cbuff[4]=='8')||(cbuff[4]=='9'))CantidadNumeros=CantidadNumeros+1; if(CantidadNumeros==4)EsNumero=1;
if((cbuff[3]=='0')||(cbuff[3]=='1')||(cbuff[3]=='2')||(cbuff[3]=='3')||(cbuff[3]=='4')||(cbuff[3]=='5')||(cbuff[3]=='6')||(cbuff[3]=='7')||(cbuff[3]=='8')||(cbuff[3]=='9'))CantidadNumeros=CantidadNumeros+1; if(CantidadNumeros==4)EsNumero=1;
if(CantidadNumeros==2) return(1);
else return(0);
}
CargarProgramas(void)//cargo los tiempos de programacion
{
///los programas estan en las posiciones:
///t1=0x20, m1=0x21
//t2=0x30, m2=0x31
//t3=0x41, m3=0x041
///t4=0x50, m4=0x51
//t5=0x60; m5=0x61
t1=read_eeprom(0x20);///lee la memoria
delay_ms(5);
t2=read_eeprom(0x30);///lee la memoria
delay_ms(5);
t3=read_eeprom(0x40);///lee la memoria
delay_ms(5);
t4=read_eeprom(0x50);///lee la memoria
delay_ms(5);
t5=read_eeprom(0x60);///lee la memoria
delay_ms(5);
m1=read_eeprom(0x21);///lee la memoria
delay_ms(5);
m2=read_eeprom(0x31);///lee la memoria
delay_ms(5);
m3=read_eeprom(0x41);///lee la memoria
delay_ms(5);
m4=read_eeprom(0x51);///lee la memoria
delay_ms(5);
m5=read_eeprom(0x61);///lee la memoria
delay_ms(5);
}
MostrarProgramas(void)
{
printf("Los Horarios programados son:\r\n");
if(t1==0xFF) printf("vacio:\r\n");
else
{
DHora=t1/10;///descompongo hora actual
UHora=t1%10;
DMinutos=m1/10;
UMinutos=m1%10;
ImprimirPlantillaReloj();
}
if(t2==0xFF) printf("vacio:\r\n");
else
{
DHora=t2/10;///descompongo hora actual
UHora=t2%10;
DMinutos=m2/10;
UMinutos=m2%10;
ImprimirPlantillaReloj();
}
if(t3==0xFF) printf("vacio:\r\n");
else
{
DHora=t3/10;///descompongo hora actual
UHora=t3%10;
DMinutos=m3/10;
UMinutos=m3%10;
ImprimirPlantillaReloj();
}
if(t4==0xFF) printf("vacio:\r\n");
else
{
DHora=t4/10;///descompongo hora actual
UHora=t4%10;
DMinutos=m4/10;
UMinutos=m4%10;
ImprimirPlantillaReloj();
}
if(t5==0xFF) printf("vacio:\r\n");
else
{
DHora=t5/10;///descompongo hora actual
UHora=t5%10;
DMinutos=m5/10;
UMinutos=m5%10;
ImprimirPlantillaReloj();
}
}
int1 ComprobarSiHora()
{
EsHora=0;
if((comprobarSiNumero()==1)&&(cbuff[6]==':'))
{
strHoras[0]=cbuff[4];
strHoras[1]=cbuff[5];
hour=atol(strHoras);
strMinutos[0]=cbuff[7];
strMinutos[1]=cbuff[8];
minute=atol(strMinutos);
if((hour<24)&&(minute<60))EsHora=1;
else EsHora=0;
}
return(EsHora);
}
ModificarSalida(void)
{
ObtenerHoraActual();//obtiene la hora
if(((t1==hour)&&(m1==minute))||((t2==hour)&&(m2==minute))||((t3==hour)&&(m3==minute))||((t4==hour)&&(m4==minute))|((t5==hour)&&(m5==minute)))Activar=1;
else Activar=0;
while((second<TActivacion)&&(Activar==1))
{
//restart_wdt();
ObtenerHoraActual();//obtiene la hora
output_high(PIN_B3);
delay_ms(1000);///espera que pase el tiempo
}
output_Low(PIN_B3);///salida rele
Activar=0;
}
void SetDateTime(){
// Convert decimal to BCD
minute = ((minute / 10) << 4) + (minute % 10);
hour = ((hour / 10) << 4) + (hour % 10);
date = ((date / 10) << 4) + (date % 10);
month = ((month / 10) << 4) + (month % 10);
year = ((year / 10) << 4) + (year % 10);
// End conversion
// Write data to DS3231 RTC
i2c_start(); // Start I2C protocol
i2c_write(0xD0); // DS3231 address
i2c_write(0);
i2c_write(0); // Reset sesonds and start oscillator
i2c_write(minute); // Write minute value to DS3231
i2c_write(hour); // Write hour value to DS3231
i2c_write(1); // Write day value (not used)
i2c_write(date); // Write date value to DS3231
i2c_write(month); // Write month value to DS3231
i2c_write(year); // Write year value to DS3231
delay_ms(200); // Wait 200ms
}
void DS3231_display(){
// Convert BCD to decimal
second = (second >> 4) * 10 + (second & 0x0F);
minute = (minute >> 4) * 10 + (minute & 0x0F);
hour = (hour >> 4) * 10 + (hour & 0x0F);
date = (date >> 4) * 10 + (date & 0x0F);
month = (month >> 4) * 10 + (month & 0x0F);
year = (year >> 4) * 10 + (year & 0x0F);
// End conversion
DHora=hour/10;///descompongo hora actual
UHora=hour%10;
DMinutos=minute/10;
UMinutos=minute%10;
printf("%u",DHora);
printf("%u",UHora);
printf(":");
printf("%u",DMinutos);
printf("%u\r\n",UMinutos);//salto de linea
}
void main(){
setup_oscillator(OSC_4MHZ); // Set internal oscillator to 8MHz
enable_interrupts(int_rda);
enable_interrupts(global);
set_tris_b (0x00);///todos Salidas
inicbuff(); // Borra buffer al inicio
output_Low(PIN_B3);///salida rele en bajo
CargarProgramas();///Cargo los programas
while(TRUE){
flagcommand=0;///todavia no recibi un comando
inicbuff(); ///borra buffer
ModificarSalida();///modifica la salida segun los programas
delay_ms(1000);///espera que pase el tiempo
if((cbuff[0]=='h')&&(cbuff[1]=='o')&&(cbuff[2]=='r')&&(cbuff[3]=='a'))///comando para ver la hour
{
flagcommand=1; ///me dice que recibio un comando
printf("%s\r\n",cbuff);//salto de linea
printf("La hora Actual es: ");
ObtenerHoraActual();////me da la hora actual
DS3231_display();///muestra la hour
inicbuff(); ///borra buffer
}
if((cbuff[0]=='t')&&(cbuff[1]=='i')&&(cbuff[2]=='e')&&(cbuff[3]=='m')&&(cbuff[4]=='p')&&(cbuff[5]=='o'))///comando para ver tiempo activacion
{
flagcommand=1; ///me dice que recibio un comando
TActivacion=LeerTActivacion();
printf("El tiempo de activacion es: ");
printf("%d\r\n",TActivacion);//salto de lineaTactivacion
inicbuff(); ///borra buffer
}
if(flagcommand==0) inicbuff(); ///borra buffer
delay_ms(1000);
}
}
int addcbuff(char c)
{ // Añade a cbuff -----------------------
cbuff[xbuff++]=c; // Añade caracter recibido al Buffer
}cual seria el codigo? if((cbuff[i]=>'0')&&(cbuff[i]<='9'))Lo del desborde del buffer no me afecta, ya que si el comando tiene mas de la longuitud maxima, no es un comando valido y por lo tanto no se debe hacer nada, pero es cierto que si yo mando ""hora1234", el comando se ejecuta igual, pero eso no tiene nada que ver con el desbordamiento. Me seria util poder obtener la longuitud de la cadena de caracteres que me envian, pero no se como hacer eso.Yo vengo de la epoca del asembler y aprendi algo de C por mi cuenta, es por eso que mi programacion es un poco rustica.
Lo segundo, segun interpreto el buffer contiene caracteres, y con los caracteres no hay uno que sea mayor al otro, por lo que no entiendo la linea:Lo que vos comparas son numeros, los caracteres estan representados por numeros hexadecimales, el '0' es el 0x30, el 9 es 0x39. Por lo tanto al comparar en realidad estamos diciendo que si es mayor o igual a 0x30 y menor o igual a 0x39, en ves de preguntar por 0x30, x031,etc ..
cual seria el codigo?Agregar una proteccion al indice... para que nunca exceda el largo dado por "lenbuff"
Como puedo solucionar el problema que se da si mando "hora1234"?ya que lo tomaria como un comando correcto?Mas que ese problema y el del buffer overflow me preocuparía por cambiar tu sistema de detección de palabras.... en alguno que sea independiente de la posición en el array.
Gracias por responder. En realidad si los comandos no son los correctos, por ejemplo "hola", no tiene que pasar nada, lo que si, si mando "hola1234", no tendria que ejecutar ningun comando. Para ello debo saber la longuitud de la palabra recibida. que supongo que puede ser aumentando un indice con cada recepcion. Voy a tratar de implementar. Yo necesito poder recibir string que empiecen igual y solo aceptar el comando si éste está en la posicion correcta y no tiene caracteres adicionales. Voy a implementar eso que me dijiste de los flag, gracias por tu tiempo.