STM32-UART串口通信,日志输出,任意长度数据接收

代码实现环境

STM32型号:STM32F103RCT6

STM32CubeMX配置:

  • 设置Connectivity的USART1的Mode为Asynchronous

  • 勾选NVIC Settings的global interrupt的Enabled

CubeMX配置

实现printf及自定义log日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LOG_ENABLE 1
#if LOG_ENABLE
#define log(format,...) printf(format"\r\n",##__VA_ARGS__)
#else
#define log(format,...)
#endif

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
// 参数1: 使用哪个usart
// 参数2: 字符,
// 参数3:输出数量,
// 参数4:超时等待时间
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1 , 0xffff);
return ch;
}
/* USER CODE END PD */

实现任意长度数据收发

1、声明变量及回调函数

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
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t RECEIVE_ARRAY[1024] = {0};
uint8_t RxByte;
uint8_t RxBuff[4096];
uint16_t Rx_Count;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
// 有串口消息进来, 这里就会执行

// if (USART1 == huart->Instance) {
//// char data[] = "hello !!!\r\n";
// // 把接收到的数据返回出去
// HAL_UART_Transmit(&huart1, RECEIVE_ARRAY, sizeof RECEIVE_ARRAY, 1000);
// // 若想中断重复生效,这里需要重新定义
// HAL_UART_Receive_IT(&huart1, RECEIVE_ARRAY, 1);
// }

/* Prevent unused argument(s) compilation warning */
UNUSED(huart);

RxBuff[Rx_Count++]=RxByte;

if(RxByte == 0x0A )
{
// 默认换行按\n退一个字节
int len = Rx_Count - 1;
// 如果换行是\r\n则要多退一个字节
if (RxBuff[Rx_Count - 2] == 0x0D){
len = Rx_Count - 2;
}
char data[len];
strncpy(data, RxBuff, len);

if (strncmp(data, "test", sizeof data) == 0) {
log("ttttt!");
}else if (strncmp(data, "good", sizeof data) == 0) {
printf("gggggggggggggggggggggggggggggggggggggggggggggggggggggggg!\r\n");
}else {
HAL_UART_Transmit(&huart1, data, sizeof data, 3000);
}
memset(RxBuff, 0, sizeof RxBuff);
Rx_Count=0;
}

if(Rx_Count>=4096)
{
memset(RxBuff, 0, sizeof RxBuff);
Rx_Count=0;
}
// 循环接收每个字节
while(HAL_UART_Receive_IT(&huart1,&RxByte,1)==HAL_OK);

}
/* USER CODE END 0 */

2、在MX_USART1_UART_Init();后添加 中断接收代码

1
2
3
/* USER CODE BEGIN 2 */
// 开启中断, 并将接收到的数据放到 RxByte 里
HAL_UART_Receive_IT(&huart1, &RxByte, 1);

3、测试发个欢迎消息给客户端

1
2
3
4
5
6
7
8
char data[] = "hello world!\r\n";
// 参数1: 使用哪个usart
// 参数2: 要发送的字符
// 参数3: 输出长度
// 参数4: 超时等待时间
HAL_UART_Transmit(&huart1, data, strlen(data), 3000);
printf("test: %d, %f \r\n", 123, 11.12345);
log("test log!");

4、如果想要使用printf输出浮点数的话,还需要做如下配置:

  • 修改CMakeLIst文件,追加-u _printf_float
1
2
3
SET(COMMON_FLAGS
"-mcpu=cortex-m3 ${FPU_FLAGS} -mthumb -mthumb-interwork -ffunction-sections -fdata-sections \
-g -fno-common -fmessage-length=0 -specs=nosys.specs -specs=nano.specs -u _printf_float")

如果仍然无法输出浮点数,就拷贝下面文件到Src目录中

1
~/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.0/Projects/STM3210C_EVAL/Examples/UART/UART_Printf/syscalls.c

这是因为我们所使用的库,默认是没有开启浮点数输出的.这里需要注意的是我们修改的是CubeMX工具自动生成的CMakeList,当我们重新使用CubeMX重新生成代码的时候,这里所做的所有修改都将会丢失.

注意:改动完成之后,请在Clion中Tools–>Cmake–>Reset Cache and Reload Project

实现效果

输入输出演示