Código binario del contador C para pic16f877a

1

Estoy intentando escribir un código para un contador binario arriba / abajo. La tarea es encender 8 leds (contador ascendente) y luego invertir el orden de iluminación (contador descendente). Estoy intentando crear una matriz de leds en mi código, pero no sé cómo hacerlo. Siempre que uso PORTB [i] recibo un puntero de error y, si uso PORTB.i, también obtengo un error. ¿Cómo puedo hacerlo? Puedo acceder a los leds conectados a portb? Es mi primera experiencia con los microcontroladores en general y realmente agradecería su ayuda. Aquí está mi código:

char LED_Direction at TRISB;
void main() {
int i;
LED_Direction=0x00;
PORTB=0x00;
//sbit LED_Array [8] = {PORTB.0,PORTB.1,PORTB.2,PORTB.3,PORTB.4,PORTB.5,PORTB.6,PORTB.7};
    while(1)
   {
      for (i=0; i<8; i++)
      {
          //LED_Array [i] = 1;
          PORTB[i]=1;
          Delay_ms(1000);
          //LED_Array [i] = 0;
          PORTB.i=1;
      }
      for (i=7; i>-1; i--)
      {
          //LED_Array [i] = 1;
          PORTB.i=1;
          Delay_ms(1000);
          PORTB.i=0;
          //LED_Array [i] = 0;
      }
    }
}
    
pregunta Nemo

3 respuestas

1

PORTB no es una estructura ni es una matriz (o puntero).
Cada bit en el valor que le asigna corresponde directamente a un pin.
Su línea de código cerca del principio de main () que lee 'PORTB = 0x00;' es la forma correcta de asignar valores a PORTB.
Si desea que el bit menos significativo sea alto con el resto bajo, configúrelo en 0x01 (0b00000001).
Si desea que el bit más significativo sea alto con el resto bajo, 0x80 (0b10000000) es su valor.
Un 0x55 (0b01010101) o 0xAA (0b10101010) establecerá bits alternos altos & bajo.
También puede utilizar el desplazamiento de bits para establecer un bit en particular, por lo que (1 < < 3) establecerá el tercer bit, y así sucesivamente.

    
respondido por el brhans
3

PORTB actúa como un entero (int). Cuando escribe en PORTB, escribe en todos los 8 bits a la vez. Solo puede usar corchetes (var [i]) con matrices y campos (var.fieldname) con estructuras. No puedes usar una variable en un nombre de campo.

Para establecer y borrar bits, use los operadores bitwise C:

PORTB |= (1 << 4);    //Set bit 4
PORTB &= ~(1 << 6);   //Clear bit 6
PORTB = 0x03;         //Set bits 0 and 1, clear all others

Estos te permiten usar una variable:

PORTB |= (1 << i);    //Set bit i
PORTB &= ~(1 << i);   //Clear bit i

Hay otras formas de hacer lo que quieres, pero esta es la más sencilla.

Su código parece encender un LED a la vez, yendo de B0 a B7 y viceversa. Si desea hacer un contador binario real, podría hacer algo como esto:

unsigned long i;

while (1)
{
    for (i = 0; i < 256; i++)
    {
        PORTB = i;
        Delay_ms(1000);
    }
}

En los PIC más recientes, es mejor usar LATB en lugar de PORTB.

ACTUALIZACIÓN: La regla básica para los operadores a nivel de bits es que usted O con 1 para configurar los bits, Y con 0 para borrar los bits, y XOR con 1 para alternar los bits. Las operaciones bitwise que usé anteriormente funcionan así:

PORTB |= (1 << 4);  //Set bit 4

es equivalente a:

PORTB = PORTB | (1 << 4);  //Set bit 4

(1 < < 4) es igual a 00010000. En decimal, eso es \ $ 1 \ cdot 2 ^ 4 \ $, o 16. En hexadecimal, es 0x10. El operador OR (|) funciona al ORAR cada bit en PORTB con el bit correspondiente en (1 < < 4). Por ejemplo, si PORTB solo tiene el bit 1 establecido para comenzar, obtendrás:

  00000010   PORTB
| 00010000   (1 << 4)
-----------
  00010010   PORTB with bit 4 set

El bit 4 se establece sin molestar a ningún otro bit.

Borrar un poco es un poco más complicado. Empecemos con un ejemplo binario. Si PORTB tiene los bits 2 y 4 establecidos, y desea borrar el bit 2, debe hacer esto:

  00010100   PORTB
& 11111011   Mask value for clearing bit 2
-----------
  00010000   PORTB with bit 2 cleared

El bit 2 se borra sin molestar a ningún otro bit. ¿Ves cómo el segundo operando es casi todos? Podríamos escribir eso manualmente en hexadecimal como 0xFB:

PORTB = PORTB & 0xFB;  //Clear bit 2

Pero entonces quienquiera que lea el código debe detenerse y pensar qué bit (s) 0xFB borra. Podemos aclarar el código estableciendo el bit que nos importa en 2 e invirtiendo el resultado:

~(1 << 2);

que da:

~ 00000100   (1 << 2)
-----------
  11111011   ~(1 << 2) = Mask value for clearing bit 2

Esto es más claro que un valor hexadecimal:

PORTB = PORTB & ~(1 << 2);  //Clear bit 2

que se acorta a:

PORTB &= ~(1 << 2)  //Clear bit 2

Cuando está configurando o borrando varios bits, es más común usar valores hexadecimales en lugar de escribir un grupo de valores desplazados. La única forma de lidiar con esto es aprender cómo se relaciona el hexadecimal con el binario, lo cual no es muy difícil.

Una advertencia importante es que los compiladores de C interpretan los números como entradas firmadas. Si un int es solo de 16 bits (lo que suele ser cierto en las MCU), algo como esto puede fallar:

unsigned long a;

a = (1 << 20);  //Needs more than 16 bits -- too big for an int!
                //a could now be equal to zero

Puedes arreglar esto lanzando uno de los números a un largo. Haga que no esté firmado para evitar advertencias cuando se establece el bit superior:

unsigned long a;

a = (1UL << 20);  //Should now work correctly

Casi siempre es mejor usar uint8_t, uint16_t y uint32_t en lugar de los tipos C nativos, pero el uso del sufijo UL sigue siendo común.

    
respondido por el Adam Haun
0
char LED_Direction at TRISB;
void main()
{
    int i;
    LED_Direction=0x00;
    PORTB=0x00;
    //sbit LED_Array [8] = {PORTB.0,PORTB.1,PORTB.2,PORTB.3,PORTB.4,PORTB.5,PORTB.6,PORTB.7};
    while(1)
   {
      for (i=0; i<8; i++)
      {
          PORTB = 1 << i;
          Delay_ms(1000);
      }
      for (i=7; i>-1; i--)
      {
          PORTB = 1 << i;
          Delay_ms(1000);
      }
      PORTB = 0;
    }
}
    
respondido por el Darko

Lea otras preguntas en las etiquetas