目录
实验:通过串口一使用接收中断实现不定长数据收发
1.头文件内容如下
#ifndef __USART_H__
#define __USART_H__
#include "sys.h"
#define UART1_RX_BUF_SIZE 128
#define UART1_TX_BUF_SIZE 64
#define UART_EOK 0
#define UART_ERROR 1
#define UART_ETIMEOUT 2
#define UART_EINVAL 3
void uart1_init(uint32_t baudrate);
void uart1_receiv_test(void);
#endif
在头文件中,我定义了接收数组的长度和发送数组的长度,同时我也定义了一些调试信息
2.对串口进行初始化
uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE];
uint16_t uart1_rx_len = 0;
uint16_t uart1_cnt = 0, uart1_cntPre = 0;
UART_HandleTypeDef uart1_handle = {0};
void uart1_init(uint32_t baudrate)
{
uart1_handle.Instance = USART1;
uart1_handle.Init.BaudRate = baudrate;
uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;
uart1_handle.Init.StopBits = UART_STOPBITS_1;
uart1_handle.Init.Parity = UART_PARITY_NONE;
uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
uart1_handle.Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(&uart1_handle);
}
跟上一篇文章里面的初始化内容一样,这里不过多赘述
3.在msp函数中对外设gpio口和nvic进行初始化
msp公用的一个函数这里有三个串口,都会调用msp,所以先进行一个判断
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpio_initstruct;
//调用GPIO初始化函数
gpio_initstruct.Pin = GPIO_PIN_9; // 两个LED对应的引脚
gpio_initstruct.Mode = GPIO_MODE_AF_PP; // 推挽输出
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOA, &gpio_initstruct);
gpio_initstruct.Pin = GPIO_PIN_10; // 两个LED对应的引脚
gpio_initstruct.Mode = GPIO_MODE_AF_INPUT; // 推挽输出
HAL_GPIO_Init(GPIOA, &gpio_initstruct);
HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_NVIC_SetPriority(USART1_IRQn, 2, 2);
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
}
}
内容与之前的一样,也不过多赘述
4.在中断服务函数里面进行数据收发
void USART1_IRQHandler(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&uart1_handle, UART_FLAG_RXNE) != RESET)
{
//需要判断数组是否接收完,防止缓冲区被刷爆
if(uart1_cnt >= sizeof(uart1_rx_buf))
uart1_cnt = 0;
HAL_UART_Receive(&uart1_handle, &receive_data, 1, 1000);
uart1_rx_buf[uart1_cnt++] = receive_data;
}
}
5.重新定向到串口1中的SR DR
int fputc(int ch, FILE *f)
{
while((USART1->SR & 0X40) == 0);
USART1->DR = (uint8_t)ch;
return ch;
}
6.判断数据是否收发完成
uint8_t uart1_wait_receive(void)
{
if(uart1_cnt == 0)
return UART_ERROR;
if(uart1_cnt == uart1_cntPre)
{
uart1_cnt = 0;
return UART_EOK;
}
uart1_cntPre = uart1_cnt;
return UART_ERROR;
}
7.在每次接收数据时,先将数组里的内容清空,避免出现问题
void uart1_rx_clear(void)
{
memset(uart1_rx_buf, 0, sizeof(uart1_rx_buf));
uart1_rx_len = 0;
}
8.测试函数 如果数据接收完整了就打印出来内容
void uart1_receiv_test(void)
{
if(uart1_wait_receive() == UART_EOK)
{
printf("recv: %s\r\n", uart1_rx_buf);
uart1_rx_clear();
}
}
9.在main函数中实现
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
uart1_init(115200);
while(1)
{
uart1_receiv_test();
delay_ms(10);
}
}
10.运行后是这个样子