Comunicacion serie entre dos Atmega8 ?

#1
Hola comunidad! Queria hacerles una consulta y espero puedan ayudarme,
Estoy iniciando en la comunicacion serial, utilizo dos Atmega8 y AtmelStudio.
Lo que intento hacer es que el uC que esta programado como TX, maneje dos pulsadores(encendido y apagado) para controlar el parpadeo de los leds conectados al uC que esta programado como RX. El problema en el cual me encuentro es que al hacer parpadear los leds no puedo apagarlos, los mismos no lo hacen debido a que no puede salir del bucle y siguen parpadeando infinitamente. Les dejo el codigo y adjunto la libreria de USART que utilizo para que puedan simularlo y agradezco si puedieran ayudarme u orientarme en el error que estoy cometiendo, desde ya muchas gracias!

Saludos!



Codigo fuente: TX

Código:
[COLOR="YellowGreen"]/*
	Nombre: TX.c
	
*/ [/COLOR]

[COLOR="yellowgreen"]/* Configuraciones Generales */[/COLOR]
#define  F_CPU 8000000UL 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usart.h"

[COLOR="yellowgreen"]/* Variables a Utilizar */[/COLOR]				
unsigned char encender = 'a';			
unsigned char apagar = 'b';			

int main(void)
{	
	[COLOR="yellowgreen"]// Comunicacion serial a 4800 baudios[/COLOR]
	SerialBegin(103);	
								
	[COLOR="yellowgreen"]// PC0 y PC1 como entrada[/COLOR]
	DDRC =  (0<<PC1) | (0<<PC0);

	[COLOR="yellowgreen"]// Limpiamos PORTC[/COLOR]
	PORTC = 0x00;										
	
    while(1)
    {
	[COLOR="yellowgreen"]// Testeo estado de PC0[/COLOR]
	if (bit_is_clear(PINC,PC0) == 0)
	{
		[COLOR="yellowgreen"]// Retardo para verificar la pulsacion[/COLOR]
		_delay_ms(50);
		
                [COLOR="yellowgreen"]// Testeo nuevamente PC0[/COLOR]			
		if (bit_is_clear(PINC,PC0) == 0)
		{
			[COLOR="yellowgreen"]// Envio el dato "encender"[/COLOR]
			SerialWrite(encender);	
		}				
	}
	[COLOR="yellowgreen"]// Testeo estado de PC1[/COLOR]
	if (bit_is_clear(PINC,PC1) == 0)
	{
		[COLOR="yellowgreen"]// Retardo para verificar la pulsacion[/COLOR]
		_delay_ms(50);

		[COLOR="yellowgreen"]// Testeo nuevamente PC1[/COLOR]
		if (bit_is_clear(PINC,PC1) == 0)
	        {
			[COLOR="yellowgreen"]// Envio el dato "apagar"[/COLOR]
			SerialWrite(apagar);
	        }			
	}			
    }
}

Codigo fuente: RX

Código:
[COLOR="YellowGreen"]/*
	Nombre: RX.c

 */ [/COLOR]

[COLOR="yellowgreen"]/* Configuraciones Generales */[/COLOR]
#define F_CPU 8000000UL 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usart.h"

[COLOR="yellowgreen"]/* Variables a utilizar */[/COLOR]
unsigned char dato_serial;
unsigned char encender = 'a';
unsigned char apagar = 'b';

int main(void)
{					
	[COLOR="yellowgreen"]// Comunicacion serial a 4800 baudios[/COLOR]
	SerialBegin(103);	
				
	[COLOR="yellowgreen"]// Puerto C como salida[/COLOR]
	DDRC = 0xFF;

        [COLOR="yellowgreen"]// Limpio PORTC[/COLOR]
	PORTC = 0x00;	

    while(1)
    {
	[COLOR="yellowgreen"]// Almaceno el dato recibido en "dato_serial" [/COLOR]
	dato_serial = SerialRead();

	[COLOR="yellowgreen"]// Es igual a "encender"?[/COLOR]
	if (dato_serial == encender)
	{
              while(true)
              {
                      [COLOR="YellowGreen"]// Parpadeo...[/COLOR]
		      PORTC = 0b11111111;
		      _delay_ms(500);
		      PORTC = 0b00000000;
		      _delay_ms(500);

                      [COLOR="yellowgreen"]// Almaceno dato recibido en "dato_serial"[/COLOR]
                      dato_serial = SerialRead();
                      [COLOR="yellowgreen"]// Es igual a "apagar"?[/COLOR]
                      if(dato_serial == apagar)
                      {
                            PORTC = 0b00000000;
                            [COLOR="YellowGreen"]// Salgo...[/COLOR]
                            break;
                      }
              }
	}
    }
}
 

Adjuntos

#2
Entierra bien hondo los delays del demonio y no los uses mas. Usa timers e interrupciones que están para eso. Lo mismo con el puerto serie.
Si estás haciendo una cosa no puedes hacer otra. Solución no hagas lo que no hace falta hacer, pones un timer y mientras llega la interrupción haces otra cosa, activas las interrupciones del puerto serie y mientras llega o no llega algo haces otra cosa.
 
#3
Hola comunidad! Queria hacerles una consulta y espero puedan ayudarme,
Estoy iniciando en la comunicacion serial, utilizo dos Atmega8 y AtmelStudio.
Lo que intento hacer es que el uC que esta programado como TX, maneje dos pulsadores(encendido y apagado) para controlar el parpadeo de los leds conectados al uC que esta programado como RX. El problema en el cual me encuentro es que al hacer parpadear los leds no puedo apagarlos, los mismos no lo hacen debido a que no puede salir del bucle y siguen parpadeando infinitamente. Les dejo el codigo y adjunto la libreria de USART que utilizo para que puedan simularlo y agradezco si puedieran ayudarme u orientarme en el error que estoy cometiendo, desde ya muchas gracias!

Saludos!
hola ., bueno por empezar tambien tendrias que publicar el esquema de coneccion de los dos atmega
Entierra bien hondo los delays del demonio y no los uses mas. Usa timers e interrupciones que están para eso. Lo mismo con el puerto serie.
Si estás haciendo una cosa no puedes hacer otra. Solución no hagas lo que no hace falta hacer, pones un timer y mientras llega la interrupción haces otra cosa, activas las interrupciones del puerto serie y mientras llega o no llega algo haces otra cosa.
querido amigo ., tenes toda la razon., con los delay
pero me suena a codigo de arduino ., aca subo dos tutoriales con el uso de la USART​
y tambien ., por lo general se usa una frecuencia de BUIDOS de 9600 ., y en el codigo no es esa (en el tuto explicaca como)​
ACLARACION : los tutos no son de mi autoria ., pero es de un integrante de ATMEL CORPORACION ., yo solo los traduje al castellano ., y tengo permiso del autor a publicarlos libremente​
 

Adjuntos

#5
Hola comunidad! Queria hacerles una consulta y espero puedan ayudarme,
Estoy iniciando en la comunicacion serial, utilizo dos Atmega8 y AtmelStudio.
Lo que intento hacer es que el uC que esta programado como TX, maneje dos pulsadores(encendido y apagado) para controlar el parpadeo de los leds conectados al uC que esta programado como RX. El problema en el cual me encuentro es que al hacer parpadear los leds no puedo apagarlos, los mismos no lo hacen debido a que no puede salir del bucle y siguen parpadeando infinitamente. Les dejo el codigo y adjunto la libreria de USART que utilizo para que puedan simularlo y agradezco si puedieran ayudarme u orientarme en el error que estoy cometiendo, desde ya muchas gracias!

Saludos!
Hola buen día. Una leída no está de sobra: http://microcontroladores-mrelberni.com/usart-avr-ejemplos/

http://winavr.scienceprog.com/examp...433-rf-modules-with-avr-microcontrollers.html

MAKI.
 
Última edición:
#6
¡¡¡ BRUJO !!!! con los delay jajajajajajajajajaja
A mi también me ha sonado a arduino más que a C. No estoy muy puesto en C.
en efecto amigo Scooter ., me sonaba a arduino ., pero la primer parte me compilo bien (TX)​
ahora la segunda parte (RX) ., mmmmmmm ., encontre varios errores​
solo repare para poder compilar ., y poder simular (traceo de linea por linea de ejecucion) el error que marcaba era​
error.jpg
lo que faltaba era una enumeracion o definicion de funcion en el while y le agregue esta definicion​
PHP:
enum {FALSE=0, TRUE=1};
bueno a partir de alli ., me compilo correctamente y sin error​
pero aqui viene lo interesante ., el traceo del compilador se detiene en un !!!!! DELAY ¡¡¡¡¡ jajajaja ., es aca​
ERROR DELAY.jpg
el programa corre perfecto y sin problemas hasta aqui​
ERROR DELAY 1.jpg
o sea que los problemas son los delay ., lo curioso es que el compilador se para ., justo donde explica el consultante​
pero nunca podria haber complado por el otro error ., y si la libreria no estaba correcta ¿¿¿ como probo en el simulador virtual ???​
conclucion : aca falta algo o nunca probo ., y como dijo Scooter ., lo delay no van., osea habria que arreglar esto​
PHP:
 while(TRUE)
              {
                      // Parpadeo...
		      PORTC = 0b11111111;
		      _delay_ms(500);
		      PORTC = 0b00000000;
		      _delay_ms(500);
hola
gracias por la info ., nunca esta demas ., mas cuando uno no usa arduino ., sino atmega y AVRstudio​
tambien subo los dos proyectos completos ., en AVRStudio 4.13 ., se abren con la extencion .aps (como en todos los AVRstudio de ATMEL) ., no importa su vercion​
 

Adjuntos

#9
Buenas a todos y muchas gracias por las respuestas, no tuve tiempo de comentar durante el dia por cuestiones laborales.
Como dice el amigo locodelafonola, lo que necesito hacer es el parpadeo de los leds sin utilizar los delay y por eso recurri a ustedes. ya que estos me perjudican al querer realizar otra tarea con el uC, tambien me he dado cuenta de los errores en el RX y ya fueron solucionados.
Creo que veo viable la opcion que me da el amigo Scooter, utilizar los timers y las interrupciones para dicha tarea y quisiera saber si podrian ayudarme a implementarla.
No es Arduino, es el mismo AVR-GCC y la libreria Usart.h la cree hace algun tiempo leyendo tutioriales con la idea de facilitarme la programacion serial! Se las adjunto aqui mismo!

Código:
[COLOR="YellowGreen"]/* 
------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------

     Nombre: usart.h
Descripción: Librería para el manejo de la USART 

------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------

Se declara la función que configura el USART en modo asincrono normal. En este ejemplo se trabajara 
el microcontrolador a una frecuencia de 8 Mhz y a una velocidad de 9600 baudios. Calculamos entonces el registro UBRR:

		UBRR = (Fosc/16*BAUD) - 1 
		
		UBRR = (8000000/16*9600) - 1
		UBRR = 51.08333

El valor obtenido para 9600 baudios fue de 51.0833 por lo tanto, 
se tomara el valor de 51 redondeando el valor obtenido y con el cual calculamos los baudios reales:
			
		BAUD = Fosc/16*(UBRR + 1)
		
		BAUD = 8000000/16*(51 + 1)
		BAUD = 9615.3846

9615.3846 Sera el valor real de baudios por segundo con los que el microcontrolador trabajara, 
pero para obtener el % de error respecto al valor de 9600 aplicamos la siguiente formula:

		ERROR = (BAUDRATE/BAUD - 1)*100%
		
		ERROR = (9615.3846/9600 - 1)*100
		ERROR = 0.16%
		
Como se puede ver el porcentaje de error es muy pequeño. Procedemos entonces a iniciar la comunicacion serial de la siguiente forma:

		SerialBegin(51);

La sentencia "SerialBegin()" inicia la comunicacion serial y tomamos el valor "51" 
obtenido del calculo que realizamos anteriormente. 

-----------------------------------------------------------------------------------------------------------------------

Estas operaciones previamente realizadas son para conocer un poco más el funcionamiento del registro 
y el cómo calcular el valor respecto a algún baud rate deseado. 
También hay una tabla que facilito con los valores más usados, la cual calcule con la formula del modo asincrono normal.

		BAUDIOS		FOSC	  UBRR		ERROR
		-------------------------------------
		2400		1Mhz	  26		0.2%
		4800		1Mhz	  13		0.2%
		9600		1Mhz	  7			-0.6%	 
		-------------------------------------
		2400		4Mhz	  104		0.2%
		4800		4Mhz	  52		0.2%
		9600		4Mhz	  26		0.2%
		-------------------------------------
		2400		8Mhz	  207		0.2%
		4800		8Mhz	  103		0.2%
		9600		8Mhz	  51		0.2%
		-------------------------------------
		2400		10Mhz	  260		0.2%
		4800		10Mhz	  130		0.2%
		9600		10Mhz	  65		0.2%
		-------------------------------------
		2400		12Mhz	  312		0.2%
		4800		12Mhz	  156		0.2%
		9600		12Mhz	  78		0.2%
		-------------------------------------	
		2400		16Mhz	  416		0.2%
		4800		16Mhz	  208		0.2%
		9600		16Mhz	  104		0.2%
		-------------------------------------
		2400		20Mhz	  520		0.2%
		4800		20Mhz	  260		0.2%
		9600		20Mhz	  130		0.2%
		-------------------------------------
*/[/COLOR]

#ifndef USART_H
#define USART_H

void SerialBegin( unsigned int baud);
void SerialWrite( unsigned char data);
unsigned char SerialRead( void );
void SerialString(char cadena[]);

[COLOR="yellowgreen"]/* Función inicializar USART */[/COLOR]
void SerialBegin( unsigned int baud )
{
    [COLOR="yellowgreen"]/* Se establece la tasa de baudios con el valor ingresado a la funcion */[/COLOR]
    UBRRH = (unsigned char)(baud>>8);
    UBRRL = (unsigned char)baud;
    [COLOR="yellowgreen"]/* Se habilita la recepción y la transmisión de datos */[/COLOR]
    UCSRB = (1<<RXEN)|(1<<TXEN);
    [COLOR="yellowgreen"]/* Se establece el formato de la trama: 8 bits de datos, 2 bits de parada, sin bits de paridad */[/COLOR]
    UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

[COLOR="yellowgreen"]/* Función para transmitir un caracter */[/COLOR]
void SerialWrite( unsigned char data )
{
    [COLOR="yellowgreen"]/* Espera hasta que el buffer esté vacio */[/COLOR]
    while ( !( UCSRA & (1<<UDRE)) );
    [COLOR="yellowgreen"]/* Pone el dato en el buffer de transmisión, envía el dato */[/COLOR]
    UDR = data;
}

[COLOR="yellowgreen"]/* Función para recibir un caracter */[/COLOR]
unsigned char SerialRead( void )
{
    [COLOR="yellowgreen"]/* Espera a recibir datos */[/COLOR]
    while ( !(UCSRA & (1<<RXC)) );
    [COLOR="yellowgreen"]/* Devuelve el dato leido */[/COLOR]
    return UDR;
}

[COLOR="yellowgreen"]/* Funcion para transmitir una cadena de caracteres */[/COLOR]
void SerialString(char cadena[])
{
	[COLOR="yellowgreen"]/* Índice */[/COLOR]
    int i;
	[COLOR="yellowgreen"]/* Recorre la cadena */[/COLOR]
    for(i=0;cadena[i]!='\0';i++) 
		/* Transmite el dato */
        SerialWrite(cadena[i]);
}
#endif


Compañeros, les adjunto archivos completos. Codigo fuente TX y RX, .HEX de cada uno y archivo de simulacion con ISIS Proteus 7.

Codigo fuente: TX

PHP:
/*
	Nombre: TX.c
	
*/ 

/* Configuraciones Generales */
#define  F_CPU 8000000UL 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usart.h"

/* Variables a Utilizar */				
unsigned char encender = 'a';			
unsigned char apagar = 'b';			

int main(void)
{	
	// Comunicacion serial a 4800 baudios
	SerialBegin(103);	
								
	// PC0 y PC1 como entrada
	DDRC =  (0<<PC1) | (0<<PC0);

	// Limpiamos PORTC
	PORTC = 0x00;										
	
    while(1)
    {
		// Testeo estado de PC0
		if (bit_is_clear(PINC,PC0) == 0)
		{
			// Retardo para verificar la pulsacion
			_delay_ms(50);
		
					// Testeo nuevamente PC0			
			if (bit_is_clear(PINC,PC0) == 0)
			{
				// Envio el dato "encender"
				SerialWrite(encender);	
			}				
		}
		// Testeo estado de PC1
		if (bit_is_clear(PINC,PC1) == 0)
		{
			// Retardo para verificar la pulsacion
			_delay_ms(50);

			// Testeo nuevamente PC1
			if (bit_is_clear(PINC,PC1) == 0)
			{
				// Envio el dato "apagar"
				SerialWrite(apagar);
			}			
		}			
    }
}
Codigo fuente RX:

PHP:
/*
	Nombre: RX.c

 */ 

/* Configuraciones Generales */
#define F_CPU 8000000UL 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usart.h"

/* Variables a utilizar */
unsigned char dato_serial;
unsigned char encender = 'a';
unsigned char apagar = 'b';

int main(void)
{					
	// Comunicacion serial a 4800 baudios
	SerialBegin(103);	
				
	// Puerto C como salida
	DDRC = 0xFF;

    // Limpio PORTC
	PORTC = 0x00;	

    while(1)
    {
	// Almaceno el dato recibido en "dato_serial" 
	dato_serial = SerialRead();

	// Es igual a "encender"?
	if (dato_serial == encender)
	{
           while(1)
           {
                // Parpadeo...
		PORTC = 0b11111111;
		_delay_ms(500);
		PORTC = 0b00000000;
		_delay_ms(500);

		// Almaceno dato recibido en "dato_serial"
		dato_serial = SerialRead();
		// Es igual a "apagar"?
		if(dato_serial == apagar)
		{
			PORTC = 0b00000000;
			// Salgo...
			break;
		}
            }
	}
    }
}
 

Adjuntos

Última edición:
#10
Hola
Buenas a todos y muchas gracias por las respuestas, no tuve tiempo de comentar durante el dia por cuestiones laborales.
Como dice el amigo locodelafonola, lo que necesito hacer es el parpadeo de los leds sin utilizar los delay y por eso recurri a ustedes. ya que estos me perjudican al querer realizar otra tarea con el uC, tambien me he dado cuenta de los errores en el RX y ya fueron solucionados.
Creo que veo viable la opcion que me da el amigo Scooter, utilizar los timers y las interrupciones para dicha tarea y quisiera saber si podrian ayudarme a implementarla.
No es Arduino, es el mismo AVR-GCC y la libreria Usart.h la cree hace algun tiempo leyendo tutioriales con la idea de facilitarme la programacion serial! Se las adjunto aqui mismo!

Código:
[COLOR="YellowGreen"]/* 
------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------

     Nombre: usart.h
Descripción: Librería para el manejo de la USART 

------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------

Se declara la función que configura el USART en modo asincrono normal. En este ejemplo se trabajara 
el microcontrolador a una frecuencia de 8 Mhz y a una velocidad de 9600 baudios. Calculamos entonces el registro UBRR:

		UBRR = (Fosc/16*BAUD) - 1 
		
		UBRR = (8000000/16*9600) - 1
		UBRR = 51.08333

El valor obtenido para 9600 baudios fue de 51.0833 por lo tanto, 
se tomara el valor de 51 redondeando el valor obtenido y con el cual calculamos los baudios reales:
			
		BAUD = Fosc/16*(UBRR + 1)
		
		BAUD = 8000000/16*(51 + 1)
		BAUD = 9615.3846

9615.3846 Sera el valor real de baudios por segundo con los que el microcontrolador trabajara, 
pero para obtener el % de error respecto al valor de 9600 aplicamos la siguiente formula:

		ERROR = (BAUDRATE/BAUD - 1)*100%
		
		ERROR = (9615.3846/9600 - 1)*100
		ERROR = 0.16%
		
Como se puede ver el porcentaje de error es muy pequeño. Procedemos entonces a iniciar la comunicacion serial de la siguiente forma:

		SerialBegin(51);

La sentencia "SerialBegin()" inicia la comunicacion serial y tomamos el valor "51" 
obtenido del calculo que realizamos anteriormente. 

-----------------------------------------------------------------------------------------------------------------------

Estas operaciones previamente realizadas son para conocer un poco más el funcionamiento del registro 
y el cómo calcular el valor respecto a algún baud rate deseado. 
También hay una tabla que facilito con los valores más usados, la cual calcule con la formula del modo asincrono normal.

		BAUDIOS		FOSC	  UBRR		ERROR
		-------------------------------------
		2400		1Mhz	  26		0.2%
		4800		1Mhz	  13		0.2%
		9600		1Mhz	  7			-0.6%	 
		-------------------------------------
		2400		4Mhz	  104		0.2%
		4800		4Mhz	  52		0.2%
		9600		4Mhz	  26		0.2%
		-------------------------------------
		2400		8Mhz	  207		0.2%
		4800		8Mhz	  103		0.2%
		9600		8Mhz	  51		0.2%
		-------------------------------------
		2400		10Mhz	  260		0.2%
		4800		10Mhz	  130		0.2%
		9600		10Mhz	  65		0.2%
		-------------------------------------
		2400		12Mhz	  312		0.2%
		4800		12Mhz	  156		0.2%
		9600		12Mhz	  78		0.2%
		-------------------------------------	
		2400		16Mhz	  416		0.2%
		4800		16Mhz	  208		0.2%
		9600		16Mhz	  104		0.2%
		-------------------------------------
		2400		20Mhz	  520		0.2%
		4800		20Mhz	  260		0.2%
		9600		20Mhz	  130		0.2%
		-------------------------------------
*/[/COLOR]

#ifndef USART_H
#define USART_H

void SerialBegin( unsigned int baud);
void SerialWrite( unsigned char data);
unsigned char SerialRead( void );
void SerialString(char cadena[]);

[COLOR="yellowgreen"]/* Función inicializar USART */[/COLOR]
void SerialBegin( unsigned int baud )
{
    [COLOR="yellowgreen"]/* Se establece la tasa de baudios con el valor ingresado a la funcion */[/COLOR]
    UBRRH = (unsigned char)(baud>>8);
    UBRRL = (unsigned char)baud;
    [COLOR="yellowgreen"]/* Se habilita la recepción y la transmisión de datos */[/COLOR]
    UCSRB = (1<<RXEN)|(1<<TXEN);
    [COLOR="yellowgreen"]/* Se establece el formato de la trama: 8 bits de datos, 2 bits de parada, sin bits de paridad */[/COLOR]
    UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

[COLOR="yellowgreen"]/* Función para transmitir un caracter */[/COLOR]
void SerialWrite( unsigned char data )
{
    [COLOR="yellowgreen"]/* Espera hasta que el buffer esté vacio */[/COLOR]
    while ( !( UCSRA & (1<<UDRE)) );
    [COLOR="yellowgreen"]/* Pone el dato en el buffer de transmisión, envía el dato */[/COLOR]
    UDR = data;
}

[COLOR="yellowgreen"]/* Función para recibir un caracter */[/COLOR]
unsigned char SerialRead( void )
{
    [COLOR="yellowgreen"]/* Espera a recibir datos */[/COLOR]
    while ( !(UCSRA & (1<<RXC)) );
    [COLOR="yellowgreen"]/* Devuelve el dato leido */[/COLOR]
    return UDR;
}

[COLOR="yellowgreen"]/* Funcion para transmitir una cadena de caracteres */[/COLOR]
void SerialString(char cadena[])
{
	[COLOR="yellowgreen"]/* Índice */[/COLOR]
    int i;
	[COLOR="yellowgreen"]/* Recorre la cadena */[/COLOR]
    for(i=0;cadena[i]!='\0';i++) 
		/* Transmite el dato */
        SerialWrite(cadena[i]);
}
#endif
en el primer link ., que publico el compañero Makitronica ., tenes el ejemplo de lo mismo con dos atmega88 (es lo mismo que el atmega 8 ., cambia solo las prestaciones)​
proba con esos ejemplos ., (tiene un solo led pero podes poner mas)​
leete los tutos que yo subi ., a ver si te sirven para entender., arma la compilacion (que compile y y tracee con F11) y subila como lo hice yo​
PD: yo no uso simulador alguno ., en caso de la USART ., se prueba en lo fisico ., el problema esta en la compilacion dentro del compilador ., es inutil la simulacion en ISIS Proteus 7 EDITO PARA NO CREAR NUEVO MENSAJE
bueno ., aca te aporto una idea de como tendria que ser el temporisador (TIMER)​
este ejemplo es muy basico ., pero se adapta a todos los atmegas usa el timer0​
PHP:
*// Demo Programa (AVR GCC)//*
*//LED@0.5 Blink Hz en PORTC [3,2,1,0]//*

 

# Include <avr/io.h> 

# include <avr/interrupt.h>

volátil count uint8_t;

void main ()

{

   // Pre-escalador = FCPU/1024 

   TCCR0 | = ( 1 << CS02) | ( 1 << CS00);

   // Habilitar Overflow Interrupt Enable 

   TIMSK | = ( 1 << TOIE0);

   // Inicializar Contador 

   TCNT0 = 0 ;

   // Inicializar nuestra varriable 

   count = 0 ;

   // Puerto C [3,2,1,0] como poner un 

   DDRC | = 0x0F ;

   // Habilitar interrupciones Global

   sei ();

   // Loop  Infinito

    while( 1 );

}

ISR (TIMER0_OVF_vect)

{

   // Esta es la rutina de servicio de interrupción de TIMER0 DESBORDAMIENTO Interrupción. 

   // CPU llamará automáticamente cuando este TIMER0 desborda.

   // Incrementar nuestra variable

   count + +;

   if (count == 61 )

   {

      PORTC = ~ PORTC;  // Invertir el valor de PORTC 

      count = 0 ;

   }

}
bueno aca tenes lo que comunmente se llama BLINKY ., que tambien lo podrias usar​
PHP:
#include <avr/io.h>

/* Este ejemplo destellar los LED en STK500, que se encarga de tendencia a la basura GCC bucles de retardo vacíos mediante la inserción de asm en línea volátil. */
   
void wait (void) 
{
	asm volatile ("nop"::);
}

int main (void) 
{
	unsigned char i;
	unsigned long j;
	
	DDRB = 0xFF;			// PORTB configurar como salida
	
	for(;;) 
	{
		for (i=0x01; i<0x80; i<<=1) 
		{
			PORTB = ~i;
			
			/* Delay */
			for (j=0; j<20000; j++) wait();
		}
		
		for (i=0x80; i>0x01; i>>=1) 
		{
			PORTB = ~i;
			
			/* Delay o Retardo, los bucles de espera definidos en avr / delay.h, también podría ser utilizado */
			for (j=0; j<20000; j++) wait();
		}
	}
}
 

Adjuntos

Última edición:
#11
¡Excelente aporte! Ayer estuve leyendo los artículos que me dejaron y se los agradezco.
Con este ejemplo espero entender un poco más. Realmente muchas gracias locodelafonola por tomarte el tiempo en ayudarme.
Ni bien pueda terminar, posteo el código completo por si a alguno de ustedes le sirve a futuro para realizar algo.
Estamos en contacto por este medio. Muchas gracias.
 
Última edición por un moderador:
#12
Buenas noches! Gracias a todos ustedes y a locodelafonola que dedico parte de su tiempo en explicarme y ayudarme, les comento que pude realizar este ejercicio que por asi decirlo no me dejaba dormir jaja
Me tome el tiempo de leer cada uno de los articulos mencionados que me han recomendado y fueron de mucha ayuda los ejemplos de locodelafonola, ahora el programa realiza lo que estaba queriendo.
Les adjunto todos los archivos que incluyen los programas para cada uC y la simulacion por Proteus, se encuentran compilados y probados al 100%. Espero que les sea de gran ayudar u ejemplo para implementar en sus proyectos.
Estoy en deuda y ojala algun dia pueda aportar un poco mas. Por el momento me encuentro aprendiendo! Les mando un saludo grande y vuelvo agradecer a todos por su tiempo! :D


Codigo fuente: TX

PHP:
/*
	Nombre: TX.c
	
*/ 

/* Configuraciones Generales */
#define  F_CPU 8000000UL 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usart.h"

/* Variables a Utilizar */				
unsigned char encender = 'a';			
unsigned char apagar = 'b';			

int main(void)
{	
	// Comunicacion serial a 4800 baudios
	SerialBegin(103);	
								
	// PC0 y PC1 como entrada
	DDRC =  (0<<PC1) | (0<<PC0);

	// Limpiamos PORTC
	PORTC = 0x00;										
	
    while(1)
    {
		// Testeo estado de PC0
		if (bit_is_clear(PINC,PC0) == 0)
		{
			// Retardo para verificar la pulsacion
			_delay_ms(50);
		
					// Testeo nuevamente PC0			
			if (bit_is_clear(PINC,PC0) == 0)
			{
				// Envio el dato "encender"
				SerialWrite(encender);	
			}				
		}
		// Testeo estado de PC1
		if (bit_is_clear(PINC,PC1) == 0)
		{
			// Retardo para verificar la pulsacion
			_delay_ms(50);

			// Testeo nuevamente PC1
			if (bit_is_clear(PINC,PC1) == 0)
			{
				// Envio el dato "apagar"
				SerialWrite(apagar);
			}			
		}			
    }
}

Codigo fuente: RX

PHP:
/*
	Nombre: RX.c

 */ 

/* Configuraciones Generales */
#define F_CPU 8000000UL 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usart.h"

/* Variables a utilizar */
unsigned char dato_serial;
unsigned char encender = 'a';
unsigned char apagar = 'b';
int contador;

ISR (TIMER0_OVF_vect)
{
	// Incrementa variable	
	contador++;

	// Pregunto si el contador es igual a 7
	if (contador == 7)
	{
		// Invierte el valor de PORTC
		PORTC = ~ PORTC;  

		// Pone contador a 0
		contador = 0 ;	
	}
}

ISR(USART_RXC_vect)
{
	// Almaceno el dato recibido por puerto serial en la variable "dato_serial"
	dato_serial = SerialRead();
	
	// Pregunto si "dato_serial" es igual a "encender"
	if (dato_serial == encender)
	{
		// Habilito interrupcion por Overflow
		TIMSK = (1<<TOIE0);
                /* Al activar el bit TOIE0 del registro TIMSK,
                   activo la interrupcion por Overflow y 
                   esto me permite el parpadeo de leds*/                  
	}
	
	// Pregunto si "dato_serial" es igual a "apagar"
	if (dato_serial == apagar)
	{
		// Deshabilito interrupcion por Overflow
		TIMSK = (0<<TOIE0);
		// Apago los leds
		PORTC = 0x00;
	}
}

int main(void)
{					
	// Comunicacion serial a 4800 baudios
	SerialBegin(103);	
				
	// Puerto C [3,2,1,0] como salida
	DDRC = 0x0F ;

    // Limpio PORTC
	PORTC = 0x00;	
	
	// Prescaler = FCPU/1024
	TCCR0 = (1<<CS02) | (1<<CS00);

	// Inicio interrupcion por Overflow deshabilitada
	TIMSK = (0<<TOIE0);
	
	// Inicializo contador en 0          
	TCNT0 = 0;

	// Habilito interrupciones globales
	sei();

    while(1)
    {
    }
}

Codigo fuente: usart.h

PHP:
/* 
------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------

     Nombre: usart.h
Descripción: Librería para el manejo de la USART 

------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------

Se declara la función que configura el USART en modo asincrono normal. En este ejemplo se trabajara 
el microcontrolador a un a frecuencia de 8 Mhz y a una velocidad de 9600 baudios. Calculamos entonces el registro UBRR:

		UBRR = (Fosc/16*BAUD) - 1 
		
		UBRR = (8000000/16*9600) - 1
		UBRR = 51.08333

El valor obtenido para 9600 baudios fue de 51.0833 por lo tanto, 
se tomara el valor de 51 redondeando el valor obtenido y con el cual calculamos los baudios reales:
			
		BAUD = Fosc/16*(UBRR + 1)
		
		BAUD = 8000000/16*(51 + 1)
		BAUD = 9615.3846

9615.3846 Sera el valor real de baudios por segundo con los que el microcontrolador trabajara, 
pero para obtener el % de error respecto al valor de 9600 aplicamos la siguiente formula:

		ERROR = (BAUDRATE/BAUD - 1)*100%
		
		ERROR = (9615.3846/9600 - 1)*100
		ERROR = 0.16%
		
Como se puede ver el porcentaje de error es muy pequeño. Procedemos entonces a iniciar la comunicacion serial de la siguiente forma:

		SerialBegin(51);

La sentencia "SerialBegin()" inicia la comunicacion serial y tomamos el valor "51" 
obtenido del calculo que realizamos anteriormente. 

-----------------------------------------------------------------------------------------------------------------------

Estas operaciones previamente realizadas son para conocer un poco más el funcionamiento del registro 
y el cómo calcular el valor respecto a algún baud rate deseado. 
También hay una tabla que facilito con los valores más usados, la cual calcule con la formula del modo asincrono normal.

		BAUDIOS		FOSC	  UBRR		ERROR
		-------------------------------------
		2400		1Mhz	  26		0.2%
		4800		1Mhz	  13		0.2%
		9600		1Mhz	  7			-0.6%	 
		-------------------------------------
		2400		4Mhz	  104		0.2%
		4800		4Mhz	  52		0.2%
		9600		4Mhz	  26		0.2%
		-------------------------------------
		2400		8Mhz	  207		0.2%
		4800		8Mhz	  103		0.2%
		9600		8Mhz	  51		0.2%
		-------------------------------------
		2400		10Mhz	  260		0.2%
		4800		10Mhz	  130		0.2%
		9600		10Mhz	  65		0.2%
		-------------------------------------
		2400		12Mhz	  312		0.2%
		4800		12Mhz	  156		0.2%
		9600		12Mhz	  78		0.2%
		-------------------------------------	
		2400		16Mhz	  416		0.2%
		4800		16Mhz	  208		0.2%
		9600		16Mhz	  104		0.2%
		-------------------------------------
		2400		20Mhz	  520		0.2%
		4800		20Mhz	  260		0.2%
		9600		20Mhz	  130		0.2%
		-------------------------------------
*/

#ifndef USART_H
#define USART_H

void SerialBegin( unsigned int baud);
void SerialWrite( unsigned char data);
unsigned char SerialRead( void );
void SerialString(char cadena[]);

/* Función inicializar USART */
void SerialBegin( unsigned int baud )
{
    /* Se establece la tasa de baudios con el valor ingresado a la funcion */
    UBRRH = (unsigned char)(baud>>8);
    UBRRL = (unsigned char)baud;
    /* Se habilita la recepción y la transmisión de datos */
	/* Tambien se habilita la interrupcion por USART por transmision y recepcion*/
    UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE);
    /* Se establece el formato de la trama: 8 bits de datos, 2 bits de parada, sin bits de paridad */
    UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

/* Función para transmitir un caracter */
void SerialWrite( unsigned char data )
{
    /* Espera hasta que el buffer esté vacio */
    while ( !( UCSRA & (1<<UDRE)) );
    /* Pone el dato en el buffer de transmisión, envía el dato */
    UDR = data;
}

/* Función para recibir un caracter */
unsigned char SerialRead( void )
{
    /* Espera a recibir datos */
    while ( !(UCSRA & (1<<RXC)) );
    /* Devuelve el dato leido */
    return UDR;
}

/* Funcion para transmitir una cadena de caracteres */
void SerialString(char cadena[])
{
	/* Índice */
    int i;
	/* Recorre la cadena */
    for(i=0;cadena[i]!='\0';i++) 
		/* Transmite el dato */
        SerialWrite(cadena[i]);
}
#endif
 

Adjuntos

Última edición:
Arriba