desktop

PIC16F886 a 125 Khz, no funciona conexión serie con PC

Hola a todos. Soy nuevo en el foro, aunque hace bastante que los sigo, es la primera vez que escribo.
Soy ingeniero electrónico y no hace mucho empecé a programar PIC.

Les cuento que estoy realizando un proyecto con PIC, el cual debe contar meses.

Utilizo un reloj de 125KHZ interno, ya que debo tener bajo consumo en el integrado, lo voy a alimentar con pilas.

Cada vez que pase algún día debo grabar en la memoria interna del PIC, la cantidad de días y meses que transcurrió.
La idea mía es que para corroborar el funcionamiento de que los días contados son los correctos, envié estos datos por la interfaz serie del PIC.
Para esto me compre un conversor USB- TTL para conectar el PIC directamente a la PC, sin utilizar el MAX232.
El problema que tengo, es que me envía basura el PIC, una vez que defino el oscilador interno. Esto me dí cuenta porque por cada línea puse un printf para saber en que momento falla.

Observen el código y me van a entender.
PHP:
#include <16f886.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC                 //Internal RC Osc,CLKOUT
#FUSES PUT                    // Power Up Timer
#FUSES MCLR                   //Master Clear pin used for I/O
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOCPD                    //No EE protection
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOWRT                    //Program memory not write protected
#use delay(internal=125khz) //OSC interno
#use rs232(baud=1200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)// preguntar si esta bien la velocidad
#include <internal_eeprom.c>
#BYTE ADRESL = 0x9e 
#BYTE ADRESH = 0x1e
#BYTE ADCON0 = 0X1F
#BYTE ADCON1 = 0X9F
int1 flanco_detectormemoria=0,grabo=0;
int8 Segundos=0,Minutos=0, Hora=0, Dias=0 , Mes=0,Mes_aux=0;

#int_timer1
void timer_1()
{
clear_interrupt(int_timer1);     // Limpiar flag por desborde del TMR1
Segundos++;
output_high(PIN_B0);
set_timer1(58550);               //Esto se hara cada 1 seg
//if(Segundos == 60){Segundos=0;Minutos++;}
}
void sonaralarma(){
   int8 i=0;
   output_high(PIN_A1);
   while(i<10){
   output_high(PIN_A2);
   delay_ms(500);
   output_low(PIN_A2);
   i++;
   }
     
}

void main()
{
   printf("comienso11\n\r");
   setup_oscillator(OSC_125KHZ); //OSC_31KHZ
   printf("comienso22\n\r");
   setup_oscillator(OSC_INTRC);  //OSCCON = 00000011;
   printf("comienso33\n\r");
   set_tris_a(0b11111000);          // ENTRADAS= RA7 RA6 RA5 RA4 RA3 SALIDAS= RA2 RA1 RA0
   printf("comienso44\n\r");
   set_tris_b(0b11110000);          // ENTRADAS= RB7 RB6 RB5 RB4 SALIDAS= RB3 RB2 RB1 RB0
   printf("comienso55\n\r");
   setup_adc(ADC_CLOCK_INTERNAL);
   printf("comienso66\n\r");
   setup_adc_ports(sAN8);// VER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   printf("comienso77\n\r");
   output_b(0b0); //Se inicializa en 0
   printf("comienso88\n\r");
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   printf("comienso99\n\r");
   enable_interrupts(int_timer1); //Habilita interrupcion del Timer 1
   printf("comienso100\n\r");
   enable_interrupts(global); // Habilita interrupcion Global
   printf("comienso110011\n\r");
   set_timer1(58550); // Carga el TMR1 con 57786
   output_low(PIN_A2);  
   //-----------------Comienzo Programa--------------------
   printf("hola mundooo11\n\r");
   if (input(PIN_B4) == 0 && input(PIN_B5) ==0 && input(PIN_B6) ==0 && input(PIN_B7) ==0){ flanco_detectormemoria=0; setup_timer_1(T1_DISABLED);grabo=0; //Reinicio Memoria del contador.
   }
   else{       if(input(PIN_B4) == 0 && input(PIN_B5) ==0 && input(PIN_B6) ==0 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =1;}            //1 Mes
               if(input(PIN_B4) == 0 && input(PIN_B5) ==0 && input(PIN_B6) ==1 && input(PIN_B7) ==0){flanco_detectormemoria=1;Mes_aux =2;}            //2 Meses  
               if(input(PIN_B4) == 0 && input(PIN_B5) ==0 && input(PIN_B6) ==1 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =3;}            //3 Meses 
               if(input(PIN_B4) == 0 && input(PIN_B5) ==1 && input(PIN_B6) ==0 && input(PIN_B7) ==0){flanco_detectormemoria=1;Mes_aux =4;}            //4 Meses
               if(input(PIN_B4) == 0 && input(PIN_B5) ==1 && input(PIN_B6) ==0 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =5;}            //5 Meses
               if(input(PIN_B4) == 0 && input(PIN_B5) ==1 && input(PIN_B6) ==1 && input(PIN_B7) ==0){flanco_detectormemoria=1;Mes_aux =6;}            //6 Meses
               if(input(PIN_B4) == 0 && input(PIN_B5) ==1 && input(PIN_B6) ==1 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =7;}            //7 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==0 && input(PIN_B6) ==0 && input(PIN_B7) ==0){flanco_detectormemoria=1;Mes_aux =8;}            //8 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==0 && input(PIN_B6) ==0 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =9;}            //9 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==0 && input(PIN_B6) ==1 && input(PIN_B7) ==0){flanco_detectormemoria=1;Mes_aux =10;}            //10 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==0 && input(PIN_B6) ==1 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =11;}            //11 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==1 && input(PIN_B6) ==0 && input(PIN_B7) ==0){flanco_detectormemoria=1;Mes_aux =12;}            //12 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==1 && input(PIN_B6) ==0 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =13;}            //13 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==1 && input(PIN_B6) ==1 && input(PIN_B7) ==0){flanco_detectormemoria=1;Mes_aux =14;}            //14 Meses
               if(input(PIN_B4) == 1 && input(PIN_B5) ==1 && input(PIN_B6) ==1 && input(PIN_B7) ==1){flanco_detectormemoria=1;Mes_aux =15;}            //15 Meses
   }
   printf("hola mundooo22\n\r"); 
   grabo=read_int1_eeprom(0x0,00);// acomodomar para leer 1 bit
   if (grabo ==0){
    Mes=read_eeprom(0x02);
    Dias=read_eeprom(0x03);
    }
 //if (Mes_aux < Mes){ sonaralarma();
 //}
 printf("hola mundooo33\n\r");
 while(flanco_detectormemoria==1)                                       // Comienza solo si se selecciono un mes
  {  
   output_high(PIN_A0);
   output_low(PIN_B0);
   output_low(PIN_A1);
   if (Segundos == 60){Minutos++;Segundos=0;sonaralarma();}
   if (Minutos == 60){Hora++;Minutos=0;}
   if(Hora == 24){Dias++;Hora=0;grabo=1;write_int1_eeprom(0x0,00,grabo);write_eeprom(0x02,Mes);write_eeprom(0x03,Dias);}// write_eeprom(0x50, Dias); Cuando pase un dia debo grabar. cuando se corte y vuelva a conectar debo ver estado de swicht 
   if(Dias ==30){Mes++;Dias=0;}
   if(Mes == Mes_aux){   sonaralarma();
   }
  }
  
}
Me parece que el problema es la velocidad de reloj interno, que no llega a transmitir.

¿Alguien pudo hacer funcionar con el reloj de 125khz el puerte serie?
Utilizo Hyperterminal, con la velocidad de 1200. Probé también con velocidad de 300 y no funcionó.

Captura de lo que recibo.

Gracias y saludos.
 

Adjuntos

  • Captura.PNG
    Captura.PNG
    11.2 KB · Visitas: 13
Última edición por un moderador:
No es excesivo el consumo del oscilador interno.
En la hoja de datos no está especificado el consumo a 125 KHz, pero a 8 MHz, el consumo es de 1.3 mA típico y a un máximo de 1.8 mA. @ 5 V.

Y si quieres ahorrar batería, entra en modo de bajo de consumo usando Sleep, y el microcontrolador despertará cuando ocurra una interrupción.
 
Creo que el problema es la velocidad de transmisión (baudios por segundo). Con 125kHz tienes un ciclo máquina de 8us, pero como cada instrucción necesita 4 ciclos máquina, entonces el tiempo de ejecución por instrucción es de 32us. Debes comprobar que el tiempo de transmisión es suficiente para enviar el paquete de datos. Prueba aumentando el valor del oscilador a 1 o 4 MHz, o también mandando una sola letra y luego una palabra.
 
Última edición:
Se supone que desde que pones #use*delay(internal=125khz) el compilador ajusta el oscilador por su cuenta, por otra parte, si marcas **setup_oscillator(OSC_125KHZ); y luego usas nuevamente **setup_oscillator(OSC_INTRC);**ahí sobrescribes una con otra. Aquí se me hace confuso el manual de tu compilador, según deberías usar*setup_oscillator(OSC_125KHZ|OSC_INTRC); pero tu valor debería ser OSCCON=0x15, yo honestamente prefiero leer la hoja de datos y cargar el registro directamente.
 
Buenas, gracias por la pronta respuesta.

Voy a probar una vez mas como menciono Nuyel. Y sino funciona subo el clock a 4mhz.

Por otro lado pensaba, ya que la comunicación serie es para corroborar el funcionamiento, no utilizarla.
Sino que directamente una vez que grabe el día y mes, leer la memoria del pic con el programador.

Les escribo con los resultados mas tarde..

Saludos y gracias nuevamente!
 
Disculpen por la demora

Ni con 125khz, 500khz y 1mhz puede hacer funcionar la comunicación serial.
Probé también configurando el registro OSCCON, sin utilizar las funciones definidas en el CCS, pero no funciono.
En 4mhz funciono todo, cosa que tendré que ver el tema del consumo. Creo que con el SLEEP va a ir bien.

Gracias a todos por la respuesta.
 
Yo sí pude hacer funcionar la comunicación con 125 KHz. @ 2400 Bps.
No más, porque el compilador no me lo permitía y con lógica razón.

No tengo un PIC16F886, pero usé un PIC16F887, que es lo mismo pero con más puertos.

Aquí unas muestras de las pruebas en físico:

Montaje básico en protoboard con un módulo que usa el C.I. FT232RL.


Dsc01990.jpg



Envío y recepción de mensajes, usando mi Interfaz RS-232
SPCTRL - Tx & Rx @ 2400 Bps.jpg

El código usado:
PHP:
#include <16f887.h>
#use     delay(internal = 125 KHz)  // Usar Oscilador interno.

#use     rs232(UART1, baud = 2400)  // Usar RS-232 por hardware.

#define  pin_led  PIN_D1

int8 buffer[20];
int1 flag_rx = 0;

// Servicio de interrupción por recepción del módulo USART.
#INT_RDA
void sdi_recepcion_usart (void)
{
   gets (buffer);                // Adquirir los datos. (gets espera un 13 al final de la cadena)
   output_high (pin_led);        // Encender el LED.
   flag_rx = 1;                  // Indicar que hay datos en el buffer.
}

void main (void)
{
   enable_interrupts (INT_RDA);
   enable_interrupts (GLOBAL);
   
   output_low (pin_led);
   
   putc (0x00);   // Inicializar la transmición RS-232. (Evita primer envío con basura)
   
   while (true)
   {
      if (flag_rx)
      {// Si hay datos en el buffer...
         printf (buffer);        // Retransmitir los datos del buffer.
         puts ("\n");            // Enviar comando de línea nueva.
         output_low (pin_led);   // Apagar el LED
         flag_rx = 0;            // Limpiar la bandera de indicación de datos en buffer.
      }
   }
}
 
Atrás
Arriba