[TUT][ASM][CODE][HARD]XmegaA3BU-Explained LCD ST7565r USART

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

11/28/12 - added more explaination and PDF file of the tutorial.

This is a tutorial on using the LCD on the XMEGA-A3BU Xplained board. The LCD controller is the Stronix ST7565r.

Get the Datasheets:

Atmel: Atmel AVR XMEGA AU Manual Manual
ATxmega256A3BU Complete
search the Atmel install directory
for A3BU (where you installed AS6).
AFS: ST7564R Display Controller Driver
Example is useful.

This tutorial is written in Assembly. The output is
repeated "S"s on the first line. Also flashed the
yellow leds.

Includes Changing the System Clock to 32M internal.
Setting up USARTD0 as Master SPI.
Reset the ST7565r.
Initialize the LCD via the ST7565.
Writing an "S" to the LCD.

There are now 3 versions of this TUTORIAL. lcd4, lcd5,lcd6.

This tutorial is about the interface of the Sitronix ST7564r Display controller to a Xmega. This is the design used on the XmagaA3BU-Xplained board. The assembly code was written and assembled using AS6, with default toolchain.

In ASF there are several examples using the LCD. Such as: ST7565R Display Controller Driver Example. This tutorial is a low level look at the procedure.

The ST7564R is connected to the pins used by USARTD0 of the ATXMega256A3BU and thus uses the USART SPI-master mode to communicate.

Some of the issues covered:
Setting the clock speed for the XCK of the USART.
1. Setting the CLKper speed
2. Setting BSEL of USARTD0

Initializing USARTD0
1. Set the pins to output
2. Set the pins to high
3. Set master mode
4. Set SPI mode 3
5. Set direction, MSB first.
6. Enable the USART

Construct USART transmit code
1. Check for transmit buffer empty
2. Fill transmit buffer
3. Check for transmit complete
4. Clear the transmit complete flag
5. Retrieve the received data. (in this case no data from the ST7565r)

Reset the ST7565r.
1. Select the controller, CS low
2. Put the reset of the ST7565r low..
3. Hold for > 1 ms.
4. Put the reset high.

Initialize the ST7565r and LCD.
1. Write command
2. Write data
3. Send initialization commands

Write to the LCD.
1. Erase the line
2. Write character

Setting the clock speed for the XCK.
Xmega chips begin at a 2MHz clock, but allow the clock to be changed while running. First set the CLKsys = 32Mhz in this example.
From the table in the Xmega AU manual (table 23-1) Fbaud < Fper/2. The baudrate must be less than the CLKper / 2. See Figure 7-5 System Clock Selection and Prescalers.
The CLKsys goes to the Prescalers A, B and C in that order.
Two cases are shown:
1. The first case in the attached lcd4.asm, sets the PrescalerA to divide by 4, thus the CLKcpu and CLKper are 8MHz.
2. The second case in the attached lcd5.asm and lcd6.asm, does not set any prescaler, thus CLKcpu and CLKper are 32MHz.

To set the correct USART speed for Master SPI mode the formula from table 23-1 is:

BSEL = (CLKper / (2 * Fbaud)) -1.

for Case 1, CLKcpu = 8MHz, CLKper = 8MHz, Fbaud = 1MHz, BSEL = 3.

for Case 2, CLKcpu = 32MHz, CLKper = 32MHz, Fbaud = 1MHz, BSEL = 15

BSEL is set in USARTD0_BAUDCTRLA "“ Baud Rate register A.

Initializing USARTD0.
Pins used are:

A3 = ST7565 reset
F3 = ST7565 chip select (CS)
D0 = ST7565 A0 pin, this selects between data and command
D2 = USARTD0 RXD (actually not used)

Set all pins except D2 to output and set to HIGH

Set Master mode is done in USARTD0_CTRLC, bits 6 & 7.

Set SPI mode 3, See figure 23-4.
SPI mode 3 inverted XCK and trigger on rising edge.

Set UCPHA bit in USARTD0_CTRLC, BIT 1. (this is the rising edge.)

SET PORTD_PIN1CTRL, bit 6 to invert the signal.

For shift MSB first, bit 2 of USARTD0_CTRLC is clear.

Also set bit 0 in CTRLC, don't know why. Is set in the ST7565r example.

Enable TX and RX in USARTD0_CTRLB. Bits 3 & 4.

Construct USART transmit code

USARTD0_STATUS register has the buffer empty, bit 5, and transmit complete, bit 7, flags.
Clear the transmit complete flag by writing to bit 7.

Write to USARTD0_DATA, also read from the register. Since when the ST7565r is in SPI mode no data can be read, reading is not necessary. In the examples lcd4.asm and lcd5.asm the data register is read, not read in example lcd6.asm. The transmit flag must be cleared.

Reset the ST7565r.

To select the ST7565r, the CS pin (F3) must be low.

Hold the ST7565r reset pin (A3) low for > 1 ms. Then set high.

Note that the delay routine must be increased by a factor of 4 in examples lcd5.asm and
lcd6.asm since the CLKcpu is 32MHz instead of 8MHz in example lcd4.asm.

The initialization sets these defaults: (from the Sitronix ST7565r datasheet.

1. Display OFF
2. Normal display
3. ADC select: Normal (ADC command D0 = "L")
4. Power control register: (D2, D1, D0) = (0, 0, 0)
5. 4-line SPI interface internal register data clear
6. LCD power supply bias rate:
1/65 DUTY = 1/9 bias
1/49,1/55,1/53 DUTY = 1/8 bias
1/33 DUTY = 1/6 bias
7. Power saving clear
8. V0 voltage regulator internal resistors Ra and Rb
9. Output conditions of SEG and COM terminals
10. Read modify write OFF
11. Display start line set to first line
12. Column address set to Address 0
13. Page address set to Page 0
14. Common output status normal
15. V voltage regulator internal resistor ratio set mode clear
16. Electronic volume register set mode clear Electronic
volume register :
(D5 , D4 , D3 , D2 , D1 , D0) = (1, 0. 0 , 0, 0,0)

Initialize the ST7565r and LCD.

The A0 pin (D0) on the ST7565r is used to differentiate between data and commands. Set CS (F3) low and for command A0 (D0) low. A0 (D0) high for data.
Send the commands:
0xA0 set adc normal
0xA6 set display normal
0xC8 set reverse scan
0xA2 set lcd bias
0x2F power control
needs a short delay here, so the power can stableize
0xF8 set booster ratio, this is a 2 byte command.
0x00 booster ratio 2x ... 4x (2nd byte is the setting)
0x21 resister ratio
0x1F set contrast, should be between 30 and 40.
0xAF Turn on display
Note: the display keeps its data until power removed.
Reset doesn't remove the data.

Write to the LCD.
3. Erase the line
4. Write character
This device is graphical, thus the pixtels must be sent. To send characters, this example shows a 5x7 font.

01 2 3 4
1 X
2 X
4 X
5 X X
The font is written by column.

Column 0. 0b00100110 0x26
1. 0b01001001 0x49
2. 0b01001001 0x49
3. 0b01001001 0x49
4. 0b01100001 0x31 (in the code I wrote 19)

Also referred to column as row.

To write a blank row for spacing use 0x00.

Noticing that the screen doesn't erase in lcd4.sam, I added an erase routinein lcd5,asm and lcd6.asm that writes 0x00 multiple times (0x93).

All the tutorials run on the XmegaA3BU-Xplained board.


Last Edited: Wed. Nov 28, 2012 - 07:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is a new version of the code. Just changes lcd4 as

1. Does away with the prescaler setting, CLKcpu &
CLKper now run at 32M.

2. Adds an erase routine to erase the first line on


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

In the write routine no longer reads the received data buffer.


Last Edited: Wed. Nov 28, 2012 - 01:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But this is not a "tutorial"? Surely it's just a project that should either be in the "Projects" section here or on the new spaces.atmel.com ?

A tutorial is something that teaches people something. That suggests some kind of explanatory text that explains why things are done and how things work. I don't see that here. It's just a .asm file?

Perhaps you could add a few paragraphs to your first post to explain the code and turn this into a tutorial?

Also a tutorial (or a "Project" for that matter) should be based on stable, finished, tried, tested code. The fact you have posted 3 versions in as many days does not give a huge air of confidence! If you use spaces.atmel.com however it's quite acceptable to put a project there at any stage from initial design to finished article. The description of the project should reflect the state of completion though.


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

Since this is not a large tutorial, I placed the tutorial as comments in the code.

Code is stable. Just tried a few ideas out to try to show some differences. All code runs just fine.