Problema al programar ATMEGA16

Buenas, saludos a todos.

estoy intentando programar un ATMEGA16, uso el AVR Studio y el WinAVR
les adjunto un programita bien sensillo donde me salta el error...


#include <io.h>

char aux=4;

void main(void){

aux=2;

while(1){

aux++;
//aux=PINC;

}
}

esa variable "aux" que declare al principio del programa, se carga con el valor 4 al iniciarla, despues cuando entra la funcion pincipal del programa, el main, se carga con el valor 2, pero el problema surge cuando entra en el bucle del while, ahi dentro nunca se carga la variable... lo hice asi de sensillo para que lo puedieran entender, estaba haciendo un programa mas complejo hasta que descubri por que no anda...

donde meti la pata ? hace falta configurar algo mas en el AVR Studio o el WinAVR sobre la memoria del micro ??

no entiendo por que no hace lo que le pido dentro del bucle del whilw, mientras que afuera si


Gracias, a quien me pueda ayudar un poco.
Saludos
 
Basalto

haciendola char, unsigned char o int, es igual, el tamaño de la variable no importa, lo que no entiendo es por que no le asigna el valor a esa variable dentro del bucle del while, afuera de este, si lo hace.
 
Cuidado con el optimizador. Usa el compilador sin optimizar -O0 y vuelvelo a probar, o si no, declara la variable como volatile. Tiene toda la pinta de que el compilador directamente borra dicha variable, o bien, la usa en un registro interno del micro, ya que no necesita para nada almacenarla en RAM, y por tanto, no ves que dicho valor en RAM sea modificado.

Otra cosa que puedes probar, es a hacer PORTx=Aux, y ver si te cambia el valor de dicho puerto, ya que así estás forzando a que copie el valor de los registros internos del micro a una variable que sí que se puede acceder.
 
Está mal el programa, no tienes forma de salir del while(), por lo tanto a lo sumo podria incrementar la variable aux solo una vez. Por supuesto que el programa nunca sale de main() tampoco.
Prueba con un bucle for(,,) y verás que si funciona.
Saludos
 
No tengo mucha experiencia en AVRstudio, pero si estuvieras trabajando en codevision tu programa tiene deberia ser mas bien asi:

#include <mega16.h> // Es la libreria especifica para tu chip en codevidsion no io.h

char aux=4; //Establece la variable aux como de 8 bits y le da el valor 4

void main(void){

DDRC=0x00; //Configura el puerto C como entrada
PORTC=0x00; //Las resistencias Pull-up internas estaran desactivadas

aux=2; // Da a la variabe aux el valor 2

while(1){ //Inicia un loop infinito
aux++; //Incrementa en 1 el valor de aux
aux=PINC; //Asigna a aux el valor del puerto C (8 bits)
}; //Indica el fin del ciclo infinito

No tenias definido el registro de direccion del puerto DDRC ni el de las resistencias Pull-up internas PORTC.

No entiendo la finalidad de tu programa. Simplemente asigna un valor inicial de 4 a la variable aux, luego lo cambia por 2, ya dentro del loop principal le suma 1 y finalmente se la pasa leyendo el puerto C y asignando su valor binario a la variable para volver a iniciar el loop. Supongo que le quitaste elementos.

Si lo que quieres es un contador binario, es decir que el puerto C valla tomando valores del 0 a 255 lo que tenias que hacer seria esto:


#include <mega16.h> // Es la libreria especifica para tu chip en CodeVision
#include <delay.h> // Esta libreria te ayuda a crear un retraso de tiempo
char aux=4; //Establece la variable aux como de 8 bits y le da el valor 4

void main(void){

DDRC=0xFF; //Configura el puerto C como entrada
PORTC=0x00; //El valor inicial del puerto C es 0 (0b00000000)

aux=2; // Da a la variabe aux el valor 2

while(1){ //Inicia un loop infinito
aux++; //Incrementa en 1 el valor de aux
PORTC=aux; //Asigna a aux el valor del puerto C (8 bits)
delay_ms(100); //Genera una pausa de 100 milisegundos
}; //Indica el fin del ciclo infinito

Se usa PORTC para escribir en el puerto y PINC para leerlo. Si no agregas el retraso de tiempo el microcontrolador trabajara tan rapido que si le conectas leds a las terminales parecerian siempre encendidos.

Espero que te haya servido de algo.

Por cierto. El atmega16 y el atmega32 tienen por default activado el modulo JTAG y se encuentra en el puerto C. De modo que parece que los bits del 2,3,4 y 5 no sirvieran. Para poder usarlos habra que editar el valor de los fusibles.
 
Última edición:
Beamspot, tenias razon, fui cambie la opcion del optimizador y ahora anda bien, justo que ya estaba por desinstalar el WinAvr y poner otro compilador ! jaja, gracias!! has calmado mi ira! jaja

wacalo, juanministrador, el programita que puse en el post era solo para mostrarles donde estaba el error...lo escribi solo para eso, si ponia el programa verdadero en el que estaba trabajando iba a complicar mi pregunta en vano...Gracias igual por la abundante ayuda!

GRacias a todos!

PD: Beamspot, cual es la variable volatile ?? no la conosco...
 
volatile le indica al compilador que la variable puede cambiar en cualquier momento y por lo tanto no debe optmizarla...

En tu programa el compilador detecto que nunca usaste la variable AUX, por lo tanto optimiza el bucle y finalmente la descarta por no ser usada para ahorrar codigo

si tu la declaras como VOLATILE UNSIGNED CHAR AUX le estas diciendo al compilador que la variable aunque no se usa en el bucle puede ser alterada por algun proceso externo y por lo tanto no la debe optimizar, el problema es que se crea un programa mas grande...

Lo mismo hiciste al cambiar la opcion del compilador a 00, simplemente hiciste la optimizacion menos estricta y el compilador no tratara de recortar tanto las variables...
 
Los modificadores volatile, const, etc son palabras que se usan para indicar al compilador que las variables que vienen definidas a continuación tienen características especiales además de la definición de tipo o longitud.

Como muy bien comenta Chico, el modificador volatile indica que es una variable que siempre se tiene que acceder desde memoria, nunca desde los registros internos del micro. Eso implica que para cada operación sobre dicha variable, se lee esta de memoria, se opera, y se vuelve a copiar a memoria (como hacen siempre para todo, por ejemplo, los PIC). Eso implica más instrucciones para hacer lo mismo, y por tanto enlentece y alarga el código, eliminando la gran ventaja de los sistemas multiacumulador como es el caso de los AVR, los ARM, etc.

Sin embargo, para casos muy concretos, como es el caso de variables compartidas con interrupciones, es fundamental su uso. Pongamos que lees datos del puerto serie mediante interrupciones (la manera habitual y lógica de hacerlo), y que interpretas estos dato en tu programa. Te interesa que los datos que recibe la rutina de interrupción se guarden en la RAM y no en los registros internos del micro, ya que estos pueden cambiar en cualquier momento, mientras que los que se almacenan en la RAM sólo cambian si alguien accede a ellos explícitamente. Al declarar dicha variable volatile, obligas a que tu programa siempre lea los datos de la RAM en lugar de cargarlos una vez y trabajar sobre lo que hay en el registro interno de la CPU, de tal manera que en cualquier momento se pueda recibir un dato nuevo por la ISR, y se actualice el valor de la RAM, y como consecuencia, también el valor tratado.
 
Saludos...nuevamente estoy trabado con un problema al programar este bicho... y como ya no se que probar recurro a este maravilloso foro...

el tema es asi.... en este programa que adjunto, puse dos pulsadores para el micro uno en el PIN 1 del puerto D y el otro en el PIN 2, que lo unico que hacen es cambiar un bit del puerto C que esta configurado como salida...cada vez que apreto un pulsador, a su vez esta activa la interrupcion por desborde el Timer0 que solo cuenta por ahora...

Lo que ocurre es que cuando alimento al micro, los dos if que estan dentro del while infinito se ejecutan siempre, sin importar lo que lea del PIND, y una vez que apreto cualquier pulsador...las interrupciones dejan de ejecutarse...ahi si, los if responden bien, pero ya no se ejecutan las interrupciones...

seguira siendo problema del compilador ?
o yo deje algo sin configurar del micro ?

aca les dejo el codigo:

PHP:
#include <avr/io.h>

#define    Tiempo_Parpadeo        50
#define    PARPADEAR            4

int cuentaparpadeo=Tiempo_Parpadeo;
unsigned char blink=1;


void TIMER0_OVF_vect (void) {

if (cuentaparpadeo==0) {
    blink ^=1;
    cuentaparpadeo=Tiempo_Parpadeo;
}

--cuentaparpadeo;


TCNT0=0x00;
SREG |= (1<<GLIE);
TIMSK |=  (1<<TOIE0);


}

int main (void){


TCCR0= TCCR0 | (0<<WGM01) | (0<<WGM00) | (0<<COM01) | (0<<COM00) | (1<<CS02) | (0<<CS01) | (0<<CS00); //seteo el registro de control del timer/counter0

SFIOR &= ~(1<<PUD); //habilita las resistencias de pull-up

DDRA=0xFF;        //puerto A como salida
PORTA=0x00;    //pone todo a cero
 
DDRD=0x00;    //puerto D como entrada
PORTD=0x00;    //activa resistencias de pull-up

DDRC=0xFF;
PORTC=0x00;

SREG |= (1<<GLIE);    //Global Interrup Enable.
TCNT0=0x00;        //contador del timer a cero.

TIMSK=0;
TIMSK |=  (1<<TOIE0);    //habilita el timer.


while(1){


    if ((PIND & 0x01)==0x01) {
        PORTC=0x03;               //se ejecuta siempre, hasta que presiono un pulsador
                                                   //y se frena el timer0
    }
    if ((PIND & 0x02)==0x02) {
        PORTC=0x00;                //se ejecuta siempre hasta que presiono un pulsador
                                                  //y se frena el timer0
    }

    PORTC=PIND;  //puse unos led en el puerto C para ver que pasaba ( y parpadean como           loco)


}

}
 
Última edición por un moderador:
Mmmm... no veo que hagas nada en la interrupcion del timer... entonces como sabes que se deja de ejecutar?

Por otro lado no entiendo que quisiste hacer en el programa... segun lo que entiendo si presionas el boton 1 el led se enciende mientras se mantenga presionado... y si presionas el boton 2 el led se mantiene apagado mientras lo mantengas presionado...
 
ups... perdon, me olvide de un renglon de codigo dentro de la funcion de la interrupcion...

es asi


PHP:
void TIMER0_OVF_vect (void) {

if (cuentaparpadeo==0) {
    blink ^=1;
    cuentaparpadeo=Tiempo_Parpadeo;
}


PORTA=blink;    //me falto esta linea!!!!

--cuentaparpadeo;

TCNT0=0x00;
SREG |= (1<<GLIE);
TIMSK |=  (1<<TOIE0);


}


esa linea hace que parpadee un led que esta en el puerto A, en el programa completo que estoy haciendo en el puerto A hay tres displays de 7seg, que estan multiplexados...pero para no poner todo el codigo yo puse solo el led para que sea mas sencillo....igual con display o led...en cuanto apreto un pulsador el led deja de parpadear...y como dije antes los led que estan en el puerto C ahora si responden bien, que por cierto no hace falta que mantenga apretado el pulsador para que el led este prendido, con solo apretarlo una vez lo prendes y con el otro pulsador lo apagas....al mejor estilo FF jaja.

se acepta cualquier posible solucion o consejo....

Gracias...
Saludos
 
lo hice anda

consegui el Codevision, otro complilador, copie el mismo codigo que puse aca...(salvo algunos ajustes) complie, lo grabe y anda lo mas bien...

asi que debe ser algo del WinAvr...



Saludos
 
Que tal poner la parte de configuración y los includes? el WinAVR es sencillo de usar si se sabe como, pero un auténtico dolor de cabeza si no se hace bien...
 
Que tal poner la parte de configuración y los includes? el WinAVR es sencillo de usar si se sabe como, pero un auténtico dolor de cabeza si no se hace bien...

si bueno, creo que tambien es bueno cuando pasa cierto tiempo de no leer un tema tambien seria bueno leer todos o por lo menos algunos mensajes anteriores.... y no solo el ultimo y responder.

De cualquier manera, gracias a todos por la info.

Bueno considero mi problema resuelto, y ahora como sigue la historia de este post ? quedas asi ? o hay que cerrarlo de alguna manera especial ? Gracias nuevamente...

Saludos.
 
Atrás
Arriba