USART, PIC->ATmega - Page 1
Forum section: electronics / beginners

author: Spekkio
author_rank: Regular Contributor
timestamp: May 08, 2011, 01:16:09 pm
content: Hi!I have written a program for PIC that responds to a Modbus request. It works fine!But I'm not going to use the PIC, instead I'm using a ATmega324P, I use the same C-code with only the minor changes ofregisters and settings ofcourse. The program works for ATMega324P. But the receiving side does not accept the data.I could not understand why, I used a display to debug. I set up both the PIC and ATmega circuit with a display to verifythat both the MCU's are receiving the same data. They do!Then I used a oscilloscope on the TX pin to verify that they were also transmitting the same data. And they do!But the difference is that the ATmega324P is sending the data a little bit slower than the PIC.And I cannot figure out why. I was thinking maybe the ATMega was set to send 9 bit's, but it's not.Both MCU's are set to 9600bps with 4MHz crystal oscillator. The ATMega is set to "Full Swing oscillator, fast rising"I have tried a different setting, same result.setting for ATMega324PUBBR0=0x19 //25 for 4MHzU2X0=0;RXEN0=1;TXEN0=1;UCSZ02=0;USBD0=1;UCSZ00=3;this is a picture of the data on the TX pin. It does seem like the ATmega is sending in 9-bit format, or sending an extra bit.since it's approx 1ms longer. This data is 13 bytes big, so 13bit's take approx 0.00135417s or 1.3ms to send in 9600bps.But it shouldn't, UCSZ00=3; is 8-bit format right?I have also tried to change the value of UBBR0 to make the MCU send data faster, but the it cannot receive data correctly...

author: Unknown
author_rank: Unknown
timestamp: May 08, 2011, 04:21:57 pm
content: I'm not familiar with the compiler you're using (which you failed to mention), assigning directly to bits (as opposed to directly assigning to registers) seems like an undesirable level of abstraction to me. So UCSZ00 refers to both UCSZ00 and UCSZ01? What is USBD0?Do you actually see a ninth bit or second stop bit? I find it hard to tell from this low-res screenshot. Try outputting something like a string of U's and measuring the baud rate for both the PIC and the AVR. I would also verify the crystal frequency (using CLKOUT and a counter/scope), maybe the micro's require a different amount of load capacitance? You expect the baud rate to be off by about 0.2% with a 4MHz crystal (use something like 3.686MHz or 7.372MHz for exact divisors), but not ~10%.Quote from: Spekkio on May 08, 2011, 01:16:09 pmIn that case the baud rate would be ~2.4% off, which is still way too much.

author: Mechatrommer
author_rank: Super Contributor
timestamp: May 08, 2011, 06:05:54 pm
content: from picture... atmega send slower bitrate compared to PIC, but it is sending the first (rising) bit faster than the PIC

author: oPossum
author_rank: Super Contributor
timestamp: May 08, 2011, 08:17:49 pm
content: Write some code to send 0xAA 0xAA and look at that on the scope. The bit timing, number of bits, and number of stop bits will be quite clear.

author: deephaven
author_rank: Frequent Contributor
timestamp: May 08, 2011, 08:48:13 pm
content: Also increase the timebase speed on the scope as it is difficult to see the true nature of the serial data with your present setting.

author: Spekkio
author_rank: Regular Contributor
timestamp: May 09, 2011, 01:48:25 pm
content: Quote from: alm on May 08, 2011, 04:21:57 pmI'm using GCC in AVR Studio 4.Quote from: deephaven on May 08, 2011, 08:48:13 pmI know, I wanted to see the entire message. I've made a program to send a smaller message.I found out I'm ofcourse sending 2-stop bits, that's the extra bit in the ATMega324P data.So I configured it to 1-stop bit, to my dissapointment it still doesn't work.I'm serious, I'm not trolling you. The exakt same serial data is sent from ATMega324PI am confused and tired of this problem.

author: bilko
author_rank: Frequent Contributor
timestamp: May 09, 2011, 02:06:43 pm
content: From your latest photo it looks like you have scopeCH1 set to 5Vand CH2 set to 200mV. assume Ref B is set to same levelWhere are you measuring the signals and what are they referenced to ?Signal timings look identical so its either the levels or you have an inverted signal

author: Mechatrommer
author_rank: Super Contributor
timestamp: May 09, 2011, 02:42:10 pm
content: get a good rest. you almost there.

author: Unknown
author_rank: Unknown
timestamp: May 09, 2011, 04:36:13 pm
content: Quote from: Spekkio on May 09, 2011, 01:48:25 pmI would double check how to set registers, because the way I'd write:Code:RXEN0=1;TXEN0=1;Is:Code:UCSR0B |= (1 << RXEN0) | (1 << TXEN0);As far as I know, constants like RXEN0 are bit positions (RXEN0=4 for the ATmega324P), so I'm not sure what an assignment is going to do. But maybe they added some magic that I'm not aware of? I haven't paid that much attention to avr-gcc development lately. In that case I'd appreciate a link to some documentation.SeeBit manipulationandUsing the USARTon AVRfreaks for more information.

author: Spekkio
author_rank: Regular Contributor
timestamp: May 09, 2011, 06:24:32 pm
content: Quote from: yachtronics on May 09, 2011, 02:06:43 pmI'm only using one channel, CH1. The other signals that are a little bit more gray are stored signalas/saved in memory.Quote from: alm on May 09, 2011, 04:36:13 pmThis is the way I wrote it in the code, sorry I could not copy&paste since it was on another computer.I will try measuring on the RS485 side of the MAX485 instead, and compare the signals. brb

author: bilko
author_rank: Frequent Contributor
timestamp: May 09, 2011, 08:03:54 pm
content: Also worth double checking you don't have your A and B lines crossed over on the RS485 side

author: Spekkio
author_rank: Regular Contributor
timestamp: May 10, 2011, 12:40:59 pm
content: I found the problem by measuring on the RS485 side instead, I should have done that from the startthe RE/DE (RE is inverted) pins can be connected together, it's connected to a digital output on the MCU to control the Receiver Output/Driver Input.To tell the MAX485 to work as a receiver or a driver.On the ATMega324P, I needed to put a small delay before setting a 0 to the RE/DE pins when the transmission of data is complete, to disable the transmitter and enable the receiver. I needed that delay because it seemed like the last bits of data was not transmitted.I dont need to do that on the PIC though..the code on the PIC to send data isCode:TXREG=data;while(!TRMT);on the ATmega324PCode:while( !(UCSR0A & (1<<UDRE0)));UDR0=data;I tried to set the while loop after the UDR0 instead, like in the PIC.It waits til the transmission is complete. But I don't really understand how it works in the ATmega,this code is directly from the datasheet.

author: Spekkio
author_rank: Regular Contributor
timestamp: May 10, 2011, 01:00:34 pm
content: And also, the ATMega was configured for 2 stop bits, and the PIC for one. So that's why it was an extra bit for every byte.Thanks for all your help

author: Psi
author_rank: Super Contributor
timestamp: May 10, 2011, 02:51:21 pm
content: Quote from: Spekkio on May 10, 2011, 12:40:59 pmThat delay should always be there, it waits for the buffer to be empty (incase its not).Thats important so that you dont write data over older data thats still waiting to be sent.Ive not checked the pic datasheet to confirm this, but i suspect you were getting confused between the two approaches of "waiting for transmit buffer to be empty" on avrs (something you want to do before sending)and "waiting for transmit to complete" on pics (something you want to do after sending)