ATMEGA 32A UART Question

Go To Last Post
57 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I hope someone can help this frustrated newbie to correct my simple UART application.

I have an LCD that communicates at 2400 Baud to accept commands and characters serially. I have written (and borrowed) the code below that is supposed to set up the UART in the 32A and then allow the sending of data (I am not interested in receiving data right now).

The data sheet for the LCD indicates that a character 254 or FE is the prefix to a command being sent and that  1  is the command to clear the screen. (when the 254 is NOT sent then what is sent is a character to show on the LCD). I am communicating  at 8,n,1 2400 baud with an external 16MHz crystal with fuses correctly set. I am using Atmel Studio with usbtiny.

 

I wonder if someone could point out my errors in the program since nothing happens on the LCD when this is executed.  Many thanks.

 

#include <avr/io.h>

#define F_CPU 16000000UL                    // set the CPU clock

#include <util/delay.h>

#define BAUD 2400UL                           // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)    // set baudrate value for UBRR

 

// function to initialize UART
void uart_init (void)
{
    UBRRH=(unsigned char)(BAUDRATE>>8);
    UBRRL=(unsigned char)BAUDRATE;                         //set baud rate
    UCSRB|=(1<<TXEN);   ///|(1<<RXEN);             //enable receiver and transmitter
    UCSRC|=(1<<URSEL);   //1 to write to UCSRC
    UCSRC|=(1<<UCSZ0)|(1<<UCSZ1);  //8 bit words
    UCSRC&= ~(1<<UPM1)|~(1<<UPM0);  //No Parity       THESE THREE STEPS PROBABLY NOT NEEDED
    UCSRC&=~(1<<UMSEL);    //Asynch mode
    UCSRC&=~(1<<USBS);     //= = 1 stop bit
    
    _delay_ms(1000);
}

 

 // function to send data
void uart_transmit (signed int x)  //transmit a 16 bit word
{
    while (!( UCSRA & (1<<UDRE)));            // wait while register is free
    UDR = x;                // load data in the register         
}

// main function: entry point of program
int main (void)
{
    _delay_ms(1000);
    uart_init();                                     // initialize UART
    _delay_ms(1000);                     
    
    uart_transmit (0xFE);           
    uart_transmit (0b00010001);     //The second 1 should show on the cleared screen
    
    _delay_ms(5000);
    
}

David Abineri

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

Is your DIV8 fuse programmed? I don't remember if the Mega32a has that fuse

Jim

 

EDIT Mega32A does not have that fuse.

 

can you post a link to the LCD?

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Last Edited: Tue. Sep 26, 2017 - 12:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    UCSRC|=(1<<URSEL);   //1 to write to UCSRC
    UCSRC|=(1<<UCSZ0)|(1<<UCSZ1);  //8 bit words
    UCSRC&= ~(1<<UPM1)|~(1<<UPM0);  //No Parity       THESE THREE STEPS PROBABLY NOT NEEDED
    UCSRC&=~(1<<UMSEL);    //Asynch mode
    UCSRC&=~(1<<USBS);     //= = 1 stop bit

Nope, that's not the way the URSEL bit works. You are writing to UBRRH actually, and because of that the baud rate is wrong.

 

Stefan Ernst

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

The way to start with UART comms is always to get the communication working with a terminal, or a terminal emulator on a PC.

 

Only when this shows that the communication is working well should you move on to the actual application.

 

How to properly post source code: http://www.avrfreaks.net/comment...

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

sternst wrote:
Nope, that's not the way the URSEL bit works.
As Stefan says you are doing that wrong. The URSEL bit must be written at the same time as any other bits in UCSRC so if you REALLY feel the need to use UCSRC then do:

 UCSRC= (1<<URSEL) |               //1 to write to UCSRC
        (1<<UCSZ0) | (1<<UCSZ1) |  //8 bit words
        (0<<UPM1)  | (0<<UPM0)  |  //No Parity       THESE THREE STEPS PROBABLY NOT NEEDED
        (0<<UMSEL) |               //Asynch mode
        (0<<USBS);                 //= = 1 stop bit

which is now just a single write to UCSRC. The 1 bit in URSEL says "the next 7 bits are to go to UCSRC not UBRRH even though they share the same location"

 

HOWEVER! When you apply power to a mega32 the value preloaded in UCSRC is the value for 8-N-1 because that's what almost everyone always wants to use. So you might want to ditch this completely and just accept the power on default.

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

By the way:

void uart_transmit (signed int x)  //transmit a 16 bit word
{
    while (!( UCSRA & (1<<UDRE)));            // wait while register is free
    UDR = x;                // load data in the register         
}

The comment is misleading. That routine only ever transmits 8 bits because UDR is an 8 bit register and the UART can only send 1 byte at a time. Either you want:

void uart_transmit (uint8_t x)  //transmit an 8bit byte
{
    while (!( UCSRA & (1<<UDRE)));            // wait while register is free
    UDR = x;                // load data in the register         
}

or if you really want a rouinte to transmit 16 bits at a time then something like:

void uart_transmit (unsigned int x)  //transmit a 16 bit word
{
    while (!( UCSRA & (1<<UDRE)));            // wait while register is free
    UDR = x >> 8;                // send uppper 8 bits of 16
    while (!( UCSRA & (1<<UDRE)));            // wait while register is free
    UDR = x & 0xFF;              // send lower 8 bits of 16
}

I would recommend unsigned int (actually better: uint16_t) rather than signed int (UDR knows nothing about sign bits). Also you might actually choose to do this as:

void uart_transmit (uint8_t x)  //transmit an 8bit byte
{
    while (!( UCSRA & (1<<UDRE)));            // wait while register is free
    UDR = x;                // load data in the register         
}

void uart_transmit16 (uint16_t x)  //transmit a 16 bit word
{
    uart_transmit(x >> 8);
    uart_transmit(x & 0xFF);
}

In all cases whether you send high byte (>> 8) followed by low byte (& 0xFF) or the other way round needs to be your choice of whether you want to use big endian or little endian.

 

Personally I doubt you ever want to send 16 bits anyway!

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

Many thanks for this, I appreciate the help.

David Abineri

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

So is your issue resolved?

 

IF so, please mark it as such - see: http://www.avrfreaks.net/comment...

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

Unfortunately these suggestions did not fix it.  The new code is attached , I wonder if you nee any errors? 

 

Are there any worthwhile free terminal programs for Win10 that I could use to test this program?

 

Thanks again,   Dave

Attachment(s): 

David Abineri

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

RealTerm

TeraTerm

KiaTerm

Putty

......

The list goes on....

 

Jim

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

Thanks, Jim

Dave

David Abineri

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

ki0bk wrote:
KiaTerm

What's that?

 

I'm finding loads of different meanings for "KIA" - but no terminal programs

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

Sorry, i think its keaterm

 

Update: Seems that one has been dead for a while! 

 

Jim

Last Edited: Fri. Sep 29, 2017 - 08:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does anyone have any ideas about the error in the code I recently posted.  It seems correct and yet by using Putty on my PC, nothing is showing.  It is as if no data is being transmitted from the chip and I cannot see the error.  I have used printable characters like 0x41 etc and still nothing.

 

There must be an error in the code somewhere but I certainly don't see it!  Code attached.

 

Any advice?     Thanks,  Dave

Attachment(s): 

David Abineri

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

dabineri wrote:
There must be an error in the code somewhere 

​It could also be a hardware problem - broken and/or incorrect connections ...

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

clawson, Is there any chance you can look at by newly posted code?  You were very helpful previously but it is still not working.

 

Do you see the error?  It all looks correct to me but I am missing something!

 

Thanks thanks,

 

Dave

David Abineri

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

You can use your PC's sound card as an oscilloscope to measure the serial data. Google soundcard oscilloscope.
There is also some confusion as to what speed your AVR is operating at. Setting F_CPU just tells the compiler what speed you think the AVR operates at, it doesn't actually do anything to the hardware.
You can also flash a led at a given rate using the delay() functions. Any gross errors should be apparent.

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

Thanks, Kartman. I am now running at 1MHz and have flased an LED to confirm this but am not getting anything on Putty.

 

Is there an error in the code?

 

Thanks,

 

Dave

David Abineri

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

You may have more than one defect and it may not be the code. I'd be using the soundcard to look at what is being sent.
How are you getting the signal from the avr pin to putty? There's a few possibilities for error there alone.

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

I am using pin PD1 (pin15), the TXD pin. Is this correct?  It seems that nothing is being sent and I cannot see why this would be the case with this code.

 

Thanks for you help,

 

Dave

David Abineri

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

I am using pin PD1 (pin15), the TXD pin. Is this correct?

For DIP package yes but not for TQFP.

 

        uart_transmit (0xF);
	uart_transmit (0xE);
	uart_transmit (0x1);
	uart_transmit (0x65);

only one character is printable, the last one,  but the other 3 may mess up the terminal.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

Last Edited: Sun. Oct 1, 2017 - 02:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't see any PORT setup. TXD should be output.
.
MG

I don't know why I'm still doing this hobby

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

The uart takes over the ports - no need for ddr setup.

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

Kartman wrote:
The uart takes over the ports - no need for ddr setup.

My bad.
.
MG

I don't know why I'm still doing this hobby

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

js wrote:

I am using pin PD1 (pin15), the TXD pin. Is this correct?

For DIP package yes but not for TQFP.

 

        uart_transmit (0xF);
	uart_transmit (0xE);
	uart_transmit (0x1);
	uart_transmit (0x65);

only one character is printable, the last one,  but the other 3 may mess up the terminal.

 

The data sheet for the LCD indicates that a character 254 or FE is the prefix to a command being sent and that  1  is the command to clear the screen.

 

You need to send two characters to clear the screen,  0xFE and 0x01,  then give the LCD time to perform the clear screen operation, (delay at lease 100ms or more, see LCD DS)

before sending any other characters.

 

Jim

 

 

 

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

ki0bk wrote:
uart_transmit (0xF); uart_transmit (0xE);
ki0bk wrote:
The data sheet for the LCD indicates that a character 254 or FE

What would the latter 0xFE "command" have to do with your transmittal of a 0x0F byte and then a 0x0E byte?

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.

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

theusch wrote:
What would the latter 0xFE "command" have to do with your transmittal of a 0x0F byte and then a 0x0E byte?

 

The OP was sending two characters 0x0F and 0x0E when (s)he should have sent a single character 0xFE, (s)he miss-understood the value of the command byte.

 

I have a similar LCD backpack, it will display normal ASCII characters, but for special commands, they are proceeded by a command escape character (in this case 0xFE) then a command value.

so to clear the screen you send <FE><01>.....

Sparkfun lcd backpack if IRC.

 

Jim

 

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

Jim, You are correct, I am using the LCD you describe that use a prefix FE, then 1 clears the screen, and 2 positions at home and then I print a couple  of characters.

 

I see nothing happen on the screen (which is filled with characters like a capital  A  all filled in).

 

This does not seem that it should be this difficult!  What am I missing?

 

My program is attached.  Any chance you would run this o your system with your LCD?

 

Many thanks,   Dave

 

Attachment(s): 

David Abineri

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

dabineri wrote:
Thanks, Kartman. I am now running at 1MHz and have flased an LED to confirm this but am not getting anything on Putty.

First have your code work with a terminal.

Only then test with LCD.

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

Visovian wrote:

dabineri wrote:

Thanks, Kartman. I am now running at 1MHz and have flased an LED to confirm this but am not getting anything on Putty.

First have your code work with a terminal.

Errr ... PuTTY is a terminal!

 

EDIT

 

However, it is possible (likely?) that a terminal - including PuTTY - would not "show" characters outside the standard printable range - like 0xFE and 0x01

 

So you need a "terminal" or some other debug utility that will display the raw hex byte values

 

I think RealTerm can do this:

enter image description here

 

Image from https://electronics.stackexchange.com/questions/38342/capture-raw-data-in-com-port - which discusses this

 

Last Edited: Tue. Oct 3, 2017 - 07:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But OP wrote he got nothing in putty.

 

Edit:

Maybe my English is not good enough.

I wanted to say:

First try the code in a terminal and after it works, test with Lcd

 

Last Edited: Tue. Oct 3, 2017 - 07:11 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Visovian wrote:
But OP wrote he got nothing in putty

Yes - to which you replied,

First have your code work with a terminal

So I just pointed out that PuTTY is a terminal; so he is already doing what you suggested - and I suggested in #4.

 

The problem here is that he is sending non-printing characters - so he needs to use a terminal that will display the raw hex values.

 

PuTTY is not such a terminal.

 

 

 

 

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

However, it is possible (likely?) that a terminal - including PuTTY - would not "show" characters outside the standard printable range

I think to test printable chars would be enough.

I do not see why uart would transmit printable right and others wrong. 

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

Quite possibly the non-printing characters could be interpreted by PuTTY to do something like clear the screen ...

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

There is some misunderstanding here.

 

Probably I should not write "your code" but

 

"First test the uart communication with a terminal ..." (which is usualy done with printable characters) 

 

Sorry.

 

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

But, at some point, the OP is still going to need to verify that the non-printing control codes are being sent correctly.

 

So it would make sense to start using a terminal that is going to be able to do that ...

 

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

Thanks for all the comments, guys!

 

Let me clarify.

 

I have tested Putty, it does receive data from another device I have.

I have tested that I am running at 1 MHz by flashing an LED.

I am only sending printable characters now (see attached program)

I am including delays in case there is a timing issue.

Putty shows NOTHING when I run this program

 

A question.  When I connect to Putty, I am using  pin PD1 (pin15), the TXD pin, of my DIP Atmega 32A and am connecting that pin to pin 3 of a female DB9. I am also connecting ground to pin 5 of the DB9.  I am assuming that those are the only connections I need for one-way communications to Putty.

 

What am I doing wrong in this simple program?  Thanks for all the help!   Program attached.

 

Dave

Attachment(s): 

David Abineri

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

dabineri wrote:
Putty ... does receive data from another device I have.

Sounds like you have a basic problem with your setup of PuTTY and/or the PC, then.

 

What is this "other device"?

 

I have tested that I am running at 1 MHz by flashing an LED.

That will tell you that you don't have a gross error - such as a factor of 2 or more - but will not reveal smaller errors that could still mean your baud rate is too far out to work ...

 

Do you have an oscilloscope to see what's actually happening on the wires?

 

EDIT

 

Please see #4 for how to properly post source code!

 

Please post a schematic showing how you are connecting to the PC - again, see #4 for instructions .

 

Photos of you setup could also help.

 

Last Edited: Tue. Oct 3, 2017 - 09:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dabineri wrote:
What am I doing wrong in this simple program?
dabineri wrote:
I am using pin PD1 (pin15), the TXD pin, of my DIP Atmega 32A and am connecting that pin to pin 3 of a female DB9.

??? You are connecting the AVR directly into a DB9 serial port on a PC?

 

If so, then that is probably an RS232 port.  So you need to connect your AVR to a transceiver...

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.

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

dabineri wrote:
I am using  pin PD1 (pin15), the TXD pin, of my DIP Atmega 32A and am connecting that pin to pin 3 of a female DB9.
So you are connecting the ATmega with a RS-232 interface directly without any adapter in between? And you are connecting TxD with TxD?

 

Stefan Ernst

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

Please clarify if you would.

 

On the PC if have a Serial Port (COM Port) to USB adapter so I am sending the data into that DB9 connector as  described.  How should I connect the output from the Atmega 32A to the Com port?

 

Many thanks,

 

Dave

David Abineri

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

On the PC if have a Serial Port (COM Port) to USB adapter so I am sending the data into that DB9 connector as  described.  How should I connect the output from the Atmega 32A to the Com port? Please describe a transceiver  if you would.

 

Many thanks,

 

Dave

David Abineri

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

dabineri wrote:
Please clarify if you would.
First, the PC should receive what the Mega32 is sending, shouldn't it? So you have to connect TxD of the Mega32 to RxD of the COM-Port.

Second, the DB9 connector is a strong indicator that the COM-Port is of type RS-232, which uses different levels than the Mega32, so you have to use an additional level adapter. (or alternatively replace the USB adapter with a more appropriate one)

Stefan Ernst

Last Edited: Tue. Oct 3, 2017 - 10:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your google must be broken. I googled avr rs232 and found this:
https://www.swharden.com/wp/2009-05-14-simple-case-avrpc-serial-communication-via-max232/

You can get little boards from china that have the max232, connector and other bits. Most would just buy arduino clones in order to avoid the mistakes you’ve made.
Now you’ve got some keywords to google with, troll some of the problems a zillion others have had and see how you compare. If you’ve managed to zap your avr, then you’ve hit the trifecta.

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

Jim, When communicating with this backpack, am I supposed to be using RS232 levels or is it a direct connection from the atmega serial out to the back pack.

 

Perhaps this is my misunderstanding.  What is the backpack expecting in terms of signal levels.

 

Many thanks,

Dave

 

 

David Abineri

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

If it has a db9 connector it is most likely RS232. Thus you need a device like the max232 to do the level translation.

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

PROBLEM SOLVED.  The serial LCD that I am trying to communicate with expects an RS232 signal and not TTL from the Atmega. It is the BPI-216 serial LCD.

 

Thanks to all who helped, I should be able to solve this now.

 

Dave

 

David Abineri

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

dabineri wrote:
PROBLEM SOLVED.  The serial LCD that I am trying to communicate with expects an RS232 signal and not TTL from the Atmega. It is the BPI-216 serial LCD.

Not quite! It will accept a TTL signal happily, but it needs to be inverted.

 

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

dabineri wrote:
PROBLEM SOLVED

Then please mark the solutionhttp://www.avrfreaks.net/comment...

 

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

 

Kartman wrote:
It will accept a TTL signal happily, but it needs to be inverted

 

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

That picture (ie the text) is misleading. Sure it says "inverted-TTL" but it is immediately preceded by "RS-232". The latter suggesting +/-12V signalling. In fact I would have suggested that "RS232" and "TTL" are oxymoronic in this sense.

Pages