Problemas con encoder y serial AVR ATMEGA168-20MHz

hola a todos

tengo problemas para mostrar los datos por serial cuando uso interrupciones para leer los encoder.

uso atmega160-20MHz y los motores EMG30 (aprox. 170RPM). el algoritmo es simple solo cuenta los encodes y si es mayor a 90 regresa y si es menor de -90 cambia su sentido de giro.

los datos por serial los muestro en el hyperterminal, y en un inicio sale todo ok, pero luego de un rato, me muestra caracteres basura (adjunto imagen).

- uso proteus + com virtual para simularlo en la PC y me sale el error que les explico.
- lo implemento en fisico y me muestra el mismo error. Entonces no es cuestrio de simulacion, pienso que le falta algo al codigo pero no se que es.

agradesco mucho su respuesta...

Código:
// atmega168
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include <stdlib.h> //strtol atoi abs labs
#include <stdio.h> //printf()

#define sbi(var, mask) ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask) ((var) &= (uint8_t)~(1 << mask))

#define FORWARD1()		cbi(PORTD, 3); sbi(PORTD, 2) 
#define BACKWARD1() 	cbi(PORTD, 2); sbi(PORTD, 3)
#define FORWARD2() 		cbi(PORTD, 7); sbi(PORTD, 4)
#define BACKWARD2() 	cbi(PORTD, 4); sbi(PORTD, 7)

void init_usart0(unsigned int baud)
{
	UBRR0 = (unsigned int)(F_CPU/16/baud-1); 	// Set Baudrate
    UCSR0C = 3 << UCSZ00;               		// Character Size 8 bit
    UCSR0B |= _BV(RXEN0) | _BV(TXEN0);  		// Receiver and Transmitter Enable
}

static int uart_putchar(char c, FILE *stream)
    {
      if (c == '\n') uart_putchar('\r', stream);
      loop_until_bit_is_set(UCSR0A, UDRE0);
      UDR0 = c;
      return 0;
    }

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,_FDEV_SETUP_WRITE);

volatile int count_m1 = 0;					//contador de Motor1
volatile int count_m2 = 0;					//contador de Motor1

volatile unsigned char last_cha1;		//ultimo estado del CHA
volatile unsigned char last_chb1;		//ultimo estado del CHB
volatile unsigned char last_cha2;		//ultimo estado del CHA
volatile unsigned char last_chb2;		//ultimo estado del CHB

void config_init(void)
{
	init_usart0(9600);			// Inicio del USART0
	stdout = &mystdout; 		// Configura printf con usart_putchar

	DDRB |= 1 << DDB5; 			// Led Green placa Down

	// Encoder de M1 y M2
	DDRC &= ~( 1 << DDC0 | 1 << DDC1 );		// INPUT CHB1:A1
	DDRC &= ~( 1 << DDC2 | 1 << DDC3 ); 	// INPUT CHB2:A2
	PORTC |= 1 << PC0 | 1 << PC1;     		// Res Pull-Up CHB1:A1
	PORTC |= 1 << PC2 | 1 << PC3;     		// Res Pull-Up CHB2:A2
	
	// Control de Motores M1 M2
	DDRD |= 1 << DDD2 | 1 << DDD3;			// OUTPUT SM11:12
	DDRD |= 1 << DDD4 | 1 << DDD7; 			// OUTPUT SM21:22

	// PWM M1(OCR0A) y M2(OCR0B)
	DDRD |= 1 << DDD6 | 1 << DDD5;			// OUTPUT OCR0A:B D6:5

	// Tipo de onda
	TCCR0A |= 1 << WGM01 | 1 << WGM00;		// Mode Fast PWM
	TCCR0B |= 0 << WGM02;     				// Mode Fast PWM
	
	// Compare Match Output A:B Mode
	TCCR0A |= 1 << COM0A1 | 0 << COM0A0;     // Set OC0A on Compare Match (normal)
	TCCR0A |= 1 << COM0B1 | 0 << COM0B0;     // Set OC0B on Compare Match (normal)

	// Pre-Escaler Clk_pwm = F_CPU/pre-escaler = 0.305 KHz
	TCCR0B |= 1 << CS02 | 0 << CS01 | 0 << CS00;		// pre-escaler = 256


	// Duty de PMW M1 y M2
	OCR0A = 0;
	OCR0B = 0;

	DDRB |= 0 << DDB0;			// INPUT Start Down
	PORTB |= 1 << PB0; 			// Res Pull-Up Start Down

	// PCINT para encoder CHA1:B1 PCINT8:9 CHA2:B2 PCINT10:11
	PCICR |= 1 << PCIE1; 		// Habilita PCINT1_vect -> PCINT14:8 (PC6:0)
	PCMSK1 |= 0x0F;				// Habilita cada PCINT11:8

	last_cha1 = (PINC >> 1) & 1; 	//PC1
	last_chb1 = (PINC >> 0) & 1; 	//PC0
	
	last_cha2 = (PINC >> 3) & 1; 	//PC3
	last_chb2 = (PINC >> 2) & 1; 	//PC2

	// Borra los Flag de los PCINTx, en caso fueran
	// antepuestas por cualquier razon
	PCIFR |= 1 << PCIF1;
	
	sei();
}


ISR(PCINT1_vect)
{
	 unsigned char cha1 = (PINC >> 1) & 1; 	//PC1
	 unsigned char chb1 = (PINC >> 0) & 1; 	//PC0

	 unsigned char cha2 = (PINC >> 3) & 1; 	//PC3
	 unsigned char chb2 = (PINC >> 2) & 1; 	//PC2

	// CHA = 0 and CHB = 1
	
	// MOTOR 1
	if (cha1 != last_cha1)
		{
			last_cha1 = cha1;
			if ((last_cha1 == last_chb1) ^ 0) count_m1 -=1;
			else count_m1 +=1;
		}

	if (chb1 != last_chb1)
		{
			last_chb1 = chb1;
			if ((last_cha1 == last_chb1) ^ 1) count_m1 -=1;
			else count_m1 +=1;
		}

	// MOTOR 2
	if (cha2 != last_cha2)
		{
			last_cha2 = cha2;
			if ((last_cha2 == last_chb2) ^ 0) count_m2 -=1;
			else count_m2 +=1;
		}

	if (chb2 != last_chb2)
		{
			last_chb2 = chb2;
			if ((last_cha2 == last_chb2) ^ 1) count_m2 -=1;
			else count_m2 +=1;
		}
}


int main (void)
{
	config_init();			// Configuracion de puertos

 	while(PINB & (1<<PINB0)) {_delay_ms(10);} 	// Button

	OCR0A = 80;
	OCR0B = 80;

	FORWARD1();
	FORWARD2();
	
	sei();

	PORTB = (1 << PB5); 	// Led green On

	while (1) {


		if (count_m1 < -90) 
				{
					FORWARD1();
				}
		else if (count_m1 > 90)
				{
					
					BACKWARD1();
				}
	
		// Motor 2
		if (count_m2 < -90) 
				{
					
					FORWARD2();
				}
		else if (count_m2 > 90)
				{
					
					BACKWARD2();
				}
	
     	printf("\n%d, %d",count_m1, count_m2);
		_delay_ms(10);

	}

	return 0;
}

Imagen
http://imageshack.us/f/651/errorserial.jpg/
 
cristian_elect, muy cierto ... pero tambien intente desactivar al momento de enviar los caracteres con cli() y volverlo a activarlo con sei() dentro del static int uart_putchar(char c, FILE *stream). Pero aun asi me muestran. tambien he intentado hacer la transmision por interrupcion pero nada...

gracias por tu ayuda
 
Atrás
Arriba