interrupciones duda avanzada

tengo un arduino uno con velocidad de reloj de 16Mhz

veréis, quiero enviar por el puerto D (pines D0-hasta D7) un valor cada cierto tiempo.

Quería una frecuencia de envío de datos al puerto D de 2MHz.
osea que debo poner cada 0.5us nuevos valors en el puerto D.

Había pensado utilizar el TIMER1 de 16 bits en modo comparador

colocando el valor apropiado en OCR1A (que he calculado igual a 7)

me debe saltar el timer cuando llegue a los 0.5us
y entonces escribir en el puerto D
ISR(TIMER1_COMPA_vect){
PORTD=numero;
}

la pregunta es:
¿Le veis alguna pega a este planteamiento?,
porque he estado simulando en proteus y no llego a esa frecuencia ni de broma, me quedo siempre en 20us.
y no tengo osciloscopio para poderlo comprobar en directo.

Un saludo.

Hola.
Sin entrar en el cálculo de tu timer, creo que el Arduino las va a pasar canutas para poder realizar lo que le pides. Igual me equivoco en mis apreciaciones, pero así a ojo de buen cubero, si el arduino realiza 16 millones de operaciones por segundo (una por ciclo de reloj) y estás pidiendo que haga 2 millones de escrituras por segundo, cada ciclo de escritura de tu programa debería consumir 8 ciclos de procesador como máximo. Si tenemos en cuenta que cada instrucción en ensamblador consume mínimo un ciclo, los saltos mínimo dos ciclos, el retorno de interrupción 5 ciclos… creo que ya nos pillamos los dedos.
Si se trata de algo muyyyyyyy específico y muyyyyy sencillo, vamos, que pudiera hacerse en un ciclo de 8 instrucciones de ensamblador, tal vez deshabilitando todas las interrupciones y ajustando para que consuma esos 8 ciclos podrías llegar a obener algo parecido.
Es mi impresión, pero a ver si alguien más opina.
Saludos.

gracias por responder....

osea que en cada escritura consumimos 8 ciclosx2millones de escrituras, estamos en 16 millones ciclos...
vamos que nos hemos caído con todo el equipo....

no obstante, siendo conservador, ¿Cuál crees que sería la frecuencia a que debería escribir en el puerto y tener sitio para
leer algunos un par pines analógicos y direccionar datos a un par de pines digitales?...
....
por otro lado el cálculo para alojar el valor en el OCR1A lo he sacado de aquí:

configuro el preescaler a x1 (sin preescaler)
el valor del registro OCR1A sale de ctc=tiempo deseado/resolución del timer-1
resolución del timer al ser el preescaler 1, 1/16Mhz=62,5ns
luego ctc=0.5us/62.5ns-1=7

luego OCR1A=7, que es de donde he sacado el valor.

salu2

Pues viendo que intentando actualizar cada 0.5us obtienes un ciclo de 20us, tal vez deberías comenzar con ciclo entre 20 y 50 us si lo quieres hacer con interrupciones, es decir 0,2 a 0,5 mhz.
Si quieres puedes poner tu código a ver si se puede “limar” algo.
Saludos.

hay poco que rascar, el código es de lo más sencillo,
una tabla 100 datos que forman un ciclo de una función seno, que direccionamos al puerto D,
para posteriormente implementar un DAC de 8 bits con resistencias tipo ladder.
Es el boceto de lo que puede ser un generador de señales en el rango del audio hasta 20kHz
Por eso si quiero generar un ciclo de onda seno de 20kz con una tabla de 100 muestras
un ciclo de 20kHz dura 50us que divido entre 100 muestras 0.5us cada muestra que debo escribir
en el puerto D.

#include <avr/io.h>
#include <avr/interrupt.h> 

byte sine[] = {127, 134, 142, 150, 158, 166, 173, 181, 188, 195, 201, 207, 213, 219, 224, 229,
               234, 238, 241, 245, 247, 250, 251, 252, 253, 254, 253, 252, 251, 250, 247, 245,
               241, 238, 234, 229, 224, 219, 213, 207, 201, 195, 188, 181, 173, 166, 158, 150,
               142, 134, 127, 119, 111, 103, 95, 87, 80, 72, 65, 58, 52, 46, 40, 34, 29, 24, 19,
               15, 12, 8, 6, 3, 2, 1, 0, 0, 0, 1, 2, 3, 6, 8, 12, 15, 19, 24, 29, 34, 40, 46, 52,
               58, 65, 72, 80, 87, 95, 103, 111, 119,};

int index;

void setup(){
  //set digital pins 0-7 as outputs
  for (int i=0;i<8;i++){
           pinMode(i,OUTPUT);
           }
 //setup for interrupts
 cli();
 TCCR1A=0;
 TCCR1B=0;//clean register
 TCCR1B |=(1<<WGM12);//comparation mode
 TCCR1B |=(1<<CS10);
 TCCR1B |=(0<<CS11);
 TCCR1B |=(0<<CS12);//clock/1
 OCR1A=7; 
 TIMSK1 |=(1<<OCIE1A);//activamos comparación
 sei();
 }

void loop(){
 }

//aqui lanzamos la tabla por el puerto D
ISR(TIMER1_COMPA_vect){
  index=(index+1)%100;
  PORTD=sine[index];
  }

veo entonces que con este sistema tendré que bajar a los 500Hz o menos…va a ser que no me sirve…si me llevo por los datos que me da el simulador…
si fuera así, tengo que buscar otras opciones.

Podrías intentar así:

byte sine[] = {
      127, 134, 142, 150, 158, 166, 173, 181, 188, 195, 201, 207, 213, 219, 224, 229,
      234, 238, 241, 245, 247, 250, 251, 252, 253, 254, 253, 252, 251, 250, 247, 245,
      241, 238, 234, 229, 224, 219, 213, 207, 201, 195, 188, 181, 173, 166, 158, 150,
      142, 134, 127, 119, 111, 103, 95, 87, 80, 72, 65, 58, 52, 46, 40, 34, 29, 24, 19,
      15, 12, 8, 6, 3, 2, 1, 0, 0, 0, 1, 2, 3, 6, 8, 12, 15, 19, 24, 29, 34, 40, 46, 52,
      58, 65, 72, 80, 87, 95, 103, 111, 119,};

int index;

void setup(){
      //set digital pins 0-7 as outputs
      for (int i=0;i<8;i++){
            pinMode(i,OUTPUT);
      }
      noInterrupts();
}

void loop(){
      index=(index+1)%100;
      PORTD=sine[index];
}

Y ver qué velocidad consigues. Si es mayor que la deseada, podrías ralentizarla metiendo alguna instrucción o bucle “inútil”; si está por debajo de la velocidad útil, creo que para tu proyecto deberás cambiar el chip (nunca mejor dicho).
Saludos

ya he probado con ese código, y me da prácticamente lo mismo en el simulador proteus...unos 500Hz el ciclo completo de la tabla seno.
me das en la nariz que el simulador debe tener algún tipo de tope de simulación...porque he visto por internet algunas pruebas de conversión audio dac resistor ladder y suelen hablar de hasta 8kHz sin problema.

Lástima no poder probarlo con osciloscopio, no me acordaba. Yo tampoco tengo, pero sería interesante probar los limites.
De todas formas, si te he entendido bien y lo que dices es que es capaz de sacar los 100 datos de la tabla a 500 hz, significaría que estás muestreando a 50khz ¿no? Creo que para sonido sería mas que aceptable.

correcto, efectivamente tengo 50000 muestras por segundo, pero estaba viendo un poco los límites de arduino,
date cuenta que la resolución en amplitud es de 8 bits, y que para llegar a una frecuencia mayor tendría que enviar los datos de la tabla de seno no consecutivos sino saltándome dos o tres valores en medio para lograr una mayor frecuencia....al final no obtengo una gráfica tan perfecta del seno, tengo que hacer pruebas en el código, cuando tenga algo escrito con sentido ya lo postearé por aquí...
muchas gracias noter. Un saludo.