【DigiKey创意大赛】基于STM32H7B3I-DK的智能家居助手+串口通讯驱动与测试
[复制链接]
为了方便与其他外设和上位机交互,先实现灵活好用的串口驱动接口。
原理
设计环形缓冲区。接收中断将数据写u人缓冲区,读API查询缓冲区。
环形缓冲区读写需要做临界段保护处理。
代码
bsp_uart.h
#ifndef BSP_UART_H
#define BSP_UART_H
#ifdef __cplusplus
extern "C" {
#endif
void bsp_uart_init(void);
#ifdef __cplusplus
}
#endif
#endif
Bsp_uart.c
#include <stdio.h>
#include "main.h"
#define USARTx USART1
#define USARTx_CLK_ENABLE() __USART1_CLK_ENABLE()
#define USARTx_RX_GPIO_CLK_ENABLE() __GPIOA_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE() __GPIOA_CLK_ENABLE()
#define USARTx_FORCE_RESET() __USART1_FORCE_RESET()
#define USARTx_RELEASE_RESET() __USART1_RELEASE_RESET()
/* Definition for USARTx Pins */
#define USARTx_TX_PIN GPIO_PIN_9
#define USARTx_TX_GPIO_PORT GPIOA
#define USARTx_TX_AF GPIO_AF7_USART1
#define USARTx_RX_PIN GPIO_PIN_10
#define USARTx_RX_GPIO_PORT GPIOA
#define USARTx_RX_AF GPIO_AF7_USART1
UART_HandleTypeDef UartHandle;
void bsp_uart_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
USARTx_TX_GPIO_CLK_ENABLE();
USARTx_RX_GPIO_CLK_ENABLE();
/* Select SysClk as source of USART1 clocks */
RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
/* Enable USARTx clock */
USARTx_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = USARTx_TX_AF;
HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
/* UART RX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_RX_PIN;
GPIO_InitStruct.Alternate = USARTx_RX_AF;
HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
/*##-1- Configure the UART peripheral ######################################*/
/* Put the USART peripheral in the Asynchronous mode (UART Mode) */
/* UART configured as follows:
- Word Length = 8 Bits (7 data bit + 1 parity bit) :
BE CAREFUL : Program 7 data bits + 1 parity bit in PC HyperTerminal
- Stop Bit = One Stop bit
- Parity = ODD parity
- BaudRate = 9600 baud
- Hardware flow control disabled (RTS and CTS signals) */
UartHandle.Instance = USARTx;
UartHandle.Init.BaudRate = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if(HAL_UART_Init(&UartHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
__HAL_UART_ENABLE_IT(&UartHandle,UART_IT_RXNE);
HAL_NVIC_SetPriority(USART1_IRQn, 5 ,0U);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
int fputc(int ch, FILE *f)
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
void uart_sendbyte(uint8_t val)
{
HAL_UART_Transmit(&UartHandle, (uint8_t *)&val, 1, 0xFFFF);
}
extern void uart_api_rx_handler(const uint8_t *buffer, uint32_t length);
void USART1_IRQHandler(void)
{
uint8_t ch;
ch = (uint16_t) READ_REG(UartHandle.Instance->RDR);
uart_api_rx_handler(&ch, 1);
}
Uart_api.c
#include "uart_api.h"
extern void uart_sendbyte(uint8_t val);
typedef struct
{
uint32_t datalen_u32;
uint32_t maxlen_u32;
uint32_t in_u32;
uint32_t out_u32;
uint8_t* buffer_pu8;
}ring_buffer_t;
static uint8_t uart_ring_buffer[UART_RING_BUFFER_SIZE];
static ring_buffer_t s_ring_buffer_t=
{
.datalen_u32 = 0,
.maxlen_u32 = sizeof(uart_ring_buffer),
.in_u32 = 0,
.out_u32 = 0,
.buffer_pu8 = uart_ring_buffer,
};
void uart_api_rx_handler(const uint8_t *buffer, uint32_t length)
{
uint32_t i;
for(i=0;i<length; i++)
{
if(s_ring_buffer_t.datalen_u32 < s_ring_buffer_t.maxlen_u32)
{
s_ring_buffer_t.buffer_pu8[s_ring_buffer_t.in_u32] = buffer;
s_ring_buffer_t.datalen_u32++;
s_ring_buffer_t.in_u32++;
s_ring_buffer_t.in_u32 %= s_ring_buffer_t.maxlen_u32;
}
else
{
/* full */
break;
}
}
}
uint32_t uart_api_read(uint8_t *buff, uint32_t len)
{
uint32_t readlen = 0;
if(s_ring_buffer_t.datalen_u32 == 0)
{
return 0;
}
Alloc_Critical();
Enter_Critical();
uint32_t i;
for(i=0;i<len;i++)
{
if(s_ring_buffer_t.datalen_u32 > 0)
{
buff = s_ring_buffer_t.buffer_pu8[s_ring_buffer_t.out_u32];
s_ring_buffer_t.datalen_u32--;
s_ring_buffer_t.out_u32++;
s_ring_buffer_t.out_u32 %= s_ring_buffer_t.maxlen_u32;
readlen++;
}
else
{
break;
}
}
Exit_Critical();
return readlen;
}
void uart_api_write(uint8_t *buff, uint32_t len)
{
uint32_t i;
for(i=0; i<len ;i++)
{
uart_sendbyte(buff);
}
}
Uart_api.h
#ifndef UART_API_H
#define UART_API_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "cmsis_os.h"
#define Alloc_Critical()
#define Enter_Critical() taskENTER_CRITICAL();
#define Exit_Critical() taskEXIT_CRITICAL();
#define UART_RING_BUFFER_SIZE (1024+64)
void uart_api_rx_handler(const uint8_t *buffer, uint32_t length);
uint32_t uart_api_read(uint8_t *buff, uint32_t len);
void uart_api_write(uint8_t *buff, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif
测试
使用上位机发送数据,板子原样返回,测试收发完全正确。
uint8_t buffer[64];
uint32_t len;
while((len = uart_api_read(buffer, sizeof(buffer))) > 0)
{
uart_api_read(buffer,len);
}
|