1 AT串口抽象层的设计思路及代码实现
1.1 AT串口抽象层的设计思路
我们先来看下AT串口的发送模型和AT串口接收模型:
下面看一下发送流程、接收流程及中断处理流程:
1.2 AT串口抽象层的代码实现
at_uart_hal.h:
#ifndef __AT_UART_HAL_H
#define __AT_UART_HAL_H
#include <stdbool.h>
bool at_uart_init(void);
bool at_uart_deinit(void);
uint32_t at_uart_send(const void *pdata, uint32_t size, uint32_t timeout);
uint32_t at_uart_receive(void *pdata, uint32_t expect_size,uint32_t timeout);
void at_uart_irq_handler(void);
#endif
at_uart_hal.c:
#include <stdbool.h>
#include "main.h"
#include "usart.h"
#include "app_debug.h"
#include "FreeRTOS.h"
#include "stream_buffer.h"
#define AT_UART huart4
#define AT_UART_SEND_BUF_SIZE 300
#define AT_UART_RECV_BUF_SIZE 300
static StreamBufferHandle_t stream_send=NULL;
static StreamBufferHandle_t stream_recv=NULL;
static bool is_inited=false;
bool at_uart_deinit(void)
{
DEBUG("at uart deinit");
is_inited=false;
__HAL_UART_DISABLE_IT(&AT_UART,UART_IT_RXNE);
__HAL_UART_DISABLE_IT(&AT_UART,UART_IT_TXE);
if(stream_send!=NULL)
{
vStreamBufferDelete(stream_send);
}
if(stream_recv!=NULL)
{
vStreamBufferDelete(stream_recv);
}
return true;
}
bool at_uart_init(void)
{
if(is_inited)return true;
DEBUG("at uart init!");
do
{
stream_send=xStreamBufferCreate(AT_UART_SEND_BUF_SIZE,1);
if(stream_send==NULL)break;
stream_recv=xStreamBufferCreate(AT_UART_RECV_BUF_SIZE,1);
if(stream_recv==NULL)break;
__HAL_UART_ENABLE_IT(&AT_UART,UART_IT_RXNE);
is_inited=true;
DEBUG("at uart init ok!");
return true;
} while (0);
at_uart_deinit();
return false;
}
uint32_t at_uart_send(const void *pdata, uint32_t size, uint32_t timeout)
{
uint32_t write_len;
if(is_inited==false)return 0;
write_len=xStreamBufferSend(stream_send,pdata,size,timeout);
__HAL_UART_ENABLE_IT(&AT_UART,UART_IT_TXE);
return write_len;
}
uint32_t at_uart_receive(void *pdata, uint32_t expect_size,uint32_t timeout)
{
uint32_t read_len;
if(is_inited==false)return 0;
read_len=xStreamBufferReceive(stream_recv,pdata,expect_size,timeout);
return read_len;
}
void at_uart_irq_handler(void)
{
uint8_t ch;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if ((__HAL_UART_GET_IT(&AT_UART,UART_IT_TXE))&&
(__HAL_UART_GET_IT_SOURCE(&AT_UART,UART_IT_TXE)!=RESET))
{
if(xStreamBufferReceiveFromISR(stream_send,&ch,1,&xHigherPriorityTaskWoken)==1)
{
AT_UART.Instance->TDR=ch;
}
else
{
__HAL_UART_DISABLE_IT(&AT_UART,UART_IT_TXE);
}
}
if ((__HAL_UART_GET_IT(&AT_UART,UART_IT_RXNE))&&
(__HAL_UART_GET_IT_SOURCE(&AT_UART,UART_IT_RXNE)!=RESET))
{
ch=(uint8_t)(AT_UART.Instance->RDR&0xff);
xStreamBufferSendFromISR(stream_recv,&ch,1,&xHigherPriorityTaskWoken);
}
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
中断中需加入如下代码:
/**
* @brief This function handles USART4 and USART5 interrupt.
*/
void USART4_5_IRQHandler(void)
{
/* USER CODE BEGIN USART4_5_IRQn 0 */
extern void at_uart_irq_handler(void);
at_uart_irq_handler();
/* USER CODE END USART4_5_IRQn 0 */
/* USER CODE BEGIN USART4_5_IRQn 1 */
/* USER CODE END USART4_5_IRQn 1 */
}
测试代码如下:
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
float temp,humi;
uint8_t write_buf[]="1234567890";
uint8_t read_buf[20];
uint16_t read_len;
#define TEST_NAME 0X0001
uint8_t buf[5];
debug_init();
led_init();
key_init();
led_blink(2,5);
sht30_init();
at_uart_init();
for(;;)
{
if(at_uart_receive(buf,1,1000))
{
DEBUG("-%c-",buf[0]);
}
//at_uart_send("12345\r\n",7,1000);
// storage_write(TEST_NAME,sizeof(write_buf),write_buf);
// memset(read_buf,0,20);
// read_len=20;
// if(storage_read(TEST_NAME,&read_len,read_buf))
// {
// DEBUG("------%s-----",read_buf);
// }
// if(sht30_get_temp_humi(&temp,&humi))
// {
// DEBUG("temp=%f,humi=%f",temp,humi);
// }
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}