ATMega8 - PUERTO C - Problema de salida digital

3

Lo que estoy tratando de hacer es configurar el pin PC0 del PUERTO C como salida para encender un LED. El código que estoy usando para eso es:

//SET PORT C
//PC0 = RELAY STATUS LED - O/P
//PC1 = RELAY CTL LINE - O/P
//PC2 = PUSH BUTTON - I/P
//PC3 = SPARE - O/P

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3) & _BV(PC2);

//SET PC0 = HIGH

PORTC |= _BV(PC0);

Pero lo anterior no funciona. He comprobado mis conexiones y no entiendo por qué no funciona. Debería ser una cosa bastante simple.

La única razón por la que creo que podría afectarlo es que también tengo un ISP conectado al AVR ⇒ PC6 que se utiliza como la línea de restablecimiento por parte de él.

¿Alguna idea de por qué lo anterior no funciona?

    
pregunta Ankit

2 respuestas

5

Tu problema:

Tu configuración de DDR es incorrecta: has escrito

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3) & _BV(PC2);

pero tú quieres

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3)
DDRC &= ~_BV(PC2);

¿Dice que desea más detalles porque simplemente emuló otras asignaciones de DDRC y no entiende realmente lo que escribió? OK, aquí va:

Cómo configurar registros con operadores bitwise en el AVR.

Desempaquetemos las definiciones de macro y PCx _BV() por un momento. _BV(x) es simplemente 1 << x . Si escribe _BV(5) , la macro evaluará el número 0b 0001 0000 . PCx es simplemente una macro definida para el valor de x, por lo que _BV(PC5) se evaluará de la misma manera que _BV(5) . Probablemente esperas que ocurra algo como lo siguiente:

   0b 0000 0001  // PC0
|  0b 0000 0010  // PC1
|  0b 0000 1000  // PC3
&  0b 0000 0100  // Misconception: AND does not cause this to output a zero at the set bit
|= ------------
   0b 0000 1011

Sin embargo, no estás eliminando PC2 correctamente. Estás aplicando un binario y al final. Y tiene una prioridad más alta que OR en C, por lo que su operación es en realidad

DDRC |= _BV(PC0) | _BV(PC1) | ( _BV(PC3) & _BV(PC2) );

PC3 es 0b 0000 1000, y PC2 es 0b 0000 0100, por lo que la sección entre paréntesis se evalúa a cero. Esto es realmente afortunado para PC2, pero desafortunado para PC3, que queda claro cuando se desea configurar. Para borrar un poco, use & , pero necesita tomar el complemento del número usando el operador ~ . En las siguientes ecuaciones, he usado ? para los bits que no queremos cambiar:

   0b ???? ???1  // Set PC0
|  0b ???? ??10  // Set PC1 
|  0b ???? 1?00  // Set PC3
|= ------------
   0b ???? 1?11

   0b ???? 1?11
&  0b 1111 1011  // Clear PC2
&= ------------
   0b ???? 1011

En el código, estas ecuaciones son:

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3)
DDRC &= ~_BV(PC2);

como se muestra arriba. Puede hacerlo en dos pasos como lo hice, o aplicar el valor anterior de DDRC con una máscara de bits:

DDRC = (DDRC & 0xF0) | ( ( _BV(PC0) | _BV(PC1) | _BV(PC3) ) & ~_BV(PC2) );

0xF0, o 0b 1111 0000, cuando AND'ed con el valor anterior de DDRC, devuelve 0b ???? 0000, a lo que podemos O nuestros cuatro bits más bajos. Creo que el método de dos pasos es más claro: sus entradas y salidas están en líneas diferentes (tenga en cuenta que puede agregar entradas adicionales, por ejemplo, DDRC &= ~_BV(PC2) & ~_BV(PC4) ). A veces, incluso lo dividiré en más líneas:

DDRC |= _BV(PC0)   // RELAY STATUS LED - O/P
DDRC |= _BV(PC1)   // RELAY CTL LINE - O/P
DDRC &= ~_BV(PC2)  // PUSH BUTTON - I/P
DDRC |= _BV(PC3)   // SPARE - O/P

Para mí, este es el mecanismo más claro posible y el más fácil de entender para los futuros lectores. También es el más detallado, pero a quién le importa? El compilador optimizará los tres mecanismos al mismo código.

    
respondido por el Kevin Vermeer
1

¿Qué microcontrolador está utilizando? ¿Es Atmega32 o 16 o cualquier otro ?, compruebe su Hoja de datos, ya sea que tengan interfaz JTAG o no. Si tienen JTAG, es posible que no pueda usar PortC Pocos pines ya que JTAG está habilitado de fábrica por defecto.

Para esto, tienes que desactivar JTAG de los fusibles, deshabilitando JTAGEN bit de fusible

o

escribiendo esto en tu inicialización o inicio de tu código

MCUCSR|= (1<<JTD);
    
respondido por el masterleous

Lea otras preguntas en las etiquetas