STM32串口发送

在能使板子灯点亮后,下一步就是对串口进行操作了,首先最基础的是让板子向串口发送信息,而后让电脑从 CH340 中接收到这些信息,本篇便是要求这个:

传输一个字节

HAL 库有 HAL_UART_Transmit 函数来传输。该函数的声明为:

1
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)

第一位指定 UART 的指针,第二为要传输内容的地址。第三项为大小,第四项为超时时间,可以用 HAL_MAX_DELAY ,其的数值非常大

1
#define HAL_MAX_DELAY      0xFFFFFFFFU

基于 HAL_UART_Transmit 函数可以实现将一字节的数据传输到串口中:

1
2
3
4
void SerialSendByte(uint8_t Byte)
{
	HAL_UART_Transmit(&huart1, &Byte, 1, HAL_MAX_DELAY);
}

效果:

1
SerialSendByte('a');

发送字符串

在实现一个字节的发送之后,可以更进一步地尝试发送一个字符串,方法也很简单,将字符串拆开一个个地发送即可:

1
2
3
4
5
6
7
void SerialSendString(char *String)
{
	for (uint16_t i = 0; String[i] != '\0';i++)
	{
		SerialSendByte(String[i]);
	}
}

因为字符串的末尾一定有 \0 终止符,所以只要自增在遇到 \0 时打断循环即可。

主要是注意数据类型,这里使用 uint16_t 。

效果:

1
		SerialSendString("Hello! ");

发送数组

在实现了发送数组功能后,可以更进一步的实现对普遍性的数组发送。这时候就没有 \0 帮助判断,需要知道数组的长度,来进行遍历。

1
2
3
4
5
6
7
void SerialSendArray(uint8_t *Array, uint16_t Length)
{
	for(uint16_t i = 0; i < Length;i++)
	{
		SerialSendByte(Array[i]);
	}
}

输入数组地址,并说明数组长度这样数组的内容就可以通过串口输入到上位机。

效果:

1
2
	uint8_t arr[4] = {1, 2, 3, 4};
	SerialSendArray(arr, 4);

发送数字

发送数字看起来挺简单,不是吗?

但是实际上我们发送的字节是以二进制发送,呈现出来的是 HEX 也就是 16 进制。如果将原本以 int 类型存储的数字转换成字符然后再传输到串口会更有可读性,这时候就有点儿复杂了。

在此之前,需要理解如何将 int 类型的数字按每一位转变成字符。

假设现在要输出数字 1234,那么需要将其分成 1 2 3 4 这几个部分分别转换成字符的数字依次输出。先提取的是最高位。比如在这里 将原本数字 / 1000 再 % 10 (可有可无的在这里),就可以得到 1,再接着 / 100 % 10 就是 2 依次进行发现整除的数字从 1000 到 100 之后是 10 直到 1。它们之间可以用 $10^{n}$ 来代表。

首先,我们需要实现一个在整型环境下的 pow 函数, c 语言数学标准库提供的是 double 类型。

非常简单:

1
2
3
4
5
6
7
8
9
uint32_t SerialPow(uint32_t x, uint32_t y)
{
	uint32_t res = 1;
	while(y--)
	{
		res *= x;
	}
	return res;
}

然后,我们根据先前总结出来的经验来编写输出函数:

1
2
3
4
5
6
7
8
void SerialSendNumber(uint32_t num, uint8_t length)
{
	uint8_t i;
	for (i = 0; i < length;i++)
	{
		SerialSendByte(num / SerialPow(10, length - i - 1)% 10 + '0');
	}
}

这里 + ‘0’ 可以从 ASCII 编码中查询到,应该是比较简单的,这里不做过多介绍。

而且这里还需要标记数字长度也就是位数。

效果:

1
		SerialSendNumber(1234, 4);

实现简单的 printf

printf 函数是很经常使用的内置库。当然,在串口中是无法直接调用的,一种方式是自己实现一个 printf 函数,需要用到可变参数,实际和真实的 printf 差别不大。

这里简单介绍下可变参数,需要使用 <stdarg.h><stdio.h> 两个头文件

1
2
3
4
5
6
7
8
9
void SerialPrintf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	SerialSendString(String);
}

实际是通过可变参数和格式化将内容输入到 string 内,而后调用 SerialSendString 来输出。

效果:

1
		SerialPrintf("Hello, %d", 11);

萌ICP备20241614号