Working with STM32F7 and UART part 1: Sending a single character

UART

In this guide, we shall discuss how to use the UART module on STM32F7xx specifically, STM32F767ZI Nucleo.

In this guide we will cover the following:

  • What is UART
  • How to configure the UART on STM32F767Zi Nucleo
  • Code
  • Demo

1. What is UART

To transfer data, computers adopt two method: serial and parallel. In serial communication data is sent a bit at a time (1 line)while in parallel communication 8 or more lines are often used to transfer data. The UART is a form of serial communication. When distance is short, digital signal can be transferred as it is on a single wire and require no modulation. This is how PC keyboard transfer data between the keyboard and motherboard. For long distances like telephone lines, serial data communication requires a modem to modulate.We will not go into the details of this in this lesson, this shall be left for subsequent lessons. 

Synchronous vs. Asynchronous

Serial communication operate in two ways : synchronous and asynchronous. In the synchronous mode, a block of data is sent at a time while in the asynchronous mode, a single byte of data is sent at a time. It is possible to write code to provide both the synchronous and asynchronous serial communication functions however this could turn out tedious and over complicated therefore, special chips are manufactured to perform these functions. When these chips are added to a microcontroller, they become known as Serial Communication Interface (SCI). The chip that provides the the asynchronous communication (UART) is the main theme of this lesson. The chip for synchronous communication is known as the USART and shall left for another lesson. 

Asynchronous Communication Data Framing

The data is received in zeros and ones format, in order to make sense of the data, the sender and the receiver must agree on a set of rules i.e. a protocol, on how data is packed, how many bits constitute a character and when data begins and ends.

The Protocol

  1. Start and Stop bits

Asynchronous serial communication is widely used in character transfer. Each character is packed between start and stop bits. This is known as the framing.

start bit :  Always 1 bit, value is always 0

stop bit:   1 or 2 bits, value is always 1

Lets take an example. Lets say we are transferring ASCII character ‘A’ 

its binary code is 0100 0001 and 0x41 in hex.Furthermore, it is framed between a start bit and 2 stop bits. This is what its frame will look like.

 2. Parity bit

Some systems require parity bit in order to maintain data integrity.The parity bit of a character byte is included in the data frame after the stop bit(s).

 3.Rate of data transfer : Baud rate/bps

We shall explain this concept with an example. Lets say we are asked to calculate the number of bits used  and time taken in transferring 50 pages of text, each with 80×25 characters. Assuming 8 bits per character and 1 stop bit

solution

For each character a total of 10 bits is used ( 1 start bit, 8 bits character, 1 stop bit).

Therefore total number of bits  = 80 x 25 x10 = 20,000 bits per page

50 pages  implies, 50×20,000  =  1,000,000 bits.

Therefore it will take 1 million bits to transfer  this information.

The time it takes to transfer the entire data using

a. 9600 baudrate implies,  1,000,000 / 9600 = 204 seconds

b. 57,600 baudrate implies 1,000,000 /57,600 = 17 seconds

Baudrate simply means the transfer of bits per second. There are various standardized baudrate we can choose from when we program our serial communication devices.  The key thing is, both communication devices must have the same baudrate. We shall see this later on in our example code.

2. How to Configure UART on STM32F767Z Nucleo-144

First things first, we need to figure out which USART is connected to the built-in ST-Link V2/1

We can find this information from the reference manual of Nucleo-144

According to the section of hardware layout, PD8 and PD9 is connected to ST-link V2/1 and they are related to USART3 in our case.

Hence we need to enable clock access to USART3

Before we enable clock access to USART3, we need to configure PD8 as alternate function and enable clock access to port D

We can enable clock access as following (how enable locate the clock source and enable clock access can be found here):

RCC->AHB1ENR|=RCC_AHB1ENR_GPIODEN;

Then we set the PD8 and alternate function (refer to this topic for how set the alternate function)

GPIOD->MODER|=GPIO_MODER_MODER8_1;

Now we need to figure out which alternate function.

We can refer to the datasheet of the STM32F767, pinout section, we can find a table that represents the alternate function

Since USART is AF7, we can use small define statement to hold this

#define AF07 0x07

Since PD8 is part of alternate function register high, we can set it as following:

GPIOD->AFR[1]|=(AF07<<0);

The GPIO configuration is completed, we can go ahead and configure the USART

First we enable clock access as following:

RCC->APB1ENR|=RCC_APB1ENR_USART3EN;

then we can set the baudrate

USART3->BRR    = 0x008B; // baud rate 115200 @16MHz

Then we enable only the TX part

USART3->CR1|=USART_CR1_TE; //enbale TX

and finally we can enable the module

USART3->CR1|=USART_CR1_UE;

for writing a single character, we can use small function for that

void uart2_write(unsigned char x)
{

USART3->TDR =(x); //send data to the buffer
while(!((USART3->ISR)&USART_ISR_TC)){;} //wait untill the transfer completed 
}

Hence, the entire code as following:

#include "stm32f7xx.h"                  // Device header

//PD8 for USART3 TX

void uart2_write(unsigned char x)
{

USART3->TDR =(x);
while(!((USART3->ISR)&USART_ISR_TC)){;}
}

int main(void)
	{
		
		//Configure GPIOD PD8 as TX pin
		RCC->AHB1ENR|=RCC_AHB1ENR_GPIODEN;
		GPIOD->MODER|=GPIO_MODER_MODER8_1;
		#define AF07 0x07
		GPIOD->AFR[1]|=(AF07<<0);
		
		//Configure the UART
		
		RCC->APB1ENR|=RCC_APB1ENR_USART3EN;
		USART3->BRR    = 0x008B; // baud rate 115200 @16MHz
		USART3->CR1    = 0; // Enable Tx and Rx and Enable USART2
		USART3->CR1|=USART_CR1_TE; //enbale TX	
		USART3->CR1|=USART_CR1_UE;
		
	while(1)
	{
		uart2_write('a');
		uart2_write('\r');
		uart2_write('\n');
		for(volatile int i=0;i<100000;i++);
		
	}
	
	
	}

3. Demo:

Once the code is compiled and uploaded, open teraterm or your favourite serial terminal and set the baudare to 115200

Add Comment

Your email address will not be published. Required fields are marked *