[AVR] ATMega88 and ATMega168 with USART interrupts

Status
Not open for further replies.

bignoob

Newbie level 2
Joined
Aug 18, 2014
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
21
Hello,
I had used USART interrupts on ATMega88 to handle sending data from PC to uC so that data can be transmitted using nRF24L01... Something like virtual serial bridge between 2 PCs. But than i had to switch on one side from ATMega88 to ATMega168 and than problem started...

Baud rate is set on both uC and it's the same.

Usart init:
Code:
        unsigned int USART_BAUDRATE = 9600;		
	unsigned int ubrr = (((F_CPU / (USART_BAUDRATE * 16UL))) - 1);	
	
	UBRR0H = (unsigned char)(ubrr>>8);
	UBRR0L = (unsigned char)ubrr;
	
	UCSR0B = (1<<RXEN0)|(1<<TXEN0);
 
	UCSR0C = (1<<USBS0)|(3<<UCSZ00);


Also i have enabled usart interrupt:
Code:
	UCSR0B |= (1<<RXCIE0);


Basically, i just now need to echo back to terminal chars that came from terminal just to debug it... (since nRF module don't send anything... )
Code:
ISR(USART_RX_vect)
{
	uint8_t W_buffer[8];
	
	int i;
	for (i=0;i<8;i++)
	{
		W_buffer[i]=usart_receive();	
		usart_transmit(W_buffer[i]);			
	}	
	
	usart_transmit('#');	
 }


void usart_transmit(uint8_t data)
{
	while ( !( UCSR0A & (1<<UDRE0)) );
	UDR0 = data;
}

uint8_t usart_receive( void )
{
	return UDR0; 
}

Here's where problem occurs... When I enter anything in terminal it goes crazy... Starts printing some symbols all the time (blinking dash goes left to right all the time in the same line...)

I have tried to print out anything when interrupt is handled.. first line in ISR just say "entered"... but that never happens ? i switch back to atmega88 and everything works just fine?!?

Could anyone have a idea what could be the issue ? I feel i just go round and round in circles....
 

Hi,

It's a bad idea to hang inside the receiver routine and to transmit. The right solution is - once you receive a symbol you enter the ISR and then you put all received characters into circular FIFO. In the main level code you check if the FIFO is non empty and if so you transmit the data from main code level. Right now your latency time is extremely high - you have to wait until all data was transmitted. Other issue - if you receive one symbol you transmit 8 symbols (you have loop for 8 transmission).
 

oh god! what a code, don't mix polling and interrupt methods...

as @luben111 said , implement a circular FIFO

Code:
#define DATA_LIMIT 100 //for example, check your available RAM

volatile char rx_data[DATA_LIMIT]; //buffer
volatile unsigned int drc=0; //rx fill pointer
volatile unsigned int dsc=0; //rx read pointer

ISR(USART0_RX_vect){
	char data;
	//RXC0 got 1, recieved data
	data=UDR0;
	rx_data[drc++]=(data);
	if (drc>=(DATA_LIMIT))drc=0;
}

uint8_t usart_receive( void ){
	char data;
	while(drc==dsc); //wait for data if there isn't data in buffer
	data=rx_data[dsc++];
	if (dsc>=(DATA_LIMIT))dsc=0;
	return data; 
}
//you don't like to wait for data? ask first!
uint8_t usart_kbhit( void ){
	return (drc!=dsc); 
}

... and some where in your main program (after your init)...


	uint8_t W_buffer[8];
	
	int i;
	for (i=0;i<8;i++)
	{
		W_buffer[i]=usart_receive();	//should wait for characters?
		usart_transmit(W_buffer[i]);			
	}		
	usart_transmit('#'); //will be send after 8 receives???

I like your usart_transmit() IF and only IF you need to transmit a few characters, not too much... not too frequently...
(like in this echo case that you transmit for each timed receive)

you want a simple echo?

Code:
int main(void){
 char d;
 init(); //init everything here
 while(1){
  d=usart_receive(); //to work with?
  usart_transmit(d);
 }
}

for your nRF I suggest you to check http://kehribar.me/hardware/nrf24_node/ and http://github.com/kehribar/nrf24L01_plus this library worked for me at the first shot...
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…