Настраиваем UART на передачу и прием данных в микроконтроллера STM32f103 в среде программирования Keil uVision.

Страница на этапе разработки

Для начала рассмотрим передачу данных. 

Данная функция необходимо для общения с некоторыми устройствами, обмен данными, а так же может помочь в настройке ПО, когда нет возможности подключиться к микроконтроллеру, но при этом надо как то мониторить процессы внутри микроконтроллера.

 В качестве переходника будем использовать USB адаптер:

Подключаем переходник к выходам РА10 и РА9:

Так как мы будем использовать HAL библиотеку, рассмотрим какие именно функции мы будем использовать:

HAL_UART_Transmit_DMA(&huartх,rx_buffer,4) — 

HAL_UART_Transmit_IT(&huart1,rx_buffer,3) — 

 

/* USER CODE BEGIN Includes */
#include
/* USER CODE END Includes */

/* USER CODE BEGIN PTD */
uint16_t g=0;
char str[16];
uint8_t rx_buffer[16];
/* USER CODE END PTD */

/* USER CODE BEGIN 0 */

void send(char chr) {
while(!(USART1->SR & USART_SR_TC));
USART1->DR = chr;
}

void send_str(char* str) {
int i=0;
while(str[i])
send(str[i++]);
}

/*———————-ITM_SendChar——————————————-*/
int _write(int file, uint8_t *ptr, int len) {
for (int DataIdx = 0; DataIdx < len; DataIdx++) {
ITM_SendChar(*ptr++);
}
return len;
}

/* USER CODE END 0 */

/////////////////////////////////////////

 g++;
sprintf(str,»g= %05i; «,g);
HAL_Delay(500);
send_str(str);
send_str(«\r\n»);
rx_buffer[0]=’D’;
rx_buffer[1]=’M’;
rx_buffer[2]= ‘A’;
rx_buffer[3]= 0x0A;
HAL_UART_Transmit_DMA(&huart1,rx_buffer,4);
HAL_Delay(100);
rx_buffer[0]=’O’;
rx_buffer[1]=’k’;
rx_buffer[2]= 0x0A;
HAL_UART_Transmit_IT(&huart1,rx_buffer,3);

Теперь  напишем программный код для приема данных. 

Для начала рассмотрим функции с которыми будем работать:
HAL_UART_Receive(&huartx, UARTx_rxBuffer, Nbyte, time);
где:
х — номер UART который мы используем
UARTx_rxBuffer — буфер куда будут помещены данные
Nbyte — количество бай которые мы ожидаем
time — время ожидания 
Данная функция является блокирующей, то есть если мы не получили данных, мы будем их ожидать в течении времени time. Для продолжения выполнения программы должны прийти данные или выйти время ожидания time.

HAL_UART_Receive_IT(&huartx, UARTx_rxBuffer, Nbyte )  — в данной функции нет времени ожидания, она работает по прерыванию. То есть, как только появляются данные, программа переходит в прерывания, получает данные и возвращается обратно к основному коду.
Данную функцию можно использовать, когда у Вас не большой поток данных, иначе микроконтроллер будет постоянно находиться в прерывании.

HAL_UART_Receive_DMA(&huartх, UARTх_rxBuffer, Nbyte)  — данная функция использует DMA, что значительно уменьшит нагрузку на микроконтроллер, так как в данном случаи данные будут помещены в нужную ячейку самостоятельно и все, что нужно будет сделать — это забрать их оттуда.

Настроим сразу все необходимые прерывания и DMA:

Включаем DMA:
Включаем прерывания:

Остальное уже относится к обработке полученных данных. Добавим светодиод который при получении символа ‘1’ будет включаться, а при получении символа ‘0’ будет выключаться. У нас на плате есть светодиод, мы его и задействуем.
Программный код:
/* USER CODE BEGIN PTD */
uint8_t UART1_rxBuffer[3] = {48};
uint8_t rx_buffer[16];
/* USER CODE END PTD */

/* USER CODE BEGIN 0 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
   //  HAL_UART_Receive_DMA (&huart1, UART1_rxBuffer, 3);
HAL_UART_Receive_IT(&huart1, UART1_rxBuffer, 3);
}
 
/* USER CODE END 0 */
 
 /* USER CODE BEGIN WHILE */
HAL_Delay(100);
  rx_buffer[0]=’O’;
  rx_buffer[1]=’k’;
  rx_buffer[2]= 0x0A;
  HAL_UART_Transmit_IT(&huart1,rx_buffer,3);
//HAL_UART_Receive_DMA (&huart1, UART1_rxBuffer, 3);
HAL_UART_Receive_IT(&huart1, UART1_rxBuffer, 3);
while (1)
  {
// HAL_UART_Receive(&huart1, UART1_rxBuffer, 3, 5000);
if(UART1_rxBuffer[0]==48){
     HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET);
}else{
  HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_SET);
}
    /* USER CODE END WHILE */