====== T04 - UART communication ======
Write a program for [[courses:be2m37mam:hardware:start|Nucleo STM32F401RE]] to send and receive characters over USART.
===== Instructions: =====
- Send single character from Nucleo to PC, see template.
- Modify template to send string (word or sentence).
- Modify template to receive character (or more) and display it on Experimental shield.
- Use [[https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html|Putty]] to communicate with Nucleo
===== Lecture =====
{{ :courses:be2m37mam:tasks:stm32-uart.pdf |}}
===== Template =====
Project: {{ :courses:be2m37mam:tasks:usart.zip |}}
==== GPIO settings ====
USART needs two of GPIO pins to serve as transmit and receive line. To enable it, GPIO pins mode shall be set like an alternate function.
* GPIOx MODER: p. 157 of reference manual
* GPIOx AFR: p. 162 of reference manual
void gpio_init (void)
{
setbit(RCC->AHB1ENR, 0); // Enable AHB1 clock
setbit(GPIOA->MODER, 5); // PA2 alternate function,
setbit(GPIOA->MODER, 7); // PA3 alternate function
GPIOA->AFR[0] |= 0x0700; // alternate function, PA2 will be USART2_TX
GPIOA->AFR[0] |= 0x7000; // alternate function, PA3 will be USART2_RX
// see p. 45 of STM32F401xE datasheet
}
==== USART ====
/*
* USART2 init
* USART2 is connected to APB1 bus
* USART2 uses PA2 as TX and PA3 as RX
*/
void usart_init (void)
{
setbit(RCC->APB1ENR, 17); // Enable APB1 clock
setbit(USART2->CR1, 13); // Enable USART2
setbit(USART2->CR1, 2); // USART2 - enable receive
setbit(USART2->CR1, 3); // USART2 - enable transmit
USART2->BRR = (104 << 4); // USART2 baudrate, first 4 bits are dedicated to fraction
/*
* STM32F401 default clock is 16MHz HSI
* BRR ~ fclk/(8*(OVER8-2)*baudrate)
* OVER8 reset state is 0
* see p. 514 of STM32F401 reference manual
*/
}
==== USART - transmit byte ====
void usart_tx (unsigned char ch) {
// wait till transmit register is empty 7th bit of SR
while (!readbit(USART2->SR, 7));
USART2->DR = ch;
}
==== USART - receive byte ====
int usart_rx (unsigned char *x)
{
// read from DR while receive register is not empty - 5th bit of SR
if (getbit(USART2->SR, 5)) {
*x = USART2->DR;
return 1;
}
return 0;
}
==== main program ====
int main(void)
{
char mess[20];
char a;
int i = 0;
gpio_init();
usart_init();
while (1)
{
if (usart_rx (&a))
{
if (a != '\r' && a != '\n')
mess[i++] = a;
else
{
send_string(mess, i);
i = 0;
}
}
}
}