串口收发

接收单字节数据

前期准备

标准库:用户已经配置好串口的时钟、引脚(MSP层)和UART参数设置,已经配置串口中断;

HAL库:使用CubeMX或CubeIDE已经配置好串口的时钟、引脚(MSP层)和UART参数设置,已经配置串口中断;

1
2
3
4
5
6
7
8
9
10
11
/* 标准库 能够接收1个字节的数据 */
uint8_t my_rx_data; //定义串口接收的数据变量
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
my_rx_data = USART_ReceiveData(USART1);

USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* HAL库 能够接收1个字节的数据  */
//main.c
uint8_t my_rx_data; //定义串口接收的数据变量
int main(void)
{
HAL_UART_Receive_IT(&huart1,&my_rx_data,1);

while(1)
{

}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1)
{
//接收数据

HAL_UART_Receive_IT(&huart1, &my_rx_data, 1);
}
}

推荐教程

接收多个数据

定义一个固定长度的全局数组或字符串;

定义一个用于记录接收数据长度的变量,初试为0,接收累加;

标准库-WIFI为例

1
2
3
4
5
/* .h文件 */
#define ESP01S_RX_BUF_MAX_LEN 1024
extern char esp01s_rx_buf[];
extern uint16_t esp01s_rx_buf_len;
extern uint8_t esp01s_rx_data;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* .c文件 */

char esp01s_rx_buf[ ESP01S_RX_BUF_MAX_LEN ];
uint16_t esp01s_rx_buf_len = 0;
uint8_t esp01s_rx_data;

void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
esp01s_rx_data = USART_ReceiveData(USART1);

if( esp01s_rx_buf_len < (ESP01S_RX_BUF_MAX_LEN-1) )
{
esp01s_rx_buf[esp01s_rx_buf_len] = esp01s_rx_data;
esp01s_rx_buf_len++;
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}

HAL库-SCPI为例

1
2
3
4
#define EL_RX_BUF_MAX_LEN	1024
extern char el_rx_buf[];
extern uint16_t el_rx_buf_len;
extern uint8_t el_rx_data;
1
HAL_UART_Receive_IT(&huart1,&el_rx_data,1);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
char el_rx_buf[EL_RX_BUF_MAX_LEN];
uint16_t el_rx_buf_len = 0;
uint8_t el_rx_data = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1)
{
//接收电子负载的数据
if( el_rx_buf_len < (EL_RX_BUF_MAX_LEN-1) )
{
//接收到1个数据,存入
el_rx_buf[el_rx_buf_len] = el_rx_data;
el_rx_buf_len++;
}

HAL_UART_Receive_IT(&huart1, &el_rx_data, 1);
}
}
  • 以上逻辑同样适用于其他数据接收

接收整个对象

前提:接收的内容格式是制定好的。

按照制定的协议,定义全局结构体,结构体成员为各部分数据;

帧头 模式 长度 数据 CRC 帧尾
0xAA 0x01 | 0x02 0x03 X Y Z 模式+长度+数据 0xFE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define FRAME_HEAD	0xAA
#defien FRAME_TAIL 0xFE

// 定义全局结构体
typedef struct {
uint8_t mode;
uint8_t data_len;
uint16_t X_axis;
uint16_t Y_axis;
uint16_t Z_axis;
uint8_t CRC_8;
} GetData;

// 声明全局变量
extern GetData g_Get_Data;

uint8_t Calculate_CRC8(uint8_t *pData, uint8_t Size);
int get_data_from_uart(uint8_t uart_data, uint16_t data_len);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

uint8_t uart1_rx_data; //定义串口接收的数据变量
void USART1_IRQHandler(void)
{
static uint8_t RxState = 0; //定义表示当前状态机状态的静态变量
static int err;
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
uart1_rx_data = USART_ReceiveData(USART1);

/*当前状态为0,接收数据包包头*/
if (RxState == 0)
{
if (RxData == FRAME_HEAD) //如果数据确实是包头
{
RxState = 1; //置下一个状态
uart1_rx_buf_len = 0; //数据包的位置归零
}
}
/*当前状态为1,接收数据包数据*/
else if (RxState == 1)
{
//这里接收全部数据
uart1_rx_buf[uart1_rx_buf_len] = uart1_rx_data; //将数据存入数据包数组的指定位置
uart1_rx_buf_len ++; //数据包的位置自增
if (uart1_rx_buf_len >= 1 + 1 + uart1_rx_buf[1] + 1)
{
RxState = 2; //置下一个状态
}
}
/*当前状态为2,接收数据包包尾*/
else if (RxState == 2)
{
if (uart1_rx_data == FRAME_TAIL) //如果数据确实是包尾部
{
//数组中接收完成,放入结构体
err = get_data_from_uart(uart1_rx_buf, uart1_rx_buf_len);
if(err)
{
//CRC错误
}
else
{
RxState = 0; //状态归0
Serial_RxFlag = 1; //接收数据包标志位置1,成功接收一个数据包
}

}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}

int get_data_from_uart(uint8_t uart_data, uint16_t data_len)
{
g_Get_Data.mode = uart_data[0];
g_Get_Data.data_len = uart_data[1];
// g_Get_Data.X_axis = uart_data[2] uart_data[3];
// g_Get_Data.Y_axis = uart_data[4] uart_data[5];
// g_Get_Data.Z_axis = uart_data[6] uart_data[7];
g_Get_Data.CRC_8 = Calculate_CRC8(uart_data,data_len-1);
if( g_Get_Data.CRC_8^uart_data[data_len-1])
{
return 1;//err
}
return 0;
}


uint8_t Calculate_CRC8(uint8_t *pData, uint8_t Size)
{
unsigned char i;
unsigned char rCRC = 0;
unsigned char CRC_8_POLYNOMIAL = 0x29;

while(Size--)
{
rCRC ^= *pData++;
for(i=8; i>0; --i)
{
if(rCRC & 0x80)
{
rCRC = (rCRC << 1) ^ CRC_8_POLYNOMIAL;
}else {
rCRC =(rCRC << 1);
}
}
}

return(rCRC);
}