8. USART

Cíle cvičení

  1. Nastavit komunikační rozhraní USART, aby MCU mohl přijímat a odesílat data po sériové lince do PC

Co je třeba si připravit

- Pro komunikaci budete potřebovat vhodný sériový terminál na PC, např.

  • Putty (Win, Linux)
  • HTerm (Win, Linux)
  • WCHSerialPort (MacOS)
  • Prostředí SES má v sobě terminálový emulátor zabudovaný. Zobrazíte ho buď nabídkou z horní lišty Tools → Terminal Emulator → Terminal Emulator nebo klávesovou zkratkou CTRL+Alt+M. Přes nastavení zadejte potřebné parametry. (Win, Linux, MacOS)
  • Prostředí STM32CubeIDE má v sobě terminál zabudovaný. Zobrazíte ho přes Window → Show View → Console, následně je třeba vytvořit rozhraní (konzoli) přes tlačítko přidat rozhraní, vyberte Command Shell Console a přidejte nové zařízení podle nastavení. Celý návod zde. (Win, Linux, MacOS)

Podklady pro cvičení

Projekty

Kódy pro cvičení

Konfigurace GPIO

USART dva GPIO piny, které slouží jako vysílací (Tx) a přijímací (Rx). Kromě standardního nastavení je třeba nastavit mód příslušných GPIO pinů jako alternativní funkce.

  • GPIOx MODER: str. 157 referenčního manuálu
  • GPIOx AFR: str. 162 referenčního manuálu

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
}                           

Inicializace 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
 * baudrate: 9600
 */
}

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

Hlavní 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;
            }
        }
    }
}

Kruhový buffer

// *******************
// main.h
#define bufferSizeMask		0x3F	// 63
#define bufferSize		64
 
enum bufferStatus_e {
	BUFFER_WAIT,
	BUFFER_SEND,
	BUFFER_SENDING
};
 
typedef struct {
	uint8_t buffer[bufferSize];
	uint8_t head;
	uint8_t tail;
	enum bufferStatus_e status;
}circularBuffer_t;
 
 
// *******************
// main.c
void copyBuffers(circularBuffer_t *d, circularBuffer_t *s){
	while(s->tail != s->head){
		d->buffer[d->head++] = s->buffer[s->tail++];
		d->head &= bufferSizeMask;
		s->tail &= bufferSizeMask;
	}
}
 
void USART2_sendBuffer(circularBuffer_t *b){
	while(b->tail != b->head){
		while(!(USART2->SR & USART_SR_TXE));
		USART2->DR = b->buffer[b->tail++];
		b->tail &= bufferSizeMask;
	}
}

courses/b2m37mam/labs/08.txt · Last modified: 2024/11/26 16:57 by skalicky