Autor Tema: Cursillo en C18 para PICS DESDE CERO  (Leído 250301 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #270 en: 20 de Diciembre de 2010, 20:03:47 »
Hola Cryn!! Estás usando el pin RW? Porque en tal caso se testea la condición del LCD y no deberia de tener problemas  :? Pero si no utilizas este pin, habría que agregar una demora luego de enviar el comando \f, o sea en flex_lcd_c18.c la función lcd_putc tiene que quedar así:

Código: C
  1. void lcd_putc(int8 c){
  2.         switch(c){
  3.                 case '\f':
  4.                         lcd_send_byte(0,1);
  5.                         _delay_5ms();   /// <<<>>>
  6.                 break;
  7.                 case '\n':
  8.                         lcd_gotoxy(1,2);
  9.                 break;
  10.                 case '\b':
  11.                 lcd_send_byte(0,0x10);
  12.                 break;
  13.                 default:
  14.                         lcd_send_byte(1,c);
  15.                 break;
  16.   }
  17. }

Respecto a que archivo agregar, en los compiladores de Microchip (Ansi C) se llama al archivo cabecera (*.h), él cual indica que funciones se implementan y algunas definiciones. Y en la estructura del proyecto se debe agregar ambos archivos para que sean compilados.

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #271 en: 21 de Diciembre de 2010, 16:46:43 »
Hola suky, gracias por responder.

No estoy usando el pin RW

He aumentado el retardo a la librería y ahora si el \f va bien.

Respecto a que archivo agregar, en los compiladores de Microchip (Ansi C) se llama al archivo cabecera (*.h), él cual indica que funciones se implementan y algunas definiciones. Y en la estructura del proyecto se debe agregar ambos archivos para que sean compilados.
Entonces al agregar el .c de la lib del LCD al proyecto ya es parte del código y no hace falta q haya un #include "flex_lcd_c18.c" e incluyendo el .h de la librería es suficiente?
.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #272 en: 21 de Diciembre de 2010, 19:00:09 »
Respecto a que archivo agregar, en los compiladores de Microchip (Ansi C) se llama al archivo cabecera (*.h), él cual indica que funciones se implementan y algunas definiciones. Y en la estructura del proyecto se debe agregar ambos archivos para que sean compilados.
Entonces al agregar el .c de la lib del LCD al proyecto ya es parte del código y no hace falta q haya un #include "flex_lcd_c18.c" e incluyendo el .h de la librería es suficiente?

Exactamente!

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #273 en: 29 de Diciembre de 2010, 13:33:16 »
Hola, he estado viendo sobre I2C y memorias eeprom por acá y lo he entendido y probado todo con buenos resultados.

Estoy usando un micro 18lf46j11 trabajando a 20MHz, y debo usar el segundo módulo I2C, I2C2, esto quiere decir que uso las funciones de la libreria i2c.h, todas las que acaban con 2, como OpenI2C2(); StopI2C2(); etc. Hice los cambios correspondientes y ha funcionado todo bien, ahora lo que pretendí también es cambiar la sintaxis de las funciones para leer y escribir en la eeprom y hacerlos similares a los que en CCS usé, es decir de esto:
Código: C
  1. unsigned char EscribeDato_i2c_eeprom(unsigned char control,unsigned char address1,unsigned char address2,unsigned char data){
llevarlo a esto:
Código: C
  1. unsigned char write_ext_eeprom(unsigned int address,unsigned char data){

Este cambio a usar una variable int(16bits) para el address porque utilizaré muchos datos de la eeprom, y creo que sería más fácil manejarlo en una variable de 16bits directamente, ya que tendré varias funciones que incrementarán la dirección de 1 en 1, o de 10 en 10, etc.

Lo que me quedó es así:

Código: C
  1. #define control 0x0a
  2.  
  3. //      Escribir un byte en Memoria EEPROM 24LC512
  4. unsigned char write_ext_eeprom(unsigned int address,unsigned char data){
  5.   IdleI2C2();                                                           // ensure module is idle
  6.   StartI2C2();                                                          // initiate START condition
  7.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  8.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  9.     return(-1);                                                 // return with Bus Collision error
  10.   else{                                                                         // start condition successful
  11.     if(WriteI2C2(control))                              // write byte - R/W bit should be 0
  12.       return(-3);                                                       // set error for write collision
  13.     IdleI2C2();                                                 // ensure module is idle
  14.     if(!SSP2CON2bits.ACKSTAT){          // test for ACK condition received
  15.                 if(WriteI2C2(*((char*)(&address+1))))                   // write word address for EEPROM
  16.                 return(-3);                                             // set error for write collision
  17.            IdleI2C2();                                                  // ensure module is idle
  18.            if(!SSP2CON2bits.ACKSTAT){           // test for ACK condition received
  19.                 if(WriteI2C2(*((char*)(&address))))             // write word address for EEPROM
  20.                         return(-3);                                     // set error for write collision
  21.                         IdleI2C2();                                             // ensure module is idle
  22.                    if(!SSP2CON2bits.ACKSTAT){   // test for ACK condition received
  23.                         if(WriteI2C2(data))             // data byte for EEPROM
  24.                          return(-3);                            // set error for write collision
  25.                    }
  26.                    else
  27.                         return(-2);                                     // return with Not Ack error condition  
  28.                 }
  29.     }
  30.     else
  31.         return(-2);                                                     // return with Not Ack error condition  
  32.   }
  33.   IdleI2C2();                                                           // ensure module is idle  
  34.   StopI2C2();                                                           // send STOP condition
  35.   while(SSP2CON2bits.PEN);                              // wait until stop condition is over
  36.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  37.      return(-1);                                                        // return with Bus Collision error
  38.   return(0);                                                            // return with no error
  39. }
  40.  
  41. //      Escribir Pagina en Memoria EEPROM 24LC512 desde una Cadena
  42. unsigned char write_string_eeprom(unsigned int address,unsigned char *wrptr){
  43.   IdleI2C2();                                                           // ensure module is idle
  44.   StartI2C2();                                                          // initiate START condition
  45.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  46.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  47.     return(-1);                                                 // return with Bus Collision error
  48.   else{                                                                         // start condition successful
  49.     if(WriteI2C2(control))                              // write byte - R/W bit should be 0
  50.        return(-3);                                              // set error for write collision
  51.     IdleI2C2();                                                 // ensure module is idle
  52.     if(!SSP2CON2bits.ACKSTAT){          // test for ACK condition received
  53.                 if(WriteI2C2(*((char*)(&address+1))))                   // write word address for EEPROM
  54.                 return(-3);                                             // set error for write collision
  55.            IdleI2C2();                                                  // ensure module is idle
  56.            if(!SSP2CON2bits.ACKSTAT){           // test for ACK condition received
  57.                 if(WriteI2C2(*((char*)(&address))))             // write word address for EEPROM
  58.                         return(-3);                                     // set error for write collision
  59. //*******************************************************************************
  60. //*******************************************************************************
  61.                         IdleI2C2();                                             // ensure module is idle
  62.                    if(!SSP2CON2bits.ACKSTAT){   // test for ACK condition received
  63.                         if(putsI2C2(wrptr))             // data byte for EEPROM
  64.                         return(-4);                             // set error for write collision
  65.                    }
  66. //*******************************************************************************
  67. //*******************************************************************************
  68.                    else
  69.                       return(-2);                                       // return with Not Ack error condition  
  70.                 }
  71.     }
  72.     else
  73.         return(-2);                                                     // return with Not Ack error condition  
  74.   }
  75.   IdleI2C2();                                                           // ensure module is idle  
  76.   StopI2C2();                                                           // send STOP condition
  77.   while(SSP2CON2bits.PEN);                              // wait until stop condition is over
  78.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  79.     return(-1);                                                 // return with Bus Collision error
  80.   return(0);                                                            // return with no error
  81. }
  82.  
  83. //      Lectura de un byte en Memoria EEPROM 24LC512
  84. unsigned char read_ext_eeprom(unsigned int address){
  85.   IdleI2C2();                                                           // ensure module is idle
  86.   StartI2C2();                                                          // initiate START condition
  87.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  88.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  89.     return(-1);                                                 // return with Bus Collision error
  90.   else{
  91.     if(WriteI2C2(control))                              // write 1 byte
  92.       return(-3);                                                       // return with write collision error
  93.     IdleI2C2();                                                 // ensure module is idle
  94.     if(!SSP2CON2bits.ACKSTAT){          // test for ACK condition, if received
  95.       if(WriteI2C2(*((char*)(&address+1))))                     // WRITE word address for EEPROM
  96.         return(-3);                                             // return with write collision error
  97.           IdleI2C2();                                                   // ensure module is idle
  98.      if(!SSP2CON2bits.ACKSTAT){         // test for ACK condition, if received
  99.         if(WriteI2C2(*((char*)(&address))))             // WRITE word address for EEPROM
  100.                   return(-3);                                   // return with write collision error
  101.                   IdleI2C2();                                           // ensure module is idle
  102.         if(!SSP2CON2bits.ACKSTAT){      // test for ACK condition, if received
  103.                   RestartI2C2();                                // generate I2C bus restart condition
  104.                   while(SSP2CON2bits.RSEN);// wait until re-start condition is over
  105.                   if(PIR3bits.BCL2IF)           // test for bus collision
  106.               return(-1);                               // return with Bus Collision error
  107.            if(WriteI2C2(control+1))     // write 1 byte - R/W bit should be 1
  108.                   return(-3);                           // return with write collision error
  109.                   IdleI2C2();                                   // ensure module is idle
  110.                   if(!SSP2CON2bits.ACKSTAT){    // test for ACK condition, if received
  111.                   SSP2CON2bits.RCEN=1;  // enable master for 1 byte reception
  112.                   while(SSP2CON2bits.RCEN);     // check that receive sequence is over
  113.                   NotAckI2C2();                                 // send ACK condition
  114.                   while(SSP2CON2bits.ACKEN);// wait until ACK sequence is over
  115.                   StopI2C2();                           // send STOP condition
  116.                   while(SSP2CON2bits.PEN);      // wait until stop condition is over
  117.                   if(PIR3bits.BCL2IF)           // test for bus collision
  118.                         return(-1);                             // return with Bus Collision error
  119.                 }
  120.                   }
  121.         else
  122.           return(-2);                                   // return with Not Ack error
  123.       }
  124.       else
  125.         return(-2);                                             // return with Not Ack error
  126.     }
  127.     else
  128.       return(-2);                                                       // return with Not Ack error
  129.   }
  130.   return((unsigned int)SSP2BUF);                // return with data
  131. }
  132.  
  133. //      Esperar Ack en Memoria EEPROM 24LC512
  134. unsigned char ack_ext_eeprom(){
  135.   IdleI2C2();                                                           // ensure module is idle
  136.   StartI2C2();                                                          // initiate START condition
  137.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  138.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  139.     return(-1);                                                 // return with Bus Collision error
  140.   else{
  141.     if(WriteI2C2(control))                              // write byte - R/W bit should be 0
  142.       return(-3);                                                       // set error for write collision
  143.     IdleI2C2();                                                 // ensure module is idle  
  144.     if(PIR3bits.BCL2IF)                                 // test for bus collision
  145.       return(-1);                                                       // return with Bus Collision error
  146.     while(SSP2CON2bits.ACKSTAT){                // test for ACK condition received
  147.       RestartI2C2();                                            // initiate Restart condition
  148.       while(SSP2CON2bits.RSEN);         // wait until re-start condition is over
  149.       if(PIR3bits.BCL2IF)                               // test for bus collision
  150.         return(-1);                                             // return with Bus Collision error
  151.       if(WriteI2C2(control))                    // write byte - R/W bit should be 0
  152.         return(-3);                                             // set error for write collision
  153.       IdleI2C2();                                                       // ensure module is idle
  154.     }
  155.   }
  156.   StopI2C2();                                                           // send STOP condition
  157.   while(SSP2CON2bits.PEN);                              // wait until stop condition is over        
  158.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  159.     return(-1);                                                 // return with Bus Collision error
  160.   return(0);                                                            // return with no error    
  161. }

Hasta ahí todo bien, al parecer no ha habido ningún error, pues he escrito en la posicion 0 y en la posición 1 de la eeprom y los datos se han guardado correctamente, he leído la memoria con mi clone del pickit2.

Lo que pretendo ahora es realizar funciones que guarden y lean en la eeprom i2c variables float, long (32bits) e int(16bits), entonces copie la idea de un archivo de ejemplo de CCS e hice esto:

Código: C
  1. void write_float_eeprom(unsigned int address,float data){
  2.    char i;
  3.  
  4.    for(i=0;i<4;++i){
  5.         write_ext_eeprom(address+i,*((char*)(&data)+i));
  6.         ack_ext_eeprom();
  7.         Delay10KTCYx(4);//8ms
  8.    }
  9. }
  10.  
  11. float read_float_eeprom(unsigned int address){
  12.    char i;
  13.    float data;
  14.  
  15.    for(i=0;i<4;++i){
  16.         *((char*)(&data)+i)=read_ext_eeprom(address+i);
  17.    }
  18.    return data;
  19. }
  20.  
  21. void write_long_eeprom(unsigned int address,long data){
  22.    char i;
  23.  
  24.    for(i=0;i<4;++i){
  25.         write_ext_eeprom(address+i,*((char*)(&data)+i));
  26.         ack_ext_eeprom();
  27.         Delay10KTCYx(4);//8ms
  28.    }
  29. }
  30.  
  31. long read_long_eeprom(unsigned int address){
  32.    char i;
  33.    long data;
  34.  
  35.    for(i=0;i<4;++i){
  36.            *((char*)(&data)+i)=read_ext_eeprom(address+i);
  37.    }
  38.    return data;
  39. }
  40.  
  41. void write_int_eeprom(unsigned int address,int data){
  42.    char i;
  43.  
  44.    for(i=0;i<2;++i){
  45.         write_ext_eeprom(address+i,*((char*)(&data)+i));
  46.         ack_ext_eeprom();
  47.         Delay10KTCYx(4);//8ms
  48.    }
  49. }
  50.  
  51. int read_int_eeprom(unsigned int address){
  52.    char i;
  53.    int data;
  54.  
  55.    for(i=0;i<2;++i){
  56.         *((char*)(&data)+i)=read_ext_eeprom(address+i);
  57.    }
  58.    return data;
  59. }
Un detalle más debo colocar además de ack un retardo después de cada escritura... Delay10KTCYx(4);//8ms

Tras hacer esto para el main, con las funciones de la memoria tambien escritas en el código:
Código: C
  1. #include <p18lf46j11.h>
  2. #include <stdio.h>
  3. #include <i2c.h>
  4. #include "flex_lcd_c18.h"
  5. #pragma config WDTEN=OFF,XINST=OFF,CP0=OFF
  6. #pragma config OSC=HS,T1DIG=OFF,LPT1OSC=ON,FCMEN=OFF,IESO=OFF
  7. #pragma config RTCOSC=T1OSCREF,IOL1WAY=OFF
  8. #pragma config WPCFG=OFF,WPDIS=OFF
  9.  
  10. //stdout =_H_USER; antes de un printf para LCD
  11. //stdout =_H_USART; antes de un printf para puerto serie
  12.  
  13. #define NDecimas 100   // Para 2 decimas.-
  14.  
  15. unsigned char a,Entero,String[4];
  16. unsigned int b=0xabcd,c,Decimal;
  17. unsigned long d=0xef123456,e;
  18. unsigned float f=1.38,g;
  19.  
  20. void pic_init(void){
  21.         ADCON0=0b00000000;
  22.         ANCON0=0b11111111;
  23.         ANCON1=0b11111111;
  24.         TRISA=0b11111000;
  25.         TRISB=0b00001111;
  26.         TRISC=0b10101010;
  27.         TRISD=0b00000011;
  28.         TRISE=0b11111111;
  29.         lcd_init();
  30.         LATA=0;
  31.         LATB=0;
  32.         LATC=0;
  33.         LATD=0;
  34.         LATE=0;
  35.         OpenI2C2(MASTER,SLEW_ON);
  36.         SSP2ADD=12;            //400KHz con 20MHz
  37.         write_int_eeprom(0,b);
  38.         write_long_eeprom(2,d);
  39.         write_float_eeprom(6,f);
  40.         c=read_int_eeprom(0);
  41.         e=read_long_eeprom(2);
  42.         g=read_float_eeprom(6);
  43.         Entero=g;
  44.         Decimal=(int)(g*NDecimas)%NDecimas;
  45.         sprintf(String,"%u.%02u",Entero,Decimal);
  46.         stdout =_H_USER;
  47.         printf("%4X %lu\n%s",c,e,String);
  48. }
  49.  
  50. void main(void){
  51.         pic_init();
  52.         while(true){
  53.                
  54.         }
  55. }
No obtengo lo que necesito, en el LCD veo:
3736 4294967295
127.67

Y tras leer la memoria con el pickit2 clone veo:
Posición 0500    CD AB FF FF FF FF FF FF FF FF FF FF FF FF FF FF
//esta el int a=abcd

Posición 0700    FF FF 56 34 12 EF D7 A3 B0 3F FF FF FF FF FF FF
//esta el long d=0xef123456(4010947670d) y el float f=1.38

El int tiene entonces un desplazo de 500h al momento de escribir en la eeprom, y los float y long un desplazo de 700h

Y las lecturas de int, float y long no tengo idea de que es lo que estan leyendo.

A donde apuntaría *((char*)(&data)) siendo data una variable de 16bits? apunta al LSB o al MSB?

Lamentablemente no existe este pic en el proteus para poder depurar, y no lo puedo probar ahí, he buscado en proteus otro pic con 2 puertos i2c y al hacer los cambios necesarios, el proteus parece no simular el segundo puerto i2c de un pic =(. Y para rematar dentro MPLAB con C18, no puedo depurar con el pickit2 porque al colocar en los config DEBUG=ON, el compilador saca un mensaje de error y no compila

Alguien me podría ayudar con este problema??

Muchas gracias, saludos.
« Última modificación: 29 de Diciembre de 2010, 15:11:30 por Cryn »
.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #274 en: 29 de Diciembre de 2010, 17:42:49 »
Bueno, pensaba que haciendo *((char*)(&address+1)) se podría también, resultó que no, hice lo mismo que en CCS address>>8  y ahora si funciona bien, ya no hay desplazamientos, se guarda todo en donde corresponde.

Sobre el Debug, todavía no di con la respuesta =(

Ahora tengo un problema mostrando una variable de 16bits por el LCD, estoy haciendo:

int c=0x7788;

stdout =_H_USER;       //modifique _user_putc.c y lo agregue al proyecto
                               //como menciona suky en mensajes anteriores.
printf("%u",c);

Y solo me muestra el MSB, en el LCD veo:
30464 que equivale a 0x7700

Supongo que con el itoa y lcd_puts funcionaría, pero que paso con el printf?

Saludos!
« Última modificación: 29 de Diciembre de 2010, 17:50:06 por Cryn »
.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #275 en: 29 de Diciembre de 2010, 19:13:14 »
Supongo que el parentesis está mal implementado, seria algo así:

*((char *)&address + 1 )
*((char *)&address + i )


Luego en printf prueba con % lu  :shock:


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #276 en: 29 de Diciembre de 2010, 19:45:22 »
Lo del parentesis lo cambie por >> como se usa en muchas librerias de memorias en CCS, y ha funcionado bien.

Use también el %lu y salia como si fuera de 32bits y se veían muchos datos raros. He estado urgando cambiando de aca para allá y al final he podido ver bien el int (16bits), no me preguntes q hice, porque ni yo mismo se que habrá pasado, porque tengo el código igual que antes...

Ahora tengo un problema con incluir esta librería nueva de funciones de lectura/escritura de bytes, ints, longs, floats, strings en el proyecto. copio todas las funciones a un archivo .h, lo incluyo en el main y lo incluyo en el proyecto y no da =( aparecen 2 tipos de mensajes de error:

1. cuando coloco en el main:
#include <p18lf46j11.h>
#include "flex_lcd_c18.h"
#include <i2c.h>
#include "eep.h"     //entre comillas
#include <stdio.h>
#pragma config WDTEN=OFF,XINST=OFF,CP0=OFF,STVREN=OFF
#pragma config OSC=HS,T1DIG=OFF,LPT1OSC=ON,FCMEN=OFF,IESO=OFF
#pragma config RTCOSC=T1OSCREF,IOL1WAY=OFF
aparece un error de sintaxis en la última linea de mi lib eep.h

2.cuando coloco todo igual exepto:
#include <eep.h>     //entre mayor menor
aparece un mensaje de error que no se encuentran las funciones de la librería que voy colocando en el main.

Como puedo hacer que el proyecto tome bien las funciones de esta nueva librería??

Muchas gracias por la ayuda, saludos.
.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #277 en: 29 de Diciembre de 2010, 21:25:21 »
Me faltó colocar:

#ifndef __EPP_H
#define __EPP_H
...
...
#endif

en mi archivo epp.h, ahora incluyéndolo con comillas va todo bien

 :-/ :-/
.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #278 en: 29 de Diciembre de 2010, 22:40:49 »
Ahora tengo otra pregunta.

Cual es el valor tamaño más grande que puede tener un arreglo? según mi deducción es de 256, pero a q se debe eso? yo en CCS he usado una vez un arreglo de más de 2500bytes claro que colocandolo como const.

En C18 he intentado hacer lo mismo y no puedo pasar más de 256bytes por arreglo =(

Y hay algo más si declaro así:

unsigned char const arreglo[256];
Y va bien ya que compila

Pero si quiero colocar valores por defecto, los 256 no me deja:
unsigned char const arreglo[256]={1,2,3,4,5,6,7,8,9,0,11,23,45,65,.......}

Aparece un mensaje de error al compilar:
Error - section '.idata_eeprom.o' can not fit the section. Section '.idata_eeprom.o' length=0x000001d4

eeprom es mi archivo main.

Caray que este C18 me esta dando más dolores de cabeza que satisfacciones =(

Saludos.
.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #279 en: 30 de Diciembre de 2010, 01:09:42 »
Por defecto 256, pero se puede modificar el archivo *.lkr. En el tutorial de C18 se explica eso  ;-)


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #280 en: 30 de Diciembre de 2010, 15:07:44 »
Saqué un par de paréntesis que estaban demás y que hacían que el cast fuera incorrecto y por ello un mal direccionamiento dentro de la memoria. Las funciones quedarían así:

Código: C
  1. #define control 0x0a
  2. //      Escribir un byte en Memoria EEPROM 24LC512
  3. unsigned char write_ext_eeprom(unsigned int address,unsigned char data){
  4.   IdleI2C2();                                                           // ensure module is idle
  5.   StartI2C2();                                                          // initiate START condition
  6.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  7.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  8.     return(-1);                                                 // return with Bus Collision error
  9.   else{                                                                         // start condition successful
  10.     if(WriteI2C2(control))                              // write byte - R/W bit should be 0
  11.       return(-3);                                                       // set error for write collision
  12.     IdleI2C2();                                                 // ensure module is idle
  13.     if(!SSP2CON2bits.ACKSTAT){          // test for ACK condition received
  14.                 if(WriteI2C2(*((char *)&address+1)))                    // write word address for EEPROM
  15.                 return(-3);                                             // set error for write collision
  16.            IdleI2C2();                                                  // ensure module is idle
  17.            if(!SSP2CON2bits.ACKSTAT){           // test for ACK condition received
  18.                 if(WriteI2C2(*((char *)&address)))              // write word address for EEPROM
  19.                         return(-3);                                     // set error for write collision
  20.                         IdleI2C2();                                             // ensure module is idle
  21.                    if(!SSP2CON2bits.ACKSTAT){   // test for ACK condition received
  22.                         if(WriteI2C2(data))             // data byte for EEPROM
  23.                          return(-3);                            // set error for write collision
  24.                    }
  25.                    else
  26.                         return(-2);                                     // return with Not Ack error condition  
  27.                 }
  28.     }
  29.     else
  30.         return(-2);                                                     // return with Not Ack error condition  
  31.   }
  32.   IdleI2C2();                                                           // ensure module is idle  
  33.   StopI2C2();                                                           // send STOP condition
  34.   while(SSP2CON2bits.PEN);                              // wait until stop condition is over
  35.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  36.      return(-1);                                                        // return with Bus Collision error
  37.   return(0);                                                            // return with no error
  38. }
  39.  
  40. //      Escribir Pagina en Memoria EEPROM 24LC512 desde una Cadena
  41. unsigned char write_string_eeprom(unsigned int address,unsigned char *wrptr){
  42.   IdleI2C2();                                                           // ensure module is idle
  43.   StartI2C2();                                                          // initiate START condition
  44.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  45.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  46.     return(-1);                                                 // return with Bus Collision error
  47.   else{                                                                         // start condition successful
  48.     if(WriteI2C2(control))                              // write byte - R/W bit should be 0
  49.        return(-3);                                              // set error for write collision
  50.     IdleI2C2();                                                 // ensure module is idle
  51.     if(!SSP2CON2bits.ACKSTAT){          // test for ACK condition received
  52.                 if(WriteI2C2(*((char *)&address+1)))                    // write word address for EEPROM
  53.                 return(-3);                                             // set error for write collision
  54.            IdleI2C2();                                                  // ensure module is idle
  55.            if(!SSP2CON2bits.ACKSTAT){           // test for ACK condition received
  56.                 if(WriteI2C2(*((char *)&address)))              // write word address for EEPROM
  57.                         return(-3);                                     // set error for write collision
  58. //*******************************************************************************
  59. //*******************************************************************************
  60.                         IdleI2C2();                                             // ensure module is idle
  61.                    if(!SSP2CON2bits.ACKSTAT){   // test for ACK condition received
  62.                         if(putsI2C2(wrptr))             // data byte for EEPROM
  63.                         return(-4);                             // set error for write collision
  64.                    }
  65. //*******************************************************************************
  66. //*******************************************************************************
  67.                    else
  68.                       return(-2);                                       // return with Not Ack error condition  
  69.                 }
  70.     }
  71.     else
  72.         return(-2);                                                     // return with Not Ack error condition  
  73.   }
  74.   IdleI2C2();                                                           // ensure module is idle  
  75.   StopI2C2();                                                           // send STOP condition
  76.   while(SSP2CON2bits.PEN);                              // wait until stop condition is over
  77.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  78.     return(-1);                                                 // return with Bus Collision error
  79.   return(0);                                                            // return with no error
  80. }
  81.  
  82. //      Lectura de un byte en Memoria EEPROM 24LC512
  83. unsigned char read_ext_eeprom(unsigned int address){
  84.   IdleI2C2();                                                           // ensure module is idle
  85.   StartI2C2();                                                          // initiate START condition
  86.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  87.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  88.     return(-1);                                                 // return with Bus Collision error
  89.   else{
  90.     if(WriteI2C2(control))                              // write 1 byte
  91.       return(-3);                                                       // return with write collision error
  92.     IdleI2C2();                                                 // ensure module is idle
  93.     if(!SSP2CON2bits.ACKSTAT){          // test for ACK condition, if received
  94.       if(WriteI2C2(*((char *)&address+1)))                      // WRITE word address for EEPROM
  95.         return(-3);                                             // return with write collision error
  96.           IdleI2C2();                                                   // ensure module is idle
  97.      if(!SSP2CON2bits.ACKSTAT){         // test for ACK condition, if received
  98.         if(WriteI2C2(*((char *)&address)))              // WRITE word address for EEPROM
  99.                   return(-3);                                   // return with write collision error
  100.                   IdleI2C2();                                           // ensure module is idle
  101.         if(!SSP2CON2bits.ACKSTAT){      // test for ACK condition, if received
  102.                   RestartI2C2();                                // generate I2C bus restart condition
  103.                   while(SSP2CON2bits.RSEN);// wait until re-start condition is over
  104.                   if(PIR3bits.BCL2IF)           // test for bus collision
  105.               return(-1);                               // return with Bus Collision error
  106.            if(WriteI2C2(control+1))     // write 1 byte - R/W bit should be 1
  107.                   return(-3);                           // return with write collision error
  108.                   IdleI2C2();                                   // ensure module is idle
  109.                   if(!SSP2CON2bits.ACKSTAT){    // test for ACK condition, if received
  110.                   SSP2CON2bits.RCEN=1;  // enable master for 1 byte reception
  111.                   while(SSP2CON2bits.RCEN);     // check that receive sequence is over
  112.                   NotAckI2C2();                                 // send ACK condition
  113.                   while(SSP2CON2bits.ACKEN);// wait until ACK sequence is over
  114.                   StopI2C2();                           // send STOP condition
  115.                   while(SSP2CON2bits.PEN);      // wait until stop condition is over
  116.                   if(PIR3bits.BCL2IF)           // test for bus collision
  117.                         return(-1);                             // return with Bus Collision error
  118.                 }
  119.                   }
  120.         else
  121.           return(-2);                                   // return with Not Ack error
  122.       }
  123.       else
  124.         return(-2);                                             // return with Not Ack error
  125.     }
  126.     else
  127.       return(-2);                                                       // return with Not Ack error
  128.   }
  129.   return((unsigned int)SSP2BUF);                // return with data
  130. }
  131.  
  132. //      Esperar Ack en Memoria EEPROM 24LC512
  133. unsigned char ack_ext_eeprom(){
  134.   IdleI2C2();                                                           // ensure module is idle
  135.   StartI2C2();                                                          // initiate START condition
  136.   while(SSP2CON2bits.SEN);                              // wait until start condition is over
  137.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  138.     return(-1);                                                 // return with Bus Collision error
  139.   else{
  140.     if(WriteI2C2(control))                              // write byte - R/W bit should be 0
  141.       return(-3);                                                       // set error for write collision
  142.     IdleI2C2();                                                 // ensure module is idle  
  143.     if(PIR3bits.BCL2IF)                                 // test for bus collision
  144.       return(-1);                                                       // return with Bus Collision error
  145.     while(SSP2CON2bits.ACKSTAT){                // test for ACK condition received
  146.       RestartI2C2();                                            // initiate Restart condition
  147.       while(SSP2CON2bits.RSEN);         // wait until re-start condition is over
  148.       if(PIR3bits.BCL2IF)                               // test for bus collision
  149.         return(-1);                                             // return with Bus Collision error
  150.       if(WriteI2C2(control))                    // write byte - R/W bit should be 0
  151.         return(-3);                                             // set error for write collision
  152.       IdleI2C2();                                                       // ensure module is idle
  153.     }
  154.   }
  155.   StopI2C2();                                                           // send STOP condition
  156.   while(SSP2CON2bits.PEN);                              // wait until stop condition is over        
  157.   if(PIR3bits.BCL2IF)                                   // test for bus collision
  158.     return(-1);                                                 // return with Bus Collision error
  159.   return(0);                                                            // return with no error    
  160. }

Código: C
  1. void write_float_eeprom(unsigned int address,float data){
  2.    char i;
  3.  
  4.    for(i=0;i<4;++i){
  5.         write_ext_eeprom(address+i,*((char *)&data+i));
  6.         ack_ext_eeprom();
  7.         Delay10KTCYx(4);//8ms
  8.    }
  9. }
  10.  
  11. float read_float_eeprom(unsigned int address){
  12.    char i;
  13.    float data;
  14.  
  15.    for(i=0;i<4;++i){
  16.         *((char *)&data+i)=read_ext_eeprom(address+i);
  17.    }
  18.    return data;
  19. }
  20.  
  21. void write_long_eeprom(unsigned int address,long data){
  22.    char i;
  23.  
  24.    for(i=0;i<4;++i){
  25.         write_ext_eeprom(address+i,*((char *)&data+i));
  26.         ack_ext_eeprom();
  27.         Delay10KTCYx(4);//8ms
  28.    }
  29. }
  30.  
  31. long read_long_eeprom(unsigned int address){
  32.    char i;
  33.    long data;
  34.  
  35.    for(i=0;i<4;++i){
  36.            *((char*)&data+i)=read_ext_eeprom(address+i);
  37.    }
  38.    return data;
  39. }
  40.  
  41. void write_int_eeprom(unsigned int address,int data){
  42.    char i;
  43.  
  44.    for(i=0;i<2;++i){
  45.         write_ext_eeprom(address+i,*((char *)&data+i));
  46.         ack_ext_eeprom();
  47.         Delay10KTCYx(4);//8ms
  48.    }
  49. }
  50.  
  51. int read_int_eeprom(unsigned int address){
  52.    char i;
  53.    int data;
  54.  
  55.    for(i=0;i<2;++i){
  56.         *((char*)&data+i)=read_ext_eeprom(address+i);
  57.    }
  58.    return data;
  59. }

Para guardar un arreglo de variables contante en la memoria de programa:
Código: C
  1. #pragma romdata TablaConstante
  2.         rom const char Buffer[2048]={"Probando ....."};
  3. #pragma romdata

Otra cosa, puedes usar directamente la función write_string_eeprom( sin agregar la palabra reservada rom para guardar el buffer. Pero ten en cuenta que el largo de la cadena (debe tener el carácter '/0' para finalización de cadena) no puede ser mayor al largo de la página de la memoria que estas usando, sino se perderán datos  :?

Saludos!

No contesto mensajes privados, las consultas en el foro

Desconectado umalrovi

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 158
    • Aplicaciones Electrónicas
C18 CAD con interrupción
« Respuesta #281 en: 03 de Febrero de 2011, 06:12:54 »
Hola compañeros!!!

En primer lugar daros las gracias por la info que habéis posteado en el foro de todopic en especial a microcadaver. Yo era un programador de CCS pero me ha dado tanto por.... los bugsss que al final he pasado al C18 ya que pienso que si microchip da este lenguaje, será por algo.

Había mandado un privado a nuestro compañero microcadaver, pero hablando con otro del foro, Azicuetano, me dijo que lo postease directamente.

Estoy intentando hacer un proyecto en el cual necesito hacer conversiones por medio de interrupción y me gustaría si me pudierais verificar este código. Os lo paso y me dicís que opinas al respecto.

Un saludo y muchas gracias por vuestra ayuda ayuda!
Código: C
  1. #include <p18f4550.h>   // Definimos el Pic a utilizar.
  2. #include <adc.h>                // Librería del ADC
  3.  
  4. #pragma config PLLDIV=5, CPUDIV=OSC1_PLL2, USBDIV=1
  5.  
  6. #pragma config FOSC=XT_XT, FCMEN=OFF, IESO=OFF
  7.  
  8. #pragma config PWRT=ON, BOR=OFF, BORV=0, VREGEN=OFF
  9.  
  10. #pragma config WDT=OFF, WDTPS=32768
  11.  
  12. #pragma config CCP2MX=OFF, PBADEN=OFF, LPT1OSC=OFF, MCLRE=ON
  13.  
  14. #pragma config STVREN=OFF, LVP=OFF, XINST=OFF, DEBUG=OFF
  15.  
  16. #pragma config CP0=ON, CP1=ON, CP2=ON, CP3=ON
  17.  
  18. #pragma config CPB=ON, CPD=ON
  19.  
  20. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
  21.  
  22. #pragma config WRTC=ON, WRTB=ON, WRTD=ON
  23.  
  24. #pragma config EBTR0=ON, EBTR1=ON, EBTR2=ON, EBTR3=ON
  25.  
  26. #pragma config EBTRB=ON
  27.  
  28.  
  29. #define Pulsador                PORTAbits.RA2
  30. #define ApagarLeds              PORTB=0x00
  31.  
  32.  
  33. unsigned        int     Valor_CAD_CH0=0x00; // Valor del ADC del canal 0
  34.  
  35.  
  36.  
  37. void interrupciones(void);      //prototipo de la interrupcion
  38.  
  39.  
  40.  
  41. #pragma code prioridad_alta = 0X0008
  42. void interrupcion_alta (void)
  43. {
  44.         _asm goto interrupciones _endasm
  45. }
  46. #pragma code//fin de la interrupcion
  47.  
  48.  
  49. #pragma interrupt interrupciones
  50. void interrupciones(void)
  51. {
  52.         if(PIR1bits.ADIF)//pregunta por bandera de interrupcion CAD
  53.         {
  54.                 Valor_CAD_CH0=ReadADC();
  55.                 PIR1bits.ADIF=0;//limpia bandera y salimos
  56.         }
  57. }
  58.  
  59.  
  60.  
  61. void main(void){
  62.        
  63. //      Configuración ADC del compilador
  64.  
  65.  
  66.         OpenADC(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_20_TAD,       //Config
  67.                         ADC_CH0 & ADC_INT_ON & ADC_REF_VDD_VSS,         //Config2
  68.                         ADC_2ANA);// PortConfig
  69.  
  70.  
  71.        
  72.         INTCONbits.PEIE=1; // Habilitamos interrupcion de perifericos.
  73.         INTCONbits.GIE=1; // Habilitamos interrupcion Global.  
  74.        
  75.         TRISA=0xFF;             //RA0:12 --> ENTRADA
  76.         TRISB=0X00;             //RB0:8 --> SALIDA
  77.         ApagarLeds;
  78.         ConvertADC(); // Empieza a realizar conversiones
  79.  
  80. while(1){
  81.  
  82.         if(Pulsador==1){//Para escribir valor en puerto LAT y para leer varlor con PORT
  83.              PORTB=Valor_CAD_CH0;// Si hemos pulsado --> copiamos el valor del CAD en el puerto B
  84.         }
  85.   }
  86. }
Aplicaciones Electrónicas
http://www.neoingenia.com/

Desconectado umalrovi

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 158
    • Aplicaciones Electrónicas
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #282 en: 03 de Febrero de 2011, 07:22:08 »
buenas enqique_86, respecto al problema que tuviste con el ADC del pic18f4550 añadiendo despues de configurar la función OpenADC tal y como pusiste,

Código: C
  1. OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_0_TAD, //Config ADCON2
  2.          ADC_CH2 & ADC_INT_OFF,                     //Config ADCON0
  3.          12);                                 //Config ADCON1
  4.    ADCON1=0x0B;

Te confirmo que el problema está en el tercer argumento de la función OpenADC, pusiste un 12 en decimal que corresponde 1100, es decir AN0:AN2 analógicas y luego pusiste un ADCON1=0x0B para corregir tu problema ya que necesitabas AN0:AN3 analógicas, eso se soluciona configurando la función OpenADC de la siguientes maneras (las dos son válidas):

1.-
Código: C
  1. OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_0_TAD, //Config ADCON2
  2.          ADC_CH2 & ADC_INT_OFF,                     //Config ADCON0
  3.          11);                                 //Config ADCON1

2.- Mira la ayuda en C:\MCC18\doc\periph-lib, este micro corresponde a V5, mira el archivo pconfig.h y viene definido ( /* ADC */
#define ADC_V5).

Código: C
  1. OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_0_TAD, //Config ADCON2
  2.          ADC_CH2 & ADC_INT_OFF,                     //Config ADCON0
  3.          ADC_4ANA);         //       analog:AN0-AN3     digital:AN4-AN15


Un saludete!!!


Hola! Bueno a peticion de microcadaver  :mrgreen: subo un ejemplo utilizando la libreria adc.h, se trata de un voltimetro implementado con un 18F4550 con un cristal de 20Mhz, el funcionamiento es sencillo utiliza el ADC para captar el voltaje en el pin AN3 y luego muestra el valor captado (previamente escalado a la resolucion del ADC) en un LCD de 2x16, la libreria del LCD la saque de otro hilo y esta basada en la libreria XLCD.h de microchip, pueden reemplazarla por la libreria de manejo de LCD que utilizen o si me la piden con gusto se las paso  :-)


#include<p18f4550.h>
#include<delays.h>
#include<stdlib.h>
#include<adc.h>
#include "lcd.h"

#pragma config PLLDIV = 5//CONFIG1L
#pragma config FCMEN = OFF,IESO = OFF,FOSC=HS //CONFIG1H
#pragma config PWRT = OFF,BORV = 0 //CONFIG2L
#pragma config WDT = OFF,WDTPS = 32768 //CONFIG2H
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF, CCP2MX = OFF//CONFIG3H
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF//CONFIG4L
#pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF//CONFIG5L
#pragma config CPB = OFF,CPD = OFF//CONFIG5H
#pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF//CONFIG6L
#pragma config WRTB = OFF,WRTC = OFF,WRTD = OFF//CONFIG6H
#pragma config EBTR0 = OFF,EBTR1 = OFF,EBTR2 = OFF//CONFIG7L
#pragma config EBTRB = OFF//CONFIG7H

unsigned float v = 0;
char s[3]={""};
void main(void)
{
   OpenXLCD(FOUR_BIT & LINES_5X7);
   WriteCmdXLCD(BLINK_ON);
   WriteCmdXLCD(CLEAR);
   TRISAbits.TRISA2 = 1;
   LATA=0x00;
   OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_0_TAD, //Config ADCON2
         ADC_CH2 & ADC_INT_OFF,                     //Config ADCON0
         12);                                 //Config ADCON1
   ADCON1=0x0B;
    for( ; ; )
   {   
      s[0] = 0;
      s[1] = 0;
      s[2] = 0;
      SetChanADC(ADC_CH3);
      Delay10TCYx(5);     //Delay de 50Ci
      ConvertADC();
      while(BusyADC());
      v = ReadADC();
      v = v * 488 / 1000;
      ultoa(v,s);         //conversion de un entero a una cadena    
      
      WriteCmdXLCD(CLEAR);//visualizacion de resultado en LCD (2x16)
      putrsXLCD("V1 = ");
      if(s[1]==0 && s[2]==0)
      {
         s[2]=s[0];
         s[1]='0';
         s[0]='0';
      }
      if(s[2]==0)
      {
         s[2]=s[1];
         s[1]=s[0];
         s[0]='0';      
      }
      putcXLCD(s[0]);
      putcXLCD('.');
      putcXLCD(s[1]);
      putcXLCD(s[2]);

      Delay10KTCYx(50); //Delay de 100ms
   }
}



Como podran ver en el datasheet del 18F4550 al ejecutar la instruccion ADCON1=0x0B lo que hago es configurar los voltajes de referencia internos a Vss y Vdd, ademas de configurar los pines analogicos que se van a emplear, esto se tendria que hacer mediante la instruccion OpenADC pero es aqui donde tuve los problemas, lo que pasa es q la libreria adc.h para el PIC 18f4550 utiliza solo numeros enteros entre 0 y 15, que al utilizarlos no contemplan la configuracion de los voltajes de referencia para el conversor ADC, pues lo pone por defecto como las entradas a los pines AN2 y AN3, y del modo que queria hacerlo esto no me funcionaba, es por eso que añado la intruccion ADCON1=0x0B luego de utilizar la instruccion OpenADC de este modo si funciono asi que aqui esta lo que hice.. Espero les sirva   :-) 

                                                                                                                          ...Saludos... :-/

 
Aplicaciones Electrónicas
http://www.neoingenia.com/

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: C18 CAD con interrupción
« Respuesta #283 en: 03 de Febrero de 2011, 12:49:40 »
Estoy intentando hacer un proyecto en el cual necesito hacer conversiones por medio de interrupción y me gustaría si me pudierais verificar este código. Os lo paso y me dicís que opinas al respecto.

Hola! Cual es el problema?  :rolleyes:
No contesto mensajes privados, las consultas en el foro

Desconectado umalrovi

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 158
    • Aplicaciones Electrónicas
Re: Cursillo en C18 para PICS DESDE CERO
« Respuesta #284 en: 03 de Febrero de 2011, 14:34:27 »
Hola Suky, gracias por contestar. Mi problema es que cuando simulo en MPLAB, y termina de realizar la conversión lo que hago es copiar el resultado de la convesión en el puerto B. Primero hago un estimulo en el pulsador y pongo el An0 a 5Vdc para que se meta dentro del bucle y ponga el valor del CAD en el puerto B. Pues leo ese valor y me da 0. Ese es mi problema y no se si hago hago mal o que es lo que ocurre.

Un saludo.
Aplicaciones Electrónicas
http://www.neoingenia.com/