uart problem with atmega16

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

hey ppl recently i got a new sharp ir , show i decided calibrate it by using uart , but when i got into hyperterminal but the hyperterminal window remained completely blank ..

my code is like this

# include
# include
# include
# include

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

unsigned int a;

void adcinitialize();
void uartinitialize();
void adcgetvalue();

int main()
{
adcinitialize();
uartinitialize();
while(1)
{
adcgetvalue();
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = a; // Send out the byte value in the variable "a"
while((UCSRA &(1<< UDRE))==0) {};

}

return(1);
}

void adcinitialize()
{

ADCSRA|=_BV(7)|_BV(2)|_BV(1);
ADMUX=0x60;
ADCSRA|=(1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
ADCSRA|=(1<<ADIF);
a=ADCH;

}

void uartinitialize()
{
UCSRB|=(1<<RXEN)|(1<<TXEN);
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
UBRRL=BAUD_PRESCALE;
UBRRH=(BAUD_PRESCALE>>;
}
void adcgetvalue()
{

ADMUX=0x61;
ADCSRA|=(1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
ADCSRA|=(1<<ADIF);
a=ADCH;
}

can anyone tell me whats the fault with my code , i need to know abt it as quickly as possible , oh yes my mcu is clocked at 8 mhz internal clock thanks..

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

Oh my, where to start...

I will assume you are using WinAVR and AVRStudio, given where you have posted your request.

Okay, first thing: Are you sure your CPU is clocking at 8 MHz? Write a simpler program to toggle a pin at 10 mS and then measure the pin. The most common problem with UARTs is that the CPU is not clocking at the frequency the programmer thinks it is.

#include 
#include 

int main( )
{
  DDRA = 0xFF
  PORTA = 0;
  while ( 1 )
  {
    _delay_ms(10)
    PORTA = 0xFF;
    _delay_ms(10)
    PORTA = 0x00;
  }

  return 0;
}

Consider passing the ADC value back from your adcgetvalue() routine. Using globals to pass data back and forth is not a good idea for the most part.

int adcgetvalue(void);

int adcgetvalue()
{
  int result;
  ADMUX=0x61;
  ADCSRA|=(1<<ADSC);
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA|=(1<<ADIF);
  result=ADCH;
  return result;
 }

Next, you will need to translate your ADC values into ASCII before passing it to the UART. Consider using itoa() (from ) to convert your ADC value to an ASCII value. Oh, and don't forget to add carriage return ("\r") and line feed ("\n") characters after the converted value. Look at strcat from . Or even better, store the "\r\n" string in program memory so you don't waste RAM (Read the PGMSPACE tutorial here)

I'm leaving the code writing of the above as an exercise for the student. :D

Consider folding your UART "send character" function into it's own routine, maybe UART_Tx(). It would send a single char and wait for it to be done, pretty much as your current while loop does.

Now, you will need to send the string out one character at a time. Perhaps another function, UART_Tx_Str, that accepts a pointer to a string, then a while loop:

void UART_Tx_String( char* Str )
{
  char* p = Str;
  while ( *p != "\0" )
  {
    UART_Tx( *p );
  }
}

This should get you started.

Stu

EDIT 1: Didn't notice the topic header - removed the whining about not giving the processor ID.

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

thanks a lot ill rectify my code and see if it works and yes i have tested that my clock is at 8 mhz

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

like u said i changed my code but still iam getting the same thing , a blank hyperterminal screen

plzz rectify me once more

# include
# include

# include
# include
# include
# include
# include



#define USART_BAUDRATE 38400 
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL)))- 1) 


 char u[11]="adcvalue\r\n";
 char *d;
 char b[10];
 char *p;
 
 unsigned int a;

void adcinitialize();
void uartinitialize();
void adcgetvalue();
void transferusart();
void printvalue(char *);

 int main(void)
  {
   adcinitialize();
   uartinitialize();
   while(1)
    {
	 adcgetvalue();
	 
      
	 p=itoa(a,b,10);
	 
	 strcat_P(b,PSTR("\r\n"));
	 
	 d=&u[0];
	 
	 transferusart();
	 
     
     }       
   
	 
   return(0);	 
   }
 
 
 
 void adcinitialize()
  {
   
  ADCSRA|=_BV(7)|_BV(ADPS2)|_BV(ADPS1);
  ADMUX=0x60;
  ADCSRA|=(1<<ADSC);
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA|=(1<<ADIF);
  a=ADCH;
 
  }
  
  void uartinitialize()
   {
    UCSRB|= (1<<RXEN) | (1<<TXEN);
    UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
    UBRRL=BAUD_PRESCALE;
	UBRRH=(BAUD_PRESCALE>>8);
   } 
void adcgetvalue()
 {
  
   ADMUX=0x61;
   ADCSRA|=(1<<ADSC);
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA|=(1<<ADIF);
  a=ADCH;
 }
 
void transferusart()
 {
    
   while (*d != '\0') 
    {
	 
     while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 
      UDR =*d ; // Echo back the received byte back to the computer 
      d++;
	 }
 printvalue(p);
 }
 
 void printvalue(char *l)
  {
   while (pgm_read_byte(l) != 0x00)
    {
	  
	 
	  while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 
      UDR =*l ; // Echo back the received byte back to the computer 
      
     
     l++;
    }
  } 
 

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

Why are you doing a pgm_read_byte(l) when l is in RAM???

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

so wat do i do i mean if i dont use the pgm then how do i use it??

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

check the uart initialization in simulation once
check the hardware connections of serial port on pc
short the rx tx on serial connector and see if data is echoing on the hyper terminal

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

i have done all that i could u tell me whats the problem

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

Quote:
so wat do i do i mean if i dont use the pgm then how do i use it??

   while (pgm_read_byte(l) != 0x00) 

should be

   while (*l != 0x00) 

or

   while (*l) 

which is the same.

Also, I have to agree with Stu, you should really try to avoid passing values in globals like that - the program becomes unreadable.
/Lars

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

Have you read the beginner's UART tutorial?
[TUT] [SOFT] Using the USART - Serial communications
Have you tried some of the examples? It may answer a lot of your questions.

So, you've checked the CPU frequency. Good. Now let's do the next simple step.

We're going to send "U" on the UART forever:

# include
# include

#define USART_BAUDRATE 38400 
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL)))- 1) 

void uartinitialize();

int main(void)
{
   uartinitialize();
   while(1)
   {
      /* Wait for UART ready to transmit */
      while ((UCSRA & (1 << UDRE)) == 0) {};
      /* Send the byte */
      UDR = 'U' ; 
   }       
 
   return(0);	 
}
 
void uartinitialize()
{
    UCSRB = (1<<RXEN) | (1<<TXEN);
    UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
    UBRRL = BAUD_PRESCALE;
    UBRRH = (BAUD_PRESCALE>>8);
} 

Note that I have removed your "Or" functions in the uartinitialize() function -- it's safer when initializing to force all the bits rather than relying on the CPU to initialize the "undesired" bits to 0.

Use a scope to look at the UART output -- the capital U will form a square wave with the pulse width equal to the baud rate. We use this to confirm two things: first, that you really are sending data out, and second that it is at the rate you expect.

You can now make sure that hyperterminal is receiving an unending string of "U". If it does not, you have a problem between the ATmega16 and your PC. Check to be sure that the proper signals are tied to your RS232 converter (you *do* have an RS-232 converter, don't you? :wink: ) and that the PC is set up correctly to receive them.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

yes i have proper rs232 converter done according to the schematic of the usart tutorial well i iam using a usb to serial converter is that the problem??

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

thank u all for helping me i finally got the uart to work , the final code is like this

# include
# include

# include
# include
# include
# include
# include



#define USART_BAUDRATE 38400 
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL)))- 1) 


 char u[11]="adcvalue\r\n";
 char *d;
 char b[10];
 char *p;
 
 unsigned int a;

void adcinitialize();
void uartinitialize();
void adcgetvalue();
void transferusart();
void printvalue(char *);

 int main(void)
  {
   adcinitialize();
   uartinitialize();
   while(1)
    {
	 adcgetvalue();
	 
      
	 p=itoa(a,b,10);
	 
	 strcat_P(b,PSTR("\r\n"));
	 
	 d=&u[0];
	 
	 transferusart();
	 
     
     }       
   
	 
   return(0);	 
   }
 
 
 
 void adcinitialize()
  {
   
  ADCSRA|=_BV(7)|_BV(ADPS2)|_BV(ADPS1);
  ADMUX=0x60;
  ADCSRA|=(1<<ADSC);
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA|=(1<<ADIF);
  TCCR1B|=(1<<CS12);
 
  }
  
  void uartinitialize()
   {
    UCSRB= (1<<RXEN) | (1<<TXEN);
    UCSRC= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
    UBRRL=BAUD_PRESCALE;
	UBRRH=(BAUD_PRESCALE>>8);
   } 
void adcgetvalue()
 {
  
   ADMUX=0x61;
   ADCSRA|=(1<<ADSC);
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA|=(1<<ADIF);
  a=ADCH;
 }
 
void transferusart()
 {
    
   while (*d != '\0') 
    {
	 
     while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 
      UDR =*d ; // Echo back the received byte back to the computer 
      d++;
	 }
	 TCNT1=0;
	 while(TCNT1<=60000){};
	 TCNT1=0;
 printvalue(p);
 }
 
 void printvalue(char *l)
  {
   
   while (*l != 0x00)
    {
	  
	 
	  while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 
      UDR =*l ; // Echo back the received byte back to the computer 
      
     
     l++;
    }
	TCNT1=0;
	 while(TCNT1<=60000){};
	 TCNT1=0;
  } 
 

   

i added the little timer delay for smooth readings to come on the hyperterminal and from nest time ill make sure that i wont us globals very much....

i was wondering though , my friend told me that if i would have used interrupts , this much problem would not have been there, but i have no idea how interrupts work.

can anyone tell me how interrupts make my life easy in uart, adc etc etc etc

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

Quote:
can anyone tell me how interrupts make my life easy in uart, adc etc etc etc

Even I would like to view the postings from here onwards.

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

that is if the experts reply

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

anmol2701 wrote:
Quote:
can anyone tell me how interrupts make my life easy in uart, adc etc etc etc

Even I would like to view the postings from here onwards.

*sigh :roll: "Please explain, in simple terms, the inner workings of quantum chromodynamics and their effects on the macro world." I'm sorry, but while interrupts can allow your processor to handle many tasks at once, I would not describe their use as "making one's life easy".

What is an interrupt? Simply put, it is an event that tells the processor to stop what it is doing and to go execute a specific instruction, called an "interrupt vector". The event can be externally generated (for example, a change of state on a pin), or internally generated (for example, the overflow of a timer or the receipt of a character in a UART).

Each kind of interrupt has a specific instruction (the "interrupt vector") in what is called the "interrupt vector table". With GCC (and most other compilers), the "interrupt vector" instruction is a jump to the Interrupt Service Routine, or ISR, for that interrupt.

If you will read your device's datasheet, you will find a list of the vectors for your device. Since these vector lists are processor specific, the compiler must know which device it is compiling for so it knows which vector list to use when it sets up the vector table.

The "interrupt vector table" is stored starting at location 0 in Flash. The instruction for each vector is 2 words (4 bytes), so the instruction for vector 0 is stored starting at location 0 (byte 0), vector 1 is stored at location 2 (byte 4), and so on. A second interrupt vector table can be set up for bootloaders in most (all?) AVR processors, but I won't go into that further here.

So, when an interrupt occurs, the following things happen:

1 - the CPU pushes the current program counter (PC) on the stack.
2 - the global interrupt enable flag is cleared (interrupts are disabled).
3 - the CPU fetches and executes the instruction from the interrupt vector table that corresponds to the interrupt the CPU received.

The ISR does what is needed as a result of the interrupt. For example, if the UART has interrupted the processor to say that it has received a character, the ISR handling that interrupt should save the character in a buffer and return. In general, an ISR should do only the bare minimum needed to service the interrupt.

(A common mistake for newbies is to throw a printf into the ISR handling, say, the A/D converter. Their first problem: "My program resets when handling a sample from the ADC (reason: they aren't paying attention to how much stack is used). Their second problem: "Why am I missing samples?" (reason: the CPU is busy formatting the sample) )

When the ISR is complete, it executes a special return instruction, RETI, that pulls the PC from the stack and re-sets the global interrupt flag (enables interrupts). The AVR will always execute at least one instruction after returning from an interrupt before it will service another interrupt.

One other item. In other processors there is a concept of "interrupt priority". In other words, it is possible in those processors to interrupt an already executing ISR if the interrupt is of "higher priority" than the interrupt being handled. The AVR does not have this concept. The closest it comes to this is that if two or more interrupts are pending, the AVR will execute the lowest numbered vector first. That order cannot be changed.

So, in terms of UARTs and making one's life easy, interrupts are a double-edged sword. You have introduced more code, new programming concepts (buffers, interrupt enabling), and the possibility that any code in your main program may be interrupted at any time. On the other hand, you can now isolate the code dedicated to serial I/O into one place.

As to how to get started, I guess I would start with the tutorials. Here's one on using interrupts with Serial I/O (UARTs):

[TUT] [SOFT] Using the USART - Interrupt driven serial comms

And here's an introduction to the A/D Converter, which has a section on using interrupts with the ADC:

[TUT] [C] Newbie's Guide to the AVR ADC

This is a very quick introduction. For more, you really need to be more specific with the problem you want to solve.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

Thanks a lot for all the help u have given . You really rock sir