【GD32】(二) 基本外设使用

张开发
2026/4/3 14:26:11 15 分钟阅读
【GD32】(二) 基本外设使用
文章目录0 前言1 关于参考代码2 时钟相关3 IIC4 CAN0 前言在上一篇博客中主要介绍了GD32的基本开发方式和标准库开发方式下模板工程的建立读者对标准库方式下的开发有了一个大体的认识但在实际开发过程中重点是对于外设的理解以及使用因此这篇文章主要是介绍GD32的外设以及标准库的使用。1 关于参考代码GD32官方效仿ST整了一个类似的图形界面快速配置芯片外设的工具想推广HAL库但在当前阶段感觉主流还是使用标准库而且对于有一定经验的开发者来说提供完善的数据手册和例程即可搭建好代码底座然后在此基础上完成业务逻辑。手册自不必说官网还是提供了比较完善的手册的。例程是很多开发者忽略的一个点其实官方为很多型号的芯片都出过评估板而且附带评估板的原理图设计手册和例程对于新接触这款芯片的开发者来说是非常重要的资料。如果没有评估板也不想买问题也不大官方的标准固件库中其实也有丰富的例程足够覆盖大部分应用场景的外设配置是重要的代码参考。如下图所示。使用方法也很简单就是将Example文件夹中的文件每一个小文件都对应一个项目复制到Template文件夹然后打开项目工程文件即可加载例程。如果不想影响模板最初的样子可以先复制一份。当然这里要注意修改一些 EVAL 相关的宏定义和自己的板子适配。这里就不再赘述一些非常基本的外设配置代码了只介绍可能出错和值得记录的点。2 时钟相关如何获取各总线时钟频率芯片固件库中提供了读取各总线频率的函数不过需要注意这个不是测量值而是根据配置的寄存器推断得到。// 输出各总线时钟uint32_tclkrcu_clock_freq_get(CK_SYS);printf(SYS_CLK: %d\n,clk);uint32_tclk1rcu_clock_freq_get(CK_AHB);printf(AHB_CLK: %d\n,clk1);uint32_tclk2rcu_clock_freq_get(CK_APB1);printf(APB1_CLK: %d\n,clk2);uint32_tclk3rcu_clock_freq_get(CK_APB2);printf(APB2_CLK: %d\n,clk3);如果测量代码的执行所消耗的时间当然可以使用定时器去配置但定时器配置要考虑模式中断等等相对麻烦。这里推荐使用dwt外设来测量。DWTData Watchpoint and Trace数据观察点和跟踪单元是Cortex-M系列单片机内核中的一个调试外设主要用于系统调试和性能分析。它包含一个32位的计数器CYCCNT可以记录内核时钟的运行次数从而实现高精度的时间测量。// DWT 寄存器地址#defineDWT_CTRL(*(volatileuint32_t*)0xE0001000)#defineDWT_CYCCNT(*(volatileuint32_t*)0xE0001004)#defineDWT_CYCCNTENA_BIT(1UL0)#defineDEM_CR(*(volatileuint32_t*)0xE000EDFC)#defineDEM_CR_TRCENA(1UL24)uint32_tstart,end;// 初始化 DWT 周期计数器voiddwt_init(void){// 使能 DWTDEM_CR|DEM_CR_TRCENA;// 使能 CYCCNTDWT_CTRL|DWT_CYCCNTENA_BIT;// 清零计数器DWT_CYCCNT0;}// 获取当前周期数staticinlineuint32_tdwt_get_cycles(void){returnDWT_CYCCNT;}// 转换为微秒 SystemCoreClock 为系统主频staticinlineuint32_tcycles_to_us(uint32_tcycles){returncycles/(SystemCoreClock/1000000U);}上面是外设初始化和函数定义实际测量时按照下面的方法非常简单。dwt_init();// 初始化DWTstartdwt_get_cycles();// 待测量的函数enddwt_get_cycles();printf(Secure Start Verifying used time: %lu us\n,cycles_to_us(end-start));注意这里可能会出现溢出的情况即start比end还大的情况但由于本身是无符号数所以相当于加了一个模长实际并不影响结果的输出。但是要注意执行时间的范围不能超过模长。DWT_CYCCNT 是 32 位约 17.9 秒溢出240MHz长时间测量需处理溢出。如果是这么长时间的话就不建议使用DWT了建议直接使用通用的定时器。3 IIC一开始参考官方例程发现怎么都不对后来参考了一个例程发现在ACK配置上有点问题。具体可以参考这篇文章。4 CAN具体可以参考这篇文章

更多文章