在STM32 HAL库中,__HAL_LINKDMA
是一个宏,用于将特定的外设(如UART、SPI等)的句柄(Handle)与其对应的DMA(直接内存访问)句柄链接起来。这样做的目的是让HAL库内部能够自动管理DMA传输,从而简化代码并减少出错的可能性。
当你在使用__HAL_LINKDMA
链接串口的handler (UART_HandleTypeDef
) 和DMA的handler (DMA_HandleTypeDef
) 时,如果看到示例代码中DMA_HandleTypeDef
前面加了extern
关键字,这通常意味着DMA_HandleTypeDef
的定义是在另一个源文件中完成的,而不是在当前文件中。
使用extern
的原因
-
跨文件引用:
extern
关键字用于声明一个变量或对象是在其他地方定义的。当你需要在多个文件中访问同一个变量或对象时,你通常在一个文件中定义它(不提供extern
),而在其他需要访问该变量的文件中声明它(使用extern
)。 -
模块化设计:在嵌入式系统开发中,模块化设计是非常重要的。通过将不同的硬件外设的初始化和管理代码放在不同的源文件中,可以提高代码的可读性和可维护性。对于DMA和串口这样的外设,可能会在不同的源文件中使用它们,因此需要使用
extern
来跨文件引用它们的句柄。
示例
假设你有两个源文件:main.c
和uart_dma.c
。
-
在
uart_dma.c
中,你定义了DMA的句柄并初始化了它:DMA_HandleTypeDef hdma_usartx_tx;void MX_DMA_Init(void) {// 初始化DMA句柄hdma_usartx_tx.Instance = DMAx_Channely; // 替换为实际的DMA实例和通道// 其他初始化代码... }
-
在
main.c
中,你需要链接串口的handler到DMA的handler,但因为你是在main.c
中引用hdma_usartx_tx
,而它是在uart_dma.c
中定义的,所以你需要在main.c
的顶部声明它:extern DMA_HandleTypeDef hdma_usartx_tx;void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USARTx_UART_Init(void);int main(void) {HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init(); // 确保DMA初始化在链接之前完成MX_USARTx_UART_Init();// 链接DMA句柄到UART句柄__HAL_LINKDMA(&huartx, hdmatx, hdma_usartx_tx);// 其他代码... }static void MX_USARTx_UART_Init(void) {huartx.Instance = USARTx; // 替换为实际的USART实例huartx.Init.BaudRate = 115200;// 其他初始化代码... }
在这个例子中,extern
关键字允许main.c
访问在uart_dma.c
中定义的hdma_usartx_tx
变量。
总结
extern
的使用是为了在多个源文件之间共享变量。在STM32 HAL库中使用__HAL_LINKDMA
时,如果DMA句柄是在另一个文件中定义的,你需要在当前文件中使用extern
来声明它,以便能够链接到串口的handler。