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

文章目录

    • 前期教程
    • [0 前言](#0 前言)
    • [1 关于参考代码](#1 关于参考代码)
    • [2 时钟相关](#2 时钟相关)
    • [3 IIC](#3 IIC)
    • [4 CAN](#4 CAN)

前期教程

0 前言

  在上一篇博客中,主要介绍了GD32的基本开发方式和标准库开发方式下模板工程的建立,读者对标准库方式下的开发有了一个大体的认识,但在实际开发过程中,重点是对于外设的理解以及使用,因此,这篇文章主要是介绍GD32的外设,以及标准库的使用。

1 关于参考代码

  GD32官方效仿ST整了一个类似的图形界面快速配置芯片外设的工具,想推广HAL库,但在当前阶段感觉主流还是使用标准库,而且对于有一定经验的开发者来说,提供完善的数据手册和例程即可搭建好代码底座,然后在此基础上完成业务逻辑。

  手册自不必说,官网还是提供了比较完善的手册的。例程是很多开发者忽略的一个点,其实官方为很多型号的芯片都出过评估板,而且附带评估板的原理图,设计手册和例程,对于新接触这款芯片的开发者来说是非常重要的资料。

  如果没有评估板也不想买,问题也不大,官方的标准固件库中其实也有丰富的例程,足够覆盖大部分应用场景的外设配置,是重要的代码参考。如下图所示。

  使用方法也很简单,就是将Example文件夹中的文件(每一个小文件都对应一个项目)复制到Template文件夹,然后打开项目工程文件,即可加载例程。如果不想影响模板最初的样子,可以先复制一份。当然,这里要注意修改一些 EVAL 相关的宏定义,和自己的板子适配。

这里就不再赘述一些非常基本的外设配置代码了,只介绍可能出错和值得记录的点。

2 时钟相关

如何获取各总线时钟频率

  芯片固件库中提供了读取各总线频率的函数,不过需要注意,这个不是测量值,而是根据配置的寄存器推断得到。

c 复制代码
// 输出各总线时钟
uint32_t clk = rcu_clock_freq_get(CK_SYS);
printf("SYS_CLK: %d\n", clk);
uint32_t clk1 = rcu_clock_freq_get(CK_AHB);
printf("AHB_CLK: %d\n", clk1);
uint32_t clk2 = rcu_clock_freq_get(CK_APB1);
printf("APB1_CLK: %d\n", clk2);
uint32_t clk3 = rcu_clock_freq_get(CK_APB2);
printf("APB2_CLK: %d\n", clk3);

如果测量代码的执行所消耗的时间

  当然可以使用定时器去配置,但定时器配置要考虑模式,中断等等,相对麻烦。这里推荐使用dwt外设来测量。DWT(Data Watchpoint and Trace,数据观察点和跟踪单元)是Cortex-M系列单片机内核中的一个调试外设,主要用于系统调试和性能分析。它包含一个32位的计数器(CYCCNT),可以记录内核时钟的运行次数,从而实现高精度的时间测量。

c 复制代码
// DWT 寄存器地址
#define DWT_CTRL            (*(volatile uint32_t *)0xE0001000)
#define DWT_CYCCNT          (*(volatile uint32_t *)0xE0001004)
#define DWT_CYCCNTENA_BIT   (1UL << 0)
#define DEM_CR              (*(volatile uint32_t *)0xE000EDFC)
#define DEM_CR_TRCENA       (1UL << 24)
uint32_t start, end;

// 初始化 DWT 周期计数器
void dwt_init(void) {
    // 使能 DWT
    DEM_CR |= DEM_CR_TRCENA;
    // 使能 CYCCNT
    DWT_CTRL |= DWT_CYCCNTENA_BIT;
    // 清零计数器
    DWT_CYCCNT = 0;
}

// 获取当前周期数
static inline uint32_t dwt_get_cycles(void) {
    return DWT_CYCCNT;
}

// 转换为微秒 SystemCoreClock 为系统主频
static inline uint32_t cycles_to_us(uint32_t cycles) {
    return cycles / (SystemCoreClock / 1000000U);
}

上面是外设初始化和函数定义,实际测量时按照下面的方法,非常简单。

c 复制代码
dwt_init();  // 初始化DWT
start = dwt_get_cycles();

// 待测量的函数

end = dwt_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

具体可以参考这篇文章

相关推荐
OIDCAT2 分钟前
CH9433技术解析:一颗芯片搞定CAN总线和9线串口
单片机·嵌入式硬件·工控·调试工具·国产芯片
简单电磁炮5 分钟前
关于can的调试
c语言·stm32·单片机
2501_922639586 分钟前
率能半导体 SS6812T双通道H桥驱动芯片:32V/1.0A,覆盖POS打印机、安防相机、办公自动化、游戏机、机器人五大应用场景
单片机·嵌入式硬件·硬件工程
女神下凡31 分钟前
芯参谋(77):裸机(无 OS)存储驱动开发指南
arm开发·单片机·嵌入式硬件·设计规范·1024程序员节
weixin_4640780732 分钟前
反激原副边之间的Y电容
单片机·嵌入式硬件
女神下凡2 小时前
芯参谋(76):电源监控复位芯片电路设计指南
arm开发·单片机·嵌入式硬件·fpga开发·设计规范
Tel199253080042 小时前
旋转变压器型编码器转多种绝对值协议 旋变转SSI/BISS-C/ENDAT2.2 RS422RTU协议+增量 转换器
单片机·自动化·工业自动化·仪器仪表·工控设备
国科安芯2 小时前
LEO卫星里的IO脉冲事件通信,毛刺误触发解析及处理方案
单片机·嵌入式硬件·fpga开发·低轨卫星·商业航天·抗辐射
2501_922639582 小时前
率能半导体 SS6813H双通道H桥驱动芯片:40V/2.5A,覆盖POS打印机、安防相机、办公自动化、游戏机、机器人五大应用场景
单片机·嵌入式硬件·硬件工程
智购科技无人售货机厂家3 小时前
自动售货机物联网平台为什么会出现在线状态不一致?~YH
python·单片机·嵌入式硬件·django·pygame