Autor Tema: Mis experiencias con Teensy 3.6  (Leído 12807 veces)

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

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Mis experiencias con Teensy 3.6
« Respuesta #30 en: 16 de Mayo de 2017, 12:54:45 »
Que frecuencia de trabajo posee tu osciloscopio?

Sds.
-
Leonardo Garberoglio

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #31 en: 16 de Mayo de 2017, 13:19:54 »
50MHz con 1GSa/s. La sonda está en modo 10x que permite ver esas frecuencias.

La frecuencia de salida del pin 13 es de 22.48MHz (Hay un pequeño error de 600ppm debido al oscilador del Teensy que no es muy exacto)

El osciloscopio puede ver frecuencias digitales mayores de 50MHz, de hecho he llegado a ver sin problema 100MHz, pero con atenuación.

En este caso puedo ver la señal entre 0 y 3.3V con un tiempo de subida de 13ns y un tiempo de bajada de 13ns del 10% al 90%
De hecho coincide con el datasheet (página 18 y 19) en el que aparece un tiempo de subida y bajada de 15ns.

En el datasheet también indica que hay un modo de funcionamiento "Slew disabled" con el que los tiempos de subida y bajada pasan a ser de 7ns. Voy a intentar activar ese modo.

Saludos.
« Última modificación: 16 de Mayo de 2017, 13:25:07 por Picuino, Razón: Añadir enlace a datasheet »

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Mis experiencias con Teensy 3.6
« Respuesta #32 en: 16 de Mayo de 2017, 13:57:31 »
Si bien no es la respuesta, evidentemente es algo conocido el límete de la velocidad en el GPIO:

http://www.kerrywong.com/2014/09/21/on-arduino-due-pwm-frequency/

sds.
-
Leonardo Garberoglio

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Mis experiencias con Teensy 3.6
« Respuesta #33 en: 16 de Mayo de 2017, 14:01:31 »
El tema es que aca no hay relacion fija de ciclos de instruccion vs ciclos de reloj

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #34 en: 16 de Mayo de 2017, 16:23:21 »
Creo que este tema ya ha dado por ahora mucho de sí. Me apunto para más adelante investigar sobre la configuración de slew en el GPIO.

DAC, PDB Y DMA
Ahora voy a pasar al conversor DAC y al DMA para generar señales analógicas a partir de una tabla de datos.

Este microcontrolador tiene dos DAC de 4096 puntos (12 bits) con las siguientes características de velocidad y rango:
(Página 50 en adelante del datasheet)

12-bit DAC operating requirements
V_DDA   Supply voltage  3.6V
V_DACR   Reference voltage  1.13V - 3.6V
C_L  Output load capacitance  100pF
I_L   Output load current  1mA

Full-scale settling time (0x080 to 0xF7F) (high-power mode) 15us
Code-to-code settling time (0xBF8 to 0xC08)  0.7us
Slew rate -80h→ F7Fh→ 80h (high-power mode) 1.7V/us
3dB bandwidth (high-power mode)  550kHz

Es importante señalar que el DAC tiene dos modos de funcionamiento, uno rápido que consume más y otro lento que consume menos. En los datos anteriores sólo he copiado los datos del modo rápido o high-power.

El programa para generar una señal senoidal es el siguiente:

Código: C
  1. /*
  2.    DAC with DMA
  3.    https://gist.github.com/samyk/6273cf9a45d63a50c38c8b50a39a8f52
  4. */
  5.  
  6. #include <DMAChannel.h>
  7. #include <math.h>
  8. #include "pdb.h"
  9.  
  10.  
  11. #define FUNC_TABLE_SIZE 3600
  12. #define DOTS_PER_CYCLE  15
  13. #define FUNC_AMPLITUDE  0.80
  14. #define DAC_MAXVALUE    4096
  15. #define DAC0_DAT16 *(volatile uint16_t *)&(DAC0_DAT0L)
  16. #define DAC1_DAT16 *(volatile uint16_t *)&(DAC1_DAT0L)
  17.  
  18. DMAChannel dma0(false);
  19.  
  20.  
  21. void fill_sin(volatile uint16_t *table, uint16_t table_size, uint16_t wave_dots) {
  22.   // Fill sine function
  23.   for (int i=0; i<table_size; i++) {
  24.      table[i] = DAC_MAXVALUE * (0.50 + 0.50 * FUNC_AMPLITUDE * cos(i * (2.0 / wave_dots) * 3.1415927));
  25.   }
  26. }
  27.  
  28.  
  29. void DAC_setup(void) {
  30.   SIM_SCGC2 |= SIM_SCGC2_DAC0; // enable DAC clock
  31.   DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // enable the DAC module, 3.3V reference
  32.   DAC0_DAT16 = DAC_MAXVALUE/2;  // Set DAC DC voltage
  33. }
  34.  
  35.  
  36. void PDB_setup(uint16_t period) {
  37.   // set the programmable delay block to trigger DMA requests
  38.   SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock
  39.   PDB0_IDLY = 0;              // Interrupt delay register
  40.   period = (period<8) ? 7 : (period>60000) ? 60000 : period - 1;
  41.   PDB0_MOD = period;          // PDB_PERIOD; // modulus register, sets period
  42.   PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;   // load registers from buffers
  43.   PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; // reset and restart
  44.   PDB0_CH0C1 = 0x0101; // channel n control register?
  45. }
  46.  
  47.  
  48. void DMA_setup(DMAChannel& dma, volatile uint16_t buff[], int tam, volatile uint16_t *dest) {
  49.   dma.begin(true);  // allocate the DMA channel first
  50.   dma.sourceBuffer(buff, tam);
  51.   dma.destination(*dest);
  52.   dma.triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
  53.   dma.enable();
  54. }
  55.  
  56.  
  57. void setup()
  58. {
  59.   Serial.begin(9600);
  60.  
  61.   // DAC and table setup
  62.   static volatile uint16_t func_table[FUNC_TABLE_SIZE];
  63.   fill_sin(func_table, FUNC_TABLE_SIZE, DOTS_PER_CYCLE);
  64.   DAC_setup();
  65.  
  66.   // PDB Setup
  67.   PDB_setup(10);
  68.  
  69.   // DMA Setup
  70.   DMA_setup(dma0, func_table, FUNC_TABLE_SIZE * sizeof(func_table[0]), &DAC0_DAT16);
  71. }
  72.  
  73.  
  74. void loop() {
  75.   int i;
  76.   while(1) {
  77.     // Change PDB speed
  78.     i = Serial.parseInt();
  79.     if (i == 0) continue;
  80.     Serial.println(i);
  81.     PDB_setup(i);
  82.   }
  83. }

Hay que acompañarle del archivo "pdb.h" de la librería Audio:
Código: C
  1. /* Audio Library for Teensy 3.X
  2.  * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
  3.  *
  4.  * Development of this audio library was funded by PJRC.COM, LLC by sales of
  5.  * Teensy and Audio Adaptor boards.  Please support PJRC's efforts to develop
  6.  * open source software by purchasing Teensy or other PJRC products.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  9.  * of this software and associated documentation files (the "Software"), to deal
  10.  * in the Software without restriction, including without limitation the rights
  11.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12.  * copies of the Software, and to permit persons to whom the Software is
  13.  * furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice, development funding notice, and this permission
  16.  * notice shall be included in all copies or substantial portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24.  * THE SOFTWARE.
  25.  */
  26.  
  27. #ifndef pdb_h_
  28. #define pdb_h_
  29.  
  30. #include "kinetis.h"
  31.  
  32. // Multiple input & output objects use the Programmable Delay Block
  33. // to set their sample rate.  They must all configure the same
  34. // period to avoid chaos.
  35.  
  36. #define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN)
  37.  
  38.  
  39. #if F_BUS == 120000000
  40.   #define PDB_PERIOD (2720-1)
  41. #elif F_BUS == 108000000
  42.   #define PDB_PERIOD (2448-1)
  43. #elif F_BUS == 96000000
  44.   #define PDB_PERIOD (2176-1)
  45. #elif F_BUS == 90000000
  46.   #define PDB_PERIOD (2040-1)
  47. #elif F_BUS == 80000000
  48.   #define PDB_PERIOD (1813-1)  // small ?? error
  49. #elif F_BUS == 72000000
  50.   #define PDB_PERIOD (1632-1)
  51. #elif F_BUS == 64000000
  52.   #define PDB_PERIOD (1451-1)  // small ?? error
  53. #elif F_BUS == 60000000
  54.   #define PDB_PERIOD (1360-1)
  55. #elif F_BUS == 56000000
  56.   #define PDB_PERIOD (1269-1)  // 0.026% error
  57. #elif F_BUS == 54000000
  58.   #define PDB_PERIOD (1224-1)
  59. #elif F_BUS == 48000000
  60.   #define PDB_PERIOD (1088-1)
  61. #elif F_BUS == 40000000
  62.   #define PDB_PERIOD (907-1)  // small ?? error
  63. #elif F_BUS == 36000000
  64.   #define PDB_PERIOD (816-1)
  65. #elif F_BUS == 24000000
  66.   #define PDB_PERIOD (544-1)
  67. #elif F_BUS == 16000000
  68.   #define PDB_PERIOD (363-1)  // 0.092% error
  69. #else
  70.   #error "Unsupported F_BUS speed"
  71. #endif
  72.  
  73. #endif

La señal producida es una onda senoidal de 500kHz y 15 puntos por ciclo.
Esta frecuencia y número de puntos se pueden cambiar fácilmente con los valores que contiene el programa en las definiciones.
El periodo del PDB (reloj del DMA) se alimenta de una señal de 60MHz y envía un pulso al DMA cada cierto periodo para que se actualice el DAC. El periodo mínimo es de 8 ciclos (60Mhz/8 = 7.5MHz) y el periodo máximo es de 60000 ciclos (60Mhz/60000 = 1kHz)
Este periodo establece cuántas veces por segundo se actualizará el DAC.

Saludos.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #35 en: 16 de Mayo de 2017, 16:29:14 »
Algunas gráficas.
El número de puntos es siempre de 15 puntos por ciclo. La señal enviada al DAC es siempre la misma y sólo cambia el periodo de escritura de datos en el DAC.

Con un periodo de 8 ciclos (7.5MHz o una escritura al DAC cada 133ns)

* NewFile1.png
(6.27 kB, 640x468 - visto 545 veces)


Con un periodo de 60 ciclos (1MHz o una escritura al DAC cada 1us)

* NewFile2.png
(6.31 kB, 640x468 - visto 590 veces)


Con un periodo de 600 ciclos (100kHz o una escritura al DAC cada 10us)

* NewFile0.png
(6.01 kB, 640x468 - visto 586 veces)


Saludos.
« Última modificación: 16 de Mayo de 2017, 17:15:15 por Picuino »

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Mis experiencias con Teensy 3.6
« Respuesta #36 en: 16 de Mayo de 2017, 17:17:27 »
.

Interesante. ¿ Que vas a hacer un generador de funciones ?.

Estaba buscando aplicación a los samples en BGA del MK66 que recibí de NXP, y podría hacerme un generador de funciones programable. Hace tiempo quería comprar uno, pero mejor hacerlo y de paso hago mi primer diseño con BGA.





Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #37 en: 16 de Mayo de 2017, 17:24:35 »
Si quieres puedes hacerte uno, pero el chip no da mucha frecuencia (500kHz) y la salida tiene un rango limitado (3.3V que yo he dejado en 2.8V para conseguir mejor velocidad y que la carga no afecte a la precisión cerca de los rail).

En realidad quiero conseguir un analizador de impedancia. Por un lado inyecto una señal senoidal y por otro leo la salida con un ADC. Luego correlaciono ambas señales para calcular ganancia y desfase. Con estas dos magnitudes puedes calcular, por ejemplo, la capacidad y la ESR de un condensador.

Calculando estas dos magnitudes para muchos puntos de frecuencia puedes graficar un bode completo de un filtro, de una fuente de alimentación, etc.


Saludos.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Mis experiencias con Teensy 3.6
« Respuesta #38 en: 16 de Mayo de 2017, 18:37:26 »
Si quieres puedes hacerte uno, pero el chip no da mucha frecuencia (500kHz) y la salida tiene un rango limitado (3.3V que yo he dejado en 2.8V para conseguir mejor velocidad y que la carga no afecte a la precisión cerca de los rail).

Es más por hacer algo con BGA con los samples que he recibido de NXP, la aplicación casi que me da igual. También puedo hacer una plaquita de evaluación, parecida al Teensy, pero sin bootloader y con acceso SWD para programar y hacer Debug con GDB.

O puedo montar una placa para controlar paneles Led RGB de 64x32 con las librerías Smartmatrix. De todas formas creo que voy a dejar los Kinetis, son caros comparados con los STM32, y mucho mejor trabajar con los SAM S70 de Atmel, más potentes y casi a mitad de precio.

Si vas a trabajar el Teensy, también puedes hacerlo desde Atmel Studio, hay un plugin gratuito para abrir proyectos Arduino.
« Última modificación: 16 de Mayo de 2017, 18:42:39 por planeta9999 »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #39 en: 17 de Mayo de 2017, 13:25:49 »
Yo haría una placa de pruebas que se pueda conectar luego a otra placa de aplicación (como las stm32 nucleo).

Tendré en cuenta lo del Atmel Studio o Eclipse.  Ahora que he conseguido compilar desde línea de comandos no es difícil pasar el proyecto a cualquier IDE.

Conversor Analógico Digital ADC
Continúo haciendo pruebas con los módulos de Teensy 3.6. En este caso pruebo el ADC con las librerías estandar de Arduino.

Código: C
  1. /*
  2.    ADC with analogRead();
  3. */
  4. const int ledPin = 13;
  5.  
  6. void setup() {
  7.   pinMode(ledPin, OUTPUT);
  8.   pinMode(A20, INPUT);
  9.  
  10.   while(1) {
  11.    *portSetRegister(ledPin) = 1;
  12.    analogRead(A20);
  13.    *portClearRegister(ledPin) = 1;
  14.   }
  15. }
  16.  
  17. void loop() {}

El código anterior consigue realizar una conversión analógico-digital cada 7us (a 142kHz). Por ahora no es mucho para este microcontrolador. Parece que tendré que modificar directamente los registros.

Saludos.

Desconectado elgarbe

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Mis experiencias con Teensy 3.6
« Respuesta #40 en: 17 de Mayo de 2017, 14:30:31 »
Solo un comentario por si no lo viste ya.
Cada periférico o grupo de perifericos tienen Fclk independientes con prescalers configurables. Quizá tu ADC estña lento porque por defecto el clk que le llega es bajo.

Saludos!
-
Leonardo Garberoglio

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #41 en: 17 de Mayo de 2017, 15:39:04 »
Si lo sé. Por eso tendré que escribir directamente en los registros de configuración para conseguir cambiar el reloj, el tiempo de adquisición, el número de bits convertidos, etc. Un poco rollo, pero no hay otra forma de optimizar la conversión.
Después tendré que asociar un generador de pulsos para que el inicio de la conversión del ADC se realice en tiempos deterministas y los dos ADC comiencen a la vez.
La idea es samplear a la vez dos señales con frecuencia y tiempos idénticos de manera que luego se pueda comparar el desfase entre las dos señales. Además, cuanto mayor sea la frecuencia, mejor.

Saludos.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #42 en: 17 de Mayo de 2017, 18:17:17 »
Bueno, objetivo conseguido.
Con el siguiente programa, se configura el reloj del ADC a partir del reloj del bus (60MHz) dividido entre cuatro, es decir, 15MHz.
La conversión es de 12bits sin signo

El resultado final es de una conversión cada 1.9us (unos 500kHz). La conversión tarda aproximadamente 28 ciclos de reloj de 15MHz. Casi coincide con el datasheet que indica 26 ciclos de reloj para esta configuración.

Código: C
  1. /*
  2.    Fast ADC
  3.    Writing config registers
  4. */
  5.  
  6. void ADC0_init(void);
  7. uint16_t ADC0_read(char channel);
  8.  
  9. void setup() {
  10.   Serial.begin(9600);
  11.  
  12.   // Config pins
  13.   pinMode(13, OUTPUT);
  14.   pinMode(A20, INPUT);
  15.  
  16.   // Inits ADC and read
  17.   ADC0_init();
  18.   for(;;) {  
  19.      ADC0_read(20);
  20.   }
  21. }
  22.  
  23. void loop() {}
  24.  
  25. // Init ADC
  26. // https://forum.pjrc.com/threads/31286-Analog-Conversion-Complete-Interrupt
  27. //
  28. void ADC0_init(void) {
  29.   uint32_t ADC_CFG1, ADC_CFG2;
  30.  
  31.   ADC_CFG1 =
  32.     //+ ADC_CFG1_ADLPC      // Low-power configuration
  33.     + ADC_CFG1_ADIV(1)    // Clock divide, 0=direct, 1=div2, 2=div4, 3=div8
  34.     //+ ADC_CFG1_ADLSMP     // Sample Time config, 0=short, 1=long
  35.     + ADC_CFG1_MODE(1)    // 0=8bit, 1=12bit, 2=10bit, 3=16bit
  36.     + ADC_CFG1_ADICLK(1); // input clock, 0=bus, 1=bus/2, 2= , 3=async
  37.   ADC0_CFG1 = ADC_CFG1;
  38.  
  39.   ADC_CFG2 =
  40.     //+ ADC_CFG2_MUXSEL
  41.     + ADC_CFG2_ADACKEN    // Async clock enable
  42.     + ADC_CFG2_ADHSC      // High speed enable
  43.     + ADC_CFG2_ADLSTS(3); // extra clocks for long conversion (0=24,1=12,2=6,3=4)
  44.   ADC0_CFG2 = ADC_CFG2;
  45.    
  46.   ADC0_SC1A =
  47.     //+ ADC_SC1_COCO  // Conversion Complete
  48.     //+ ADC_AIEN   // Interrupt Enable
  49.     //+ ADC_DIFF   // Differential Mode Enable
  50.     + 20;        // Input channel select
  51.  
  52.   ADC0_SC2 =
  53.     //+ ADC_SC2_ADACT      // Conversion active
  54.     //+ ADC_SC2_ADTRG      // Conversion Trigger 0=Software, 1=Hardware
  55.     //+ ADC_SC2_ACFE       // Compare Function Enable
  56.     //+ ADC_SC2_ACFGT      // Compare Function Greater Than Enable
  57.     //+ ADC_SC2_ACREN      // Compare Function Range Enable
  58.     //+ ADC_SC2_DMAEN      // DMA Enable
  59.     + ADC_SC2_REFSEL(0); // Voltage Reference 0=Ext pins, 1=Alternate Ext. pins
  60.    
  61.   ADC0_SC3 =
  62.     //+ ADC_SC3_CAL     // Init Calibration
  63.     //+ ADC_SC3_CALF    // Calibration Failed
  64.     //+ ADC_SC3_ADCO    // Continuous conversion Enable
  65.     //+ ADC_SC3_AVGE    // Hardware average enable
  66.     //+ ADC_SC3_AVGS(3) // Hardware average 0=4 sampl, 1=8 sampl, 2=16 sampl, 3=32 sampl
  67.     +0;
  68.  
  69.   // Start Calibration
  70.   ADC0_SC3 |= ADC_SC3_CAL;
  71.   while ((ADC0_SC3 & ADC_SC3_CAL)) {
  72.     if (ADC0_SC3 & ADC_SC3_CALF) {
  73.       Serial.println("Calibration error");
  74.       return;
  75.     }
  76.   }
  77.   Serial.println ("ADC0 Calibrated");        
  78.   ADC0_CFG1 = ADC_CFG1;
  79.   ADC0_CFG2 = ADC_CFG2;
  80.   ADC0_SC3 = 0;  
  81. }
  82.  
  83. // Read ADC
  84. uint16_t ADC0_read(char channel) {
  85.   ADC0_SC1A = channel & 0x1F; // Init conversion
  86.   *portSetRegister(13) = 1;
  87.   while ((ADC0_SC1A & ADC_SC1_COCO)==0);
  88.   *portClearRegister(13) = 1;
  89.   return ADC0_RA;
  90. }

Investigaré un poco para saber si se pueden arañar dos ciclos menos de reloj. De todas formas considero que esta velocidad es lenta. Para conseguir mayores velocidades (el datasheet declara un máximo de 1.2Msamples/s) será necesario bajar a una conversión de 8bit y aumentar la velocidad de reloj.

Saludos.
« Última modificación: 17 de Mayo de 2017, 18:21:22 por Picuino »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #43 en: 17 de Mayo de 2017, 18:26:43 »
El datasheet indica una velocidad máxima de reloj de 24MHz para conversiones menores de 14bits.
El caso es que no puedo conseguir esta velocidad a partir de una velocidad de bus de 60MHz. Puedo conseguir 15MHz, que es lento, y 30MHz, que es demasiado rápido y puede distorsionar las medidas.
Tendré que hacer pruebas a 30MHz y 8 bit a ver si el error es suficientemente bajo como para poder utilizar esa frecuencia.

Por ahora esa configuración (ADC=8bit sin signo, f_ADCK=30MHz) consigue realizar conversiones en 864ns (1.16Msamples/segundo).

Saludos.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Mis experiencias con Teensy 3.6
« Respuesta #44 en: 18 de Mayo de 2017, 13:45:53 »
Este otro programa hace trabajar al ADC en modo "continuous sampling" de manera que la siguiente conversión del ADC se inicia nada más terminar la anterior.
El reloj del ADC está configurado a 15MHz. Aunque el ADC puede funcionar más rápido, en el datasheet (página 47) aparece una gráfica en la que se puede ver que el ENOB decrece por encima de los 7-8MHz y llega a unos 12bits a 15MHz (hay que extrapolar la gráfica).

* ENOB.png
(18.4 kB, 634x383 - visto 540 veces)


El programa consigue tiempos de conversión de 20 ciclos a 15Mhz (750ksamples/s = 1.3333us/sample) que no está del todo mal.

Código: C
  1. /*
  2.    Fast ADC
  3. */
  4.  
  5. void ADC0_init(char channel);
  6. uint16_t ADC0_read(void);
  7.  
  8. void setup() {
  9.   Serial.begin(9600);
  10.  
  11.   // Config pins
  12.   pinMode(13, OUTPUT);
  13.   pinMode(A20, INPUT);
  14.  
  15.   // Inits ADC and read
  16.   ADC0_init(20);
  17.   for(;;) {  
  18.      ADC0_read();
  19.   }
  20. }
  21.  
  22. void loop() {}
  23.  
  24. // Init ADC
  25. // https://forum.pjrc.com/threads/31286-Analog-Conversion-Complete-Interrupt
  26. void ADC0_init(char channel) {
  27.   uint32_t ADC_CFG1, ADC_CFG2;
  28.  
  29.   ADC_CFG1 =
  30.     //+ ADC_CFG1_ADLPC     // Low-power configuration
  31.     //+ ADC_CFG1_ADLSMP    // Long Sample Time
  32.     + ADC_CFG1_MODE(1)   // 0=8bit, 1=12bit, 2=10bit, 3=16bit
  33.     + ADC_CFG1_ADIV(1)   // Clock divide, 0=direct, 1=div2, 2=div4, 3=div8
  34.     + ADC_CFG1_ADICLK(1) // Input clock, 0=bus, 1=bus/2, 2= , 3=async
  35.     + 0;
  36.   ADC0_CFG1 = ADC_CFG1;
  37.  
  38.   ADC_CFG2 =
  39.     //+ ADC_CFG2_MUXSEL     // Selects ADxxB channels instead ADxxA channels
  40.     //+ ADC_CFG2_ADACKEN    // Async clock enable
  41.     //+ ADC_CFG2_ADHSC      // Add 2 extra clocks to conversion (for high speed clocks)
  42.     //+ ADC_CFG2_ADLSTS(3) // Extra clocks for long conversion (ADLSMP=1) (0=24,1=12,2=6,3=4)
  43.     + 0;
  44.   ADC0_CFG2 = ADC_CFG2;
  45.    
  46.   ADC0_SC1A =
  47.     //+ ADC_SC1_COCO // Conversion Complete
  48.     //+ ADC_AIEN     // Interrupt Enable
  49.     //+ ADC_DIFF     // Differential Mode Enable
  50.     + 0;           // Input channel select
  51.  
  52.   ADC0_SC2 =
  53.     //+ ADC_SC2_ADACT      // Conversion active
  54.     //+ ADC_SC2_ADTRG      // Conversion Trigger 0=Software, 1=Hardware
  55.     //+ ADC_SC2_ACFE       // Compare Function Enable
  56.     //+ ADC_SC2_ACFGT      // Compare Function Greater Than Enable
  57.     //+ ADC_SC2_ACREN      // Compare Function Range Enable
  58.     //+ ADC_SC2_DMAEN      // DMA Enable
  59.     + ADC_SC2_REFSEL(0); // Voltage Reference 0=Ext pins, 1=Alternate Ext. pins
  60.    
  61.   ADC0_SC3 =
  62.     //+ ADC_SC3_CAL     // Init Calibration
  63.     //+ ADC_SC3_CALF    // Calibration Failed
  64.     + ADC_SC3_ADCO    // Continuous conversion Enable
  65.     //+ ADC_SC3_AVGE    // Hardware average enable
  66.     //+ ADC_SC3_AVGS(3) // Hardware average 0=4 sampl, 1=8 sampl, 2=16 sampl, 3=32 sampl
  67.     +0;
  68.  
  69.   // Start Calibration
  70.   ADC0_SC3 |= ADC_SC3_CAL;
  71.   while ((ADC0_SC3 & ADC_SC3_CAL)) {
  72.     if (ADC0_SC3 & ADC_SC3_CALF) {
  73.       Serial.println("Calibration error");
  74.       return;
  75.     }
  76.   }
  77.   ADC0_SC3 &= ~ADC_SC3_CAL;
  78.   Serial.println ("ADC0 Calibrated");
  79.   ADC0_CFG1 = ADC_CFG1;
  80.   ADC0_CFG2 = ADC_CFG2;
  81.  
  82.   // Conversion init
  83.   ADC0_SC1A = channel & 0x1F; // Init conversion
  84. }
  85.  
  86. // Read ADC
  87. uint16_t ADC0_read(void) {
  88.   while ((ADC0_SC1A & ADC_SC1_COCO)==0);
  89.   *portSetRegister(13) = 1;
  90.   *portClearRegister(13) = 1;
  91.   return ADC0_RA;
  92. }

Un saludo.