MyTetra Share
Делитесь знаниями!
FreeRTOS. USART
Время создания: 04.05.2018 11:45
Раздел: Electronics - Microcontrollers - STM32 - CMSIS

USART2:

TX - PA2

RX - PA3


Подаем тактирование на UART, GPIO и альтернативную функцию (AFIO).


По DS видим, что USART2 сидит на шине APB1. Включаем тактирование USART и порта А:


RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //enable RCC for PortA

RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //enable UART clocking


Включаем алтернативную функцию. В даташите находим, что USART1..3 = AF7 (схема Figure 26. Selecting an alternate function). За AF7 отвечает регистр GPIOx_AFRLy. Поскольку нас интересуют порты PA2 и PA3, то мы записываем комбинацию 0111 (соответствует AF7) в AFRL2 и AFRL3:


//PA2 alternate function (USART = 0111)

GPIOA->AFR[0] |= GPIO_AFRL_AFSEL2; //set all bits

GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL2_3; //clr last bit


//PA3 alternate function (USART = 0111)

GPIOA->AFR[0] |= GPIO_AFRL_AFSEL3; //set all bits

GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL3_3; //clr last bit


Индекс массива задает старшую (1) или младшую (0) половину регистра.

Далее ТХ, поскольку он является выходом, необходимо настроить в соответствующее состояние с Push-Pull, а RX как плавающий вход.

Говорилось, что ТХ настраиваем как выход, т.е:


//PA2 Alternate Push-Pull (01)

GPIOA->MODER &= ~GPIO_MODER_MODE2;

GPIOA->MODER |= GPIO_MODER_MODE2_0;


Но у меня в таком ражиме не заработало. Зато все поехало после того, как перевел порт в альтернативный режим:


//PA2 Alternate Push-Pull (10)

GPIOA->MODER &= ~GPIO_MODER_MODE2;

GPIOA->MODER |= GPIO_MODER_MODE2_1;


Настройка RX:

//PA3 floating input (00)

GPIOA->MODER &= ~GPIO_MODER_MODE3;

GPIOA->MODER |= GPIO_MODER_MODE3_1;

Настройка скорости (не обязательно):


//PA2 speed

GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED2;

GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED2_1;


Вычисляем Baudrate:



#define APB1CLK 42000000UL

#define BAUDRATE 9600UL

USART2->BRR =(APB1CLK+BAUDRATE/2)/BAUDRATE;


Меняем скорость шины под свою, если необходимо.

Включаем прием и передачу TE и RE через регистр CR1. Включаем работу UARTA битом UE.


USART2->CR1 |= USART_CR1_RE; //RX enable

USART2->CR1 |= USART_CR1_TE; //TX enable

USART2->CR1 |= USART_CR1_UE; //USART1 enable


По идее, с этим уже можно работать. Закидываем данные в регистр DR и принимаем их на той стороне. Функции для передачи байта и строки:


void USART2_send_byte(char ch)

{

while(!(USART2->SR & USART_SR_TC)); //waiting for byte receiving complete

USART2->DR = ch; //WRITE_REG our char

}


void USART2_send_string(char* str)

{

uint8_t i = 0;

while(str[i])

USART2_send_byte(str[i++]);

}


Чтобы принимать данные, включаем прерывание по окончании приема данных и объявляем вектор прерывания:


USART2->CR1 |= USART_CR1_RXNEIE; //RXNE interrupt enable

NVIC_EnableIRQ(USART2_IRQn); //interrupt vector


Инициализируем функцию прерывания:


void USART2_IRQHandler(void)

{

if(USART2->SR & USART_CR1_RXNEIE)

{

USART2->SR &= ~USART_CR1_RXNEIE;

//IRQ programm...

}

}


В условии if проверяем флаг, означающий, что на вход поступили данные. Если флаг установлин, то мы его сбрасываем и производим обработку данных.


Полный код:


#include "stm32f4xx.h"

#include "FreeRTOS.h"

#include "task.h"

#include "queue.h"


#define APB1CLK 42000000UL

#define BAUDRATE 9600UL


void RCC_init(void);

void GPIO_init(void);

void UART2_init(void);

void USART2_send_byte(char ch);

void USART2_send_string(char* str);

//***FreeRTOS functions

void vTaskLedArrow(void *argument);

void vTaskLedBlink(void *argument);

void vTaskCheckButton(void *argument);


xTaskHandle xLedBlinkHandle = NULL;


int main(void)

{

RCC_init();

GPIO_init();

UART2_init();


USART2_send_string("\rWelcome!\n\r");

xTaskCreate(vTaskLedArrow, "Arrow", 32, NULL, 1, NULL);

xTaskCreate(vTaskLedBlink, "Blink", 32, NULL, 1, &xLedBlinkHandle);

xTaskCreate(vTaskCheckButton, "UsrBttn", 32, NULL, 1, NULL);

vTaskStartScheduler();

while(1)

{

/*Code Section for Error Indication*/

GPIOD->BSRR |= GPIO_BSRR_BS12;

GPIOD->BSRR |= GPIO_BSRR_BS13;

GPIOD->BSRR |= GPIO_BSRR_BS14;

GPIOD->BSRR |= GPIO_BSRR_BS15;

}

}


void RCC_init(void)

{

RCC->CR |= (RCC_CR_HSEON); //Enable HSE

while( !(RCC->CR & RCC_CR_HSERDY) ) {}; //ready to start HSE


//FLASH

FLASH->ACR |= FLASH_ACR_LATENCY //latency for flash memory

| FLASH_ACR_PRFTEN

| FLASH_ACR_ICEN

| FLASH_ACR_DCEN;

//PLL - HSE

RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE; //set HSE as PLL source

RCC->CR &= ~(RCC_CR_PLLON); //disable PLL before changes

//PLL M

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLM); //clear all PLLM bits

RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_2; //set PLLM = 4 (100)


//PLL P

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLP); //main PLL division PLLP = 2: 00

//PLL N

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLN); //clear all PLLN bits with mask

RCC->PLLCFGR |= (RCC_PLLCFGR_PLLN_3 //set PLLN = 168 (1010 1000)

| RCC_PLLCFGR_PLLN_5 //for 8 or 16 MHz HSE

| RCC_PLLCFGR_PLLN_7); //

//PLL Q 7 (0111)

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLQ);

RCC->PLLCFGR |= (RCC_PLLCFGR_PLLQ_0

| RCC_PLLCFGR_PLLQ_2

| RCC_PLLCFGR_PLLQ_2);

//AHB Prescaler

RCC->CFGR &= ~(RCC_CFGR_HPRE); //Prescaler = 1

RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB = SYSCLK/1

//APB1 Prescaler 4

RCC->CFGR &= ~(RCC_CFGR_PPRE1);

RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

//APB2 Prescaler 2

RCC->CFGR &= ~(RCC_CFGR_PPRE2);

RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

//PLL enable

RCC->CR |= RCC_CR_PLLON; //enalbe PLL

while((RCC->CR & RCC_CR_PLLRDY) == 0) {} //wait for PLL is ready

//PLL System

//RCC->CFGR &= ~RCC_CFGR_SW;

RCC->CFGR |= RCC_CFGR_SW_PLL; //PLL selected as system clock

while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} //wait for PLL is used

}


void GPIO_init(void)

{

//RCC

RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; //enable RCC for PortD

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //enable RCC for PortA

//Port A

GPIOA->MODER &= ~(1 << 0); //Set output mode for PA0 (User Button)

//Port D

GPIOD->MODER = 0x55000000; //0b0101.0101 0000.0000 0000.0000 0000.0000

GPIOD->OTYPER = 0; //push-pull enable

GPIOD->OSPEEDR = 0; //low speed

GPIOD->BSRR = 0xF0000000; //turn off all LED

}


void UART2_init(void)

{

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //enable RCC for PortA

RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //enable UART clocking

//USART2 TX - PA2

//USART2 RX - PA3

//PA2 alternate function (USART = 0111)

GPIOA->AFR[0] |= GPIO_AFRL_AFSEL2; //set all bits

GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL2_3; //clr last bit

//PA3 alternate function (USART = 0111)

GPIOA->AFR[0] |= GPIO_AFRL_AFSEL3; //set all bits

GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL3_3; //clr last bit

//PA2 Alternate Push-Pull (10) !!! ALTERNATE !!!

GPIOA->MODER &= ~GPIO_MODER_MODE2;

GPIOA->MODER |= GPIO_MODER_MODE2_1;

//PA3 floating input (10)

GPIOA->MODER &= ~GPIO_MODER_MODE3;

GPIOA->MODER |= GPIO_MODER_MODE3_1;

//PA2 speed

/* GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED2;

GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED2_1;*/

USART2->BRR =(APB1CLK+BAUDRATE/2)/BAUDRATE;

USART2->CR1 |= USART_CR1_RE; //RX enable

USART2->CR1 |= USART_CR1_TE; //TX enable

USART2->CR1 |= USART_CR1_UE; //USART1 enable

NVIC_EnableIRQ(USART2_IRQn); //interrupt vector

USART2->CR1 |= USART_CR1_RXNEIE; //RXNE interrupt enable

}


void USART2_send_byte(char ch)

{

while(!(USART2->SR & USART_SR_TC)); //waiting for byte receiving complete

USART2->DR = ch; //WRITE_REG our char

}


void USART2_send_string(char* str)

{

uint8_t i = 0;

while(str[i])

USART2_send_byte(str[i++]);

}


void USART2_IRQHandler(void)

{

if(USART2->SR & USART_SR_RXNE)

{

USART2->SR &= ~USART_SR_RXNE;

//IRQ programm...

USART2_send_byte(USART2->DR);

}

}


void vTaskLedArrow(void *argument)

{

while(1)

{

GPIOD->BSRR |= GPIO_BSRR_BR13;

GPIOD->BSRR |= GPIO_BSRR_BR15;

vTaskDelay(3000); //300 ms

GPIOD->BSRR |= GPIO_BSRR_BS13;

vTaskDelay(3000);

GPIOD->BSRR |= GPIO_BSRR_BS15;

vTaskDelay(3000);

GPIOD->BSRR |= GPIO_BSRR_BR13;

vTaskDelay(3000);

}

}


void vTaskLedBlink(void *argument)

{

while(1)

{

GPIOD->BSRR |= GPIO_BSRR_BS12;

GPIOD->BSRR |= GPIO_BSRR_BS14;

vTaskDelay(2000); //300 ms

GPIOD->BSRR |= GPIO_BSRR_BR12;

GPIOD->BSRR |= GPIO_BSRR_BR14;

vTaskDelay(2000);

}

}


void vTaskCheckButton(void *argument)

{

uint8_t taskState = 1;

while(1)

{

if(GPIOA->IDR & GPIO_IDR_ID0)

{

while(GPIOA->IDR & GPIO_IDR_ID0)

{ vTaskDelay(100); }


if(taskState)

{

USART2_send_string("LED are deactivated\n\r");

GPIOD->BSRR |= GPIO_BSRR_BR12;

GPIOD->BSRR |= GPIO_BSRR_BR14;

vTaskSuspend(xLedBlinkHandle);

taskState = 0;

}

else

{

USART2_send_string("LED are activated\n\r");

vTaskResume(xLedBlinkHandle);

taskState = 1;

}

}

vTaskDelay(300);

}

}






























 
MyTetra Share v.0.53
Яндекс индекс цитирования