====== 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; } } } }