Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

16/07/2015 #1

Avatar de JCAK

Pausa con cada dato enviado por SPI
Hola, Amigos.

Ya he modificado varias veces el código para el envío de 13 cadenas de 16 bits en modo SPI y no logro resolver una pausa que se genera entre cada cadena de 16 bits.
O sea, las 13 cadenas de 16 bits que debo enviar, se debería ver como si enviara 208 bits, pero cada vez que lee una cadena, por lo visto pierde tiempo allí y eso genera la pausa.

¿Alguien me puede orientar en lo que debo corregir para eliminar la pausa?
¿Cómo mejoro este código para resolverlo?

Muchas gracias.
Código PHP:
while(1){
for (
uint8_t s=0;s<13;s++)
          {

             
// Valor de 16 bits que quiero enviar
             
uint16_t data[13]={0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};

             for (
uint8_t i=0;i<16;i++)
             {

                 if (
data[s] & 0x8000)
                 {
                          
Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
                 
}
                 else
                 {
                          
Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
                 
}

                 if (
i%== 0)
                 {
                          
Pixel_PORT|=(1<<Pixel_SCK);                // SCK high
                     
}
                 else
                 {
                          
Pixel_PORT&=(~(1<<Pixel_SCK));                // SCK low
                     
}

                 
data[s] <<= 1;                                        // shift
             
}
         }
                       } 
16/07/2015 #2

Avatar de TRILO-BYTE

bueno yo normalmente en un ciclo no declaro o mas bien reservo memoria

ejemplo

while(ciclo)
{
int valor; //en este paso estoy declarando memoria dentro de un ciclo
//codigo
}

yo digo que las declaraciones de variables y reservas de memoria deben ir fuera de un ciclo que se va a repetir.

a lo mejor esas reservas generan pequeñas pausas
16/07/2015 #3

Avatar de JCAK

Hola, Trilo-byte

Yo había probado hacer algo como lo que vos decís, que es lo que muestro a continuación, pero me pasan dos cosas.
La primera, es que no me lee los datos, de la variable "data", es como que no están.
Lo segundo, efectivamente se acorta la pausa pero sigue existiendo y debo resolverlo también.

Por qué no lee los datos al cambiarlo de lugar, no lo entiendo, así que si me podes orientar con eso, también te agradecería mucho.

Hasta pronto.
Código PHP:
while(1){ // Valor de 16 bits que quiero enviar
              
uint16_t data[13]={0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000  ,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};for (uint8_t s=0;s<13;s++)
           {
 
 for (
uint8_t i=0;i<16;i++)
              {
 
                  if (
data[s] & 0x8000)
                  {
                      
Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
                  
}
                  else
                  {
                      
Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
                  
}
 
                  if (
i%== 0)
                  {
                      
Pixel_PORT|=(1<<Pixel_SCK);                // SCK high
                      
}
                  else
                  {
                      
Pixel_PORT&=(~(1<<Pixel_SCK));                // SCK low
                      
}
 
                  
data[s] <<= 1;                                        // shift
              
}
          }
                        } 
16/07/2015 #4

Avatar de TRILO-BYTE

Bueno, es que escribir SPI no es difícil si se hace por software.

Yo lo hago así, más o menos:
Código PHP:
char _74HC595(char dato)
{
   
char i,dat=0;   
   
//LATCH=0;
 
 
   
for(i=0i!=i++)
   {

      
      
dat=dato<<i;
      
dat=dat&0b10000000;

      if(
dat==0)
      {
         
DATA=0;
      }
      else 
      {
         
DATA=1;
      }

      
CLOCK=0;
      
CLOCK=1;          
   }
   
   
//LATCH=1;
   
   
return dato;

Todo eso está en 1 función y como verás uso un char, que no es más que un vulgar byte.
Esa función yo la meto como librería para poderla llamar en diferentes programas.


Ahora lo que hago, es lo siguiente:

Ejemplo:
Código PHP:
#include <bla bla.h>
#include<74hc595.h>

void main()
{
valor=3;

LATCH=0;
_74HC595(valor); // en el SPI emulado escribo 3
LATCH=1;

//si quiero 16 bit escribo 2 veces
char X=10;
char Y=80;

LATCH=0;
_74HC595(X);
_74HC595(Y);
LATCH=1;

//si quiero escribir una cadena de texto
char contador=0;
char cadena[5]=""gato" //recuerda que existe el caracter NULO

LATCH=0;

while(cadena[contador] != '\0' ) //cuando llegue al caracter nulo
{
_74HC595(cadena[contador); //escribira en el SPI hasta que encuentre el caracter nulo
}
LATCH=1;


Post data: en algunas dudas que te he respondido me haz subestimado e incluso insultado, pero aún así, no sé por qué sigo ayudando.
17/07/2015 #5

Avatar de Scooter

¿No tienes spi por hardware?

Al ser protocolo síncrono no debería de influir si algunos bits van más rápidos o más lentos, el bit es válido cuando llega el clock, tarde más o tarde menos.
17/07/2015 #6

Avatar de JCAK

Hola Scooter

Lo que tu dices es correcto para algunos casos, pero este IC en particular necesita recibir los datos con pulsos con un determinado ancho máximo o mínimo, el tema es que yo estoy en el límite del máximo y no me puedo exceder más. Si el tiempo es muy largo lo toma como fin de la recepción, espera a los pulsos que siguen y según la cantidad y ancho de los mismos acciona un latch interno, es para evitar usar una tercer linea de datos.

El otro problema del envío por hardware con el Atmega48 que estoy usando, es que cada pulso de dato es acompañado de un pulso de reloj, mientras que el IC esclavo lee durante la subida y bajada del pulso, o sea que por cada dos datos usa un solo pulso de reloj y no tengo como configurarlo en el MCU por hardware, por eso recurro al software.

Saludos y gracias
18/07/2015 #7

Avatar de TRILO-BYTE

efectivamente el uso del poder del software aveces es por necesidad como los siguientes ejemplos:

1.-varios PWM en mi caso he llegado a usar 32 PWM independientes con un micro de 28 pines
2.-un DAC.
3.-SPI por software cuando las lineas del PCB se van complicando.

aveces resulta mas conveniente hacer las cosas por software total al micro le cuesta solo unas micras de segundo ejecutar eso.

todo lo metes a una libreria y lo mapeas dondequieres sin hacer uso de registro y reflejar el registro a otro pin del micro, si haces eso los 2 pines del micro estan trabajando "el pin del hardware y el reflejado".
18/07/2015 #8

Avatar de Ardogan

JCAK dijo: Ver Mensaje
Hola, Amigos.

... no logro resolver una pausa que se genera entre cada cadena de 16 bits.
O sea, las 13 cadenas de 16 bits que debo enviar, se debería ver como si enviara 208 bits, pero cada vez que lee una cadena, por lo visto pierde tiempo allí y eso genera la pausa.
En este caso te puede ayudar ver el código en assembler (objdump -S) que genera el compilador y ver que instrucción en C genera la mayor cantidad de código assembler. Por ejemplo, sospecho que la operación módulo 2:
if (i%2 == 0)
puede estar generando código de más -mejor dicho llamando a una función de división-, cuando se puede hacer lo mismo con una operación and con 0x01. Eso si el compilador es bobo y no optimiza.
O quizás declarando el array de datos como global tarda menos?: variables locales van en la pila si mal no recuerdo, y eso puede hacer más lento la lectura de cada uint16_t data[]. No estoy seguro, por eso lo mejor es ver el disassembly.

JCAK dijo: Ver Mensaje
Hola, Amigos.
El otro problema del envío por hardware con el Atmega48 que estoy usando, es que cada pulso de dato es acompañado de un pulso de reloj, mientras que el IC esclavo lee durante la subida y bajada del pulso, o sea que por cada dos datos usa un solo pulso de reloj y no tengo como configurarlo en el MCU por hardware, por eso recurro al software.
Interesante... y que tal si ponés un divisor x2 en la línea de reloj del SPI?:


(Imagen de http://www.electronics-tutorials.ws/...r/count_1.html).
De esa forma vas a tener 1 dato por flanco ascendente/descendente respecto de la frecuencia de salida.
Entonces ahí podrías intentar usar spi hardware, y para cargar el registro de transmisión usar interrupciones (que puede ser lento por tener que guardar el contexto, saltar a la rutina de interrupción, etc) o polling (usar un while bloqueante para testear el flag de transmisión, y dentro del while solo una instrucción para cargar el registro y después incrementar el puntero al array de datos).
18/07/2015 #9

Avatar de TRILO-BYTE

yo logre hacer PWM para controlar 5 leds RGB via SPI

me di cuenta que tardabamucho el algoritmo de 16 bits es decir yo enviaba mis PWM a 8 bits hiba perfecto
pero cuando mandaba mi dato de 16 bits hacia efecto blinking

¿que es lo que ocurria?

bueno eso lo vi con los leds que un char va de 0 a 255
y un unsigned int a 16 va de 0 a 65535

entonces si yo mando un dato en el rango de 0 a 255 va a tardar menos que recorrer 0 a 65535

por eso se generaban muchas pausas

asi que decidi hacer un SPI a software de 8 bits

si yo queria enviar 16 bits enviaba 2 veces mi registro de 8 bits
y el blinking desaparecio como por arte de magia

pues total el SPI mas o menos funciona asi:

latch //habilito el chip

dato(valor); //envio 8 bits

latch // deshabilito el chip

si queremos 16 bits

latch //habilito el chip

dato(valor); //envio 8 bits
dato(valor2); //envio otros 8 bits

latch // deshabilito el chip

lo que sucede aqui es que al enviar un dato de 8 bits pude ser enpujado 8 casillas con el nuevo dato dando como resultado 16 bits

si queremos 32 bits


latch //habilito el chip

dato(valor); //envio 8 bits
dato(valor2); //envio otros 8 bits
dato(valor3); //envio otros 8 bits
dato(valor4); //envio otros 8 bits

latch // deshabilito el chip

en este caso se van enpujando los bytes de uno en uno dando como resultado un dato de 32 bits cuando en realidad se envian por pedazos

si yo definiera como lo estan haciendo

for (uint8_t i=0;i<16;i++)

que es un dato de 16 bits esta tardando mucho en recorrer 16 casillas

y si fuera un INT de 32 bits que seria asi:

for (uint8_t i=0;i<32;i++)

tardaria el doble que la de 16 bits generando muchas pausas

en cambio si yo mandara

for (uint8_t i=0;i<8;i++)

las veces que fueran necesarias solo recorreria una pequeña fraccion de para enviar un dato

digo hay que ver el dato como una trama y no como un registro entero asi se ahorra mucho tiempo de ejecucion
19/07/2015 #10

Avatar de Scooter

Ya no me acuerdo de como hice el spi por software . Me parece que como lo que quería era velocidad y no me importaba ocupar un poco mas no hice un bucle, puse dieciséis instrucciones de lectura seguidas.
Para eso los macros van bien. De ese modo son idénticas y no hay un if que cambie velocidades ni nada por el estilo. Era ensamblador eso si.

Luego aprendí a usarlo por hard y ya no lo usé más veces .
19/07/2015 #11


http://www.mikroe.com/forum/viewtopic.php?f=13&t=2187

Yo me base en este codigo y despues lo pase asm con mejoras para enviar nBytes
21/07/2015 #12

Avatar de JCAK

HOLA A TODOS ... volvi luego de algunas pruebas y sinceramente no logré mucho.

Ardogan que le debo respuesta puntual a su ayuda, el tema con lo que comentás del asembler prometo revisarlo ver eso del 0x01 que vos decis para optimizar, aún no lo vi pero lo dejo para luego porque ahora me estoy rompiendo la cabeza con el tema de la variable global. Lo de poner un hardware más para dividir el clock por dos, no quiero gastar extra ni ocupar más espacio del circuito, por eso sigo insitiendo con tratar de hacerlo andar con código.

Ahora lo que sigue, le comento a todos los colegas ...
Ya puse la declaración de la cadena fuera del loop pensando que de este modo sería global, pero no se qué es lo que declaro mal porque el dato desapaece, lo conecto al oscillo y no tengo pulsos. Ahora si la cadena "data[13]" la meto dentro del loop los pulsos aparecen. Necesito ponerlo global para ver cuánto optimizo, alguien me puede decir qué hago mal, por qué los datos se pierden en la nada?

Saludos y gracias
21/07/2015 #13

Avatar de Ardogan

JCAK dijo: Ver Mensaje
Ardogan que le debo respuesta puntual a su ayuda, el tema con lo que comentás del asembler prometo revisarlo ver eso del 0x01 que vos decis para optimizar, aún no lo vi pero lo dejo para luego porque ahora me estoy rompiendo la cabeza con el tema de la variable global. Lo de poner un hardware más para dividir el clock por dos, no quiero gastar extra ni ocupar más espacio del circuito, por eso sigo insitiendo con tratar de hacerlo andar con código.
No hay problema, si estás más cómodo con el software seguí tranquilo por ese lado.

JCAK dijo: Ver Mensaje
Ahora lo que sigue, le comento a todos los colegas ...
Ya puse la declaración de la cadena fuera del loop pensando que de este modo sería global, pero no se qué es lo que declaro mal porque el dato desapaece, lo conecto al oscillo y no tengo pulsos. Ahora si la cadena "data[13]" la meto dentro del loop los pulsos aparecen. Necesito ponerlo global para ver cuánto optimizo, alguien me puede decir qué hago mal, por qué los datos se pierden en la nada?

Saludos y gracias
"Afuera del loop", no significa que sea variable global.
El programa es así?:
Código:
#include "blablalba.h"
void main(void)
{
  uint16_t data[13]={valores...};
 
  //Inicialización...
  while(1)
  {
    //código transmisión en alguna parte...
  }
}
o así?

Código:
#include "blablalba.h"
uint16_t data[13]={valores...};
void main(void)
{ 
  //Inicialización...
  while(1)
  {
    //código transmisión en alguna parte...
  }
}
La propuesta era de la última forma, si lo hiciste así y no anda... entonces quizás estas corto de memoria RAM?, cual es la salida del compilador? (no hay error o warnings o algo raro?).
Va a ser mejor si posteás el programa (las partes relevantes al menos), para no hablar en base a suposiciones.
21/07/2015 #14

Avatar de TRILO-BYTE

aa mira cuando es variable global, esa variable se puede llamar en diferentes funciones
ejemplo:

Código:
#include <me_vale.h>

int contador;

void suma()
{
contador=10;
//codigo
}

void imprime()
{
printf("%d",contador);
}

void main()
{
while(1)
{
//codigo

contador=0;
}
}

en cambio una variable que no es global solo se declara dentro de una funcion pero no puede ser llamada en otra funcion

ejemplo:

Código:
void suma()
{
int contador;

contador=8;
}

void imprimir()
{
printf("%d",contador); //me daria error pues no esta declarada en la funcion

}
22/07/2015 #15

Avatar de JCAK

Aquí les paso el código con el que estoy lidiando.
En el segundo ejemplo sólo la línea que "data[13]" es la que cambia de lugar, y hecho eso el resultado es que no se ve nada a la salida.

Código PHP:
#include <avr/io.h>
#include <stdint.h>

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

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

void PixelInit(void)
{
    
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++)
        {
            
uint16_t data[13]={0xFFFF,0xAAAA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
        
            for (
uint8_t i=0;i<16;i++)
            {

                if (
data[s] & 0x8000)
                {
                    
Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
                
}
                else
                {
                    
Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
                
}
                
                
                if (
i%== 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
            
}
        }    
    }

Esta es la modificación fuera del loop:
Código PHP:
#include <avr/io.h>
#include <stdint.h>

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

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

void PixelInit(void)
{
    
Pixel_DDR = (1<<Pixel_DOUT)|(1<<Pixel_SCK);
}

int main(void) {
    
// Inicializa los pines de MCU
    
PixelInit();

uint16_t data[13]={0xFFFF,0xAAAA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
        
    while(
1){
    
        for (
uint8_t s=0;s<13;s++)
        {
            
            for (
uint8_t i=0;i<16;i++)
            {

                if (
data[s] & 0x8000)
                {
                    
Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
                
}
                else
                {
                    
Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
                
}
                
                
                if (
i%== 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
            
}
        }    
    }

También hice la prueba tal como dice Ardogan, debajo del #include, pero pasa lo mismo, no anda.
Incluso declaré las variables una por una, línea por línea en lugar de enviarlas en un array, pero nada.

Saludos y gracias.
22/07/2015 #16

Avatar de TRILO-BYTE

¿que se supone que hace?

if (data[s] & 0x8000)
24/07/2015 #17

Avatar de JCAK

TRILO-BYTE dijo: Ver Mensaje
¿que se supone que hace?

if (data[s] & 0x8000)
Hace una verificación para ver si el valor es verdadero, en ese caso tengo 1 a la salida
24/07/2015 #18

Avatar de TRILO-BYTE

osea enmascaras

el byte con 1000000000000000 para solo obtener un 1

---------- Actualizado después de 2 minutos ----------

creo que es mas eficiente que la mia para obtener un 1 o un 0

dat=dat&0b10000000; //mascara

if(dat==0) //pregunto si es 0
{
DATA=0;
}
else //entonces es 1
{
DATA=1;
}
25/07/2015 #19

Avatar de Ardogan

JCAK dijo: Ver Mensaje
Aquí les paso el código con el que estoy lidiando.
En el segundo ejemplo sólo la línea que "data[13]" es la que cambia de lugar, y hecho eso el resultado es que no se ve nada a la salida.
Y puede ser que no veas nada a la salida porque el array de datos tiene un par de valores distintos de 0, pero luego todo 0?.

Mi sugerencia era hacer algo así:
Código PHP:
#include <avr/io.h>
#include <stdint.h>

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

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

//Ahora data[13] es global y no variable local
uint16_t data[13]={0xFFFF,0xAAAA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};

void PixelInit(void)
{
    
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++)
        {
            
/*Justamente la idea era sacar esto de acá y ponerlo arriba
            uint16_t data[13]={0xFFFF,0xAAAA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
            */
        
            
for (uint8_t i=0;i<16;i++)
            {

                if (
data[s] & 0x8000)
                {
                    
Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
                
}
                else
                {
                    
Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
                
}
                
                
//              if (i%2 == 0) //Si la variable es impar se cumple el IF
//                A ver si así cambia algo:
                
if ( (&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
            
}
        }    
    }

[/QUOTE]

Pensando en otro tema, ahora también se me ocurreo que si el avr es de 8 bits, va a romperse un poco la cabeza tratando de lidiar con 16 bits. Bah, no es que no puede trabajar con 16 bits, pero el compilador va a generar instrucciones extra para hacer funcionar un micro de 8 bits con 16 bits.
Entonces la modificación sería trabajar todo con char/uint8_t/unsigned int o como te guste:

Código PHP:
#include <avr/io.h>
#include <stdint.h>

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

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

//Ahora data[13] es global y de 8 bits
uint8_t data[26]={0xFF0xFF,0xAA0xAA}; 
//creo que lo que no está inicializado debería ponerlo en 0, pero no sé,
//verificar por las dudas. Sino escribir los ceros a mano

void PixelInit(void)
{
    
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++)
        {
            
/*Justamente la idea era sacar esto de acá y ponerlo arriba
            uint16_t data[13]={0xFFFF,0xAAAA,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
            */
       
            
for (uint8_t i=0;i<16;i++)
            {

                if (
data[s] & 0x8000)
                {
                    
Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
                
}
                else
                {
                    
Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
                
}
               
               
//              if (i%2 == 0) //Si la variable es impar se cumple el IF
//                A ver si así cambia algo:
                
if ( (&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
            
}
        }   
    }

Y por otra parte, se puede utilizar una operación de desplazamiento con carry para hacerlo más rápido. Asi en vez de hacer la AND con el bit más significativo y desplazar se hace todo en 1 solo paso. La cuestión es que no se si el compilador tiene alguna instrucción especial para eso, de lo contrario solo queda recurrir a assembler para hacer algo como:
LSL registroConDato; desplaza y carga el carry con bit7
BRCS esUno;
esCero:
blabla;pixelPort = 0
esUno:
blublu;pixelPort=1

No tengo muy presente el assembler, ver
http://www.atmel.com/images/Atmel-08...Set-Manual.pdf
Entonces con esas 3 instrucciones de assembler reemplazamos a:
Código PHP:
if (data[s] & 0x8000)
{
  
Pixel_PORT |= (1<<Pixel_DOUT);                // Data High
}
else
{
  
Pixel_PORT &= ~(1<<Pixel_DOUT);            // Data Lo
}
// ... y también...
data[s] <<= 1;                                        // shift 
Y otra cosa más, para línea de clock se puede usar un toggle/xor, y te ahorrás el if. En vez de:
Código PHP:
                if ( (&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
                

Usar:
Pixel_PORT^=(1<<Pixel_SCK);
El sombrerito es operación xor, si antes el bit Pixel_SCK era 1 la xor pone un 0, y viceversa.

Ah sí... me faltó cambiar el loop/máscara/etc para pasar de 16 bits a 8 bits. Tarea para la casa :P
25/07/2015 #20

Avatar de TRILO-BYTE

yo igual use la instruccion XOR pero da fallos con el clock en velocidades grandes o almenos no lo supe usar bien

y es lo que yo decia un micro de 8 bits con SPI emulado de 16 bits es bastante lento por eso puse el ejemplo de los LED RGB SPI que me dio muchos fallos de blinking

lo que hise fue un SPI emulado de 8bits

si queria 16 enviaba 2 veces mi registro solo era jugar con el LATCH

ejemplo a 8 bits

enable
envia(valor);
enable

ejemplo a 16 bits

enable
envia(valor1);
envia(valor2);
enable

asi de simple muchas pausas que se generan con un algoritmo de 16 bits desaparecen al enviar 2 veces 8 bits
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.