TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: macedo en 25 de Mayo de 2012, 21:32:14

Título: Comienzo en C
Publicado por: macedo en 25 de Mayo de 2012, 21:32:14
  :D Hola gente, les escribo para que me puedan ayudar en la transición de lenguajes de programación, yo programo en ASM y quiero pasarme al C, mas especifico C18, y tengo muchas dudas, he leído y visto programas y cada vez que lo hago me surgen mas dudas ya que veo los ejemplos y mayormente tienen algo cambiado que no se encuentra en algún ejemplo para aclarártelo,
Bueno empiezo con algunas preguntas:

1_ Siempre tengo que generar un archivo que sea main.c, o puede ser otro como test.c el que tenga el cuerpo principal del programa?

2_ Los archivos con extensiones .c serian como la parte principal del programa o periférico y los archivos .h como pedazos del programa que contengan rutinas especificas, yo los
igualo con los archivos .asm y .inc respectivamente.

3_ La declaración #Pragma se puede usar de estas dos formas:
A:
Código: C
  1. #pragma config WDTEN = OFF, LVP = OFF
ó
Código: C
  1. #pragma config WDTEN = OFF
  2. #pragma config  LVP = OFF
B: También la vi en esta instrucción:
Código: C
  1. #pragma code high_vector=0x08
  2. void InterruptTimerHigh (void)
  3. {  _asm    goto Timer1ISRHigh  _endasm
  4. }
#pragma code
Se que es una interrupcion de halta prioridad pero el "code" no lo vi en ningun ejemplo hay mas quw utilice pragma?
C: Y este VOID esta en una  linea diferente de la función:
Código: C
  1. #pragma interrupt Timer1ISRHigh
  2. void
  3. Timer1ISRHigh(void)

no deberia ser:
Código: C
  1. void Timer1ISRHigh(void)

4_A
 A raíz del ejemplo anterior las etiquetas de las funciones son asi:
Código: C
  1. void mi ejemplo (void)

El (void) indica que es un LABEL, y las que terminan así
Código: C
  1. void mi ejemplo ()

B_Tambien vi esta que empieza con una declaracion de enteros

Código: C
  1. int check_bat_sense(void)

que significan?

Bueno son muchas preguntas que tengo pero se las dire mientras vaya creando mi programa.
Les paso una pagina de programacion en C++ que me saca de algunas dudas.
http://www.zator.com/Cpp/E_Ce.htm

Saludos y gracias
Título: Re: Comienzo en C
Publicado por: Suky en 25 de Mayo de 2012, 22:22:15
1. Puede tener cualquier nombre, lo único debe existir uno principal que tenga la función void main(void)

2. Los archivos .c contienen el código fuente, ya sea de una librería o del proyecto. Y los archivos .h contienes las declaraciones de las funciones que son utilizadas en otros módulos, definiciones, etc.

3. Es una palabra reservada para indicarle al compilador que el trozo de código que sigue corresponde a algo "especial", bits de configuración, cierta dirección dentro de la memoria de programa, etc.

4. Hay que leer los fundamentos de C. Una función puede devolver o no valores, y también pueden recibir o no parámetros. Te recomiendo leer algún libro de C como para tener por lo menos el mínimo de conocimiento de C.


Saludos!


Título: Re: Comienzo en C
Publicado por: macedo en 28 de Mayo de 2012, 14:26:17
Gracias Suky, estuve leyendo y me di cuenta de que las funciones se escriben asi:

Código: C
  1. int mi_ejemplo (void)

el primer "int" indica que la función devolverá un dato del tipo int, o sea el primero indica la devolucion de un dato, y el "(void)" corresponde a que no tendrá parámetros.

2_ Las expresiones INT y CHAR son iguales?, ya que int representa a enteros y char a caracteres, según he leído, pero he visto a char servir para números enteros, puede ser?

3_ en tu ejemplo de "c18 desde 0" esta expresion en while:

Código: C
  1. while (1) {
  2.              if (PORTA....sigue

Ese (1) que significa, me desconcerta el if que sigue a la instruccion, el while verifica si es un 1 el if?, me perdi aca.
Saludos
Título: Re: Comienzo en C
Publicado por: tannke en 28 de Mayo de 2012, 14:54:12
Te respondo a esto ultimo como buenamente pueda (yo uso mikroc para programar)
-1º Lo que has puesto sobre la función es correcto.
-2º Int y char no son lo mismo,
           INT representa un nº de 16bits (signed -32768 a 32767 / unsigned 0 a 65535)
 
           CHAR representa un nº de 8bits (signed -128 a 127 / unsigned 0 a 255)          
           * esto puede varía entre compiladores, en la tabla que adjunto puedes ver los de mikroC

-3º Ese "1" del while hace que el bucle siempre se repita. El bucle while simpre se repite mientras el valor entre parentesis no sea 0 (false), podrías colocar una variable y controlar cuando salir de ese bucle.
     Por lo tanto se irá repitiendo ese if, cuando ese if sea verdadero (true)(valor de la variable distinto a 0) se ejecutarán las lineas que contenga ese if

Esto ultimo es puro C, te recomendaría hicieras caso a Suky y te leyeras algún manual/libro de C, que no tiene porque estar orientado a la programación de pics. Yo todo esto lo aprendí cuando estudié C# para pc y cuando empece con el C para los pic vi que el funcionamiento era el mismo.

Un saludo

Edit punto 2. * con ccs si es lo mismo. gracias bigluis.

Otro saludo
Título: Re: Comienzo en C
Publicado por: bigluis en 28 de Mayo de 2012, 18:57:45
En lo que respecta a los tipos de variables, hay ciertas variaciones entre cada Compilador. Por ejemplo, un int en CCS es de 8 bits mientras que en MikroC es de 16bits. Por otro lado, un short en CCS es de 1 bit mientras que en MikroC es de 8 bits.

Para estar seguro lo mejor es buscar en la ayuda de cada IDE.
Título: Re: Comienzo en C
Publicado por: macedo en 28 de Mayo de 2012, 19:14:47
Hola, entendí por que se usa char, en el ejemplo que vi este va de 0 a 255 como me lo dijeron así también van los caracteres, si no uso números mas grandes  puedo usar unsigned char tranquilamente.
estoy leyendo algunos apuntes y viendo libros pero este es mi segundo día y siempre encuentro diferencias en los ejemplos o no se explican,
otra pregunta también vi: while (thru), es lo mismo que while (1)
Saludos
Título: Re: Comienzo en C
Publicado por: Suky en 28 de Mayo de 2012, 20:11:48
Es while(TRUE)... TRUE es una definición (Macro) correspondiente a 1

O sea, es lo mismo.


Saludos!
Título: Re: Comienzo en C
Publicado por: macedo en 30 de Mayo de 2012, 12:50:50
Gracias voy a seguir leyendo.
Saludos
Título: Re: Comienzo en C
Publicado por: macedo en 30 de Mayo de 2012, 21:02:10
Hola mi primer pregunta es sobre prototipos: el prototipo se define en el archivo header del principal para que se lo creo, o sea por ejemplo test.c el header sera test.h, y debe ser exacto a la funcion que representa:
Código: C
  1. int test_led (void);

La funcion seria
Código: C
  1. int test_led (void) {
  2. .....
  3. }

siempre debe terminar con un ";" y el header debe de incluirse en el archivo principal antes de llamar a esta función?
por lo que entendí  son para verificar que la función este correctamente escrita?
Son necesarios? ya que vi que el compilador muestra un mensaje de advertencia cuando no estan pero compila todo bien.

Segunda pregunta sobre arreglos.
Estube leyendo un ejemplo
Código: C
  1. int getline(char s[], int lim)
Donde s es el arreglo, por lo que entiendo al colocar [] se establece que es un arreglo y que se debe de guardar memoria consecutiva para el mismo pero donde se define el tamaño del mismo y para que casos se usan, este es uno para caracteres
este otro:
Código: C
  1. unsigned char TestMMC_e[]={"MMC error\0"};

TestMMC_e es el arreglo y que contiene los caracteres MMC error para mostrar, en este caso, en un display?

Gracias
Título: Re: Comienzo en C
Publicado por: bigluis en 31 de Mayo de 2012, 02:45:20
1. El Header no es 100% necesario, es realmente una forma de ayudar al compilador y a las personas con quien compartas el código.

Es decir, es mucho más fácil leer solamente la forma en que debes declarar las funciones y las variables que estas necesitan en vez de leer todo el código y buscar cada función dentro de un archivo grande.

2. Los arreglos son sumamente útiles cuando trabajas con listas, cadena de caracteres, matrices, etc... Por ejemplo, si deseas almacenar información sobre cierta variable (Por ejemplo un Dataloger) y luego procesar estos datos. La manera más eficaz de hacer esto es utilizando arreglos.

Imagina que deseas almacenar 100 valores, en vez de declarar 100 variables distintas es más fácil declarar una sola variable con un tamaño definido.

Los arreglos son muchas veces utilizados en conjunto con los ciclos o Bucles, principalmente el For ya que esto permite trabajarlos de manera rápida y sin utilizar mucha memoria.

Por ejemplo
Código: [Seleccionar]
char a[100]; //Declaras un arreglo de 100 datos tipo char
for(i=0;i<100;i++){   //Para i desde 0 hasta i menor a 100, incrementando en 1
   a[i]=Read_ADC();   //Almacena el i-esimo valor del ADC en el i-esimo posición de a
}

Si desearás realizar la sumatoria de esos 100 valores sería algo así
Código: [Seleccionar]
for(i=0,sum=0;i<100;i++){   //Para i desde 0 hasta 100, incrementando en 1.
   sum+=a[i];   //Sum será igual al valor anterior de Sum + el valor del i-esimo termino de a
}

O talvés el promedio de esos 100 valores una vez obtenida la suma de los mismos
Código: [Seleccionar]
prom=sum/100;  //El promedio es la sumatoria de todos los valores entre la cantidad de valores.
Título: Re: Comienzo en C
Publicado por: Suky en 31 de Mayo de 2012, 12:19:36
Código: C
  1. int getline(char s[], int lim)

En ese caso es un puntero a un arreglo. El tamaño del arreglo, el cual los pasas como dirección en la función, es el de la declaración. O sea:

Código: C
  1. // Declaración de buffers
  2. char Buffer1[11]="Hola Mundo" ;
  3. char Buffer2[20]="Hola ...." ;
  4. // Declaración de la función
  5. int getline(char s[], int lim);
  6.  
  7.  
  8. // Llamado a la función en cualquier sector del código
  9. getline(Buffer1,val);
  10. getline(Buffer2,val2);

Saludos!
Título: Re: Comienzo en C
Publicado por: macedo en 31 de Mayo de 2012, 14:41:35
Gracias muy buena explicación, deberían escribir un libro ya que en los que lei no explican de esta forma.
Saludos
Título: Re: Comienzo en C
Publicado por: macedo en 31 de Mayo de 2012, 19:50:24
Hola me sale este error y siempre es con la función sprintf
Warning [2054] suspicious pointer conversion
Warning [2066] type qualifier mismatch in assignment

Código: C
  1. sprintf(ext_test_state,"TEST EXT 1 OK");
  2. sprintf(ext_test_state2,"TEST EXT 2 OK");

y las declaraciones en main son:
Código: C
  1. extern unsigned char ext_test_state[20];       // usado en la seccion TEST Extesion Port y en test.c por sprintf
  2. extern unsigned char ext_test_state2[20];      // usado en la seccion TEST Extesion Port y en test.c por sprintf

No se a que se refieren.
Título: Re: Comienzo en C
Publicado por: jukinch en 01 de Junio de 2012, 00:00:38
Macedo:
Warning [2054] suspicious pointer conversion te dice que sprintf está esperando un tipo de dato diferente.

Si ves el prototipo de la función vas a ver que espera un char y no un unsigned char. Cambiá las definiciones de los arrays así:

     extern char ext_test_state[20];       // usado en la seccion TEST Extesion Port y en test.c por sprintf
     extern char ext_test_state2[20];      // usado en la seccion TEST Extesion Port y en test.c por sprintf
     
sinó tenés que hacer casting para convertir el tipo de dato al tipo que espera la función.

este otro Warning [2066] type qualifier mismatch in assignment te lo debe estar dando porque tenés seleccionado el small code model y la libreria standard stdio.h de c18 está precompilada para el large memory mode.

Andá a Project, build option..., project, luego en la solapa MPLAB c18, elegí en Categories en el menucito desplegable, buscá memory model y te ba a dejar seleccionar las opciones de large code model.

fuente: (página 41 del manual MPLAB_C18_Getting_Started_51295f. En esa página vas a ver la foto de lo que te digo más arriba)
"When using the standard libraries by including stdio.h, the large code model should
be selected for the project"

     Animo que vas bien!
            Saludos.
                    Jukinch
Título: Re: Comienzo en C
Publicado por: macedo en 01 de Junio de 2012, 14:55:56
Hola jukinch, tiene tres opciones el menú desplegable:
code model
data model
stack model

solo se selecciona en code model o en los otros también el modo large? ya que solo seleccione en code model y el error se fue pero me queda la duda.

con lo de Warning [2054] suspicious pointer conversion , no se fue el error y me genero otros, voy a ver como se hace lo del casting y te comento como me fue.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 01 de Junio de 2012, 15:26:14
Solo code model modificá.

Por el otro warning cambiaste en los dos archivos el tipo de dato de unsigned char a char? Es decir, en el archivo *.c y e el *.h?

Subí el proyecto zipeado y lo vemos.
Título: Re: Comienzo en C
Publicado por: macedo en 01 de Junio de 2012, 23:17:59
Hola Jukinch, este cod. es parte de un modulo marca Olimex,
 
Código: C
  1. extern char ext_test_state[20];       // usado en la seccion TEST Extesion Port y en test.c por sprintf
  2.   extern char ext_test_state2[20];      // usado en la seccion TEST Extesion Port y en test.c por sprintf

están declarados en main.c y test.c,los cambie y sigue igual, pero no es gran molestia para que te lo tomes ya que solo estoy aprendiendo y como programo en ASM no dejo que me ponga el compilador ningún mensaje de advertencia trato de resolverlo hasta que salga, si queres decirme u orientarme te lo agradeceré.
Saludos
Título: Re: Comienzo en C
Publicado por: Suky en 01 de Junio de 2012, 23:21:56
Son advertencias, no errores.


Saludos!
Título: Re: Comienzo en C
Publicado por: jukinch en 02 de Junio de 2012, 03:25:59
Macedo:   
Para eliminar el warning [2073] null-terminated initializer string too long

reemplacé en main.c unsigned char Menu[MENU_NUMB][15]  por unsigned char Menu[MENU_NUMB][16] porque le faltaba agrandarlo para que pueda entrar una de las cadenas.



Para eliminar el warning [2058] call of function without prototype


en test.c luego de

#include "test.h"

agregué:

extern void Delay(unsigned long a) ;
extern void Delayc(unsigned char a) ;


en user.c luego de

#include "lcd.h"

agregué:

extern void LCDStr(unsigned char row, const unsigned char *dataPtr, unsigned char inv );
extern unsigned char GetJoystickPosition (void);


en lcd.c luego de
#define RES_LOW         PORTDbits.RD3=0

agregué:
void LCDStr(unsigned char row, const unsigned char *dataPtr, unsigned char inv );


en main.c luego de

#pragma config CCP2MX   = DEFAULT

agregué:
extern void LCDStr(unsigned char row, const unsigned char *dataPtr, unsigned char inv );


para eliminar el Warning [2054] suspicious pointer conversion

en main.c reemplacé en todos los sprintf
sprintf(buf,"X=0x");
así:
sprintf((char *)buf,(rom far char*)"X=0x");

casi todos los arrays han sido declarados como unsigned char y el primer parámetro del prototipo de sprintf te pide un puntero a char con signo.

para evitar el warning hay que castearlo con (char*)
así:
sprintf((char *)buf,"X=0x");

el segundo parámetro de sprintf te pide un rom far char* y si no tenés el large memory model seleccionado
hay que castear con (const rom char *)

asi:
sprintf((char *)buf,(rom far char*)"X=0x");



The compiler libraries are built with the large memory model (far rom pointers) while the compiler uses the near memory model (near rom pointers) by default, unless you compile with -ml. The compiler is complaining that you're passing a 16-bit pointer to a string constant to a function that expects a 24-bit pointer. The compiler knows how to perform that conversion, so the code will work correctly even with the warning. Most any random char* cast applied to the string literal will suppress the warning while still generating correct code. The correct cast is (const rom far char *), but incorrect casts like (char *) will work, and even meaningless casts like (near far rom rom rom char *) will work.

fuente: http://www.microchip.com/forums/tm.aspx?m=53856

sino podés elegir el large memory model desde build option project y listo.
Pero a buf si o si lo tenés que castear porque sprintf espera char* y no unsigned char*

Adjunto proyecto con cero warnings y build success!  :-/
      Saludos
          Jukinch
Título: Re: Comienzo en C
Publicado por: macedo en 02 de Junio de 2012, 22:21:59
Hola jukinch, sos un genio!, gracias, yo había visto lo del menú y lo agrande,  puedo preguntarte por que usas extern para declarar los protortipos,
yo declare en lcd.h:
Código: C
  1. void LCDStr(unsigned char row, const unsigned char *dataPtr, unsigned char inv );
y dejo de decirme warning [2058] call of function without prototype.
Tambien estan declarados en el mismo archivo
Código: [Seleccionar]
[code=c]extern void Delay(unsigned long a) ;
extern void Delayc(unsigned char a) ;
pero los sigue tirando, te hablo del archivo original[/code] que te envie. por que?
Lo de sprintf me supera pero dejame ver si lo entendí: esta expresion (char *)buf, castearlo, hace que buf cambie de unsigne char a char pero solamente en esta función para poder utilizarlo en este momento sin que afecte o que cambie el valor en otra parte del programa?
Como se selecciono large memory la funcion deberia quedar asi:
Código: C
  1. sprintf((char *)buf,"X=0x");
y no asi:
Código: C
  1. sprintf((char *)buf,(rom far char*)"X=0x");

te pregunto es lo mismo far rom char * que rom far char*? y segun el ejemplo no es (const rom far char *)?

Gracias por tomarte el tiempo.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 03 de Junio de 2012, 16:39:23
macedo:
       el warning "call of function without prototype." te dice que estás llamando a una función que todavía no se ha declarado su prototipo. Por eso declarando los prototipos desaparecen los warnings. Lo de extern lo puse porque me lo daba en un archivo diferente a donde estaba definida la función. Por eso lo de extern.
     
El tema de los warnings en sprintf está relacionado con los tipos de datos y los parámetros que recibe una función.
Siempre que tengas un warning de ese estilo en el uso de una función tenés que ver como es el prototipo de la misma.

en el caso del sprintf podés ver el manual "C18 Compiler Libraries"

sprintf
Function: Formatted string output to a data memory buffer.
Include: stdio.h
Prototype: int sprintf (char *buf, const rom char *fmt, ...);

Los 2 parámetros que te pide son:
 
un puntero a char   

y

un puntero a const rom char

      En tu programa para dar cumplimiento al primer parámetro, debés hacer casting así: (char *)buf     
para poder convertir el tipo que le estás pasando: unsigned char* al tipo correcto que espera la función, es decir: char* .
      El casting hace la conversión sólo en esa sentencia. Y no cambia el tipo de dato de buf, el cual va a seguir siendo unsigned char*.
      Con respecto a si es lo mismo far rom char* que rom far char* no lo se.
Pero en el manual  mplab_c18_users_guide_51288j.pdf en la página (DS51288J-page 14) está como rom far char* y siempre lo pongo así.
              Saludos.
                      Julkinch
Título: Re: Comienzo en C
Publicado por: macedo en 04 de Junio de 2012, 14:34:36
Gracias por aclarármelo, voy a ver que saco de todo esto y te comento.
Saludos
Título: Re: Comienzo en C
Publicado por: macedo en 07 de Junio de 2012, 14:02:17
una pregunta, este codigo esta antes y fuera del  void main (void), no es llamado por nadie y configura puertos y parte del USB, no debería estar dentro del main y si  puedo yo hacer una funcion con todas las configuraciones de los pines del micro y llamarla desde el main o antes de este para configurarlo.
Les paso el cod.:
Código: C
  1. ////////////////////////////////////////////////////////////////////////////////////////
  2. static void InitializeSystem(void)
  3. {
  4.         //On the PIC18F87J50 Family of USB microcontrollers, the PLL will not power up and be enabled
  5.         //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
  6.         //This allows the device to power up at a lower initial operating frequency, which can be
  7.         //advantageous when powered from a source which is not gauranteed to be adequate for 48MHz
  8.         //operation.  On these devices, user firmware needs to manually set the OSCTUNE<PLLEN> bit to
  9.         //power up the PLL.
  10.  
  11.         #if defined(__18F87J50)||defined(__18F86J55)|| \
  12.         defined(__18F86J50)||defined(__18F85J50)|| \
  13.         defined(__18F67J50)||defined(__18F66J55)|| \
  14.         defined(__18F66J50)||defined(__18F65J50)
  15.  
  16.     unsigned int pll_startup_counter = 600;
  17.  
  18. //I comment next line to enable debugging somehow///////////////////////////////////////////////////
  19.     OSCTUNEbits.PLLEN = 1;  //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module
  20.  
  21.     while(pll_startup_counter--);
  22.     //Device switches over automatically to PLL output after PLL is locked and ready.
  23.  
  24.         //Configure all I/O pins to use digital input buffers.  The PIC18F87J50 Family devices
  25.         //use the ANCONx registers to control this, which is different from other devices which
  26.         //use the ADCON1 register for this purpose.
  27.     WDTCONbits.ADSHR = 1;                       // Select alternate SFR location to access ANCONx registers
  28.     ANCON0 = 0xFF;                  // Default all pins to digital
  29.     ANCON1 = 0xFF;                  // Default all pins to digital
  30.     WDTCONbits.ADSHR = 0;                       // Select normal SFR locations
  31. //      ADCON1 |= 0x0F;   //I put that here
  32.  
  33.     #elif defined(PIC18F4550_PICDEM_FS_USB)
  34.     ADCON1 |= 0x0F;                 // Default all pins to digital
  35.  
  36.     #else
  37.         #error Double Click this message.  Please make sure the InitializeSystem() function correctly configures your hardware platform.
  38.                 //Also make sure the correct board is selected in usbcfg.h.  If
  39.                 //everything is correct, comment out the above "#error ..." line
  40.                 //to suppress the error message.
  41.     #endif
  42.  
  43.  
  44.     #if defined(USE_USB_BUS_SENSE_IO)
  45.     tris_usb_bus_sense = INPUT_PIN; // See io_cfg.h
  46.     #endif
  47.  
  48.     #if defined(USE_SELF_POWER_SENSE_IO)
  49.     tris_self_power = INPUT_PIN;
  50.     #endif
  51.    
  52. //    mInitializeUSBDriver();         // See usbdrv.h
  53.     UserInit();                       // See user.c & .h
  54.  
  55. }//end InitializeSystem

Userinit es otra configuración de puertos.
Todo esto es para C18
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 07 de Junio de 2012, 19:02:44
Macedo:
            Podés escribir código fuera de main. Por ejemplo podés definir variables globales. podés definir funciones, etc. y luego llamarlas desde dentro de main. Lo que no podés hacer es escribir sentencias, selectivas, if, while, for, switch, etc. Todas esas si o si deben ir dentro de una función, no pueden estar sueltas fuera de main. recordá que main es una función más.  ;-)

         Por tu inquietud sobre el tema de las configuraciones de los pines del micro podrías hacer una función con toda la configuración y llamarla desde main para configurarlos y hacer un código más estructurado. Hasta podrías incluir dicha función en un archivo separado para que quede prolijo el código y luego llamarla desde main.

Código: C
  1. /***** funcion de configuracion de puertos ******/
  2. void inicializarpuertos(void)
  3. {       //inicializar puertoA como digital
  4.         //todos los pines
  5.         //seran digitales. Para ello debemos desactivar el ADC y los comparadores
  6.  
  7.                 ADCON0 = 0X00;  //ADC desactivado
  8.                         ADCON1=0x0F;    /* Todos entradas/salidas digitales - equivalente en binario ADCON1= 0b00001111*/
  9.                         CMCON = 0X07;   //Comparadores desactivados
  10.  
  11. /*****configuracion de los bits de entradas / salidas del puerto A ******/
  12.                         TRISAbits.TRISA0=1; // rA0  como entrada  - para teclaUp y TeclaDebugger
  13.                         TRISAbits.TRISA1=1; // rA1  como entrada  - para teclaDown
  14.                         TRISAbits.TRISA2=1; // rA2  como entrada  - para teclaSelect
  15.                         TRISAbits.TRISA3=1; // rA3  como entrada  - para teclaBack
  16.  
  17. /*****configuracion de los bits de entradas / salidas del puerto C ******/
  18.                         TRISCbits.TRISC2=1; // rC2 como entrada
  19.                         TRISCbits.TRISC1=1; // rC1 como entrada
  20.                         TRISCbits.TRISC0=1; // rC0 como entrada
  21.                                        
  22. /*****configuracion de los bits de entradas / salidas del puerto B ******/
  23.                         TRISBbits.TRISB7=0; // rB7 como salida
  24.                         TRISBbits.TRISB6=0; // rB6 como salida
  25.                         TRISBbits.TRISB5=0; // rB5 como salida
  26.                         TRISBbits.TRISB4=0; // rB4 como salida
  27.                         TRISBbits.TRISB3=0; // rB3 como salida
  28.                         TRISBbits.TRISB2=0; // rB2 como salida
  29.                         TRISBbits.TRISB1=0; // rB1 como salida
  30.                         TRISBbits.TRISB0=0; // rB0 como salida
  31.  
  32.  
  33.        
  34. /*****configuración de los bits de entradas / salidas del puerto D ******/
  35.                         TRISDbits.TRISD7=0; // rD7  como salida
  36.                         TRISDbits.TRISD6=0; // rD6  como salida
  37.                         TRISDbits.TRISD5=0; // rD5  como salida
  38.                         TRISDbits.TRISD4=0; // rD4  como salida
  39.                         TRISDbits.TRISD3=0; // rD3  como salida
  40.                         TRISDbits.TRISD2=0; // rD2  como salida
  41.                         TRISDbits.TRISD1=0; // rD1  como salida
  42.                         TRISDbits.TRISD0=0; // rD0  como salida
  43. }

y luego llamarla desde main.

Código: C
  1. void main(void)
  2. {
  3.  inicializarpuertos();
  4.  
  5. // codigo
  6. // codigo
  7. // codigo
  8.  
  9. }

           Con respecto a tu duda sobre la función InitializeSystem verás que si es llamada desde dentro de main.  Y si observas el contenido de la función InitializeSystem encontrarás que llama a la función Userinit();

 Hacé control + f para buscarla dentro de main y vas a encontrar el llamado de la misma aquí:            
Código: C
  1. //////////////////TEST USB///////////////////////////////////////////////
  2.                         if(MenuPos==4)
  3.                                 {       LCDClear();
  4.                                     LCDUpdate();//check this
  5.                                          
  6.                                         if(PORTEbits.RE5==1)
  7.                                                 {      
  8.                                                 LCDStr(0,USB_C,0);
  9.                                                 Delay(300000); 
  10.                                                 LCDUpdate();    //clear screen
  11.                                                 InitializeSystem();
                Saludos.
                         Jukinch
Título: Re: Comienzo en C
Publicado por: macedo en 07 de Junio de 2012, 20:51:01
Hola jukinch, gracias por la explicación, lo que me llama la atención es que en este proyecto cuando testeas una parte configuras los pines en ese momento, yo estoy acostumbrado a configurar todo al principio y por lo general dejarlo así .
Te pregunto, asi yo empeze a configurar los puertos:
Código: C
  1. void main(void)
  2. {
  3.             OSCTUNEbits.PLLEN = 0;  //Disable the PLL
  4.             //Configure all I/O pins to use digital input buffers.  The PIC18F87J50 Family devices
  5.             //use the ANCONx registers to control this, which is different from other devices which
  6.             //use the ADCON1 register for this purpose.
  7.             WDTCONbits.ADSHR = 1;   // Select alternate SFR location to access ANCONx registers
  8.             ANCON0 = 0xFF;          // Default all pins to digital
  9.             ANCON1 = 0xFF;          // Default all pins to digital
  10.             WDTCONbits.ADSHR = 0;   // Select normal SFR locations
  11.  
  12.             TRISA  = 0XFF;          // Config del Puerto A [ RA5 RA4 RA3 RA2 RA1 RA0]
  13.                                     //                     [  E   E   E   E   E   E ]  
  14.  
  15.             TRISB  = 0X00           // Config del Puerto B [ RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0]
  16.                                     //                     [  E   E   E   E   E   E   E   E ]
  17.  
  18.             TRISC  = 0X83           // Config del Puerto C [ RC7 RC6 RC5 RC4 RC3 RC2 RC1 RC0]
  19.                                         //                     [  E   S   S   S   S   S   E   E ]
  20.  
  21.             TRISD  = 0X20           // Config del Puerto D [ RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0]
  22.                                     //                     [  S   S   E   S   S   S   S   S ]
  23.  
  24.             TRISE  = 0X23           // Config del Puerto E [ RE7 RE6 RE5 RE4 RE3 RE2 RE1 RE0]
  25.                                     //                     [  S   S   E   S   S   S   E   E ]
  26.  
  27.             TRISF  = 0X08           // Config del Puerto F [ RF7 RF6 RF5 RF4 RF3 RF2 RF1 RF0]
  28.                                     //                     [  S   S   S   S   E   S   X   X ]
  29.  
  30.  
  31.             TRISG  = 0X03          // Config del Puerto G [ RG7 RG6 RG5 RG4 RG3 RG2 RG1 RG0]
  32.                                        //                     [  X   X   X   S   S   S   E   E ]
  33.  
  34.             LATA   = 0X00;         // Apagamos todo el puerto A
  35.             LATB   = 0X00;         // Apagamos todo el puerto B
  36.             LATC   = 0X00;         // Apagamos todo el puerto C
  37.             LATD   = 0X00;         // Apagamos todo el puerto D
  38.             LATE   = 0X00;         // Apagamos todo el puerto E
  39.             LATF   = 0X00;         // Apagamos todo el puerto F
  40.             LATG   = 0X00;         // Apagamos todo el puerto G

Pero también esta esta otra posibilidad de configuración de cada puerto:
Código: C
  1. //Port B initialization
  2.         PORTB=PORTB &  0x00;//0b11111111;
  3.         TRISB=TRISB | 0b11111111;

Quiero entender esto:

PORTB=PORTB &  0x00;          // esto es una operacion AND Y borra el puerto o que significa?
TRISB=TRISB | 0b11111111;   // Aca digo como si van a ser entradas o salidas pero con una OR?

Cual de las dos posibilidades es mejor para programar.
Gracias por lo de control + f, funciona!
Saludos


Título: Re: Comienzo en C
Publicado por: jukinch en 08 de Junio de 2012, 01:07:19
Macedo: antes de usar los puertos debés configurarlos de acuerdo a tu hard mediante el registro tris.
Pero si luego tu programa requiere cambiar de sentido el pin de un puerto podés cambiar la configuración del tris en cualquier momento.

fuente:
http://www.microchip.com/forums/m569575.aspx
http://ww1.microchip.com/downloads/en/devicedoc/70058d.pdf
http://ww1.microchip.com/downloads/en/appnotes/00234a.pdf
http://informatica.uv.es/iiguia/SBM/manual.pdf pág 21/22

Con respecto a la forma de configurar los puertos podés usar la forma que más te convenga, a mi me gusta la sintaxis que te detallo más abajo porque me permite visualizar mejor cada pin y lo puedo comentar a la derecha.

así:
TRISAbits.TRISA0=1; // rA0  como entrada  - para teclaUp y TeclaDebugger
TRISAbits.TRISA1=1; // rA1  como entrada  - para teclaDown
TRISAbits.TRISA2=1; // rA2  como entrada  - para teclaSelect
TRISAbits.TRISA3=1; // rA3  como entrada  - para teclaBack


PORTB=PORTB &  0x00; // acá se hace una operación and entre PORTB y el valor 0x00 y luego se asigna a PORTB. es una operación a nivel de bit. El and funciona como una máscara o colador que deja pasar los bits que estén en 1. pero como la máscara está en cero (el valor 0x00) no deja pasar nada y pone a todo el puertob en cero.

Te paso ejemplos de  Operadores a nivel de bit (bitwise operators)
--------------------------------------------------------------------------------------------------------------

El operador AND "&" compara dos bits; si los dos son 1 el resultado es 1, en otro caso el resultado será 0.
Ejemplo:

        c1 = 0x45         --> 01000101
        c2 = 0x71         --> 01110001  // fijate que hace de colador
        ---------------------------
        c1 & c2 = 0x41 -->  01000001

--------------------------------------------------------------------------------------------------------------
El operador OR  "|" compara dos bits; si cualquiera de los dos bits es 1, entonces el resultado es 1;
en otro caso será 0. Ejemplo:

        i1 = 0x47      --> 01000111
        i2 = 0x53      --> 01010011
        ---------------------------
        i1 | i2 = 0x57 --> 01010111


--------------------------------------------------------------------------------------------------------------
El operador exclusivo (XOR) "^", da por resultado 1 cuando los dos operandos tienen distinto valor.

Cuando los dos operandos son distintos da 1.-
ej: 1 y 0    =1
    0 y 1    =1

Cuando los dos operandos son iguales da 0.-
    0 y 0    =0
    1 y 1    =0

 Ejemplo:

        i1 = 0x47      --> 01000111
        i2 = 0x53      --> 01010011
        ---------------------------
        i1 ^ i2 = 0x14 --> 00010100

--------------------------------------------------------------------------------------------------------------
El operador de complemento a 1 "~" cambia cada dígito del operando por su opuesto:

si el bit es 1 se cambia por 0 y viceversa


        c = 0x45  --> 01000101
        ----------------------
        ~c = 0xBA --> 10111010

--------------------------------------------------------------------------------------------------------------
Los operadores de desplazamiento a nivel de bit "<<" y ">>" Desplazan a la izquierda o a la derecha un número
especificado de bits.
En un desplazamiento a la izquierda los bits que sobran por el lado izquierdo se descartan y se rellenan los nuevos
espacios con ceros. De manera análoga pasa con los desplazamientos a la derecha.
Veamos un ejemplo:

        c = 0x1C    00011100
c << 1    c = 0x38    00111000
c >> 2    c = 0x07    00000111

Como en binario se trabaja en base dos cada posición de desplazamiento implica dividir o multiplicar por 2
>> divide por 2.
<< multiplica por 2

        c = 0x1C    00011100

c << 1    c = 0x38    00111000 multiplica por 2
c >> 2    c = 0x07    00000111 divide 2 veces por 2 (divide por 4)


Título: Re: Comienzo en C
Publicado por: macedo en 08 de Junio de 2012, 10:02:10
    (((:-))) Impresionante gracias!
Título: Re: Comienzo en C
Publicado por: macedo en 08 de Junio de 2012, 11:00:51
Hola que es este start:
Código: C
  1. start:          UpdateMenu(MenuPos);
En la función main que no puedo encontrar referencias.
Saludos
Título: Re: Comienzo en C
Publicado por: macedo en 08 de Junio de 2012, 11:06:03
Ha lo vi, es como una etiqueta (Label) en ASM, el programa hace un "goto start" para volver a empezar:
Código: C
  1. //while (!(joystick_left()&& joystick_select() && joystick_down()) );
  2.         if(MenuPos == 2) {             
  3.                 if(TestUEXT())  test_state=1;
  4.                         else    test_state=0;
  5.                                         if(test_state)                                 
  6.                                         {
  7.                                       LCDInit();
  8.                                       LCDContrast(0x45);
  9.                                           LCDClear();
  10.  
  11.                                       LCDStr ( 2, uext_test_state, 0 );
  12.                                       Delay(500000);
  13.                                       //LCDUpdate();
  14.                                         //  while(1);
  15.                                     }
  16.                                     else {
  17.                                
  18.                                       LCDInit();
  19.                                       LCDContrast(0x45);
  20.                                                                
  21.                                       LCDClear();
  22.                                       LCDStr ( 2, uext_test_state, 0 );
  23.                                       Delay(500000);
  24.                                       LCDUpdate();
  25.                                          // while(1);
  26.                                     }
  27.                                         goto start;    
  28.                                 }
  29. /

Se puede poner varias etiquetas y volver a ellas con goto?
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 08 de Junio de 2012, 11:06:39
Es un label. Es una etiqueta para un "mala palabra en C" :5] goto  :D

buscá en el código y encontrarás esta línea.
 goto start; // esto hace ir al label start al programa.




Título: Re: Comienzo en C
Publicado por: jukinch en 08 de Junio de 2012, 11:09:57
Respondimos los dos juntos. Tené presente que en C para algunos el uso de goto es mala palabra. Y que debés evitarlo.
mirá este hilo http://www.todopic.com.ar/foros/index.php?topic=38049

Título: Re: Comienzo en C
Publicado por: macedo en 08 de Junio de 2012, 13:16:21
Bueno no al "goto", soy muy asembleroso todavía!, cuando tenga una función que requiera "volver a" te pregunto asi me ayudas a resolverlo.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 08 de Junio de 2012, 15:47:21
Macedo: El tema del goto es filosófico!. Esta contemplado en el lenguaje c. Y se puede usar.
Es una herramienta más. Y por algo está. Y cada uno hace uso como mas le guste. Y podríamos escribir muuuchas horas al respecto. Están los pro y los contra en el hilo que te cité.
Para "volver a.. "  
Pensalo como que una función cuando termina vuelve a donde se la llamó. Y dentro de los bucles te van a ser de ayuda los break y continue. Igualmente debes tener presente que un label debe estar dentro de la función en donde se va a usar. Es decir no podes hacer un label en main y hacer un goto a ella desde fuera de main.
Saludos
       Jukinch
Título: Re: Comienzo en C
Publicado por: macedo en 09 de Junio de 2012, 10:27:49
Hola jukinch, leí el post y es como dos bandos divididos por el uso o no del mismo, voy a tratar de no usarlo y es buena la aclaración de que solo en la función se podría llamar al "goto" y no desde otra.
Gracias
Título: Re: Comienzo en C
Publicado por: jukinch en 09 de Junio de 2012, 10:44:11
Macedo:
        para que quede claro el hilo subo un ejemplo.
             Saludos.
                 Jukinch

Código: C
  1. /* Cuando se puede usar y cuando no se puede usar el goto.
  2. Un label debe estar dentro de la función en donde se va a usar el goto.
  3. */
  4.  
  5. void testgoto(void)
  6. {
  7.   label1:
  8.   goto label1; // permitido está dentro de la función
  9. }
  10.  
  11. void testgoto2(void)
  12. {
  13.   //goto labelEnMain; // error no se puede llamar a un label fuera de esta función
  14. }
  15.  
  16.  
  17. void main (void)
  18. {
  19.   labelEnMain:
  20.                    testgoto();
  21.   goto labelEnMain; // permitido está dentro de la función
  22. }
Título: Re: Comienzo en C
Publicado por: macedo en 09 de Junio de 2012, 11:11:22
Hola me quedo claro, solo dentro de la misma funcion.
Te pregunto sobre esta funcion:
Código: C
  1. if (joystick_up() && joystick_left()&& joystick_select())
  2.      { return KEY_UP; }

Título: Re: Comienzo en C
Publicado por: jukinch en 09 de Junio de 2012, 11:21:54
Sobre esto tenés que ver evaluaciones de expresiones, precedencia de operadores, y relaciones de expresiones en cortocircuito.

citando a CONCLASE.NET http://c.conclase.net/curso/?cap=004c

"Existe una regla que en muchas ocasiones nos puede resultar útil, ya que nos puede ahorrar tiempo y comprobaciones adicionales.

Esta regla se conoce como "cortocircuito" o "shortcut", y se aplica de forma diferente a expresiones AND y OR.

En el caso de operaciones AND, consiste en que si la primera expresión evaluada es false, la segunda ni siquiera se evalúa, ya que el resultado será siempre false independientemente del valor del segundo operando.

En el caso de operaciones OR, si la primera expresión sea true, la segunda no se evalúa, ya que el resultado será siempre true, independientemente del valor de la segunda expresión."


     if (joystick_up() && joystick_left()&& joystick_select()) { return KEY_UP; }
        ________________________________________
                                |
                                |
         si todo lo que está aqui dentro es verdadero    se devuelve KEY_UP y como KEY_UP está declarado como un 1 con un define en el archivo user.h del proyecto PIC-LCD3310_TEST_DEMO, el compilador en realidad cambia el texto KEY_UP por un 1 por lo que ese trozo de código queda como return 1;
         Es decir que si el resultado del if es verdadero se devuelve un 1.


Código: C
  1. //joystick definition
  2. #define KEY_NONE    0
  3. #define KEY_UP      1
  4. #define KEY_DOWN    2
  5. #define KEY_LEFT    3
  6. #define KEY_RIGHT   4
  7. #define KEY_CENTER  5

Definición de macros y expansión

Hay dos tipos de macros: las que son como objetos y las que son como funciones. Las que se asemejan a funciones toman parámetros mientras que las que se asemejan a objetos no. La forma de definir un identificador como una macro de cada tipo es, respectivamente:

#define <identificador> <lista de tokens a reemplazar>
#define <identificador>(<lista de parámetros>) <lista de tokens a reemplazar>

Hay que tener en cuenta que no hay ningún espacio entre el identificador de la macro y el paréntesis izquierdo.

Cada vez que el identificador aparezca en el código fuente será reemplazado por la lista de tokens. Incluso si está vacía. Los identificadores declarados como funciones solo se reemplazan cuando se invoca con los parámetros con los que se definió la macro.

Las macros tipo objetos se usan normalmente como parte de prácticas de buena programación para crear nombres simbólicos para constantes. Por ejemplo:

#define PI 3.14159

en vez de utilizar el número tal cual en el código.

Un ejemplo de macro actuando como función es:

#define RADAGRA(x) ((x) * 57.29578)

Esta macro define la forma de convertir radianes a grados. Después podemos escribir RADAGRA(34). El preprocesador sustituirá la llamada a la macro por la multiplicación definida antes. Las macros aquí mostradas están escritas en mayúsculas. Esto permite distinguir fácilmente entre macros y funciones compiladas en el código fuente.

fuente: http://es.wikipedia.org/wiki/Preprocesador_de_C
Título: Re: Comienzo en C
Publicado por: macedo en 09 de Junio de 2012, 11:42:22
Gracias por responder, pero lo que te iba a preguntar, se me  reseteo la pc cuando estaba escribiendo,  como hace la evaluación la estructura if, primero confirma joystick_up()=1 luego de tener este valor verdadero sigue confirmando los otros dos o con este le vasta y si no si uno de los demás valores son falso todo se cansela?, ahí es donde me trabe ya que es una función solo para el switch UP y no los demás, lo de las definiciones lo entendi pero gracias por tomarte el tiempo de explicarlo nuevamente.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 09 de Junio de 2012, 11:45:31
Macedo:
          modifiqué el post anterior mientras estabas escribiendo. Agregué el tema de relaciones de expresiones en cortocircuito con lo que se debe aclarar tu duda. Como son AND deben ser todas verdaderas. Pero con una que sea false el resultado del if será falso. Y no se siguen consultando los demás.
           Jukinch
           
Título: Re: Comienzo en C
Publicado por: macedo en 09 de Junio de 2012, 12:50:29
Hola eso es lo que no entendía, no se por que esta así si son tres switch diferentes que se accionan individualmente, para mi la función seria:
Código: C
  1. if (joystick_up() ==1)
  2.       { return KEY_UP; }
Si no tendría que accionar los tres a la vez para que me dijese que esta accionado el UP.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 09 de Junio de 2012, 18:14:17
Lo que hace el   if (joystick_up() && joystick_left()&& joystick_select())
        { return KEY_UP; }es eso. Si se pulsaron los tres contactos del joystick retorna 1. Ese caso se da cuando movés el joystick al corner superior izquierdo pulsando también select, todo eso a la vez.
           
Título: Re: Comienzo en C
Publicado por: macedo en 10 de Junio de 2012, 13:55:00
Hola, gracias me confunde algunas veces estos cod. nuevos voy a estudiarlos mas!
Saludos
Título: Re: Comienzo en C
Publicado por: macedo en 11 de Junio de 2012, 14:26:33
una pregunta, estoy leyendo unos ejemplos del tutorial de suky y me tope con esta instruccion que quiero saber como funciona, es de la pag. 30, cod 2.13.3:
Código: C
  1. }else if (PORTAbits.RA0==0){
  2.     ++i;
  3.       if (i==10){i=0;}
  4.       LATB=Display7seg[i];
  5.       Delay10KTCYx(30);
  6. }

Se lo que quiere explicar, con un pulsador aumento i y esta es la variable para que display7seg muestre su valor, pero he visto la estructura "if else" no al reves, como funciona?.
El "else" tiene que estar en la misma linea de la llave que cierre la estructura anterior?
Primero se verifica si (PORTAbits.RA0==0) si es verdadero aumenta "i" y continua con "if" o si no salta directo al "if" y continua?
Saludos
Título: Re: Comienzo en C
Publicado por: Suky en 11 de Junio de 2012, 15:04:45
Si(x==0){

}sino si(y==0){

}

Entonces, x!=0 pero y==0.

Saludos!
Título: Re: Comienzo en C
Publicado por: macedo en 11 de Junio de 2012, 15:09:57
Hola ve verificando una por una hasta que encuentra una que sea verdadera la ejecuta y regresa el control a la función?
Título: Re: Comienzo en C
Publicado por: macedo en 13 de Junio de 2012, 11:37:38
Hola como borro el WD en C, vi estos ejemplos:

Código: C
  1. _asm
  2.  CLRWDT
  3. _endasm
otro:
Código: C
  1. void CLRWDT(void) {
  2.          _asm clrwdt  _endasm
  3.         }

Código: C
  1. CLRWDT();

Esta funcion vi que es un macro, pero me da error el compilador, saben como puedo hacer.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 13 de Junio de 2012, 20:33:28
Macedo. C es case sensitive. Es decir debés respetar mayúsculas y minúsculas.
así no va CLRWDT ni así clrwdt

Probá así. ClrWdt()

está definido como una macro. página 37 del manual mplab_c18_users_guide_51288j (DS51288J-page 37)

fuente: http://www.microchip.com/forums/m110249.aspx
          Saludos.
                   Jukinch
Título: Re: Comienzo en C
Publicado por: macedo en 14 de Junio de 2012, 10:52:31
Si gracias, sabes lo que me paso esta pagina la habia visto pero la traduje con el google y me cambio el "ClrWdt" a todo mayúscula "CLRWDT" y lo tome así por eso no me funcionaba , puse la funcion como dicen ahi:
Código: C
  1. // prototype
  2.  void Clear_WDT(void);
  3.  
  4.  [...]
  5.  
  6.  // function definition
  7.  void Clear_WDT(void)
  8.  {
  9.         ClrWdt();
  10.  }

Gracias

y hasta ahora funciona correcto
Gracias.
Título: Re: Comienzo en C
Publicado por: macedo en 15 de Junio de 2012, 13:58:31
Hola, estoy en una duda con estas sentencia:
Código: C
  1. SSP1BUF = data;
  2.         while(!PIR1bits.SSP1IF);
  3.         PIR1bits.SSP1IF = 0;
  4.         LCD_E_HIGH;
  5. }
Es un equivalente a esto:
Código: ASM
  1. movFf   TEMP_CARACTER, SSP1BUF          ; Transmision por puerto SPI           
  2.  
  3. SPI_DELAY
  4.                 NOP
  5.                 NOP
  6.                 btfss   PIR1,SSP1IF                     ; Espera a que se envie el dato
  7.                 goto    SPI_DELAY
  8.                 bcf     PIR1,SSP1IF                     ; borra flag interrupcion
  9.                 bsf     LCD_SCE                         ; display OFF = LCD_E_HIGH;
  10.                 RETLW   0X00

El ASM es mi cod, lo que quiero saber es sobre el "while(!PIR1bits.SSP1IF);", este tiene la condición pero no hay bucle entre {}, mi pregunta es de esta manera espera siempre a que sea TRUE la condición y continua con la siguiente linea (PIR1bits.SSP1IF = 0; o salta fuera y retorna el control sin seguir con las demás lineas.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 15 de Junio de 2012, 15:15:11
   while(!PIR1bits.SSP1IF);

Hace que mientras PIR1bits.SSP1IF sea falso se quede iterando dentro de ese while.
El ; que está después de los paréntesis sería lo que se ejecuta. Y como no hay nada, está vacío, no hace nada.
Muchas veces vas a ver esto también while(1); que hace que el código se quede iterando en esa línea
... hasta el infinito y más allá!


Título: Re: Comienzo en C
Publicado por: macedo en 15 de Junio de 2012, 16:13:19
gracias
Título: Re: Comienzo en C
Publicado por: jukinch en 15 de Junio de 2012, 19:07:42
Macedo:
        Tené presente como es la sintaxis del while para no poner signos ; de más.

mientras(condición) ejecutar sentencia; // acá si va el ;

pero podés también reemplazar la sentencia única por un bloque de sentencias mediante el uso de las llaves {   }

while (condición)
       { 
       // código a ejecutar mientras la condición sea verdadera
       } // acá no va el ;

Si pusieras:
while (condición)
       { 
       // código a ejecutar mientras la condición sea verdadera
       };

En realidad estarías ejecutando el bucle while y además una sentencia vacía generando código innecesario.  ;-)

Título: Re: Comienzo en C
Publicado por: macedo en 16 de Junio de 2012, 11:54:01
Hola jukinch, dejame ver si es así, el "while" se ejecuta solo si tiene la condición "TRUE", si no es así se queda esperando hasta que la condición sea "TRUE" y entonces ejecuta su bloque, si no tiene nada se pasa a la siguiente linea.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 16 de Junio de 2012, 11:58:48
No macedo:
              El while solo se ejecuta si la condición es true, sinó el programa sigue de largo.
ojo que en este while(!PIR1bits.SSP1IF); hay un operador que invierte la condición. Un signo !
Título: Re: Comienzo en C
Publicado por: macedo en 16 de Junio de 2012, 14:57:49
Te pongo el cod. entero, es la transmicion por SPI:
Código: C
  1. void LCDSend(unsigned char data, unsigned char cd) {
  2.  
  3.         PIR1bits.SSP1IF = 0;   // borra flag interrupcion
  4.         LCD_E_LOW;             // Enable display!!!!!!!!!!!!!!!!!!!!!!
  5.  
  6.         if(cd == SEND_CHR) {
  7.         DC_HIGH;
  8.         }
  9.         else {
  10.         DC_LOW;
  11.         }
  12.                                                  //while((SSP1STAT & 0x01 == 0));
  13.         SSP1BUF = data;
  14.         while(!PIR1bits.SSP1IF);
  15.         PIR1bits.SSP1IF = 0;
  16.                                             //while((SSP1STAT & 0x01 == 0));
  17.         LCD_E_HIGH;
  18. }

Fijate como lo usa, según lo que me explicaste esta solo la condición y no hay sentencia para ejecución, el programa tendría que revisar "(!PIR1bits.SSP1IF);" si es FALSE volver al "while" y comprobar nuevamente asi haste que se vuelva TRUE  y continue en "PIR1bits.SSP1IF = 0;" y seguir, por eso creí que se quedaba ahí, no veo un bucle de espera hasta que termine la transmición como el ejemplo en ASM que puse.
Podes entender lo que quiero explicarte del porque mi confución en este programa.
Saludoss
Título: Re: Comienzo en C
Publicado por: macedo en 16 de Junio de 2012, 15:14:48
Hola creo que lo entendí:
Código: C
  1. SSP1BUF = data;                    // ENVIO EL DATO AL BUFFER DE LA SPI PARA ENVIARLO A LA LCD
  2.  
  3.         while(!PIR1bits.SSP1IF);           // ACA REVISO EL FLAG DE TRANSMICION, SI TERMINO SSP1IF= 1, PERO AL NO TERMINAR DE TRANSMITIR SSP1IF= 0,
  4.                                            // AL TENER !  QUEDA NEGADO Y ES SSP1IF= 1 ENTONCES EL WHILE ES "TRUE" Y SIEMPRE ESTA REVISANDO QUE LO SEA, UN BUCLE EN SI MISMO YA QUE NO TIENE SENTENCIAS DE EJECUCION,
  5.                                            // AL TERMINAR DE TRANSMITIR EL SSP1IF= 1, NEGADO ES SSP1IF= 1,  EL WHILE SE VUELVE "FALSE" Y CONTINUA CON LAS DEMAS LINEAS.
  6.         PIR1bits.SSP1IF = 0;               // CONTINUO CON MI PROGRAMA, BORRO EL FLAG Y CONTINUO
  7.                                            
  8.         LCD_E_HIGH;

Creo que así es, que me dicen.
Saludos
Título: Re: Comienzo en C
Publicado por: macedo en 18 de Junio de 2012, 11:02:59
Hola, necesito una mano, tengo en un proyecto que crear "menús" en un LCD Nokia 3310, y son varios, están los títulos de la pantalla, la descripción de los mismos, muestra y describe los errores producidos y muestra en el lcd resultados obtenidos con breves reseñas, todas estas frases deben estar escritas en el pic, la pregunta del millón es como, he visto ejemplos de esta forma:
Código: C
  1. unsigned char mnsj4[]  = {"Distribucion :\0"};
  2. unsigned char mnsj5[]  = {"00 38\0"};
  3. unsigned char mnsj6[]  = {"FR\0"};
  4. unsigned char mnsj7[]  = {"USA\0"};
  5. unsigned char mnsj8[]  = {"> Simulacion Juego <\0"};
  6. unsigned char mnsj9[]  = {"* En Juego... *\0"};
  7. unsigned char mnsj10[] = {"Numero Cantado:\0"};
  8. unsigned char mnsj11[] = {"Win :--\0"};
  9. unsigned char mnsj12[] = {"Games:\0"};
Pero me sale un error:
"Error - section '.idata_lcd.o' can not fit the section. Section '.idata_lcd.o' length=0x00000177"
El pic es el 18F67J50.
Por lo que pude interpretar de http://www.xargs.com/pic/c18-sections.html estoy cargando todo a la RAM y me sobrepase, lo que tengo que hacer es cargar los menus en la ROM.
Puede ser una forma asi:
Código: C
  1. unsigned char Menu[MENU_NUMB][16] = {
  2.  "Test EXT 1&2  \0",
  3.  "Test LEDS  \0",
  4.  "Test GUIA \0",
  5.  "Test MMA      \0",
  6.  "Test Joystick \0"
  7. };
Pero esta forma también me ocupa RAM no?
Puse el ejemplo:
Código: C
  1. rom rom char * array [] =
  2. {
  3.    "Cadena de 1",
  4.    "Cadena de 2",
  5. };
Pero no me funciona, mi cod:
Código: C
  1. LCDMsnj (0, 0, array[1]);

Los dos primeros ceros son las coordenadas y array el mensaje a mostrar.
Me pueden ayudar.
Gracias
Título: Re: Comienzo en C
Publicado por: jukinch en 18 de Junio de 2012, 15:02:32
Macedo:

Con respecto a tu anterior post, no se si quedó claro el tema del operador not o ! dentro del while.

a este while(!PIR1bits.SSP1IF); debés analizarlo en dos tramos.

primero evaluar la expresión a la derecha del operador !, es decir, PIR1bits.SSP1IF. Luego a ese resultado lo negás con el !.
Pero el operador ! no altera el valor del  bit SSP1IF.

Mirá este ejemplo en pseudo código :


unsigned char x; // variable global

interrupción:
{
x=0;
}


void main(void)
{
x=1;
while(!(X==0));   // mientras x sea distinto a 0 se quedará iterando dentro del while.

                            // El programa primero evalúa el valor de x(que vale 1) con 0, lo que da false. Y al resultado lo niega.
                            // Eso es lo que toma como condición el while, siendo en definitiva la condición evaluada verdadera.
                            // pero x sigue teniendo su valor propio no siendo afectado por el operador !, ya que no se hace ninguna
                            // asignación a x.
                            // Cuando ocurra la interrupción se le cambiará el valor a la variable x pasando a valer 0, lo que
                            // hará que al salir de la interrupción x haga cambiar el resultado de la comparación con 0 y
                            // se resuelva como verdadera (equivalente a 1). Luego es negada por el operador not ! haciéndola falsa
                            // nuevamente. Entonces allí si saldrá del while.
                            //
}

Lo que quiero que quede claro en tu ejemplo es que el operador not no altera el valor del bit PIR1bits.SSP1IF .
Ese bit no se verá afectado por el while en si. Dicho valor solo será cambiado al ocurrir la interrupción pasando a valer 1.
No se en que pic estás trabajando.  En mi 18f4550 tengo que valdrá 1 cuando suceda una escritura o lectura en el SPP
y 0 mientras no haya ni lectura ni escritura.

SPPIF: Streaming Parallel Port Read/Write Interrupt Flag bit
1 = A read or a write operation has taken place (must be cleared in software)
0 = No read or write has occurred

while(!PIR1bits.SSP1IF); // se quedará iterando en  este while mientras no haya lectura ni escritura.
                                    // Cuando se produzca la interrupción sale del while.
PIR1bits.SSP1IF = 0; // luego borra el flag.




Con respecto al siguiente post debés cargar tu texto en rom para que no te ocupe memoria ram:


#pragma romdata
const rom char Palabra_Contador[]="CONTADOR"; // cadena de texto. se agregará el \0 al final
const rom char my_const_array [5] = {'a','b','c','d','e'}; array de caracteres. // no se agrega el \0 al final
#pragma romdata

mirá las páginas 24 y 25 del tutorial de suky. (las del texto no del pdf!) :)

modificado: (aclaré que las páginas son las del texto y no del pdf!)
Título: Re: Comienzo en C
Publicado por: macedo en 19 de Junio de 2012, 10:57:27
Hola jukinch, gracias por molestarte y tomarte el tiempo en responder, el post anterior lo comprendí, el operador ! solo niega, y PIR1bits.SSP1IF esta en "0" , al tener ! queda en 1 entonces se queda iterando en el while hasta que termine la transmición y PIR1bits.SSP1IF cambie a 1 pero con el ! queda en 0 entonces continua. Lo comprendí gracias, lo único que me desoriento es que no tenia llaves con sentencias para hacer algo, creí que no se podía hacer así que si o si debia de hacer algo.

Con respecto al otro post vi la conf. #pragma romdata  pero no me salia usarla así que iprobe con esto:
Código: C
  1. sprintf((char*)BusChar,(rom far char*)"> Simulacion Juego <");
  2.          LCDMsnj ( 0, 3, BusChar);

Es lo que me explicaste al principio, funciona, lo único es que tengo que cargar sprintf con cada frase y creo que llevara mucho código ya que son muchas. Otra pregunta es necesario colocar \0" al final de la frase "> Simulacion Juego <" en sprintf?
Voy a probar lo que me enseñaste y te comento.
Cual es el texto de suky ya que tengo dos pdf de el.
Saludos
Título: Re: Comienzo en C
Publicado por: macedo en 19 de Junio de 2012, 16:06:40
Hola, estuve probando pero necesito aprender mas sobre punteros. Coloque mi menu de esta forma:
Código: C
  1. #pragma romdata
  2. ....
  3. const rom char mnsj2[]="*Init. Cilindro*\0";
  4. ....
  5. ...
  6. #pragma romdata

Uso mi funcion asi:
Código: C
  1. LCDMsnj ( 0, 0, mnsj2);

Y la funcion es:
Código: C
  1. void LCDMsnj(unsigned char x,unsigned char y, const unsigned char *dataPtr) {
  2.  
  3.    rom unsigned char ** near_rom_ptr;
  4.    *near_rom_ptr=FontLookup[0];
  5.  
  6.    LCDSend(0x80|x, SEND_CMD );
  7.    LCDSend(0x40|y, SEND_CMD );
  8.  
  9.    while ( *dataPtr )                                   // loop to the end of string
  10.  {                    
  11.   for(k=0; k<6; k++)                                    // k<5
  12.       LCDSend(FontLookup[*dataPtr - 32][k], SEND_CHR);  //near_rom_ptr
  13.    
  14.       dataPtr++;
  15. //      LCDSend (0x00,SEND_CHR);                          // Espacio entre caracteres.
  16.   }
  17.  
  18. }

Bueno como sabran me tira este error: Warning [2054] suspicious pointer conversion, y no muestra nada en el LCD.
Help! :(
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 20 de Junio de 2012, 01:32:30
Hola Macedo:
                 tenés que diferenciar lo que es una cadena de texto almacenada en un array de un simple array de caracteres.
Una cadena de texto es una secuencia de caracteres cuyo último carácter es '\0' el cual indica el final de la misma.
Un ejemplo de cadena es: "*Init. Cilindro*" // fijate que saqué el \0 que le habías puesto vos porque el compilador lo agrega automáticamente al final porque estamos usando comillas dobles.
¿que tamaño deberá tener el array para almacenar "*Init. Cilindro*"?
ojo que la catindad no es 16, sino 17.

Debemos almacenar los caracteres:  '*' 'I' 'n' 'i'  't'  '.'   ' '   'C'  'i'  'l'   'i'  'n'  'd'  'r'  'o'  '*' y el final de cadena '\0'  
                                                      1   2  3  4   5  6    7     8   9  10 11 12  13 14  15  16                               17

Fijate que usé comillas simples para indicarte los caracteres.
Cuando querés indicar un único caracter debés hacerlo entre comillas simples.
Si escribís "a" no le estás indicando al compilador sólo la letra 'a' sino la 'a' más el '\0'

Si entendiste lo que te expliqué más arriba estarás en condiciones de responderme que tamaño tendrá y que se almacenará en el siguiente array:

char my_array="";

¿y en este otro?
char my_array=" ";


cuando declarás un array así:
char texto[] = “Hola”; // el compilador reserva la cantidad de caracteres para hola más el \0, es decir 5

también podrías crearlo así:
char texto[5] = “Hola”;

Lo que no podés hacer es declarar el array y luego pretender cargarle valores con el operador de asignación =

por ejemplo:

char texto[5];
texto="hola"  // ERROR!!

Para cargarle al array la palabra "hola" luego de crearlo debés asignar elemento por elemento, así:

char texto[5];
texto[0]='h';
texto[1]='o';
texto[2]='l';
texto[3]='a';
texto[4]='\0'

El ejemplo que te transcribo aquí abajo ya no es una cadena de caracteres sino un simple array de caracteres.
char my_array [5] = {'a','b','c','d','e'}; array de caracteres. // no se agrega el \0 al final

El tutorial oficial de Suky  ((:-)) es uno solo y está en este link http://www.micros-designs.com.ar/tutorial-mplab-c18/

En respuesta al tema de guardar datos en rom, debés hacer así.

#pragma romdata seccionAbcdario
const rom char letras[]={' ','A','B','C','D','E','F',
                   'G','H','I','J','K','L',
                   'M','N','O','P','Q','R',
                   'S','T','U','V','W','X',
                             'Y','Z'};
#pragma romdata

En cuanto al problema del lcd nokia no puedo ayudarte porque nunca hice nada con el. Pero imagino que debe ser similar a los glcd. Suky hizo un tutorial aquí: http://www.micros-designs.com.ar/libreria-glcd-128x64-c/


Con relación a este Warning [2054] suspicious pointer conversion no es un error, solo es un warning, y  te lo debe estar dando porque le estás pasando a la función  LCDMsnj(unsigned char x,unsigned char y, const unsigned char *dataPtr) un dato como parámetro distinto del que está definido en la función.
const unsigned char   y const rom char. Es decir no es ni rom ni unsigned.


Para entender el tema punteros te recomiendo leas los tutoriales que están acá. http://www.ucontrol.com.ar/forosmf/programacion-en-c/tutorial-sobre-punteros-en-c-ansi/

Título: Re: Comienzo en C
Publicado por: macedo en 20 de Junio de 2012, 13:56:52
Gracias jukinch por tomarte el tiempo y enseñarme, bueno esto explica porque veia ejemplos con el caracter final o no"\0":
Citar
Un ejemplo de cadena es: "*Init. Cilindro*" // fijate que saqué el \0 que le habías puesto vos porque el compilador lo agrega automáticamente al final porque estamos usando comillas dobles.

char my_array="";    Tiene un tamaño de un caracter el "\0" solamente

char my_array=" ";   Tienen un largo de dos caracteres el espacio y el "\0"

Este ejemplo
Citar
El ejemplo que te transcribo aquí abajo ya no es una cadena de caracteres sino un simple array de caracteres.
char my_array [5] = {'a','b','c','d','e'}; array de caracteres. // no se agrega el \0 al final

Los array de caracteres empiezan y terminan con {}? y las de cadena de caracteres?
Mira este ejemplo.
Código: C
  1. unsigned char Menu[MENU_NUMB][16] = {
  2.  "Test LEDS 12345 \0",
  3.  "Test IGT SAS  \0",
  4.  "Test CARBONERA  \0",
  5.  "Test macedo   \0",
  6.  "Test MMA      \0",
  7.  "Test Joystick \0"
  8. };
MENU_NUMB indica la cantidad de valores que contiene y el 16 el largo, pero empieza  y termina con {} y esto tiene algún limite?
Los arrays se guardan en ROM o RAM?

Con respecto a esto:
Citar
#pragma romdata seccionAbcdario
const rom char letras[]={' ','A','B','C','D','E','F',
                   'G','H','I','J','K','L',
                   'M','N','O','P','Q','R',
                   'S','T','U','V','W','X',
                             'Y','Z'};
#pragma romdata
Es semejante a hacer "org 0x200" y escribir mi tabla en ASM?
Le debo decir al programa donde empieza Abcdario y donde termina?

Como llamo al valor en este array, así:  Abcdario[2], que seria la letra"A".

Gracias y estoy viendo los tutoriales muy buen trabajo el de suky, sin desmerecer el tuyo.
Saludos




Título: Re: Comienzo en C
Publicado por: jukinch en 20 de Junio de 2012, 23:22:50
char my_array="";    Tiene un tamaño de un caracter el "\0" solamente

char my_array=" ";   Tienen un largo de dos caracteres el espacio y el "\0"

10 puntos Macedo.  :-/


Los array de caracteres empiezan y terminan con {}? y las de cadena de caracteres?

Un array de caracteres puede ser también una cadena. Lo que hace que sea cadena es el \0 del final. Es sólo una cuestión de nombres y convenciones.

Podés usar las dos formas para cargar un array,
                      con comillas dobles
                   y con llaves y comillas simples.

Pero con comillas dobles siempre tendrás un \0 al final. Y no sería un array de caracteres por el \0.
Lo importante es que sepas que con " " tenés un \0 y con {' ',' '} vos elegís si está o no está el \0.

char palabra[5] = {‘H’, ‘o’, ‘l’, ‘a’, ‘\0’}; // acá podés elegir si querés un \0 al final o no porque lo ponés vos.
char palabra[5] = “Hola”; //  // acá siempre tendrás un \0 al final.

mirá este tutorial: http://wikipnfi.wikispaces.com/file/view/Cadenas.pdf

En el caso de [MENU_NUMB][16] tenés un array multidimensional. Es una matriz de dos dimensiones.
MENU_NUMB debe estar definido en tu código en algún lado con un #define así:

#define MENU_NUMB 6

entonces te queda una matriz de 6*16

Una de las cosas que siempre confunde es que los arrays se definen de un tamaño n pero luego el índice para llamar a un elemento del array arranca desde 0. Es decir que el índice es siempre n-1;

en este ejemplo lo vas a ver claro:

char letra;
char palabra[5] = {‘H’, ‘o’, ‘l’, ‘a’, ‘\0’};

para acceder a la letra 'H' debo indicar indice 0
letra=palabra[0];
para acceder a la letra 'a' debo indicar indice 3
letra=palabra[3];


Es semejante a hacer "org 0x200" y escribir mi tabla en ASM?
Le debo decir al programa donde empieza Abcdario y donde termina?
De asm ni la más mínima idea. Ya me pasarás algún par de trucos para hacer un blink led  :-/.


Como llamo al valor en este array, así:  Abcdario[2], que seria la letra"A".
Abcdario[2] sería la letra b  acordate que arranca en 0 el índice. :)

Los arrays se guardan en ROM o RAM?
Podés cargarlo tanto en rom como en ram. Para ello debés usar los modificadores rom y ram. (página 21-24 del tutorial de Suky) y la directiva pragma romdata

#pragma romdata array_en_rom
const rom int myarray[10];
#pragma romdata

mirá también este link http://www.forosdeelectronica.com/f24/acceso-memoria-pic-c18-13884/

te paso otro link interesante con faqs. http://www.xargs.com/pic/c-faq.html#c18absolute  
                Saludos.
                        Jukinch

Título: Re: Comienzo en C
Publicado por: macedo en 21 de Junio de 2012, 10:22:04
GRACIAS MAESTRO! (((:-)))
Título: Re: Comienzo en C
Publicado por: macedo en 22 de Junio de 2012, 09:16:55
Hola estuvi leyendo y aplicando lo que me dijiste, pero encontre algo que no me cierra, hize esto:
Código: C
  1. #pragma romdata array_temps=0x400
  2. const rom unsigned char mnsj2[]={"*Init. ale*\0"};
  3. const rom char mnsj3[]="Tipo Cilindro:\0";
  4. const rom char mnsj4[]="Distribucion :\0";
  5. #pragma romdata
  6.  
  7. unsigned char *men1;
  8. extern unsigned char mnsj2[];            // esta en otro archivo
  9.  
  10.  
  11.  
  12. void main(void) {
  13.  
  14.              men1=mnsj2;                // tiene que estar dentro de la funcion que lo llama o no?
  15.              LCDMsnj (0, 2, men1);   // escribo en el lcd
  16.  
  17.                         while(1)       
  18.                                 {
  19. ....
  20. ....
  21. ....
  22. }
Pero no sale nada en el LCD y el compilador no muestra error al compilar.
Otra forma es:
Código: C
  1. ]#pragma romdata array_temps=0x400
  2.  unsigned char mnsj2[]={"*Init. ale*\0"};
  3. const rom char mnsj3[]="Tipo Cilindro:\0";
  4. const rom char mnsj4[]="Distribucion :\0";
  5. #pragma romdata
Asi si muestra el mensaje en el LCD, siempre con mnsj2.
La rutina de envío, LCDMnsj esta descrita mas arriba.
Por que lo hace si me dijiste que colocara con "const rom" y no funciona.
Saludos


Título: Re: Comienzo en C
Publicado por: jukinch en 22 de Junio de 2012, 09:35:45
Macedo: subí el código de la función LCDMsnj así veo que debe recibir. Y los warnings que debés estar recibiendo.

¿Porque agregás el \0 acá?: {"*Init. ale*\0"}; El texto entre comillas dobles ya te lo genera.

para copiar el contenido de un array a otro deberás usar una función, dependiendo de donde estén guardados, si en ROM o en RAM, deberás usar:
strcpy
strcpypgm
strcpypgm2ram
strcpyram2pgm
página DS51297F-page 126 del manual de librerias de c18.



mirá este link http://www.microchip.com/forums/m218767-print.aspx
y este otro http://www.programatium.com/manuales/c/18.htm
aquí tutorial de cadenas:
http://www.todopic.com.ar/foros/index.php?topic=25785

Título: Re: Comienzo en C
Publicado por: macedo en 22 de Junio de 2012, 12:10:38
Hola es raro para mi lo que hace, te comento que sigo probando tratando de descubrir el problema, te paso los cod.
Código: C
  1. unsigned char My_Msnj[6][20] = {
  2. "*Init. ale*",
  3. "Tipo Cilindro:",
  4. "Distribucion :",
  5. "00 38",
  6. "* En Juego... *",
  7. "Win :--"
  8. };
  9.  
  10. unsigned char Inversion [] ={0,0,0,0,0,0};      // usado por UpdateMenu
  11. unsigned char offset=0, menu_flag=0;            // usado en UpdateMenu
  12. unsigned char MenuPos=0;                          // usado en UpdateMenu
  13.  
  14.  
  15. void LCDMsnj(unsigned char x,unsigned char y, const unsigned char *dataPtr) {
  16.  
  17.    rom unsigned char ** near_rom_ptr;
  18.    *near_rom_ptr=FontLookup[0];
  19.  
  20.    LCDSend(0x80|x, SEND_CMD );
  21.    LCDSend(0x40|y, SEND_CMD );
  22.  
  23.    while ( *dataPtr )                                   // loop to the end of string
  24.  {                    
  25.   for(k=0; k<6; k++)                                    // k<5
  26.       LCDSend(FontLookup[*dataPtr - 32][k], SEND_CHR);  //near_rom_ptr
  27.    
  28.       dataPtr++;
  29. //    LCDSend (0x00,SEND_CHR);                          // Espacio entre caracteres.
  30.   }
  31. }
  32.  
  33. void LCDStr(unsigned char row, const unsigned char *dataPtr, unsigned char inv ) {
  34.  
  35.   unsigned char x = 0;                    // variable for X coordinate
  36.  
  37.   while ( *dataPtr )                      // loop to the and of string
  38.           {
  39.     if(inv)
  40.                 LCDChrXY(0,row,'*');
  41.         if(inv)
  42.             {
  43.                 LCDChrXY( x+5, row, (*dataPtr));
  44.       //LCDChrXYInverse(x, row, (*dataPtr));
  45.       }
  46.     else
  47.             {
  48.       LCDChrXY( x, row, (*dataPtr));
  49.       }
  50.     x=x+6;      // x++;
  51.     dataPtr++;
  52.   }
  53. }  
  54.  
  55. void UpdateMenu(unsigned char pos) {
  56.  
  57.   Inversion[pos-1] = 1;
  58.  
  59.   Inversion[pos-1] = 1;
  60.  
  61.   LCDUpdate();
  62.   LCDClear();
  63.   LCDStr ( 0, My_Msnj[0+offset], Inversion[0]);
  64.   LCDStr ( 1, My_Msnj[1+offset], Inversion[1]);
  65.   LCDStr ( 2, My_Msnj[2+offset], Inversion[2]);
  66.   LCDStr ( 3, My_Msnj[3+offset], Inversion[3]);
  67.   LCDStr ( 4, My_Msnj[4+offset], Inversion[4]);
  68.   LCDStr ( 5, My_Msnj[5+offset], Inversion[5]);
  69.   Delay(65000);
  70. //  LCDUpdate();
  71.   Inversion[pos-1] = 0;
  72. };
Esto esta en un archivo LCD.c

Te comento que al llamar las funciones en main.c
Código: C
  1. LCDMsnj (0, 2, My_Msnj[1]);
  2.               LCDStr (0, My_Msnj[1], Inversion[0]);
Me dan "Warning [2054] suspicious pointer conversion", pero la funcion:
Código: C
  1. UpdateMenu(MenuPos);
No!, y si te fijas es igual a la que hize para probar:
Código: C
  1. LCDStr (0, My_Msnj[1], Inversion[1]);
Esta función me muestra la primer linea del mensaje en la LCD si a My_Msnj le quito [] y no me tira el error. Una esta en LCD.c y la otra que da error en main.c
La verdad que cada vez que te pregunto salgo con algo mas complicado, me debes querer matar.
Voy a revisar lo que me mandastes.
Saludos


Título: Re: Comienzo en C
Publicado por: macedo en 23 de Junio de 2012, 13:45:21
Bueno resumo lo anterior:
Tengo mi arreglo multidimensional en el archivo LCD.c:
Código: C
  1. unsigned char My_Msnj[6][20] = {
  2. "Primera Linea",
  3. "Segunda Linea",
  4. "Tercera Linea",
  5. "Cuarta Linea",
  6. "Quinta Linea",
  7. "Sexta Linea"
  8. };

y mis dos funciones:
En el archivo main.c:
Código: C
  1. LCDMsnj (0, 2, My_Msnj[1]);

Y en el archivo lcd.c:
Código: C
  1. UpdateMenu(MenuPos);

La cosa es así, si yo lllamo a UpdateMenu(0), en lcd.c, me muestra todo el arreglo en la lcd perfecto, y si yo llamo a LCDMsnj (0, 2, My_Msnj[1]), en main.c, no muestra nada y debería mostrarme "Segunda Linea", cabe aclarar que para que me muestre algo debo quitarle el indice a My_Msnj asi:
Código: C
  1. LCDMsnj (0, 2, My_Msnj);
Y me muestra solamente "Primera Linea".

Si yo cambio de archivo a mi arreglo, o sea pasarlo de lcd.c a main.c y viceversa dependiendo en que archivo este la función funciona que este en el mismo archivo funcionara perfecto, si mi arreglo esta en main.c la función LCDMsnj (0, 2, My_Msnj[1])
funciona perfecto y UpdateMenu(0) NO, y viceversa.

Otra cosa que vi tambien acompañado de este cambio de archivo de mi arreglo es que la funcion que no este en el mismo que mi arreglo debo castearla, asi:
Código: C
  1. LCDMsnj (0, 2, (unsigned char*) My_Msnj[0]);

Para que no me salga: Warning [2054] suspicious pointer conversion.
y si se fijan mi arreglo es unsigned char, espero haberlo puesto bien.
Esto es lo que me detiene por el momento  :5]
Espero que puedan entender lo que me pasa y me digan donde me equivoco, ya leí los ejemplos creo que el arreglo esta bien pero no veo aun el error.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 23 de Junio de 2012, 15:30:05
Macedo. Cuando haces uso de un array multidimensional tenés que indicar los dos indices.

My_Msnj[0][0] para la primera línea.
 My_Msnj[1][0] para la segunda

My_Msnj[2][0] para la tercera

Etc.

Y ojo que so lo pones así suelto:
  My_Msnj es un puntero.
Título: Re: Comienzo en C
Publicado por: macedo en 23 de Junio de 2012, 15:38:47
Ya lo había probado pero me tira el error:
Error [1129] [] operator requires a pointer and an integer as operands
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 23 de Junio de 2012, 18:54:01
Macedo:
          Vamos a tener que ver estos temas para poder entender como solucionar el problema.
             Punteros,
             Aritmética de punteros,
             Arrays bidimensionales y punteros,
             Como hacer para pasarle un array multidimensional a una función.-

         Tené presente que cuando invocás la función LCDMsnj el compilador no copia todo el array a la función.
Solo podés pasar un puntero y eso es lo que debe hacer tu código.

           En tu código el puntero dataPtr, sirve para recorrer tu matriz de 6 bytes*20 bytes = 120 bytes.
Esos 120 bytes son consecutivos, ya que la función no lo toma como un array, ni unidimensional ni bidimensional. Solo los ve como bytes consecutivos.

probá así:
 LCDMsnj (0, 2, (My_Msnj+20));

Si mis cálculos no me fallan deberían mostrarte la segunda línea.

Subí si podés el proyecto completo zipeado así podemos probar compilarlo.


Mirá esta página que te había comentado.
http://www.xargs.com/pic/c-faq.html#twodarray

Código: C
  1. How can I pass a pointer to a two-dimensional array to a function, or declare a pointer to a two-dimensional array?
  2.  
  3. With a two-dimensional array, the compiler needs to know how many elements are in a column to move from one row to the next, but movement within a row is always by a single element, so the compiler doesn't need to know the number of rows. Thus the pointer declaration must include the number of columns in the array:
  4.  
  5. char array[2][3] = { "19", "42" };
  6.  
  7. void func(char (*ptr)[3])
  8. {
  9.   puts(ptr[1]);      // prints "42"
  10. }
  11.  
  12. func(array);
  13.  
  14. /* or */
  15.  
  16. char (*ptr)[3];
  17. ptr = array;


Si vos tenés un array:         char array[6][20];

Un puntero al primer elemento de la segunda fila sería:

char *ptr;
ptr = &array[1][0];


Luego podés incrementar el puntero para ir avanzando a los elementos subsiguientes de ese renglón.

No se como te manejás con el tema de los punteros. Parecen un cuco pero no lo son. Pero si hay que dedicarles su tiempo y práctica.-

podés ver este link:
http://www.monografias.com/trabajos38/manual-programacion/manual-programacion-c4.shtml
allí buscá Punteros y Arreglos.

aquí también tenés más info sobre el tema de los arrays:
http://www.microchip.com/forums/m161017-print.aspx
http://www.microchip.com/forums/m145824-print.aspx
http://www.microchip.com/forums/m573688.aspx
http://www.todopic.com.ar/foros/index.php?topic=12926.0

Te recomiendo leas este hilo también:
http://www.todopic.com.ar/foros/index.php?topic=27462

Encontré este video en inglés pero muy copado.
Agrego otro más sobre cadenas y punteros.

              Saludos.
                    Jukinch

Modifique: el 6 por el 20
LCDMsnj (0, 2, (My_Msnj+20));

Modifiqué. agregué otro video más.

modifiqué: lo tachado. ya que mis cálculos me fallaron. jijiji :)

Título: Re: Comienzo en C
Publicado por: jukinch en 24 de Junio de 2012, 04:38:47
Macedo:
          Hice este código en c y lo compilé con devc++ para hacer pruebas y pude acceder a los elementos del array multidimensional. Pero no como te había indicado. Por eso modifiqué el post anterior tachando lo que creo que no va antes de generar más confusión.  :-)
          Habría que adaptarlo a tu proyecto y probar.
                Saludos.
                        Jukinch
Código: C
  1. #include <stdio.h>
  2.  
  3. int main(void)
  4. {
  5. // ---------------------------------------------------------------------------
  6. // ejemplo de arrays unidimensionales y bidimensionales y uso de punteros
  7.  
  8. unsigned char miCadena[10] = "JUKINCH";
  9.  
  10. unsigned char My_Msnj[6][20] = {"Primera Linea",
  11.                                 "Segunda Linea",
  12.                                 "Tercera Linea",
  13.                                 "Cuarta Linea",
  14.                                 "Quinta Linea",
  15.                                 "Sexta Linea"
  16.                                 };
  17.  
  18.  
  19.  
  20. printf("%c\n",*(miCadena+0)); // J
  21. printf("%c\n",*(miCadena+1)); // U
  22. printf("%c\n",*(miCadena+2)); // K
  23. printf("%c\n",*(miCadena+3)); // I
  24. printf("%c\n",*(miCadena+4)); // N
  25. printf("%c\n",*(miCadena+5)); // C
  26. printf("%c\n",*(miCadena+6)); // H
  27. printf("\n");
  28. printf("%s\n",miCadena); // JUKINCH
  29. printf("\n");
  30.  
  31. printf("%c \n",*(My_Msnj[0]+0)); // P
  32. printf("%c \n",*(My_Msnj[0]+1)); // r
  33. printf("%c \n",*(My_Msnj[0]+2)); // i
  34. printf("%c \n",*(My_Msnj[0]+3)); // m
  35. printf("%c \n",*(My_Msnj[0]+4)); // e
  36. printf("%c \n",*(My_Msnj[0]+5)); // r
  37. printf("%c \n",*(My_Msnj[0]+6)); // a
  38. printf("\n");
  39.  
  40. printf("%c \n",*(My_Msnj[1]+0)); // S
  41. printf("%c \n",*(My_Msnj[1]+1)); // e
  42. printf("%c \n",*(My_Msnj[1]+2)); // g
  43. printf("%c \n",*(My_Msnj[1]+3)); // u
  44. printf("%c \n",*(My_Msnj[1]+4)); // n
  45. printf("%c \n",*(My_Msnj[1]+5)); // d
  46. printf("%c \n",*(My_Msnj[1]+6)); // a
  47. printf("\n");
  48. printf("%c \n",*(*(My_Msnj+0)+0)); // P
  49. printf("%c \n",*(*(My_Msnj+0)+1)); // r
  50. printf("%c \n",*(*(My_Msnj+0)+2)); // i
  51. printf("%c \n",*(*(My_Msnj+0)+3)); // m
  52. printf("%c \n",*(*(My_Msnj+0)+4)); // e
  53. printf("%c \n",*(*(My_Msnj+0)+5)); // r
  54. printf("%c \n",*(*(My_Msnj+0)+6)); // a
  55. printf("\n");
  56. printf("%c \n",*(*(My_Msnj+1)+0)); // S   EQUIVALENTE printf("%c \n",**(My_Msnj+1)); // S
  57. printf("%c \n",*(*(My_Msnj+1)+1)); // e
  58. printf("%c \n",*(*(My_Msnj+1)+2)); // g
  59. printf("%c \n",*(*(My_Msnj+1)+3)); // u
  60. printf("%c \n",*(*(My_Msnj+1)+4)); // n
  61. printf("%c \n",*(*(My_Msnj+1)+5)); // d
  62. printf("%c \n",*(*(My_Msnj+1)+6)); // a
  63. printf("\n");
  64. printf("%c \n",*(*(My_Msnj+2)+0)); // T
  65. printf("%c \n",*(*(My_Msnj+2)+1)); // e
  66. printf("%c \n",*(*(My_Msnj+2)+2)); // r
  67. printf("%c \n",*(*(My_Msnj+2)+3)); // c
  68. printf("%c \n",*(*(My_Msnj+2)+4)); // e
  69. printf("%c \n",*(*(My_Msnj+2)+5)); // r
  70. printf("%c \n",*(*(My_Msnj+2)+6)); // a
  71.  
  72. printf("\n");
  73.  
  74. system("PAUSE");
  75. return 0;
  76. }

Título: Re: Comienzo en C
Publicado por: jukinch en 24 de Junio de 2012, 15:52:33
Macedo:
        Adjunto un proyecto en c18 en donde mustra el contenido de un array de 1d y otro de 2d con varias variantes para mostrar el texto. Lo probé en mi placa entrenadora Multiboard Pictrainer 2.0 de Felixls y funciona ok.
              Saludos.
                    Jukinch

Código: C
  1. /*
  2. programa: EJEMPLO DE USO DE ARRAYS DE 1 y 2 dimensiones
  3.  
  4. pic 18f4550
  5. crystal: 4 MHz CPU 4MHZ
  6.  
  7. CONEXIONES:
  8. lcd conectado en PUERTO D
  9.  
  10. bus de datos en el nible alto conector idc D4a7
  11.  
  12. DATA7    PUERTO D.7
  13. DATA6    PUERTO D.6
  14. DATA5    PUERTO D.5
  15. DATA4    PUERTO D.4
  16.  
  17.  
  18. bus de control en el nible bajo conector idc rD0a3
  19.  
  20. E_PIN    PUERTO D.3
  21. RS_PIN   PUERTO D.2
  22. RW_PIN   PUERTO D.1
  23.  
  24. */
  25.  
  26.  
  27. /*Includes globales*/
  28. #include <p18F4550.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <delays.h>
  32.  
  33.  
  34.  
  35. /*Includes locales*/
  36. #include "xlcd_portd.h"
  37.  
  38.  
  39.  
  40. /* Bits de configuración*/
  41.  
  42. #pragma config FOSC = XT_XT, CPUDIV = OSC1_PLL2 // Cristal de 4 Mhz y Frecuencia de trabajo del CPU a 4Mhz
  43. #pragma config FCMEN = OFF,IESO = OFF
  44. #pragma config PWRT = ON,BOR = OFF,BORV = 0
  45. #pragma config WDT = OFF,WDTPS = 32768
  46. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
  47. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
  48. #pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF
  49. #pragma config CPB = OFF,CPD = OFF
  50. #pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF
  51. #pragma config WRTB = OFF,WRTC = OFF,WRTD = OFF
  52. #pragma config EBTR0 = OFF,EBTR1 = OFF,EBTR2 = OFF
  53. #pragma config EBTRB = OFF
  54.  
  55.  
  56.  
  57.  
  58. /********************** DEFINICIONES *********************/
  59. #define CLOCK 4000000
  60. #define TCY 4/CLOCK
  61. #define BITRATE 100000
  62.  
  63. // 1 TCY se calcula como 4/fosc  
  64. // 1 TCY = X segundos      ======>      4/4000000hz =0,000001s = 1us
  65.  
  66. // 1.000.000 de TCYs equivalen a 1 segundo.
  67. // Delay10KTCYx(100)= 100*10000*TCY=1s
  68. // Delay10KTCYx(100)= 100*10000*1us=1s
  69. // Delay10KTCYx(10)= 100*10000*1us=100ms
  70.  
  71.  
  72.  
  73. #pragma romdata seccionAbcdario
  74. const rom unsigned char My_Msnj[6][20] = {"Primera Linea",
  75.                                                   "Segunda Linea",
  76.                                                   "Tercera Linea",
  77.                                                   "Cuarta Linea",
  78.                                                   "Quinta Linea",
  79.                                                   "Sexta Linea"
  80.                                                   };
  81. const rom unsigned char miCadena[10] = "JUKINCH"; // cadena para mostrar en lcd
  82.  
  83. #pragma romdata
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91. /*declaración de funciones*/
  92.  
  93. void DelayFor18TCY(void);
  94. void DelayPORXLCD(void);
  95. void DelayXLCD(void);
  96. void initlcd(void);
  97. //******************************************************//
  98. // Programa Principal
  99. //******************************************************//
  100. void main(void)
  101. {
  102. ADCON0 = 0X00,ADCON1 = 0X0F,CMCON = 0X07; //puerto A con todos los pines digitales
  103. TRISA = 0X00;
  104. TRISB = 0XFF;
  105. TRISC = 0X00;
  106.  
  107. LATA = 0X00;
  108. LATB = 0X00;
  109. LATC = 0X00;
  110.  
  111.  
  112.  
  113. initlcd(); // inicializamos lcd
  114.  
  115.  
  116. WriteCmdXLCD(LINE_0+0);
  117. putrsXLCD("  MULTIBOARD");
  118. WriteCmdXLCD(NEXT_LINE+0);
  119. putrsXLCD("PIC TRAINER 2.0");
  120. Delay10KTCYx(100);    //Retardo para mostrar valor                                      }
  121. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  122. WriteCmdXLCD(LINE_0+0);
  123. putrsXLCD("arrays de 1 y 2D");
  124. WriteCmdXLCD(NEXT_LINE+0);
  125. while(BusyXLCD()){}
  126. WriteCmdXLCD(CURSOR_OFF & BLINK_OFF);
  127. Delay10KTCYx(100);    //Retardo para mostrar valor                                      }
  128.  
  129.  
  130. /////////////// PRUEBA DE ESCRITURA DE ARRAY DE 1D con putrs y con putc ///////////////
  131.  
  132. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  133. WriteCmdXLCD(LINE_0+0);
  134.  
  135. putrsXLCD(miCadena); // escribe JUKINCH
  136.  
  137. WriteCmdXLCD(NEXT_LINE+0);
  138. putcXLCD(*(miCadena+0)); // J
  139. putcXLCD(*(miCadena+1)); // U
  140. putcXLCD(*(miCadena+2)); // K
  141. putcXLCD(*(miCadena+3)); // I
  142. putcXLCD(*(miCadena+4)); // N
  143. putcXLCD(*(miCadena+5)); // C
  144. putcXLCD(*(miCadena+6)); // H
  145.  
  146. Delay10KTCYx(100);    //Retardo para mostrar valor                                      }
  147.  
  148. // PRUEBA DE ESCRITURA DE ARRAY DE 2D con putrs pasando My_Msnj, My_Msnj+1 y My_Msnj+2 //
  149. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  150. WriteCmdXLCD(LINE_0+0);
  151. putrsXLCD(My_Msnj); // escribe Primera Linea
  152.  
  153. WriteCmdXLCD(NEXT_LINE+0);
  154. putrsXLCD(My_Msnj+1); // escribe Segunda Linea
  155. Delay10KTCYx(100);    //Retardo para mostrar valor                                     
  156.  
  157. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  158. WriteCmdXLCD(LINE_0+0);
  159. putrsXLCD(My_Msnj+2); // escribe Tercera Linea
  160. Delay10KTCYx(100);    //Retardo para mostrar valor                                     
  161.  
  162.  
  163. /////////////// PRUEBA DE ESCRITURA DE ARRAY DE 2D con aritmética de punteros ////
  164.  
  165. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  166. WriteCmdXLCD(LINE_0+0);
  167. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  168. putcXLCD(*(*(My_Msnj+0)+0)); // P
  169. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  170. putcXLCD(*(*(My_Msnj+0)+1)); // r
  171. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  172. putcXLCD(*(*(My_Msnj+0)+2)); // i
  173. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  174. putcXLCD(*(*(My_Msnj+0)+3)); // m
  175. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  176. putcXLCD(*(*(My_Msnj+0)+4)); // e
  177. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  178. putcXLCD(*(*(My_Msnj+0)+5)); // r
  179. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  180. putcXLCD(*(*(My_Msnj+0)+6)); // a
  181. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  182. putcXLCD(' '); // espacio
  183. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  184. putcXLCD(*(*(My_Msnj+2)+0)); // T
  185. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  186. putcXLCD(*(*(My_Msnj+2)+1)); // e
  187. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  188. putcXLCD(*(*(My_Msnj+2)+2)); // r
  189. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  190. putcXLCD(*(*(My_Msnj+2)+3)); // c
  191. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  192. putcXLCD(*(*(My_Msnj+2)+4)); // e
  193. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  194. putcXLCD(*(*(My_Msnj+2)+5)); // r
  195. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  196. putcXLCD(*(*(My_Msnj+2)+6)); // a
  197.  
  198. WriteCmdXLCD(NEXT_LINE+0);
  199.  
  200. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  201. putcXLCD(*(*(My_Msnj+4)+0)); // Q
  202. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  203. putcXLCD(*(*(My_Msnj+4)+1)); // u
  204. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  205. putcXLCD(*(*(My_Msnj+4)+2)); // i
  206. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  207. putcXLCD(*(*(My_Msnj+4)+3)); // n
  208. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  209. putcXLCD(*(*(My_Msnj+4)+4)); // t
  210. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  211. putcXLCD(*(*(My_Msnj+4)+5)); // a
  212. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  213. putcXLCD(' '); // espacio
  214. putcXLCD(' '); // espacio
  215. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  216. putcXLCD(*(*(My_Msnj+5)+0)); // S
  217. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  218. putcXLCD(*(*(My_Msnj+5)+1)); // e
  219. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  220. putcXLCD(*(*(My_Msnj+5)+2)); // x
  221. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  222. putcXLCD(*(*(My_Msnj+5)+3)); // t
  223. while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  224. putcXLCD(*(*(My_Msnj+5)+4)); // a
  225.  
  226. Delay10KTCYx(100);    //Retardo para mostrar valor                     
  227.  
  228. /////////////// PRUEBA DE ESCRITURA DE ARRAY DE 2D con  [][] ////
  229.  
  230. WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  231. WriteCmdXLCD(LINE_0+0);
  232. putrsXLCD(&My_Msnj[3][0]); // escribe Cuarta Linea
  233. Delay10KTCYx(100);    //Retardo para mostrar valor                                     
  234.  
  235. while (1);
  236.  
  237.  
  238.                
  239.  
  240.  
  241. //*******************************************************
  242. //*******************************************************
  243. }
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++*/
  252. /*++++++++++++++++++++++++++++             F U N C I O N E S          +++++++++++++++++++++++++++++++*/
  253. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  254.  
  255.  
  256. /****************** Funciones de retardos para librería del lcd **************************************/
  257.  
  258. /*
  259.  *              - The user must provide three delay routines:
  260.  *              - DelayFor18TCY() provides a 18 Tcy delay
  261.  *              - DelayPORXLCD() provides at least 15ms delay
  262.  *              - DelayXLCD() provides at least 5ms delay
  263.  
  264. para aprender como se calcularon los delays de abajo ver el archivo:
  265. "D:\My Dropbox\c18\delays - calculo de demoras\calculo de retardos ejemplos con varios cristales - leo.txt"
  266.  
  267. TCY se calcula como 4/fosc
  268.  
  269. donde fosc = frecuencia de trabajo del CPU
  270.  
  271. Ejemplo a velocidad de CPU de 4mhz
  272.  
  273.     TCY = 4/4000000 = 0,000001s
  274.   1 TCY = 0,000001s
  275.   1s / 0,000001s = 1.000.000TCY
  276.  
  277. A  4mhz         1 Tcy equivale a 1  us =======> 20Tcy = 20us
  278.  
  279.                
  280. ***********************************************************************************************************/
  281.  
  282. // para velocidad de CPU de 4mhz descomentar el siguiente código y comentar el de 20mhz
  283.                 void DelayFor18TCY(void)
  284.                 {
  285.                 Delay10TCYx(2); //provides a 20 Tcy delay.          
  286.                 }      
  287.                 void DelayPORXLCD(void)
  288.                 {
  289.                    Delay1KTCYx(15); //Delay 15 mSeg        para CPU de  4mhz. 1 Tcy equivale a 1  us =======> 15000Tcy =15ms              
  290.                 }
  291.                
  292.                 void DelayXLCD(void)
  293.                 {
  294.                    Delay1KTCYx(5);  // Delay 5 mSeg        para CPU de  4mhz. 1 Tcy equivale a 1  us =======>  5000Tcy =5ms
  295.                 }
  296.  
  297.  
  298.  
  299. // para velocidad de CPU de 20mhz descomentar el siguiente código y comentar el de 4mhz
  300. /*
  301.                 void DelayFor18TCY(void)
  302.                 {
  303.                 Delay10TCYx(2); //provides a 20 Tcy delay.          
  304.                 }      
  305.                 void DelayPORXLCD(void)
  306.                 {
  307.                Delay1KTCYx(75); //Delay 15 mSeg        para CPU de 20mhz. 1 Tcy equivale a 0,2us =======> 75000Tcy =15ms              
  308.                 }
  309.                
  310.                 void DelayXLCD(void)
  311.                 {
  312.                    Delay1KTCYx(25); // Delay 5 mSeg                para CPU de 20mhz. 1 Tcy equivale a 0,2us =======> 25000Tcy =5ms
  313.                 }
  314.  
  315. */
  316. /****************** fin de Funciones de retardos para librería del lcd *******************************/
  317.  
  318.  
  319.  
  320. /*************** función inicialización del lcd *****************************************************/
  321. void initlcd(void)
  322.         {
  323.                 Delay10KTCYx(10);    //Retardo para esperar que pase cualquier transitorio
  324.                 OpenXLCD(FOUR_BIT&LINES_5X7);   //inicializamos LCD con varias lineas y caracteres 5x7
  325.                 WriteCmdXLCD(0x01);             // Borra pantalla y vuelve al origen.-
  326.                 while(BusyXLCD()){}     //Preguntamos al RW si el display esta ocupado  
  327.                 WriteCmdXLCD(0x80);     // Nos posicionamos en la la posicion x=0 Y=0
  328.         }
  329. /*************** final función inicialización del lcd ***********************************************/

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=38441.0;attach=18849)
Título: Re: Comienzo en C
Publicado por: macedo en 24 de Junio de 2012, 16:36:36
Gracias jukinch sos un groso, pero vos tenes declarados los array en main.c, trata de cambiarlo a otro archivo como lcd.c y decime si te funciona igual, es lo que me pasa: tengo declarado mi array en lcd.c y no en main.c:
Código: C
  1. unsigned char My_Msnj[6][20] = {
  2. "Primera Linea",
  3. "Segunda Linea",
  4. "Tercera Linea",
  5. "Cuarta Linea",
  6. "Quinta Linea",
  7. "Sexta Linea"
  8. };

En main.c lo declaro asi:
Código: C
  1. extern unsigned char My_Msnj[];

entonces por lo que me diste a probar:
Código: C
  1. LCDMsnj (0, 2, (My_Msnj+20));

Si funciona y deduzco que el compilador no lo toma bidimencional sino como una linea de caracteres consecutivos, pero si coloco el array en main.c y lo llamo con la funcion:
Código: C
  1. LCDMsnj (0, 0, My_Msnj[0]);

Funciona perfecto y puedo hacer:
Código: C
  1. LCDMsnj (0, 0, My_Msnj);   //primera linea
  2. LCDMsnj (1, 1, My_Msnj);   //segunda linea
  3. LCDMsnj (2, 2, My_Msnj);   //tercera linea
  4. LCDMsnj (3, 3, My_Msnj);   //cuarta linea
  5. LCDMsnj (4, 4, My_Msnj);   //quinta
Todo esto sin problemas.

Ves la pregunta del millón: ¿POR QUE SI CAMBIO EL ARRAY DE ARCHIVO NO FUNCIONA?
Saludos

Título: Re: Comienzo en C
Publicado por: jukinch en 24 de Junio de 2012, 17:11:15
Macedo:
           en main declarás el array como unidimensional My_Msnj[];

Código: C
  1. extern unsigned char My_Msnj[];
pero en lcd.c lo definís como bidimensional My_Msnj[6][20];
Código: C
  1. unsigned char My_Msnj[6][20] = {
  2. "Primera Linea",
  3. "Segunda Linea",
  4. "Tercera Linea",
  5. "Cuarta Linea",
  6. "Quinta Linea",
  7. "Sexta Linea"
  8. };
Será por eso?

probá ponerlo así en main.c

extern unsigned char My_Msnj[][20];

luego en donde le asignas la dirección de memoria al puntero myptr deberás ponerlo así:
myptr = &My_Msnj[0][0];

Probá y comentá.
        Saludos.
               Jukinch
Título: Re: Comienzo en C
Publicado por: macedo en 25 de Junio de 2012, 12:24:23
Gracias jukin, era eso, gracias, te paso como quedaron las llamadas de distintas formas, me verificas que las dos ultimas no me funcionan y no se por que:
Código: C
  1. myptr = &My_Msnj[0][0];
  2.  
  3.            LCDMsnj (0, 0, (unsigned char*)myptr);                //primera linea funciona , este solo funcioma con la primer linea
  4.            LCDMsnj (0, 1, (unsigned char*)(My_Msnj+1));          //segunda linea funciona
  5.            LCDMsnj (0, 2,  My_Msnj[2]);                          //tercera linea funciona
  6.            LCDMsnj (0, 3, (unsigned char*) (*(My_Msnj+3)+0));    //cuartalinea funciona
  7.            LCDMsnj (0, 4, (unsigned char*) (*(myptr+4)+0));      //quinta linea no funciona
  8. //         LCDMsnj (0, 5, (unsigned char*)*(*(myptr+5)+0));      //sexta linea no funciona    133:Error [1130] pointer operand required for '*'

El apuntador myptr no me funciona para seleccionar las diferentes filas por que?
Saludos

Título: Re: Comienzo en C
Publicado por: jukinch en 25 de Junio de 2012, 12:40:33
Macedo:
          la función espera un puntero. Y no el contenido a donde apunta el puntero myptr. (al contenido se accede desreferenciando el puntero con el operador *
La función es la que se encarga de procesar el contenido a donde apunta el puntero myptr. Vos sólo le debés pasar el puntero. (para llegar a la línea que querés mostrar  deberás incrementar a  myptr mediante aritmética de punteros)
Es medio traba lengua. Pero es así.
Y si le pasás así el parámetro también debería funcionar.

&My_Msnj[4][0]

fijate el ejemplo que te pasé en c18 que ahí lo uso así.
Título: Re: Comienzo en C
Publicado por: Suky en 25 de Junio de 2012, 13:22:45
Estas comenzando con C y ya te estas metiendo con punteros?  :shock:
Título: Re: Comienzo en C
Publicado por: macedo en 25 de Junio de 2012, 14:42:33
Hola, tienen razón demasiado pronto para romperme la cabeza, es que cuando tengo una duda en algo hasta que no me sale no me gusta dejarla pero gracias por el aporte y la paciencia, entendí lo del puntero que no funciona y es, si no me equivoco, este debería estar dentro del la función principal y dentro de otra ya que como dijo jukinch la función principal espera un puntero y no su dirección.
Ahora todas estas funcionan:
Código: C
  1. LCDMsnj (0, 0, (myptr+0));                        //primera linea funciona con aritmetica de punteros, sumar de a 20 segun array
  2.            LCDMsnj (0, 1, (unsigned char*)(My_Msnj+1));      //segunda linea funciona
  3.            LCDMsnj (0, 2,  My_Msnj[2]);                      //tercera linea funciona
  4.            LCDMsnj (0, 3, (*(My_Msnj+3)+0));                 //cuarta linea funciona
  5.            LCDMsnj (0, 4,  &My_Msnj[4][0]);                  //quinta linea funciona

Diferentes formas de llamar al array.
Funciona. :-/
Lo que ne me funciona es *(*(My_Msnj+5)+0)); como el de tu ejemplo me da este error: 133:Error [1130] pointer operand required for '*'

Voy a continuar con el proyecto ahora viene la parte de la USART y debo comparar datos en cadena. Voy a tratar de hacerlo solo ;-)
Saludos :lol:

Título: Re: Comienzo en C
Publicado por: macedo en 30 de Junio de 2012, 12:18:20
Hola me pueden ayudar con esto, estoy probando la insercion de delays en ASM y tengo algunos problemas, mi cod:
Código: C
  1. unsigned char CounterA=0, CounterB=0, CounterC=0;
  2.  
  3. /******* PIC Time Delay = 5,00000000 s with Osc = 18432000 Hz *****/
  4. void MY_Delay_5s(void) {
  5.  
  6.         _asm
  7.                 movlw   117
  8.                 movwf   CounterC,0          //0=Access RAM
  9.                 movlw   226
  10.                 movwf   CounterB,0          //0=Access RAM
  11.                 movlw   195
  12.                 movwf   CounterA,0          //0=Access RAM
  13.    loop:
  14.                 decfsz  CounterA,1,0        //0=Access RAM
  15.                 goto    loop
  16.                 decfsz  CounterB,1,0        //0=Access RAM
  17.                 goto    loop
  18.                 decfsz  CounterC,1,0        //0=Access RAM
  19.                 goto    loop
  20.                 retlw   0
  21.         _endasm
  22. }

El header:
Código: C
  1. /****************************************************************************/
  2. /*  Delay ASM                                                               */
  3. /*  Function : MY_Delay_5s                                                  */
  4. /*      Parameters                                                          */
  5. /*          Input   :  Nothing                                              */
  6. /*          Output  :  Nothing                                              */
  7. /****************************************************************************/
  8. void MY_Delay_5s(void);

Así lo llamo en main.c
Código: C
  1. #include        "My_Delays.h"
  2.  
  3. void main(void) {
  4. ...
  5. ...
  6.             My_Delay_5s();    //
  7. ...

Pero me dice estos errores:
120:Warning [2058] call of function without prototype
Error - could not find definition of symbol 'My_Delay_5s' in file './Main.o'.

La verdad es que no se que pueda ser, el prototipo esta declarado, la función también, no se por donde buscar ya revise muchos ejemplos y me parece que esta todo bien.
Me dan una mano
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 30 de Junio de 2012, 13:51:07
Macedo subí el proyecto completo o aunque sea el main.
Título: Re: Comienzo en C
Publicado por: macedo en 30 de Junio de 2012, 14:25:23
Hola jukinch, ya esta creo que se colgo el MPLab, tenia otros abierto tambien, y funciona todo lo que quiero preguntarte es sobre esta funcion:
Código: C
  1. #include        "My_Delays.h"
  2.  
  3. /******* PIC Time Delay = 5,00000000 s with Osc = 18432000 Hz *****/
  4. void MY_Delay_5s(void) {
  5.  
  6. unsigned char CounterA=0, CounterB=0, CounterC=0;
  7.  
  8.          _asm
  9.                 movlw   117
  10.                 movwf   CounterC,0          //0=Access RAM
  11.                 movlw   226
  12.                 movwf   CounterB,0          //0=Access RAM
  13.                 movlw   195
  14.                 movwf   CounterA,0          //0=Access RAM
  15.    loop:
  16.                 decfsz  CounterA,1,0        //0=Access RAM
  17.                 goto    loop
  18.                 decfsz  CounterB,1,0        //0=Access RAM
  19.                 goto    loop
  20.                 decfsz  CounterC,1,0        //0=Access RAM
  21.                 goto    loop
  22.                 retlw   0
  23.          _endasm
  24. }

El "unsigned char CounterA=0, CounterB=0, CounterC=0;" se puede declarar global ya que pretendo hacer varias así, con ASM, y todas tienen estas variables, es un cod. generado por PicLoops v2.2, las puse fuera de "void MY_Delay_5s(void)" pero dejo de funcionar la función, la puse en main.c y la función deja de funcionar, si la saco de la función esta no funciona mas.
Orientame por favor s i es que se puede o vale la pena hacerlo.
Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 30 de Junio de 2012, 15:53:15
Macedo:
Debes declarar CounterA B y C como globales.
unsigned char CounterA=0, CounterB=0, CounterC=0;// debes ponerlo en el archivo main.c al principio luego de los includes y antes de:
void main(void)
{
}
No dentro de main. Si lo ponés dentro de la funcion main serán declaradas como locales dentro de main.
Título: Re: Comienzo en C
Publicado por: macedo en 13 de Julio de 2012, 13:16:45
Hola perdón la tardanza, lo declare en el main pero el compilador no me deja hacerlo, creo que no se puede muestra esto:

Error [1510] CounterA cannot have 'extern' storage class, block scope, and an initializer
Error [1510] CounterB cannot have 'extern' storage class, block scope, and an initializer
Error [1510] CounterC cannot have 'extern' storage class, block scope, and an initializer
Halting build on first failure as requested.

o esto:

This feature is not implemented in compiler. There may be a definition of external symbol 'CounterC' found instead of its declaration

Al parecer no quiere que loa llame como extern en la función, ya que si no lo pongo así dice que no existe.
La única forma de que funcione es así:
Código: C
  1. void Delay_5s(void) {
  2. unsigned char CounterA=0, CounterB=0, CounterC=0;
  3.  _asm
  4.                 movlw   117
  5.                 movwf   CounterC,0          //0=Access RAM
  6.                 movlw   226
  7.                 movwf   CounterB,0          //0=Access RAM
  8.                 movlw   195
  9.                 movwf   CounterA,0          //0=Access RAM
  10.    loop:
  11.                 decfsz  CounterA,1,0        //0=Access RAM
  12.                 goto    loop
  13.                 decfsz  CounterB,1,0        //0=Access RAM
  14.                 goto    loop
  15.                 decfsz  CounterC,1,0        //0=Access RAM
  16.                 goto    loop
  17. //              retlw   0x00
  18. _endasm
  19. }

Otra pregunta, no se si notaron el "retlw 0x00" al final, debe ir? ya que si lo coloco parte del programa se pone "loco" pero si no andanda todo bien!.
Saludos


Título: Re: Comienzo en C
Publicado por: jukinch en 13 de Julio de 2012, 18:48:43
Macedo:
declaraste CounterA B y C como globales (fuera de main) ?.
           Jukinch
Título: Re: Comienzo en C
Publicado por: macedo en 14 de Julio de 2012, 10:44:45
Hola asi las declare como me dijiste:
Código: C
  1. int i,j;                                 // Global, usado por LCD configuration
  2.  
  3. unsigned char vcc_state;          // usado en TEST Extesion Port
  4. unsigned char gnd_state;          // usado en TEST Extesion Port
  5. unsigned char test_state=0;                     // usado en UpdateMenu
  6. unsigned char BusChar[15];
  7. unsigned char pos;
  8. unsigned char CounterA=0, CounterB=0, CounterC=0;

Y en el archivo delay.c asi:
Código: C
  1. #include        "My_Delays.h"
  2.  
  3. extern unsigned char CounterA=0, CounterB=0, CounterC=0;
  4. /******* PIC Time Delay = 5,00000000 s with Osc = 18432000 Hz *****/
  5. void Delay_5s(void) {
  6.  
  7.  _asm
  8.                 movlw   117
  9.                 movwf   CounterC,0          //0=Access RAM
  10.                 movlw   226
  11.                 movwf   CounterB,0          //0=Access RAM
  12.                 movlw   195
  13.                 movwf   CounterA,0          //0=Access RAM
  14.    loop:
  15.                 decfsz  CounterA,1,0        //0=Access RAM
  16.                 goto    loop
  17.                 decfsz  CounterB,1,0        //0=Access RAM
  18.                 goto    loop
  19.                 decfsz  CounterC,1,0        //0=Access RAM
  20.                 goto    loop
  21. //        retlw   0x00
  22.  //       return 0x00
  23. _endasm
  24. }

Saludos
Título: Re: Comienzo en C
Publicado por: jukinch en 14 de Julio de 2012, 15:01:01
Subí el proyecto completo así lo vemos.
Título: Re: Comienzo en C
Publicado por: jukinch en 14 de Julio de 2012, 16:39:20
Macedo:
        No podés declarar una variable global con un valor definido y luego declararla como extern asignándole un nuevo valor.

         Vos en el archivo principal.c les asignás el valor cero a CounterA B y C, es decir, las declarás y las definís dándole el valor 0.
         Luego en el archivo delays.c las declarás como extern y le volvés a asignar el valor cero.
         Para solucionar tu problema tenés que declararlas y definirlas globalmente en el archivo principal y luego en tu otro archivo.h las declarás como extern y nada más. Es decir, sin volver a asignarle el cero.
          Luego, dentro de la función del archivo externo, si vas a poder cambiar el valor a las variables.
              
A continuación acompaño dos archivos para compilarlos con devc++ a modo de ejemplo.

Código: C
  1. // ARCHIVO MAIN.C
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "source2.h"
  5.  
  6. unsigned char CounterA=0, CounterB=0, CounterC=0;
  7. extern     void mifuncion(void);    
  8. int main(int argc, char *argv[])
  9. {
  10.    
  11.  
  12.    printf("hola desde main\n");
  13.    printf("counterA= %d\n", CounterA);
  14.    printf("counterB= %d\n", CounterB);
  15.    printf("counterC= %d\n", CounterC);
  16.  
  17.     mifuncion();
  18.  
  19.  
  20.   system("PAUSE");     
  21.   return 0;
  22. }

Código: C
  1. // ARCHIVO source2.h
  2. extern unsigned char CounterA, CounterB, CounterC;
  3.  
  4. void mifuncion(void)
  5.      {
  6. CounterA=10;
  7. CounterB=10;
  8. CounterC=10;
  9.      printf ("hola desde source2.h\n");
  10.      printf("counterA= %d\n", CounterA);
  11.      printf("counterB= %d\n", CounterB);
  12.      printf("counterC= %d\n", CounterC);
  13.      }

y la salida:
Código: C
  1. hola desde main
  2. counterA= 0
  3. counterB= 0
  4. counterC= 0
  5. hola desde source2.h
  6. counterA= 10
  7. counterB= 10
  8. counterC= 10
  9. Presione una tecla para continuar . . .

dale una lectura a estos links:
http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c/1433387#1433387
http://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/CONCEPT/storage_class.html
Título: Re: Comienzo en C
Publicado por: macedo en 17 de Julio de 2012, 13:41:08
Hola jukinch, gracias por los link, nunca esta demás el conocimiento, te comento lo que hice:
Declare en main.c como dijiste:
Código: C
  1. unsigned char CounterA=0, CounterB=0, CounterC=0;
y en delay.h como extern:
Código: C
  1. extern unsigned char CounterA, CounterB, CounterC;
y delay.h lo inclui en delay.c donde esta mi funcion:
Código: C
  1. #include        "My_Delays.h"
  2.  
  3. /******* PIC Time Delay = 5,00000000 s with Osc = 18432000 Hz *****/
  4. void Delay_5s(void) {
  5.  
  6.  _asm
  7.                 movlw   117
  8.                 movwf   CounterC,0          //0=Access RAM
  9.                 movlw   226
  10.                 movwf   CounterB,0          //0=Access RAM
  11.                 movlw   195
  12.                 movwf   CounterA,0          //0=Access RAM
  13.    loop:
  14.                 decfsz  CounterA,1,0        //0=Access RAM
  15.                 goto    loop
  16.                 decfsz  CounterB,1,0        //0=Access RAM
  17.                 goto    loop
  18.                 decfsz  CounterC,1,0        //0=Access RAM
  19.                 goto    loop
  20. //      retlw   0x00
  21.         return 0x00
  22. _endasm
  23. }
Pero con esta configuración la función se cuelga y el pic queda ahí sin hacer nada.
Otra:
Defini en main.c como extern:
Código: C
  1. extern unsigned char CounterA, CounterB, CounterC;
En delay.c:
Código: C
  1. unsigned char CounterA=0, CounterB=0, CounterC=0;

Pero la funcion no funciona, se saltea esta parte y continua con el programa! :shock:

Te pregunto sera que funciona asi por ser una función con assembler?
De esta manera funciona:
Código: C
  1. /******* PIC Time Delay = 5,00000000 s with Osc = 18432000 Hz *****/
  2. void Delay_5s(void) {
  3. unsigned char CounterA=0, CounterB=0, CounterC=0;
  4.  
  5.  _asm
  6.                 movlw   117
  7.                 movwf   CounterC,0          //0=Access RAM
  8.                 movlw   226
  9.                 movwf   CounterB,0          //0=Access RAM
  10.                 movlw   195
  11.                 movwf   CounterA,0          //0=Access RAM
  12.    loop:
  13.                 decfsz  CounterA,1,0        //0=Access RAM
  14.                 goto    loop
  15.                 decfsz  CounterB,1,0        //0=Access RAM
  16.                 goto    loop
  17.                 decfsz  CounterC,1,0        //0=Access RAM
  18.                 goto    loop
  19. //      retlw   0x00
  20. //      return 0x00
  21. _endasm
  22. }

Saludos

Título: Re: Comienzo en C
Publicado por: jukinch en 17 de Julio de 2012, 16:39:35
Macedo: en ASM no tengo idea  :?. Probá simular o debuggear el código para ver que pasa.
        Jukinch