7 votos

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

¿Qué hace que al encender un pin de salida en el 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 sólo un bit para controlar el estado del pin. Estoy usando el compilador Hi-Tech C aquí. Estoy determinando el estado del pin con 9 LEDs que consumen 3 mA cada uno. Esto está muy por debajo de las especificaciones de potencia máxima.

El archivo de cabecera mplab tiene el pin 0 del puerto A declarado como tal:

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

Enciendo 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 fundirlo? Si es así, ¿no debería el compilador darme un error?

RA0 = (bit) 1;

Si escribo en todo el puerto todo funciona como se espera:

PORTA = 0b00000001;

16voto

Mark Biek Puntos 41769

Es el conocido problema de lectura-modificación-escritura, encontrarás los detalles en la hoja de datos. Tienes que escribir en todo el registro, como has comprobado. Los dispositivos de 18F y 16 bits no tienen el problema. Hay una buena descripción en la página 2 de este documento . El cambio de bits en un registro "sombra" y la escritura del registro en el puerto de salida se utilizan a menudo para evitar el problema.

0 votos

¿Está seguro de que este es el problema? Me imagino que RA0 = 1 debería generar ASM que utiliza BSF, lo que no debería afectar a los bits 1-7.Deberías comprobar el archivo de listado de ensamblaje. Creo que Hi-Tech C lo genera automáticamente como el archivo .lst.

2 votos

BSF en realidad hace afectan a todos los bits 0-7, aunque todos deseamos que no sea así. Véase techref.massmind.org/techref/readmodwrite.htm .

1voto

dalore Puntos 1029

Asegúrate de que el puerto que utilizas está definido como digital. ANSEL = 0;

Si un puerto está definido como analógico y se hace una lectura digital devuelve 0. Así, cuando el PIC F16xxx hace la operación de lectura-modificación-escritura lee 0 en todos los pines analógicos. Luego escribe 0 en todos estos pines.

Si tienes ANSEL ajustado a 1 para el PUERTO B, el código de abajo encenderá el PUERTO B durante 500ms, y luego leerá PORTB como 0b00000000 (porque es analógico). Luego apagará PORTB porque pensó que estaba apagado.

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

Asegúrate de poner el bit ANSEL correspondiente a 0 para cualquier pin que quieras utilizar como digital.

0voto

dragonmantank Puntos 5316

Utilizo el compilador de Microchip. Tiene un archivo de cabecera donde todos los registros tienen una unión con los bits definidos. Así, en mi código escribo

LATAbits.LATA0 = 1;

Además, yo usaría el registro latch en lugar del registro PORT para establecer la salida. Creo que a algunos chips no les importa, pero a otros sí.

2 votos

Los PICs 16F no tienen registros LAT, de ahí el problema.

2 votos

@Leon Heller: Los registros latch separados eran una característica de las últimas piezas PIC de General Instruments que, por desgracia, no se incorporaron a las piezas PIC de Microchip hasta la serie 18F; impar que GI señaló el problema de los registros PORTx de lectura/escritura en los años 80, pero Microchip no se ocupó de ello durante décadas.

0voto

tenfour Puntos 118

Estoy 99% seguro de que el compilador está haciendo esto. Cualquiera que sea la estructura definida para acceder al pin tiene una ambigüedad que el compilador está resolviendo para crear este comportamiento. El casting de bits podría ayudar pero no sé cómo se define (bit) así que no puedo estar seguro. El compilador no te dará necesariamente un error si el valor que se escribe en el pin es del tipo apropiado - supongo que la máscara de (bit) podría activar alguna lógica para preservar el estado de los otros pines pero aún así devolver el mismo tipo que tu constante.

No es sorprendente que escribir en el puerto en sí funcione, pero trabajar con pines individuales es mucho más complicado. O bien hay un error en el código proporcionado, no estaba destinado a ser utilizado con este compilador o simplemente no lo estás utilizando correctamente.

3 votos

¡No tiene nada que ver con eso!

0 votos

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 debería utilizar un registro sombra. Así que, al final, tienes razón, @LeonHeller. Estoy empezando a odiar los compiladores de C, especialmente el XC8 hoy en día..

-2voto

Simon Gillbee Puntos 366

Escribir todo el puerto a 1 te muestra el problema. En binario, eso es 0b00000001, así que de hecho estás poniendo los primeros siete bits en off y el último en on.

Tienes que usar operadores binarios para asegurarte de que sólo estás haciendo el cambio en ese bit específico. Haz 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 volverá a ser verdadera y el bit permanecerá activado.

Para hacer que un bit sea bajo, utiliza una operación binaria AND:

PORTA &= 1;

Tenga en cuenta que algunos compiladores tendrán macros específicas para hacer esto (por ejemplo, _BV() en avr-gcc) y algunos micros tendrán direcciones específicas aliasadas a 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)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X