bs_bcu_app/drv/drv_usart.c

244 lines
8.0 KiB
C
Raw Normal View History

2024-11-07 17:24:19 +08:00
/**
****************************************************************************************************
* @file bsp_delay.c
* @author
* @version V1.0
* @date 2024-02-10
* @brief
****************************************************************************************************
*/
#include "drv_sys.h"
#include "drv_usart.h"
/* 如果使用os,则包括下面的头文件即可 */
#if SYS_SUPPORT_OS
#include "os.h" /* os 使用 */
#endif
/******************************************************************************************/
/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */
#if 1
#if (__ARMCC_VERSION >= 6010050) /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t"); /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t"); /* AC6下需要声明main函数为无参数格式否则部分例程可能出现半主机模式 */
#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
#endif
/* 不使用半主机模式至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
/* FILE 在 stdio.h里面定义. */
FILE __stdout;
/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
while ((USART1->SR & 0X40) == 0); /* 等待上一个字符发送完成 */
USART1->DR = (uint8_t)ch; /* 将要发送的字符 ch 写入到DR寄存器 */
return ch;
}
#endif
/***********************************************END*******************************************/
#if USART_EN_RX /* 如果使能了接收 */
/* 接收缓冲, 最大USART_REC_LEN个字节. */
uint8_t g_usart_rx_buf[USART_REC_LEN];
/* 接收状态
* bit15
* bit14 0x0d
* bit13~0
*/
uint16_t g_usart_rx_sta = 0;
uint8_t g_rx_buffer[RXBUFFERSIZE]; /* HAL库使用的串口接收缓冲 */
2024-11-11 17:18:25 +08:00
UART_HandleTypeDef g_uart2_handle; /* UART句柄 */
2024-11-07 17:24:19 +08:00
/**
* @brief X初始化函数
* @param baudrate: ,
* @note : , .
* USART的时钟源在sys_stm32_clock_init().
* @retval
*/
void usart_init(uint32_t baudrate)
{
2024-11-11 17:18:25 +08:00
g_uart2_handle.Instance = USART_UX; /* USART2 */
g_uart2_handle.Init.BaudRate = baudrate; /* 波特率 */
g_uart2_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
g_uart2_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
g_uart2_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
g_uart2_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
g_uart2_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&g_uart2_handle); /* HAL_UART_Init()会使能UART1 */
2024-11-07 17:24:19 +08:00
/* 该函数会开启接收中断标志位UART_IT_RXNE并且设置接收缓冲以及接收缓冲接收最大数据量 */
2024-11-11 17:18:25 +08:00
HAL_UART_Receive_IT(&g_uart2_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
2024-11-07 17:24:19 +08:00
}
/**
* @brief UART底层初始化函数
* @param huart: UART句柄类型指针
* @note HAL_UART_Init()
* 使
* @retval
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct;
2024-11-11 17:18:25 +08:00
if(huart->Instance == USART_UX) /* 如果是串口2进行串口2 MSP初始化 */
2024-11-07 17:24:19 +08:00
{
2024-11-11 17:18:25 +08:00
USART_UX_CLK_ENABLE(); /* USART2 时钟使能 */
2024-11-07 17:24:19 +08:00
USART_TX_GPIO_CLK_ENABLE(); /* 发送引脚时钟使能 */
USART_RX_GPIO_CLK_ENABLE(); /* 接收引脚时钟使能 */
gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* TX引脚 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
2024-11-11 17:18:25 +08:00
// gpio_init_struct.Alternate = USART_TX_GPIO_AF; /* 复用为USART2 */
2024-11-07 17:24:19 +08:00
HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct); /* 初始化发送引脚 */
gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* RX引脚 */
2024-11-11 17:18:25 +08:00
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
// gpio_init_struct.Alternate = USART_RX_GPIO_AF; /* 复用为USART2 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
2024-11-07 17:24:19 +08:00
HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 初始化接收引脚 */
#if USART_EN_RX
HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3); /* 抢占优先级3子优先级3 */
2024-11-11 17:18:25 +08:00
HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART2中断通道 */
2024-11-07 17:24:19 +08:00
#endif
}
}
/**
* @brief Rx传输回调函数
* @param huart: UART句柄类型指针
* @retval
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
2024-11-11 17:18:25 +08:00
if(huart->Instance == USART_UX) /* 如果是串口2 */
2024-11-07 17:24:19 +08:00
{
if((g_usart_rx_sta & 0x8000) == 0) /* 接收未完成 */
{
if(g_usart_rx_sta & 0x4000) /* 接收到了0x0d */
{
if(g_rx_buffer[0] != 0x0a)
{
g_usart_rx_sta = 0; /* 接收错误,重新开始 */
}
else
{
g_usart_rx_sta |= 0x8000; /* 接收完成了 */
}
}
else /* 还没收到0X0D */
{
if(g_rx_buffer[0] == 0x0d)
{
g_usart_rx_sta |= 0x4000;
}
else
{
g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0] ;
g_usart_rx_sta++;
if(g_usart_rx_sta > (USART_REC_LEN - 1))
{
g_usart_rx_sta = 0; /* 接收数据错误,重新开始接收 */
}
}
}
}
}
}
/**
2024-11-11 17:18:25 +08:00
* @brief 2
2024-11-07 17:24:19 +08:00
* @param
* @retval
*/
void USART_UX_IRQHandler(void)
{
uint32_t timeout = 0;
uint32_t maxDelay = 0x1FFFF;
#if SYS_SUPPORT_OS /* 使用OS */
OSIntEnter();
#endif
2024-11-11 17:18:25 +08:00
HAL_UART_IRQHandler(&g_uart2_handle); /* 调用HAL库中断处理公用函数 */
2024-11-07 17:24:19 +08:00
timeout = 0;
2024-11-11 17:18:25 +08:00
while (HAL_UART_GetState(&g_uart2_handle) != HAL_UART_STATE_READY) /* 等待就绪 */
2024-11-07 17:24:19 +08:00
{
timeout++; /* 超时处理 */
if(timeout > maxDelay)
{
break;
}
}
timeout=0;
/* 一次处理完成之后重新开启中断并设置RxXferCount为1 */
2024-11-11 17:18:25 +08:00
while (HAL_UART_Receive_IT(&g_uart2_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE) != HAL_OK)
2024-11-07 17:24:19 +08:00
{
timeout++; /* 超时处理 */
if (timeout > maxDelay)
{
break;
}
}
#if SYS_SUPPORT_OS /* 使用OS */
OSIntExit();
#endif
}
#endif