核心结论(死记这两句)
- . :结构体 变量 直接用,取成员
- ->:结构体 指针 专用,取成员
1. 符号 . (点)
使用场景 :你定义的是结构体普通变量
直接访问它的成员,和地址无关
cs
// 定义一个结构体变量(STM32常用)
TIM_HandleTypeDef htim2;
// 用 . 访问成员
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
2. 符号 -> (箭头)
使用场景 :你定义的是结构体指针
作用:指针指向的结构体对象的成员
它 等价于 (*指针).成员
cs
// 定义结构体指针
TIM_HandleTypeDef *p_tim = &htim2;
// 用 -> 访问成员(指针专用)
p_tim->Instance = TIM2;
// 等价于 (*p_tim).Instance = TIM2;
纠正小误区
❌ 说:->是需要指向结构体成员的地址
✅ 正确说法:
-> 是结构体指针 用来访问成员的符号,不是取地址
取地址用的是 &,和 -> 没关系!
终极口诀(STM32通用)
变量用点 . ,指针用箭头 ->
举个代码里的例子
cs
// 这是结构体变量 → 用 .
WS2812_HandleTypeDef ws2812;
ws2812.tim = &htim2;
// 这是结构体指针 → 用 ->
WS2812_HandleTypeDef *p_ws = &ws2812;
p_ws->tim = &htim2;

我们不让他累加,收到什么就发送什么。

这样子看起来挺正常的。

如果我们吧这个数值修改为10,就发现bug了。

还可能有的问题。

我们需要修改这里,来使得我们的接收DMA进入循环模式。我们不要让程序来启动DMA,要用硬件来启动DMA。

开启硬件DMA之后,我们就可以看到,就不需要我们手动开启DMA了。

只需要我们再接收时候,开启一次DMA就可以了。以后都由硬件帮我们启动DMA。我们现在第一次设置的字节是100,当我们接收的数据超过100之后,硬件就会帮我们启动DMA。

这个函数还是用来处理三种中断。

我们也可以导入我们的工程。

记得晶振要配置为72Mhz。
有点小问题,但是我们应该可以以后用到时候,进行一下处理,我们先看一看增加串口3的通信。

打开这个USART3。

异步串口。

添加DMA,接收的话,用循环DMA。

发送的话正常就可以了。

要开启全局中断。

可以看到串口1和串口3都被初始化了。

我们增加串口 3 的结构体。

我们跳转一下定义,发现有这个句柄就可以。

我们再默认任务里面,打开串口 3。

我们还需要再数组放入我们的句柄。

编译发现一个错误,我们来解决一下。所的是串口3未定义,我们需要声明一下。

就和串口1一样的进行声明。

还有变量也要声明。

然后再发送完成,添加接收的函数。

之后所有的判断是huart1的代码,都要加一份huart3。

DMA的初始化。

然后因为,串口3是一个结构体,他不是指针,所以我们改为这个。

之后编译发现没有错误和警告。

我们可以看到,发送什么就可以收到什么。