Autor Tema: DSPIC33EP256GP502 Iniciación..  (Leído 3797 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #15 en: 29 de Junio de 2017, 02:57:45 »
Vaya que cosa mas buena, sin duda una buena herramienta. Como lo explicó elgarbe ayuda muchisimo, no solo en transportar datos. Me imagino para manejar pantallas gráficas donde requieres mandar muchos datos el DMA hace a un micro muy robusto. Como mencione anteriormente, no me habia dado a la tarea de poder manejar micros fuera de los 16F y 18F. Ahora con mas entusiasmo quiero seguir conociendolos, voy a probar el ADC con y sin DMA haber que sucede. KillerJC muchas gracias.

 ((:-))

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #16 en: 02 de Julio de 2017, 03:23:18 »
Después de leer la sección de ADC y tratar de comprender los ejemplos, tomé el más simple de los ejemplos. Código

Código: C
  1. #include <p33Exxxx.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <xc.h>
  5. #include <libpic30.h>
  6.  
  7. #pragma config  ICS = PGD3               // Comm Channel Select (Communicate on PGC1/EMUC1 and PGD1/EMUD1)
  8. #pragma config  JTAGEN = OFF             // JTAG Port Enable (JTAG is Disabled)
  9. #pragma config  FNOSC= FRC
  10. #pragma config  IESO= OFF
  11. #pragma config  FCKSM= CSECMD
  12. #pragma config  OSCIOFNC=OFF
  13. #pragma config  POSCMD=NONE
  14.  
  15.  
  16. void initAdc1(void);
  17. void Delay_us(unsigned int);
  18. int ADCValue, i, j;
  19.  
  20. int main()
  21. {
  22.  // Configure PLL prescaler, PLL postscaler, PLL divisor
  23.  PLLFBD=63; // M=65
  24.  CLKDIVbits.PLLPOST=0; // N2=2
  25.  CLKDIVbits.PLLPRE=1; // N1=3
  26. // Initiate Clock Switch to FRC oscillator with PLL (NOSC=0b001)
  27.  __builtin_write_OSCCONH(0x01);
  28.  __builtin_write_OSCCONL(OSCCON | 0x01);
  29.  // Wait for Clock switch to occur
  30.  while (OSCCONbits.COSC!= 0b001);
  31.  // Wait for PLL to lock
  32.  while (OSCCONbits.LOCK!= 1);
  33.  TRISB=0X0000;
  34.  
  35.  initAdc1();
  36.  
  37.  while(1)
  38.  {
  39.   Delay_us(100); // Sample for 100 us
  40.   AD1CON1bits.SAMP = 0; // Start the conversion
  41.   while (!AD1CON1bits.DONE); // Wait for the conversion to complete
  42.   AD1CON1bits.DONE = 0; // Clear conversion done status bit
  43.   ADCValue = ADC1BUF0; // Read the ADC conversion result
  44. //  LATB=ADCValue;
  45.   if(ADCValue >= 1300)
  46.   {
  47.       LATBbits.LATB6=1;
  48.   }
  49.   else
  50.   {
  51.       LATBbits.LATB6=0;
  52.   }
  53.  
  54.  }
  55. }
  56.  
  57. void initAdc1(void)
  58. {
  59. /* Set port configuration */
  60. TRISAbits.TRISA0=1;
  61. ANSELA = ANSELB = 0x0000;
  62. ANSELAbits.ANSA0 = 1; // Ensure AN5/RB5 is analog
  63. /* Initialize and enable ADC module */
  64. AD1CON1 = 0x0004;
  65. AD1CON2 = 0x0000;
  66. AD1CON3 = 0x00FF;
  67. AD1CON4 = 0x0000;
  68. AD1CHS0 = 0x0005;
  69. AD1CHS123 = 0x0000;
  70. AD1CSSH = 0x0000;
  71. AD1CSSL = 0x0000;
  72. AD1CON1bits.ADON = 1;
  73. Delay_us(20);
  74. }
  75. void Delay_us(unsigned int delay)
  76. {
  77. for (i = 0; i < delay; i++)
  78.   {
  79.     __asm__ volatile ("repeat #39");
  80.     __asm__ volatile ("nop");
  81.   }
  82. }

Leí los registros, y creo que estan bien. Ya que en los AD1CON solo configuro lectura manual sin DMA, el código ejemplo es de otro canal y lo cambié al CH0 del ADC. Para poder comprobar el funcionamiento del mismo, he realizado una pequeña comparación del dato obtenido pero no tengo resultado alguno.  :(

Que podria estar mal?

Saludos
« Última modificación: 02 de Julio de 2017, 03:26:52 por Pinolillo16 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #17 en: 02 de Julio de 2017, 19:52:48 »
La diferencia del ADC con los demas PICs , es que podes controlar el sampling y la conversion independientemente, ademas posees 4 S/H
Y no solo eso, sino que cuando los lei me di cuenta el DESASTRE que hicieron los de Microchip en documentar estos micros. Es la peor documentacion que eh visto. Por que trata las cosas muy generales, y encima tenes que abrir cerca de 4 documentos mas para ver un modulo, Ej.. para el ADC tenes que tener el datasheet del micro + datasheet de los pines configurables/alternativos, etc. Sinceramente lo lees y en ves de explicarte te llena de mas dudas.

Vos queres:
- Sampleo automatico
- Conversion manualmente.

Una cosa que tiene una nota:

Citar
Do not clear the DONE bit in software if ADC Sample Auto-Start is enabled (ASAM = 1).
Lo raro es que el codigo que te provee Microchip posee la limpieza del bit DONE.

Creo que tu problema se encuentra en:

Código: C
  1. AD1CHS0 = 0x0005;

El cual deberia ser para unir AN0 con CH0

Código: C
  1. AD1CHS0 = 0x0000;

Otra cosa mas, el tema de los tiempos

Código: C
  1. AD1CON3 = 0x00FF;

Como es auto-sampling deberias darle tiempo, No deberias dejarlo en 0 TAD, hay una acotacion en el datasheet. Imagino que podrias utilizar el oscilador interno que posee el ADC, Por las dudas tambien seleccionamos 31 TAD en el Sampling dejando:

Código: C
  1. AD1CON3 = 0xFF00;

-----------------------------------------------------------

PD... me parecio raro que no posea un delay, entonces busque y encontre esto en el MPLAB® XC16 C Compiler User’s Guide:

Citar
3.5.7 How Can I Implement a Delay in My Code?
Using a device timer to generate a delay is the best method. If no time is available, then
you can use the library functions _delay32, __delay_ms, or __delay_us, as they
are described in the following document. It is available for download from the Microchip
Technology website, www.microchip.com.
“16-Bit Language Tools Libraries Reference Manual” (DS50001456)

El tema es que buscas ese archivo y no dice NADA de NADA de delays, podrias probar ponerlo y ver si funciona.
« Última modificación: 02 de Julio de 2017, 20:03:58 por KILLERJC »

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #18 en: 03 de Julio de 2017, 02:52:56 »
 :shock: si fue exactamente eso Killer, el codigo quedo asi:

Código: C
  1. #include <p33Exxxx.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <xc.h>
  5. #include <libpic30.h>
  6.  
  7. #pragma config  ICS = PGD3               // Comm Channel Select (Communicate on PGC1/EMUC1 and PGD1/EMUD1)
  8. #pragma config  JTAGEN = OFF             // JTAG Port Enable (JTAG is Disabled)
  9. #pragma config  FNOSC= FRC
  10. #pragma config  IESO= OFF
  11. #pragma config  FCKSM= CSECMD
  12. #pragma config  OSCIOFNC=OFF
  13. #pragma config  POSCMD=NONE
  14.  
  15.  
  16. void initAdc1(void);
  17. void Delay_us(unsigned int);
  18. int ADCValue, i, j;
  19.  
  20. int main()
  21. {
  22.  // Configure PLL prescaler, PLL postscaler, PLL divisor
  23.  PLLFBD=63; // M=65
  24.  CLKDIVbits.PLLPOST=0; // N2=2
  25.  CLKDIVbits.PLLPRE=1; // N1=3
  26. // Initiate Clock Switch to FRC oscillator with PLL (NOSC=0b001)
  27.  __builtin_write_OSCCONH(0x01);
  28.  __builtin_write_OSCCONL(OSCCON | 0x01);
  29.  // Wait for Clock switch to occur
  30.  while (OSCCONbits.COSC!= 0b001);
  31.  // Wait for PLL to lock
  32.  while (OSCCONbits.LOCK!= 1);
  33.  TRISB=0X0000;
  34.  
  35.  initAdc1();
  36.  
  37.  while(1)
  38.  {
  39.   Delay_us(100); // Sample for 100 us
  40.   AD1CON1bits.SAMP = 0; // Start the conversion
  41.   while (!AD1CON1bits.DONE); // Wait for the conversion to complete
  42.   AD1CON1bits.DONE = 0; // Clear conversion done status bit
  43.   ADCValue = ADC1BUF0; // Read the ADC conversion result
  44. //  LATB=ADCValue;
  45.   if(ADCValue >= 800)
  46.   {
  47.       LATBbits.LATB6=1;
  48.   }
  49.   else
  50.   {
  51.       LATBbits.LATB6=0;
  52.   }
  53.  
  54.  }
  55. }
  56.  
  57. void initAdc1(void)
  58. {
  59. /* Set port configuration */
  60. TRISAbits.TRISA0=1;
  61. ANSELA = ANSELB = 0x0000;
  62. ANSELAbits.ANSA0 = 1; // Ensure AN5/RB5 is analog
  63. /* Initialize and enable ADC module */
  64. AD1CON1 = 0x0004;
  65. AD1CON2 = 0x0000;
  66. AD1CON3 = 0xFF00;
  67. AD1CON4 = 0x0000;
  68. AD1CHS0 = 0x0000;
  69. AD1CHS123 = 0x0000;
  70. AD1CSSH = 0x0000;
  71. AD1CSSL = 0x0000;
  72. AD1CON1bits.ADON = 1;
  73. Delay_us(20);
  74. }
  75. void Delay_us(unsigned int delay)
  76. {
  77. for (i = 0; i < delay; i++)
  78.   {
  79.     __asm__ volatile ("repeat #39");
  80.     __asm__ volatile ("nop");
  81.   }
  82. }

Dados los consejos, lei nuevamente el manual ADC. Lo del tiempo creo que lo entiendo un poco ya que el mismo manual me dice, que solo deje TDA en 0 cuando es lectura simultanea para poder hacerlo más rápido. Ahora no me queda del todo claro lo del AD1CHS0, lo tenia igual a= 0x0005. Y para que funcione me indica que es 0x0000... Mi lógica indica que esto funciona asi debido a los registros y pines del puerto A, como el pin correspondiente al ADC0 esta en RA0. Por eso le coloco este 0? Digo mi lógica dice que es por esa razon, ya que el ejemplo del manual indica tener el ADC0 en RB5....

Cuando volvi a ver la información del manual entiendo lo siguiente:


* adcch0.PNG
(82.33 kB, 665x478 - visto 383 veces)

 :D

Bueno continuo la respuesta, ahora mismo que queria subir la información abri el datasheet sobre el mismo registro:


* adcch01.PNG
(61.8 kB, 588x426 - visto 396 veces)

Y queda todo claro. Tienes razón sobre la documentación, tienes que abrir muchos archivos. No me quedaba del todo claro porque había tanta información y creo que ahora solo necesito revisar todos los documentos ejemplo y luego el data sheet para saber que sucede.

Nuevamente gracias Killer por tus sabios consejos, bien. Me dispondré a probar ahora con el DMA pero, antes creo que voy a realizar algún código con SPI para poder ver la diferencia, o que será mejor probar un PWM? Quisiera saber que tan poderoso es el DMA y a la vez que tan latoso, pero necesito algo donde pueda ver datos procesados por el DSP vs el DMA por eso quisiera mostrarlos en alguna pantalla. Como son dispositivos completamente nuevos me gustaría que me dieran alguna sugerencia para practicar más y que si pueda hacerla. Voy directo a la pantalla? o exploro poco a poco los módulos?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #19 en: 03 de Julio de 2017, 16:06:57 »
El DMA es mejor verlo con una comunicacion, y que mejor un SPI o una UART para eso. Ejemplo llena un buffer y luego dispara el DMA, mientras haces NADA. y que solo se encargue de llevar los datos.

Respecto a los modulos la verdad que yo solo me pondria a renegar solo si necesito hacerlo, si queres probar adelante. Ejemplo multiple sampling y demas. Al igual que si uqeres ir incrementalmente, pone la interrupcion, y que en ves de saltar a la primer lectura lo hagas en la 4ta por ejemplo.

Y mas que nada, ya comenzaria a jugar con las librerias, no se si vale la pena ya en un micro de ese tamaño ir por registros, mas cuando son 478174138993 miles de estos.

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #20 en: 10 de Agosto de 2017, 17:42:57 »
Colegas del foro, seguiré alimentando este tema. Lo último que estuve estudiando fue el DMA, que pensaba utilizarlo en ADCs pero siguiendo el conejo de KillerJC no vale la pena en ese modulo es mejor en una comunicación, asi que me dispuse a diseñar y montar una tarjeta con DSP que tenia a la mano, DSPIC33EP256MC504 en QFN. Ya que cuento con varios de ellos quise comenzar a conocerlos de una manera mas profunda y bueno el resultado es este:


* dsP1.jpg
(171.81 kB, 841x473 - visto 347 veces)

Recien recibi las tarjetas solde los componentes y fue buena la primera prueba ya que los leds prendieron  :-/ meti unos 0402 que casi no veia.


* DSP2.jpg
(90.2 kB, 519x292 - visto 341 veces)

Como veran le deje los pines compatibles para una OLED de I2C. Estare testeando más codigos para ver que tal funcionan.

Espero sus observaciones colegas.


* DSP3.jpg
(116.05 kB, 648x364 - visto 371 veces)

PD: KillerJC en un post anterior me dijo que estaba dificil poder montar un entrenador completo ya que a veces faltaban cosas o sobraban, en mi caso solo fue el gusto.

Saludos

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #21 en: 10 de Agosto de 2017, 18:30:54 »
Citar
PD: KillerJC en un post anterior me dijo que estaba dificil poder montar un entrenador completo ya que a veces faltaban cosas o sobraban, en mi caso solo fue el gusto.

Es complejo y se hace gigante la placa para lograr hacer que todo se pueda con los pines. Pero lo que hiciste no lo veo como una entrenadora sino una placa de evaluacion que es perfecta para probar cualquier cosa. Ya que teniendo los pines a disposicion podes conectar lo que sea sobre un protoboard, mientras que una entrenadora tenes lo que tenes en la placa.

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #22 en: 27 de Agosto de 2017, 21:32:18 »
Con un poco de tiempo, estuve intentando usar el code configurator. Me pueden apoyar?

Al configurar el I2C en el canal dos con el code configurator. Me manda esta funcion en C:

Código: C
  1. void I2C2_MasterWrite(
  2.                                 uint8_t *pdata,
  3.                                 uint8_t length,
  4.                                 uint16_t address,
  5.                                 I2C2_MESSAGE_STATUS *pstatus)
  6. {
  7.     static I2C2_TRANSACTION_REQUEST_BLOCK   trBlock;
  8.  
  9.     // check if there is space in the queue
  10.     if (i2c2_object.trStatus.s.full != true)
  11.     {
  12.         I2C2_MasterWriteTRBBuild(&trBlock, pdata, length, address);
  13.         I2C2_MasterTRBInsert(1, &trBlock, pstatus);
  14.     }
  15.     else
  16.     {
  17.         *pstatus = I2C2_MESSAGE_FAIL;
  18.     }
  19.  
  20. }

Para el archivo .h generado tengo:

Código: C
  1. void I2C2_MasterWrite(
  2.                                 uint8_t *pdata,
  3.                                 uint8_t length,
  4.                                 uint16_t address,
  5.                                 I2C2_MESSAGE_STATUS *pstatus);

Mis dudas son:

Para el I2C no se supone que mandamos primero Address? porque estuve tratando de entender la secuencia que me arroja ya que pienso utilizarlo para manejar un LCD oled con controlador SSD13006.

Pero antes de continuar me gustaria saber si alguno de ustedes ya ha usado el codigo del code configurator? Que me ayudara a entender. O sera mejor hacerlo por uno mismo?

Saludos

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:DSPIC33EP256GP502 Iniciación..
« Respuesta #23 en: 27 de Agosto de 2017, 22:09:15 »
Dentro de ese archivo podes ver que hace las 2 funciones.

el I2C2_MasterWriteTRBBuild rellena la estructura trBlock con la direccion, largo y el puntero a los datos. Ya que esta estructura es la que acepta la proxima funcion.
el I2C2_MasterTRBInsert inserta ese trBlock en un Queue de largo (I2C2_CONFIG_TR_QUEUE_LENGTH) para que luego sea enviado.

De aca luego lo dirije a la interrupcion (disparandolo poniendo el flag a 1), al menos es el codigo que vi yo, tampoco se si es el mismo ya que este es un dsPIC. Ahi dentro de la interrupcion tiene una maquina de estado. Entra y envia la direccion, luego los datos, etc.

Esto esta en la funcion I2C2_ISR.

En resumen lo unico que te importa es meter los datos en un array de uint8_t, luego darle la cantidad de datos, y definir la direccion



Simplificado, algo asi en caso de tener un solo dato:

Código: C
  1. uint8_t I2C2_write (uint8_t device_address, uint8_t reg_address, uint8_t wr_data){
  2.     I2C2_MESSAGE_STATUS status = I2C2_MESSAGE_PENDING;
  3.     uint8_t         write_buffer[2];
  4.     write_buffer[0] = reg_address;
  5.     write_buffer[1] = wr_data;
  6.     I2C2_MasterWrite(&write_buffer, 2, device_address, &status);  // pointer la valoarea wr_data
  7.     while(status == I2C2_MESSAGE_PENDING);
  8.     return (status == I2C2_MESSAGE_COMPLETE);
  9. }

Ese  codigo fue sacado de otro lado. Por mi pienso que no es necesario el bloqueo del while que posee, por que ya en la funcion I2C2_MasterTRBInsert, tenes esto:

Código: C
  1. // for interrupt based
  2.     if (*pflag == I2C2_MESSAGE_PENDING)
  3.     {
  4.         while(i2c2_state != S_MASTER_IDLE);
  5.         {
  6.             // force the task to run since we know that the queue has
  7.             // something that needs to be sent
  8.             PIR3bits.SSP2IF = true;
  9.         }
  10.     }   // block until request is complete

Que lo bloquea hasta que salga de ese estado.
« Última modificación: 27 de Agosto de 2017, 22:13:56 por KILLERJC »