[DIS] - Interrupts Conflict USART and TIMER1

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 

I'm a newbie in this world, but i have to be able to code as well as i can. Need a lot to become familiar with this, so i'm asking if somebody can help me with this trouble. 

First of all, this is a simple code that i want to optimize with the minimum mods to it. As it has been working already in the first step.

The first step - i had created routines and function calls to send and receive data by USART. And it is all working good, after a few days learning and testing and correcting... whatever. It's running.
The second step is my simple (BUT BIG PROBLEM)- I need to toggle a led each second. For that i use timer interruptions each second. So far so good. And it works too. (Right now you must be laughing of me)smiley
My problem is...
(Oh i forgot. I'm using Atmega328P)
When i only use the function calls in the first step - All communications are OK. I can communicate with Terminal, Send and receive it's all good.
But when i use the timer interrupts - and for that i use the "sei" instruction as it need to be (i think) - the toggling on PINB0 is Ok but the communications fail.

If i comment out the "sei();" instruction - the communications are Ok but no toggling (sure... the global interrupts aren't enabled).

So... Can anyone help me? I've seen something like this trouble in the forum but was with another XMega and don't work with my ATMEGA328P.

I will post the code here...
 

#define	F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include "bit_tools.h"

#define USART_BAUDRATE 250000		// Define usart baud rate
#define MYUBRRN	((F_CPU/(USART_BAUDRATE<<4))-1) //define UBRR(usart baud rate register) as UBRRN=11 has i had calculated

// prototipes

void initUsart (uint16_t MY_UBBR);
void sendChar (uint8_t data);
void sendString ( char *data);
void configTimer1();

//////////////////////////////////
//Function :  Config the timer
//////////////////////////////////// 
void configTimer1()
{

TCCR1B	|=	(1<<WGM12); // CTC Mode

TIMSK1	=	(1<<OCIE1A); // Enable Timer 1 Interrupt

OCR1A	=	31249; // Load Value calculated to have 1 second / Prescaler = 256 @ 8Mhz

TCCR1B	|=	(1<<CS12);   // Set Prescaler @ 256

}




//////////////////////////////////
//Function :  Config the usart baudrate
//////////////////////////////////// 
void initUsart(uint16_t MY_UBBR) // NOTE: THE ARGUMENTS CANNOT BE EQUAL TO MACROS!!!!
{											
	//cli(); 					//Disable Global Interrupts to config USART
	UBRR0H	=	(unsigned char )(MY_UBBR>>8);	//LOAD UPPER-8 BITS OF UBRR VALUE in register High 
	UBRR0L	=	(unsigned char )MY_UBBR;	//LOAD LOWER-8 BITS OF UBRR VALUE IN REGISTER LOW
	
	UCSR0B	=	(1<<TXEN0) | (1<<RXEN0)|(1<<UDRIE0);//ENABLE TX, RX AND DATA REGISTER EMPTY ENABLE INTERRUPT USART REGISTER 0 TO TRANSMIT AND RECEIVE DATA
	UCSR0C  = (1<<UCSZ01)|(1<<UCSZ00);		    //SETTING THE NUMBER OF DATA BITS (8)
								
	//UCSR0B	|=	(1<<RXCIE0);		    //ENABLE USART RECEIVE COMPLETE INTERRUPT
}



//////////////////////////////////
//Function :  send char to the usart
////////////////////////////////////
 
void sendChar(uint8_t data)
{	
	while ( ( UCSR0A & (1<<UDRE0))==0 );		// DO NOTHING UNTIL UDR BECOME READY TO RECEIVE DATA
	
	UDR0	=	data;				//RECEIVING DATA FROM THE VARIABLE TO UDR0 AND SEND VIA USART TX
}



////////////////////////////////////
//Function :  write string to the usart
////////////////////////////////////
 
void sendString(char *data)
{
int len, i;

		len = strlen(data);		//STORE THE ARRAY SIZE IN VARIABLE (LEN)
		for (i=0; i<len; i++){		// FOR CYCLE FROM BEGINNING OF CHAR ARRAY TILL THE END (LEN VALUE)
			if(data[i]=='\0')	//CHECK EMPTY DATA INSIDE CHAR ARRAY 
			{
				return;
			}
			else
			{	
				sendChar(*(data+i));	//CALL FUNCTION AND SEND CHAR IN THAT POSITION
			}
		}
		
	//while(*data !=0x00){
	//	sendChar(*data);
	//	data++;
	//}
}
	
uint8_t read_char(void)
{
char buffer[50]={0};			//STARTING EMPTY ARRAY ={0}
int i=0;

	for(i=0;i<49;i++)		//RUNNING ARRAY POSITIONS
	{	
		while ( !(UCSR0A & (1<<RXC0)) );	//WAIT TILL BUFFER BE READY TO RECEIVE DATA
			buffer[i]	=	UDR0;	// READ STRING VIA RX, CHAR BY CHAR
			
			if (buffer[i]=='\b')		//CHECK BACKSPACE KEY
				
				buffer[i]='\b';		//ERASE LAST VALUE
							
			if(buffer[i]=='\r')		//CHECK ENTER KEY
			{	
				sendString("\rO nome inserido foi :\r");	//CALL FUNCTION AND SEND STRING VIA TX
				sendString(buffer);				//CALL FUNTION AND SEND THE "buffer" DATA 
				return;										
			}
			
				sendChar(buffer[i]);				//PRINT CHAR BY CHAR "REAL TIME" AS IT'S PRESSED ON KEYBOARD
	}					
			sendString("\rcaracteres a mais\r");			// PRINT STRING IF OVERCOME 49 ARRAY POSITIONS
			sendString(buffer);					//PRINT ALL THE DATA IN THE "buffer" THAT HAS BEEN INSERTED (THE 50 CHARS)
}
	
	
ISR(TIMER1_COMPA_vect)
{
	PORTB ^=(1<<PINB0);//Toggle PINB0
}
	
////////////////////////////////////
//Function :  main cycle
////////////////////////////////////
 
int main(void)
{
char nome[] ="Nelson Macieira";


	DDRB	|=	(1<<PINB0);		// DEFINE PINB0 AS OUTPUT
	CLKPR	=	(1<<CLKPCE);	        // PREPARING PRESCALER TO EDITION
	CLKPR	=	(0);			// EDITING PRESCALER TO 0, F_CPU=8000000/1
	configTimer1();
	
	initUsart(MYUBRRN); 
	sei(); //Enable all activated interruptions
	while(1)
	{
		sendString("\r\n");
		sendString(nome);
		sendString("\r\n");
		sendString("Insira um nome\r\n");
		read_char();
	}
	
}

Any help will be appreciated... ;)

Last Edited: Thu. Feb 19, 2015 - 04:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have chosen a rather unrealistic baudrate.   Unless you are a very swift typist !

 

You must have an ISR() for every interrupt that you enable.   You have enabled UDRIE.

 

Your sendchar() function is a polled function.

And quite honestly,  you might just as well use polling for your getchar() function too.  i.e. forget about USART interrupts completely.

 

I suggest that you use = rather than |= when initialising Special Function Registers.   i.e. set/clear all the bits in one go.

Only use |= when you know what the other bits are.

 

Good Luck.

 

David.

 

David.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But when i use the timer interrupts - and for that i use the "sei" instruction as it need to be (i think) - the toggling on PINB0 is Ok but the communications fail.

If i comment out the "sei();" instruction - the communications are Ok but no toggling (sure... the global interrupts aren't enabled).

So... Can anyone help me?

	UCSR0B	=	(1<<TXEN0) | (1<<RXEN0)|(1<<UDRIE0);//ENABLE TX, RX AND DATA REGISTER EMPTY ENABLE INTERRUPT USART REGISTER 0 TO TRANSMIT AND RECEIVE DATA

 

You have enabled an interrupt source for which there is no ISR.

 

In addition, UDRE fires continually when there is an available buffer slot in the USART.  It should only be enabled during buffered multi-byte output and disabled otherwise.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. Feb 19, 2015 - 04:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys, thanks a lot for your prompt replys, i had commented out the UDRIE0 and it is working great.
I'm a newbie and all help is very apreciated. 
Thanks once more for helping me. 
The Usart interrupt was messing it all.
It's working now. But i have one question, why was the code running good before i place the toggling led. In my step 1 "lesson" the micro was communicating with terminal, and then i place the led and activate timer 1 to toggle it ( and the interrupt) and then i only have a toggling led and no communications. If "sei()" commented out i have communications but no toggling led. The last part i think i understand, i can't have an interrupt if i don't set it. But why the conflict? 
Just to understand...
Thanks ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the SEI() is not present,   the UDRIE will never fire.    So your polled sendChar() will work just fine.

 

If SEI() is there,   the UDRIE interrupt will fire constantly and have nowhere to go to.    So it will reset the AVR.

 

David.

 

Edit.   Please could a Moderator lock one of these 'identical' threads.    Or perhaps the OP can post a message to "close" comments on one of the threads.

 

Edit again.   It appears that it is a single thread but shows up twice in "recent messages"

Last Edited: Thu. Feb 19, 2015 - 09:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the explanation David.

 

Great forum, great people, i'll be a pro.... some day :)
Thanks a lot for contributing to my learning. I which i can do whatever i want with AVR's. I know i will have a lot of projects to work on. 

By now, i'm just a newbie coding.

Last Edited: Thu. Feb 19, 2015 - 11:24 PM