¿Qué causa que al encender un solo pin de salida en Microchip PIC16F690 se apague espontáneamente otro pin en el mismo puerto?

¿Qué causa que al encender un solo pin de salida en Microchip PIC16F690 se apague espontáneamente otro pin en el mismo puerto? Puedo solucionar este problema escribiendo un byte en todo el puerto, controlando todos los pines simultáneamente, en lugar de solo un poco para controlar el estado del pin. Estoy usando el compilador Hi-Tech C aquí. Estoy determinando el estado del pin con 9 LED, cada uno de los cuales consume 3 mA. Esto está muy por debajo de las especificaciones de potencia máxima.

El archivo de encabezado de mplab tiene el pin 0 en el puerto A declarado como tal:

volatile       bit RA0  @ ((unsigned)&PORTA*8)+0;

Estoy activando el pin escribiendo un valor alto en él.

RA0 = 1;

¿El problema es que el compilador trata el "1" como un byte y escribe en todo el puerto? ¿Necesito lanzarlo? Si es así, ¿no debería haberme dado un error el compilador?

RA0 = (bit) 1;

Si escribo en todo el puerto, todo funciona como se esperaba:

PORTA = 0b00000001;

Respuestas (5)

Es el conocido problema de lectura-modificación-escritura, encontrará detalles en la hoja de datos. Tienes que escribir a todo el registro, como lo has encontrado. Los dispositivos de 18F y 16 bits no tienen el problema. Hay una buena descripción en la página 2 de este documento . Cambiar bits en un registro "sombra" y luego escribir el registro en el puerto de salida a menudo se usa para solucionar el problema.

¿Estás seguro de que este es el problema? Me imagino que RA0 = 1 debería generar ASM que usa BSF, lo que no debería afectar los bits 1-7. Debe verificar el archivo de lista de ensamblaje. Creo que Hi-Tech C lo genera automáticamente como el archivo .lst.
BSF en realidad afecta todos los bits 0-7, aunque todos desearíamos que no lo hiciera. Consulte techref.massmind.org/techref/readmodwrite.htm .

Asegúrese de tener el puerto que está utilizando definido como digital. ANSEL = 0;

Si un puerto se define como analógico y realiza una lectura digital, devuelve 0. Entonces, cuando el PIC F16xxx realiza la operación de lectura, modificación y escritura, lee 0 en todos los pines analógicos. Luego se vuelve a escribir 0 en todos estos pines.

Si tiene ANSEL establecido en 1 para el PUERTO B, el siguiente código activará el PUERTO B durante 500 ms, luego leerá el PUERTO B como 0b00000000 (porque es analógico). Luego apague PORTB porque pensó que estaba apagado.

    ANSEL = 0b11111111;
    TRISB = 0;
    PORTB = 0b11111111;
    __delay_ms(500);
    current = PORTB;
    PORTB = current;
    __delay_ms(500);

¡Asegúrese de establecer el bit ANSEL correspondiente en 0 para cualquier pin que desee usar como digital!

Yo uso el compilador de Microchip. Tiene un archivo de cabecera donde todos los registros tienen una unión con los bits definidos. Entonces, en mi código escribo:

LATAbits.LATA0 = 1;

Además, usaría el registro de bloqueo en lugar del registro PORT para configurar la salida. Creo que a algunas fichas no les importa, pero a otras sí.

Los PIC 16F no tienen registros LAT, de ahí el problema.
@Leon Heller: Los registros de pestillo separados fueron una característica de las piezas PIC posteriores de General Instruments que, lamentablemente, no se incorporaron a las piezas PIC de Microchip hasta la serie 18F; Es extraño que GI notara el problema con los registros PORTx de lectura/escritura en la década de 1980, pero Microchip no se ocupó de ello durante décadas.

Estoy 99% seguro de que el compilador está haciendo esto. Cualquier estructura que se defina para acceder al pin tiene ambigüedad que el compilador está resolviendo para crear este comportamiento. La transmisión de bits podría ayudar, pero no sé cómo se define (bit), así que no puedo estar seguro. El compilador no necesariamente le dará un error si el valor que se escribe en el pin es del tipo adecuado. Supongo que la máscara (de bits) podría activar alguna lógica para preservar el estado de los otros pines pero aún devolver el mismo escriba como su constante.

No es sorprendente que la escritura en el puerto funcione, pero trabajar con pines individuales es mucho más complicado. O hay un error en el código proporcionado, no estaba destinado a usarse con este compilador o simplemente no lo está usando correctamente.

¡No tiene nada que ver con eso!
Bueno, en realidad los compiladores de C pueden ser la razón de muchos de los problemas. Este problema es causado por el compilador, ya que probablemente esté usando algo como XORWF, sin embargo, no es culpa del compilador. El programador debe usar un registro de sombra. Entonces, al final, tienes razón, @LeonHeller. Estoy empezando a odiar los compiladores de C, especialmente XC8 hoy en día.

Escribir todo el puerto a 1 le muestra el problema. En binario, eso es 0b00000001, por lo que de hecho está desactivando los primeros siete bits y activando el último bit.

Debe usar operadores binarios para asegurarse de que solo está realizando el cambio en ese bit específico. Hacer esto:

PORTA = PORTA | 1;
// Equivalently:
current = PORTA;
new = current | 1;
PORTA = new;

Si los pines 2-8 están actualmente en nivel alto, la operación OR devolverá verdadero y el bit permanecerá establecido.

Para hacerlo un poco bajo, use una operación AND binaria:

PORTA &= 1;

Tenga en cuenta que algunos compiladores tendrán macros específicas para hacer esto (es decir, _BV() en avr-gcc) y algunos micros tendrán direcciones específicas con alias para cada bit periférico para que no tenga que hacer este ciclo de lectura-modificación-escritura ( memoria de banda de bits en Cortex-M3)