Pausa con cada dato enviado por SPI

Amigos, sigo sin dar en la tecla pese a los cambios y ajustes que se me ocurren o proponen.

Acá posteo el código casi como eran mis pruebas originales de 8 bits.
Digamos que intento hacer lo más básico que hay, nada raro pero no funciona.
Agregué en un RAR los dos archivos Main y Makefile por si alguien lo quiere simular.

A ver si encuentran algo que yo no. No sé. :cool:
PHP:
#include <avr/io.h>
#include <stdint.h>

#define Pixel_PORT   PORTB
#define Pixel_DDR    DDRB
#define Pixel_DOUT     PINB1      //DataOut pin location
#define Pixel_SCK     PINB0      //Clock pin location

#define PixelDataHigh()      (Pixel_PORT|=(1<<Pixel_DOUT))
#define PixelDataLow()      (Pixel_PORT&=(~(1<<Pixel_DOUT)))

//Si declaro globalmente los datos, o sea esta linea, no tengo señal de datos a la salida. Ver más abajo otra linea comentada.
uint8_t data[13]={0xFF,0xAA,0x00,0xAA,0xAA,0x00,0x00,0xAA,0x00,0xAA,0xAA,0x00,0x00};


void PixelInit(void)
{
    // Set Pixel_DOUT and Pixel_SCK output, all others input
    Pixel_DDR = (1<<Pixel_DOUT)|(1<<Pixel_SCK);
}

int main(void) {

    // Inicializa los pines de MCU
    PixelInit();
    
    while(1){
    
        for (uint8_t s=0;s<13;s++)
        {
        
            // Si declaro los datos aqui funciona bien, pero si lo declaro global no tengo datos a la salida ¿por qué?
            //uint8_t data[13]={0xFF,0xAA,0x00,0xAA,0xAA,0x00,0x00,0xAA,0x00,0xAA,0xAA,0x00,0x00};
        
            // Shift MSB
            for (uint8_t i=0;i<16;i++)
            {

                if (data[s] & 0x80)
                {
                    Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
                }
                else
                {
                    Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
                }
                
                if ( (i &0x01) == 0) //Si la variable es impar se cumple el IF
                {
                    Pixel_PORT|=(1<<Pixel_SCK);                // SCK high
                }
                else
                {
                    Pixel_PORT&=(~(1<<Pixel_SCK));                // SCK low
                }
                
                data[s] <<= 1;                                        // shift
            }
        }

    }
}
Saludos y gracias



Un detalle que encontré recién haciendo otra prueba, los datos están a la salida sólo en el primer microsegundo que conecto la tensión, luego desaparecen.
O sea, como si algo pusiera los datos en 0 pero yo no pongo nada en cero.
¿Por qué desaparecen?

Pregunto... ¿data <<= 1 acaso no es temporal, o quiere decir que el dato se va desplazando y al no haber mas datos se completa con 0?
Si es eso, me quiero morir por mi error.
 

Adjuntos

  • prueba shift 8 bits.rar
    6.4 KB · Visitas: 2
Última edición por un moderador:
Pregunto ... data <<= 1 acaso no es temporal, o quiere decir que el dato se va desplazando y al no haber mas datos se completa con 0. Si es eso me quiero morir por mi error.


Si data = 0b00001111, al hacer data<<=1 va a quedar data = 0b00011110, y en el próximo data<<=1 será data = 0b00111100, etc
 
Bueno ... aclarado una ramificación de este post, una burrada mia de la cual me hago cargo, perdón por desviarnos y ahora retomo ...

Pero retomando el titulo del post, aún me queda dando vuelta la pausa que se produce al enviar una cadena con datos de 8 o 16 bit. Cada vez recurre a la cadena para leer el dato que debe enviar serial, tarde un cachito más que lo que tarda en hacer el desplazamiento y se genera una pausa mayor en el pulso de salida que separa cada dato de la cadena.

Se me ocurre preguntar si hay una forma de crear un buffer lo suficientemente grande en donde guardar los 13 datos de 16 bit, o sea, 208 bit, para que luego una rutina los lea y se mantenga constante la velocidad, evitando la pausa.

Yo habia usado memcpy_P para copiar los dato[13], pero el resultado era como si lo hiciera tal cual el codigo de ejemplo anterior ... Mi pregunta es si hay manera de meter la cadena como una grrraaaannnn cadena unica de 208 bit. Ahora voy a leer un poco más sobre el uso de memcpy_P para probar, pero debo usar memcpy_P o me conviene usar otra forma de almacenamiento, alguien sabe.

Saludos y gracias
 
Pero retomando el titulo del post, aún me queda dando vuelta la pausa que se produce al enviar una cadena con datos de 8 o 16 bit. Cada vez recurre a la cadena para leer el dato que debe enviar serial, tarde un cachito más que lo que tarda en hacer el desplazamiento y se genera una pausa mayor en el pulso de salida que separa cada dato de la cadena.

Sí, eso va a pasar irremediablemente, porque el programa tiene que poner un valor nuevo en el registro de trabajo, y esa operación de lectura desde memoria va a introducir un retardo adicional... no veo como podría eliminarse, aunque sí se podría tratar de hacer más lenta la operación bit a bit para ponerla a tono.
Mi pregunta es, existe un requerimiento tan fuerte que requiere que no haya ni 1 microsegundo de diferencia de tiempo de bit para toda la trama de 208 bits?.
¿Realmente es intolerable tener una variación tan mínima como para ejecutar 1 o 2 instrucciones adicionales de lazo?. De donde sale ese requerimiento?.

Se me ocurre preguntar si hay una forma de crear un buffer lo suficientemente grande en donde guardar los 13 datos de 16 bit, o sea, 208 bit, para que luego una rutina los lea y se mantenga constante la velocidad, evitando la pausa.

Se puede hacer que el desplazamiento bit a bit sea más lento simplemente insertando __nop(); en todos los bits menos en el 8vo (que es cuando se tiene que cargar un nuevo byte).
Dentro del lazo for algo como:

PHP:
for(s=0; blablabla)    //for de bytes
{    
    //este bucle for envia 7 bits, no 8
    for(i = 0; i<7; i++)    //for de bits
    {
        escribir puerto;
        desplazar bit;
        __nop();
        __nop();
        ....
        __nop();
        //tantos nops como sean necesarios para igualar/aproximar velocidades    
    }

    //acá solo falta enviar el ultimo bit
        escribir puerto;
        desplazar bit;
}

Yo habia usado memcpy_P para copiar los dato[13], pero el resultado era como si lo hiciera tal cual el codigo de ejemplo anterior ... Mi pregunta es si hay manera de meter la cadena como una grrraaaannnn cadena unica de 208 bit. Ahora voy a leer un poco más sobre el uso de memcpy_P para probar, pero debo usar memcpy_P o me conviene usar otra forma de almacenamiento, alguien sabe.

Saludos y gracias
memcpy es una función de copia de bytes, no veo como podría hacer una diferencia. Lamentablemente el procesador trabaja con N bits, si bien puede hacer operaciones con bits no ve la memoria como una colección de bits sino como un colección de bytes.
 
Atrás
Arriba