Atmega8 usart interfering w/ i/o ports

Hi, I’ve been wrestling with this problem for a couple of days now. Can anyone help me with this.

I want to program my atmega8 to read in a byte from serial and and then set certain pins to go high. I’ve used the usart example from http://booksbybibin.14.forumer.com/viewtopic.php?t=119 . The problem is that if I set n number of pins, only the last pin set will be high, the other pins will go high for just one moment then they go low. For example, if I read in an ‘a’ I want to set pd2, pd3, pd4 to go high but only pd4 goes high. Below is sample of my code:

#include <avr/io.h>

/* Function prototypes */

void InitUART( unsigned char baudrate );

unsigned char ReceiveByte( void );

void TransmitByte( unsigned char data );

/* Main */

int main(void) {

unsigned char cmd;

DDRD = ( 1 << PD2 ) | ( 1 << PD3 ) // PD2 - PD6 = red leds

| ( 1 << PD4 ) | ( 1 << PD5 )

| ( 1 << PD6 );

InitUART( 25 ); /* Set the baudrate to 2400 bps using a 1MHz crystal */

while(1) {

cmd = ReceiveByte();

TransmitByte(cmd);

PORTD = ( 1 << PD2);

PORTD = ( 1 << PD3);

PORTD = ( 1 << PD4);

}

}

/* Initialize usart */

void InitUART( unsigned char baudrate ) {

UBRRL = baudrate; /* Set the baud rate */

UCSRB = (UCSRB | _BV(RXEN) | _BV(TXEN) ); /* Enable UART receiver and transmitter */

}

/* Read usart */

unsigned char ReceiveByte( void ) {

while ( !(UCSRA & (_BV(RXC))) ); /* Wait for incomming data */

return UDR;/* Return the data */

}

/* Write usart */

void TransmitByte( unsigned char data ) {

while ( !(UCSRA & (_BV(UDRE))) ); /* Wait for empty transmit buffer */

UDR = data; /* Start transmittion */

}

The pins on port d are connected to leds. It doesn’t matter how I change the order of the pins, only the last one in the code stays on. I can see the other flashed on for a moment. I’d really appreciate if someone can help with this. Thanks.

Jimmy

jaytee0108:
Hi, I’ve been wrestling with this problem for a couple of days now. Can anyone help me with this.

I want to program my atmega8 to read in a byte from serial and and then set certain pins to go high.

#include <avr/io.h> 

/* Function prototypes */
void InitUART( unsigned char baudrate );
unsigned char ReceiveByte( void );
void TransmitByte( unsigned char data );

/* Main */
int main(void) {

unsigned char cmd;
DDRD = ( 1 << PD2 ) | ( 1 << PD3 )       // PD2 - PD6 = red leds
     | ( 1 << PD4 ) | ( 1 << PD5 )
     | ( 1 << PD6 );
	 
InitUART( 25 ); /* Set the baudrate to 2400 bps using a 1MHz crystal */

}

/* Initialize usart /
void InitUART( unsigned char baudrate ) {
UBRRL = baudrate; /
Set the baud rate /
UCSRB = (UCSRB | _BV(RXEN) | _BV(TXEN) ); /
Enable UART receiver and transmitter /
}
/
Read usart /
unsigned char ReceiveByte( void ) {
while ( !(UCSRA & (_BV(RXC))) ); /
Wait for incomming data /
return UDR;/
Return the data */
}

/* Write usart /
void TransmitByte( unsigned char data ) {
while ( !(UCSRA & (_BV(UDRE))) ); /
Wait for empty transmit buffer /
UDR = data; /
Start transmittion */
}




Happy to help...

Looks like you are using an older version of winAVR. The macro _BV has been omitted lately. Not sure where PD1 et al are define. I assume they are bit numbers, like 0 = bit 0, 1 = bit 1 etc. 



Anyway...



If you want to copy the received byte to the port with the LEDs, you could




while(1) {
cmd = ReceiveByte();
PORTD = cmd; // just copy incoming (ASCII?) byte to port
PORTD = ~cmd; // use this depending on how the LEDs are wired
TransmitByte(cmd);
}




Or (forgive me if you know this already)




switch (cmd)  {  // decode what char just came in
   case 'a'  : 
     PORTD ^=  (1 << PD1);  // toggle this LED
     break;
   case 'b' :
     PORTD |=  (1 << PD2);  // change this out bit to a 1
     break;
   case 'c' :
     PORTD &=  ~(1 << PD2);  // change this LED to a 0
     break;
}


and so forth, depending on what you want to do.



I also suppose you know about avrfreaks.net - forums and hundreds of sample programs.



cheers - ask again if more questions

jaytee0108:

PORTD = ( 1 << PD2);

PORTD = ( 1 << PD3);
PORTD = ( 1 << PD4);

I could be wrong, but this looks like you’re basically setting, then immediately clearing PD2 and PD3 here. Instead, you could try:

PORTD = ( 1 << PD2);
PORTD |= ( 1 << PD3);
PORTD |= ( 1 << PD4);

Hope this helps.

I think roach is right.

When you assign to PORTD, you’re setting the values of all of the PORTD pins. Normally you would bitwise-OR together the values for each pin. Anything you don’t set to 1 will be set to 0.

PORTD = (1 << PD2) | (1 << PD3) | (1 < PD4)

Or you culd use C’s read-modify-write operator, like roach posts.