fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

ATmega644 Comunicac...
 
Avisos
Vaciar todo

ATmega644 Comunicacón con puerto serie

18 Respuestas
4 Usuarios
0 Reactions
8,525 Visitas
mediopixel
Respuestas: 41
Topic starter
(@mediopixel)
Eminent Member
Registrado: hace 19 años

Hola, estoy haciendo pruebas con un ATmega644 y comunicación serie. Tengo un programita que envía "HOLA" por el puerto serie y lo único que recibo son caracteres raros (sólo cuadraditos).

Utilizo AVR Studio 4 para compilar y cargar el programa en el micro.
¿Alguien tiene alguna idea de lo que puede estar pasando?
Gracias!

Os dejo el programita:

/**************************************************
UART_Test
************************************************/
#define F_CPU 16000000UL
#include <avr>
#include <util>

void USART_Init();
void USART_Transmit( unsigned char );
unsigned char USART_Receive( void );

int main(void)
{
USART_Init();
for(;;)
{
USART_Transmit('H');
USART_Transmit('O');
USART_Transmit('L');
USART_Transmit('A');
USART_Transmit('n');
USART_Transmit('r');
_delay_ms(25);
_delay_ms(25);
}
}
/***********************************************
Functions from UART_Test
***************************************************/
void USART_Init(){
/*
19200 baudios
cristal de 16 MHz
UBRR = 16^7/(16*9600) - 1
UBRR = 16000000/(16*19200)-1
UBRR = 16000000/307200-1
UBRR = 52.083-1
UBRR = 51.083
*/
//registro UBRRL
UBRR0H = 0;
UBRR0L = 51;

/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

void USART_Transmit( unsigned char data ){
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}

unsigned char USART_Receive( void ){
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
return UDR0;
}


Responder
17 respuestas
luison
Respuestas: 495
(@luison)
Reputable Member
Registrado: hace 17 años

/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);

En cuanto a lo demás... me he visto por encima la UART en el datasheet. En la página 187 tienes valores para el UBRR.
Por lo demás mus, menuda configuración y programación, veo ese código en ensamblador y en C, y porque pone que es ensamblador y C, pero "mi no entender". Sorry. 😳

Responder
ranganok
Respuestas: 3875
(@ranganok)
Ardero
Registrado: hace 19 años

Si estas poniendo 2 bits de stop en el micro y 1 bit de stop en el PC es posible que por ahí tengas el error.

S2

Ranganok Schahzaman

Responder
beamspot
Respuestas: 1132
(@beamspot)
Noble Member
Registrado: hace 17 años

Hola:

Tarde como siempre, y encima con preguntas tontas, pero es que mi cerebro no da para más:

Necesitaría saber si tienes lo fuses del micro por defecto (es decir, con el reloj interno a 1MHz), y cómo tienes configurado el oscilador externo. Mi apuesta es porque te hayas dejado el reloj dividido por 8 en los fuses o en el registro de la CPU que controla la velocidad.

O incluso que funciones desde el reloj interno a 1MHz. De todas maneras, no me acuerdo muy bien del micro que comentas si tiene un reloj a 8MHz y un divisor interno, o si tiene varias opciones de reloj. Asegurate que los fuses están puestos para funcionar con un reloj externo, y que tienes el cristal adecuado.

Respecto de la configuración del reloj, se hace desde el AVRStudio en las opciones de proyecto (un botón que tiene el icono de un engranaje), pero debería aceptar correctamente tus código, que por otro lado, me parece correcto.

Aún así, debería revisar el datasheet del micro en cuestión, ya que me parece que hay un registro que te divide la frecuencia del reloj para poder tener la CPU trabajando más lentamente ya cambiar así el consumo del mismo. Podría ser que viniese por defecto dividiendo por 8, tal y como se puede forzar (y de hecho viene de fábrica así) por los fuses.

Suerte.

Responder
mediopixel
Respuestas: 41
Topic starter
(@mediopixel)
Eminent Member
Registrado: hace 19 años

Necesitaría saber si tienes lo fuses del micro por defecto (es decir, con el reloj interno a 1MHz), y cómo tienes configurado el oscilador externo. Mi apuesta es porque te hayas dejado el reloj dividido por 8 en los fuses o en el registro de la CPU que controla la velocidad.

O incluso que funciones desde el reloj interno a 1MHz. De todas maneras, no me acuerdo muy bien del micro que comentas si tiene un reloj a 8MHz y un divisor interno, o si tiene varias opciones de reloj. Asegurate que los fuses están puestos para funcionar con un reloj externo, y que tienes el cristal adecuado.

beamspot, gracias por tu respuesta. Al parecer estás bastante acertado. He estado mirando los fuses y las opciones que vienen seleccionadas en el AVRstudio como bien dices son por defecto (pongo un pantallazo, si alguien considera que debo quitarla la quito):
fuses

la cosa está en que desactivé el checkbox de "divide clock by 8 internally..." y el de "Int. RC Osc.;Start-up time: 6CK + 65ms;..." y activé el de "Ext. RC Osc.;Start-up time: 6CK + 65ms;..." y pulsé "Program".

Tras eso he dejado de tener acceso por ISP y ya no puedo reprogramar el ATmega644.

Estoy utilizando un cristal de cuarzo de 16Mhz.

¿Sabes qué es lo que he hecho y cuál es el problema? ¿me he cargado el micro?

Por otro lado, sigo sin saber (no entiendo muy bien) cómo configuar correctamente el uart del micro para una velocidad de 9600 baudios y un reloj externo a 16Mhz. No sé si tengo que hacerlo en el programa en C, en el makefile o en alguna de las opciones de configuración del IDE que estoy utilizando. Desconozco muchas cosas y no alcanzo a entender la lógica de esto.

Saludos y gracias por todo lo que voy aprendiendo.

Responder
beamspot
Respuestas: 1132
(@beamspot)
Noble Member
Registrado: hace 17 años

Hola:

A ver si tengo tiempo de explicarlo todo.

La opción de Ext RC no es la correcta. La correcta es External Crystal Osc, freq 8 (o superiores). El problema que tienes ahora es que espera un oscilador RC, y en su lugar tienes un cristal de cuarzo. Por eso, la mejor salida es o bien poner un oscilador RC, o lo mejor (lo que yo haría), conectar en la entrada (ver datasheet) una señal cuadrada de la frecuencia que puedas, con una resistencia en serie de digamos 100R a 1K. De esta manera, el ISP 'revivirá'.

El problema de que está 'muerto' es común, y se debe al fallo (según mi humilde opinión subjetiva) de que el micro necesita un sistema de reloj para poderse programar a través del ISP, en lugar de usar el reloj propio del ISP. Por tanto, una selección incorrecta de los fusibles (fuses en castellano) elige un sistema de reloj que no funciona (lo típico es habilitar un cristal externo, sin tener nada conectado). Y la solución es siempre 'inyectar' una señal de reloj, tal y como he explicado.

De todas maneras, revisa que el cristal de 16MHz y los condensadores del mismo son los adecuados y están correctamente conectados.

Lo de la frecuencia del puerto serie necesita que la programes tu. De todas maneras, nunca está de más, por aquello de las librerías, de indicar la frecuencia de trabajo en el desplegable de opciones (el botón con el icono de un engranaje, que en el fondo, es el makefile).

Hay algún ejemplo en C que viene con los datasheets del AVR en cuestión, que indican cómo programar el baudrate y todo lo demás. En la web de los foros de electrónica hay un ejemplo muy bueno de comunicaciones serie con un ATmega32 que es compatible en cuanto a pines y registros con el ATmega644, y que podrías reutilizar.

Lo habitual es tener una rutina tipo void USARTInit(void) donde inicializas todos los registros de configuración que afectan al puerto serie, incluida la velocidad, las interrupciones, etc. Y luego las interrupciones de UDREmpty, RxDint, y quizás de TxDint, junto con los buffers y demás variables que se usen a tal efecto.

Algún día miraré de poner ejemplos de cómo usar los puertos serie usando las interrupciones como pseudo DMA, buffers, y ModBus, pero todo es cuestión de tiempo.

Espero haber sido de ayuda.

Responder
Página 2 / 4
Compartir: