USART waveform question

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

The following is a code snippet I am running on the attiny427. The USART should basically produce a repeating data transmission of 0x0F using asynchornous 9600N1 mode.

#define USART0_BAUD_RATE(BAUD_RATE) ((float)(20000000 * 64 / (16 * (float)BAUD_RATE)) + 0.5)
#define TXD_PB 2

int main(void){
    CCP = CCP_IOREG_gc;			//Configuration Change Protection
    CLKCTRL.OSC20MCALIBA = 13;	//Calibration for 20MHz
    
    PORTB.DIR |= (1 << TXD_PB); //Set TXD as output pin
    
    sei(); // Global interrupt enable
    
    //Serial data transmission
    USART0.CTRLB |= USART_TXEN_bm;			//Tx enable
    PORTB.PIN2CTRL = PORT_PULLUPEN_bm;		//Enable pull up resistor for TxD
    USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600); //9600 Baud
    USART0.CTRLC = USART_CHSIZE_8BIT_gc;	//8 bit data
    USART0.CTRLA = USART_TXCIE_bm;	//Enable USART Transmit Complete Interrupt Enable
    USART0.TXDATAL = 0x0F;          //First data
    
}

ISR(USART0_TXC_vect){	//Transmission complete interrupt
	USART0.STATUS |= USART_TXCIE_bm;	//Clear the transmit complete interrupt flag
	USART0.TXDATAL = 0x0F;              //Next data
}

 

On the oscilloscope, the waveform looks like as shown in the attached image. I have identified the start and stop bits and the 8 data bits. But there is one extra bit that I am unable to identify. It looks like a "1" after the start bit, but the datasheet does not make any reference to such a bit. Any suggestions or clues would be appreciated. 

 

 

 

 

Attachment(s): 

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

 

 

The image looks like the correct waveform.

 

 

EDIT:

 

 Oh, I made a mistake.
The data order of the images is 11110000.

 

 

Last Edited: Tue. Jan 4, 2022 - 09:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Why do you need float for baud rate calculations?

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Not to be overly critical but your scope probe really needs to be compensated.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Are you just seeing the signal going to its normal high standby level, after sending out a byte (that's the only way to create the start bit).

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

asarangan wrote:
data transmission of 0x0F using asynchornous 9600N1 mode.

The waveform shape looks perfect, the actual baudrate achieved however is completely wrong. (Your scope timebase of 1s/div should have got you worried)

 

Your bug is this:

#define USART0_BAUD_RATE(BAUD_RATE) ((float)(20000000 * 64 / (16 * (float)BAUD_RATE)) + 0.5)

MSVC gives me a compiler warning for that line: warning C4307: '*': integral constant overflow

 

You need to completely rework this because you cannot use the usually recommended #include <util/setbaud.h>

 

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

You are 90% of the way to the "classic" test -- send the 'U' character continuously at 8-N-1 and you get a nice square wave where the bit times can easily be measured. 

 

Admittedly, start/stop will look just like a pair of data bits.  But given the regularity, any ??? will be readily apparent.

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

I don't believe that the formula for baud rate is correct.  I know...I know...the datasheet says ...  But, at this point, I really don't trust anyone at Atmel to write an easy-to-understand and implement baud-rate or I2C rate formula for their data sheets.   And the situation gets worse with the ever-increasing level of complexity of their <$1 low-end devices.

 

  For instance, take this USART.  Typical AVR UARTS are set to run at 16 times the baud rate so that the RX circuitry can take three samples of the incoming data level on the RX line and present the average of the three as the valid data bit.   Then, (in classic AVRs) the main system clock is divided by (16*baudrate) to get the value that is put into the USART's baud-rate H:L register pair.  This appears to be the formula used here, but there is this weird multiply-by-64 factor tossed into the formula (with no explanation of what it is or what it is for, nor any examples of using this incomprehensible formula in the data sheet with standard baud rates like 9600). 

 

  The new tiny AVRs seem to use a different clock (CLK_PER) to run the peripherals from the system clock (CLK_CPU).  I suspect that the CLK_PER is 1/64th the speed of the CLK_CPU.  I'm not sure because no one is paying me to figure out this overly-complicated data sheet.  I use Arduino now: I don't fool around trying to figure out baud-rate formulas anymore.

 

I'm going out on a limb and suggest that you try using:    20,000,000 / (16*9600) as the value put into the baud-rate registers.  That way you won't get UART 10-bit frame that is over a second long.

Last Edited: Tue. Jan 4, 2022 - 02:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
  The new tiny AVRs seem to use a different clock (CLK_PER) to run the peripherals from the system clock (CLK_CPU).

This came up recently: https://www.avrfreaks.net/commen...

 

I suspect that the CLK_PER is 1/64th the speed of the CLK_CPU.  I'm not sure because no one is paying me to figure out this overly-complicated data sheet.

What makes you think that?

 

Seems to me  like CLK_CPU has to be the same as CLK_PER: https://www.avrfreaks.net/commen...

 

El Tangas thinks so, too: https://www.avrfreaks.net/commen...

 

You can easily measure CLK_PER: https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


These newer AVRs are changing so fast we can't keep up: It looks like the formula is correct:

 

24.3.2.2.1 The Fractional Baud Rate Generator

...

...

S is the number of samples per bit

  • Asynchronous Normal mode: S = 16
  • Asynchronous Double-Speed mode: S = 8
  • Synchronous mode: S = 2

 

 

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

Yep, you are right. I guess I was reading the waveform backwards in time.  Thanks!

 

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

kabasan wrote:

 

 

The image looks like the correct waveform.

 

 

EDIT:

 

 Oh, I made a mistake.
The data order of the images is 11110000.

 

 

 

Yep, you are right. I guess I was reading the waveform backwards in time.  Thanks!

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

N.Winterbottom wrote:

These newer AVRs are changing so fast we can't keep up: It looks like the formula is correct:

 

24.3.2.2.1 The Fractional Baud Rate Generator

...

...

S is the number of samples per bit

  • Asynchronous Normal mode: S = 16
  • Asynchronous Double-Speed mode: S = 8
  • Synchronous mode: S = 2

 

 

 

I believe my equation is correct. The float may not be necessary, but I took that suggestion from an Atmel application note.

 

However, there is a problem nevertheless. When I use the equation as described in the datasheet, my data rate is 8 times slower. In other words, the bits are 833us long instead of 104us long. I fixed it by modifying the equation with a /8. Its not clear to me whether the datasheet is wrong, or if my implementation is wrong. 

 

I verified that my CPU clock was 20MHz by sending it to the CLKOUT pin and measuring the rate. There is a factor of 8 missing somewhere. 

 

 

 

 

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

asarangan wrote:
my data rate is 8 times slower.

Sounds like you have a divide-by-8 prescaler somewhere that you've omitted to take into account ...

 

Have you measured your CLK_PER frequency? See #9 ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is a factor of 8 missing somewhere.

In older chips there is a default clock divide by 8 fuse set, the newer chips have a divide by 6.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I can't figure out how the program you've listed produces a 20mhz CPU clock. The CPU prescaler is enabled by default in /6 mode and you don't disable this. Additionally you configure the 20mhz oscillator calibration to somewhere around 13mhz according to the typical characteristics chart. In total this would yield just over 2mhz and still not explain 833uS bits...

 

 

Simonetta wrote:

I don't believe that the formula for baud rate is correct.  I know...I know...the datasheet says ...  But, at this point, I really don't trust anyone at Atmel to write an easy-to-understand and implement baud-rate or I2C rate formula for their data sheets.   And the situation gets worse with the ever-increasing level of complexity of their <$1 low-end devices.

 

  For instance, take this USART.  Typical AVR UARTS are set to run at 16 times the baud rate so that the RX circuitry can take three samples of the incoming data level on the RX line and present the average of the three as the valid data bit.   Then, (in classic AVRs) the main system clock is divided by (16*baudrate) to get the value that is put into the USART's baud-rate H:L register pair.  This appears to be the formula used here, but there is this weird multiply-by-64 factor tossed into the formula (with no explanation of what it is or what it is for, nor any examples of using this incomprehensible formula in the data sheet with standard baud rates like 9600). 

 

  The new tiny AVRs seem to use a different clock (CLK_PER) to run the peripherals from the system clock (CLK_CPU).  I suspect that the CLK_PER is 1/64th the speed of the CLK_CPU.  I'm not sure because no one is paying me to figure out this overly-complicated data sheet.  I use Arduino now: I don't fool around trying to figure out baud-rate formulas anymore.

 

I'm going out on a limb and suggest that you try using:    20,000,000 / (16*9600) as the value put into the baud-rate registers.  That way you won't get UART 10-bit frame that is over a second long.

 

The factor of 64 is to accommodate 6 bits of fractional baud. To quote the datasheet: "The fractional baud rate generator expects the BAUD register to contain the desired division factor left shifted by six bits".

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

The main clock setting is incorrect.

    CCP = CCP_IOREG_gc;			//Configuration Change Protection
    CLKCTRL.OSC20MCALIBA = 13;	//Calibration for 20MHz

 

Please replace it with this.

	_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, CLKCTRL.MCLKCTRLB & (~CLKCTRL_PEN_bm));

 

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

I did some more digging, and I finally figured out what's going on. I wanted to double check the CPU clock. I enabled the CLKOUT using

PORTB.DIR |= (1 << 5);       //PB5 is output for CLKOUT
CCP = CCP_IOREG_gc;			//Configuration Change Protection
CLKCTRL.MCLKCTRLA = CLKCTRL_CLKOUT_bm;  //Enable CLKOUT on PB5

Surprisingly, this produced an output of 3.38 MHz output, not 20MHz.  I thought I had checked this before, but I must have overlooked something. As far as I can tell there is nothing in the datasheet that says the default value for the clock prescaler is /6. Next, I did the following:

PORTB.DIR |= (1 << 5);       //PB5 is output for CLKOUT
CCP = CCP_IOREG_gc;			//Configuration Change Protection
CLKCTRL.MCLKCTRLA = CLKCTRL_CLKOUT_bm;  //Enable CLKOUT on PB5
CCP = CCP_IOREG_gc; //Configuration Change Protection
CLKCTRL.MCLKCTRLB &= ~CLKCTRL_PEN_bm;   //Write 0 to PEN

This produced the expected 20MHz output. 

 

It's crazy that the datasheet would leave this important piece of information out. Actually, this is what it says:

 

Bit 0 – PEN Prescaler Enable

This bit must be written to ‘1’ to enable the prescaler. When enabled, the division ratio is selected by the PDIV bit field.
When this bit is written to ‘0’, the main clock will pass through undivided (CLK_PER = CLK_MAIN), regardless of the value of PDIV.

What the datasheet does not say is what happens if you don't write anything to PEN. I had assumed it would be 0, but it seems the default is 1, and the default for PDIV[3:0] is 0x08 (which is divide by 6). 

 

 

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


The default value is listed underneath each bit in the row titled "reset".

 

 

On a related note the USARTn_CTRLC register reset value is no parity 8N1 asynchronous mode so you don't need to set it like you have.

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

 

asarangan wrote:

It's crazy that the datasheet would leave this important piece of information out. 

 

Ahem...

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Last Edited: Thu. Jan 6, 2022 - 04:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

7string wrote:

The default value is listed underneath each bit in the row titled "reset".

 

 

On a related note the USARTn_CTRLC register reset value is no parity 8N1 asynchronous mode so you don't need to set it like you have.

 

Wow, thanks! I would not have caught that! 

 

 

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

asarangan wrote:

7string wrote:

The default value is listed underneath each bit in the row titled "reset".

 

 

On a related note the USARTn_CTRLC register reset value is no parity 8N1 asynchronous mode so you don't need to set it like you have.

 

Wow, thanks! I would not have caught that! 

 

 

 

Just an additional note, in case there are other newbies like me following this thread. After writing the signature to the CCP regsiters, the command needs to be executed within 4 CPU instructions. I was doing CLKCTRL.MCLKCTRLB &= ~CLKCTRL_PEN_bm; which wasn't working, but CLKCTRL.MCLKCTRLB  = 0; worked. Presumably the & and ~ was taking more than four instructions to execute. 

 

 

 

 

 

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

That is the exact reason the _PROTECTED_WRITE() macro exists. It is written in hand crafted Asm so it guarantees the 4 cycle thing is adhered to whatever the compiler build settings are. Don't try and implement your own CCP unlock stuff because it may happen to work with this week's compiler version or build switches but if any of those change later it could stop working which could be a very subtle bug to try and track down depending on what diagnostic tools you have available.