Pasando puerto / pin a una función definida por el usuario en código 89c52

0

Quiero pasar un valor de pin en la función de definición de usuario en el código 89c52 como se indica a continuación

#include <AT89c52.h>
sbit myBit = P1^5;
void f(sbit recievedBit){
     recievedBit = ~recievedBit;
}
void main(){
   myBit = 0;
 while(1){
        f(myBit);
        //some delay here
   }
}

Pero me da un error de compilación.

También probé el tipo 'bit' en lugar de 'sbit' como argumento de función, esta vez no hay error, pero no hay nada en el pin.

    
pregunta Dani

2 respuestas

1

El procesador 8051 tiene un diseño de memoria peculiar, que puede ser muy útil para manipular bits. Además del direccionamiento de bits "normal", soportado por muchos procesadores (dirección de ubicación + número de bit), el 8051 tiene un direccionamiento de "modo de bit": un solo byte (0-255) puede direccionar 256 bits diferentes (en dos áreas diferentes) con una sola instrucción. Muchos periféricos internos están asignados en esa área de bits direccionable.

El lenguaje C, en cambio, no está muy versado en la manipulación de bits. En el momento de la 80C51, los procesadores también eran lentos y estaban equipados con poca memoria de código.

Para aprovechar el modo de direccionamiento de bits del 8051, algunos compiladores de C (por ejemplo, Keil, pero probablemente muchos otros) inventaron un nuevo tipo de datos "sbit", que está vinculado a una dirección de bits específica, y puede ser manipulado con una sola instrucción de dirección corta (como SETB y CLRB, si recuerdo bien).

El nombre "sbit" lo dice todo: un bit especial, con una dirección fija. Por lo tanto, no puede utilizar el tipo sbit dentro de un parámetro formal de función, no tiene sentido porque una variable de tipo sbit tiene una dirección fija y, por lo tanto, no puede ser "paramétrica". Esta es la explicación del error del compilador.

Una subrutina, o incluso una macro como la sugerida por Swanand, usando sintaxis "normal" y conceptos "C" normales, funcionará, pero será mucho menos eficiente que usar la instrucción 8051 nativa.

Han pasado muchos años desde que usé el 8051, por lo que puedo estar equivocado; pero creo que un buen compilador puede hacer lo que usted quiera: una rutina general capaz de manipular un bit sbit, pasándole la dirección del bit (especial). Dicha rutina, capaz de modificar el argumento pasado, necesita un puntero (pasar por referencia): esto es normal en C. Así que su rutina f () estaba equivocada por concepto. Puedes intentar escribir

void f(sbit* recievedBit){
  *recievedBit = !*recievedBit;
}

... si su compilador es lo suficientemente inteligente, entenderá correctamente la función anterior y usará las capacidades intrínsecas del 8051, ya que la función es correcta tanto para la semántica C como para la arquitectura 8051. Tenga en cuenta también que dicha rutina, por definición, solo puede gestionar variables de tipo sbit; NO residen los bits en una ubicación diferente de las dos áreas especiales reservadas para los sbits. Por supuesto, dicha rutina se invocaría con "f (& P1 ^ 5)" (de nuevo la sintaxis de C normal con respecto a "&"). Lea atentamente el manual del compilador de C, especialmente las extensiones de C para 8051, y la sección sobre punteros (incluso para acceso normal / byte, el 8051 puede usar 3 modos diferentes, ¡así que 3 tipos de punteros diferentes!).

El 8051 (y sus derivados como tu AT89C52) son MCU realmente divertidos ...

    
respondido por el linuxfan
0

void f(sbit recievedBit){ recievedBit = ~recievedBit; }

Cuando llama a f(myBit) , el valor de myBit se asigna a la variable local recievedBit y en la función f , solo se conmuta el valor de esa variable local. Esto se llama como "Pase por valor". Estás pasando valor no el bit real.

Hay otro método como "Pasar por referencia". Puede leer sobre esto pero no se recomienda usarlo en los registros.

Por lo tanto, le sugeriría que, en lugar de pasar el valor y luego cambiarlo, cambie directamente myBit en la función.

#include <AT89c52.h>
sbit myBit = P1^5;
void toggle_myBit(){
     myBit = ~myBit;
}
void main(){
   myBit = 0;
 while(1){
       toggle_myBit();
        //some delay here
   }
}

o

Escriba una macro para alternar el bit

#define TOGGLE_PIN((sfr), (bit))       (sfr)=(sfr) ^ (1<<(bit))

y utilízalo como TOGGLE_PIN(P1,5)

    
respondido por el Swanand

Lea otras preguntas en las etiquetas