#if defined(__PCM__)
#include <16f886.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock = 4000000)
#use rs232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#use standard_io(c)
int dato;
float contador,caudal;
// Función de interrupción por recepción en modo asíncrono
#INT_RDA
void recepcion()
{
// Se captura el valor del dato transmitido
dato = getch();
// Si el dato recibido es y entonces transmite el caudal
if (dato == 0x79)
{
caudal = 10*contador;
printf("%f", caudal);
contador = 0;
}
}
// Función de interrupción por cambio de flanco en RB0
#INT_EXT
void externa()
{
// Si entra a la interrupción se incrementa el contador que lleva la cuenta
// de los pulsos enviados por el medidor de caudal en respectivo tiempo de
// Muestreo
contador = contador + 1;
}
void main()
{
//float caudal;
// Puerto a y b como entradas digitales
set_tris_b(0xff);
set_tris_a(0xff);
// Se configuran las interrupciones por recepción en Rs232 y por cambio de flancon en RB0
enable_interrupts(INT_RDA);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
// Se configura el flanco de activación de la interrupción externa
ext_int_edge(H_TO_L );
// Se inicializan las variables de interés
caudal = 0;
contador = 0;
// Se actival la pull-up en el puerto B del micro
port_b_pullups(TRUE);
setup_uart(UART_WAKEUP_ON_RDA);
do
{
sleep(); // Se queda dormido hasta que ocurra la interrupción por trasmisión o recepción en la USART
}while(true);
}
do
{
sleep(); // Se queda dormido hasta que ocurra la interrupción por trasmisión o recepción en la USART
}while(true);void recepcion() pero tengo entendido que el micro, cuando despierta de un SLEEP por una interrupción, siempre ejecuta al siguiente instrucción al SLEEP, ya que el PC pasa a valer PC+1
Creo que se cual es el problema, recuerdo que la funcionalidad de despertar al recibir un caracter por el puerto serial solo se puede realizar con micros que traen el EUSART, el PIC16F886 lo trae, pero aqui viene el detalle primero tiene que enviarle al micro el caracter BREAK ,es decir 0x00, no puede tomar el primer caracter como valido, creo que ahi esta su error.
En la hoja de datos en la seccion AUTO-WAKE-UP ON BREAK se encuentran los pasos a seguir para salir del SLEEP, la verdad no se como lo hara el CCS, talvez deba declarar los registros y los bits involucrados para hacerlo a mano.
Fijate en la imagen que te mostré, cuando el micro se despierta primero se ejecuta la instrucción de PC+1 y luego va ha la interrupción, tal como o aclara la Nota 1, por eso en ASM siempre se coloca un NOP después de un SLEEP.Citarpero tengo entendido que el micro, cuando despierta de un SLEEP por una interrupción, siempre ejecuta al siguiente instrucción al SLEEP, ya que el PC pasa a valer PC+1
Sinceramente nunca había trabajado con el modulo sleep de los microcontroladores pero según entiendo el micro puede salir de tal estado a producirse ciertas interrupciones ya sean por hardware o por software (esto depende del micro), una vez la rutina de interrupción se ejecuta el microcontrolador retorna al PC +1 pero tengo entendido que primeramente ejecuta las instrucciones que se encuentra en la respectiva interrupción que lo saco de tal estado.
Fijate en la imagen que te mostré, cuando el micro se despierta primero se ejecuta la instrucción de PC+1 y luego va ha la interrupción, tal como o aclara la Nota 1, por eso en ASM siempre se coloca un NOP después de un SLEEP.
#if defined(__PCM__)
#include <16f886.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock = 4000000)
#use rs232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#use standard_io(c)
int dato,Envia;
float contador,caudal;
// Función de interrupción por recepción en modo asíncrono
#INT_RDA
void recepcion()
{
// Se captura el valor del dato transmitido
dato = getch();
//setup_uart(UART_WAKEUP_ON_RDA);
// Si el dato recibido es y entonces transmite el caudal
if (dato == 0x79)
{
Envia = 1;
}
}
// Función de interrupción por cambio de flanco en RB0
#INT_EXT
void externa()
{
// Si entra a la interrupción se incrementa el contador que lleva la cuenta
// de los pulsos enviados por el medidor de caudal en respectivo tiempo de
// Muestreo
contador = contador + 1;
}
void main()
{
//float caudal;
// Puerto a y b como entradas digitales
set_tris_b(0xff);
set_tris_a(0xff);
// Se configuran las interrupciones por recepción en Rs232 y por cambio de flancon en RB0
enable_interrupts(INT_RDA);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
// Se configura el flanco de activación de la interrupción externa
ext_int_edge(H_TO_L );
// Se inicializan las variables de interés
caudal = 0;
contador = 0;
// Se actival la pull-up en el puerto B del micro
port_b_pullups(TRUE);
//setup_uart(UART_WAKEUP_ON_RDA);
do
{
setup_uart(UART_WAKEUP_ON_RDA);
sleep(); // Se queda dormido hasta que ocurra la interrupción por trasmisión o recepción en la USART
delay_ms(5);
if(Envia == 1)
{
caudal = 10*contador;
printf("%f", caudal);
contador = 0;
Envia = 0;
}
}while(true);
}
#if defined(__PCM__)
#include <16f886.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock = 4000000)
#use rs232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#use standard_io(c)
#bit WUE = 0X187.1
int dato,Envia,duerme;
float contador,caudal;
// Función de interrupción por recepción en modo asíncrono
#INT_RDA
void recepcion()
{
// Se captura el valor del dato transmitido
if(duerme)
{
while(WUE==1);
duerme = 0;
dato = getch();
}
else
{
dato = getch();
//setup_uart(UART_WAKEUP_ON_RDA);
// Si el dato recibido es y entonces transmite el caudal
if (dato == 0x79)
{
Envia = 1;
}
}
}
// Función de interrupción por cambio de flanco en RB0
#INT_EXT
void externa()
{
// Si entra a la interrupción se incrementa el contador que lleva la cuenta
// de los pulsos enviados por el medidor de caudal en respectivo tiempo de
// Muestreo
contador = contador + 1;
}
void main()
{
int conta;
//float caudal;
// Puerto a y b como entradas digitales
set_tris_b(0xff);
set_tris_a(0xff);
// Se configuran las interrupciones por recepción en Rs232 y por cambio de flancon en RB0
enable_interrupts(INT_RDA);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
// Se configura el flanco de activación de la interrupción externa
ext_int_edge(H_TO_L );
// Se inicializan las variables de interés
caudal = 0;
contador = 0;
// Se actival la pull-up en el puerto B del micro
port_b_pullups(TRUE);
duerme = 1;
conta = 0;
Envia = 0;
do
{
setup_uart(UART_WAKEUP_ON_RDA);
sleep(); // Se queda dormido hasta que ocurra la interrupción por trasmisión o recepción en la USART
delay_us(8);
while(duerme == 0)
{
if(Envia == 1)
{
caudal = 10*contador;
printf("%f", caudal);
contador = 0;
Envia = 0;
duerme = 1;
}
}
}while(true);
}