电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
GD32VF103之定时器最小配置
分 享
扫描二维码分享
GD32VF103之定时器最小配置
定时器
gd32vf
gcrisis
关注
发布时间: 2020-10-12
丨
阅读: 750
![](https://cf04.ickimg.com/bbsimages/202010/4be90afeb37c2984f4c96ac6e29080ce.png) 定时器是每一个芯片必备的外设,它的作用就如它的名字一样,是用来计时的。当然它不会直接告诉你具体的时间值,而是一个特定时间间隔的计数,通过这个数乘以时间间隔就是这段时间的长度。定时器在计时的基础上可以实现很多其他功能,比如定时中断、pwm输出、输入捕获、正交译码等等。 下面这张图是gd32vf103所有定时器的分类和功能汇总。 ![](https://cf04.ickimg.com/bbsimages/202010/07c02fd0813cb85e41660dd104785f02.png) 我会按照功能分别予以介绍,本文先介绍最基本的定时、计数功能,以定时器0为例。 ###定时器计时配置步骤如下: **1、打开定时器时钟源; 2、设置定时器时钟的预分频; 3、设置计数方向、对齐模式、时钟分频; 4、设置自动重载值和重复计数值; 5、触发软件更新事件更新寄存器的值; 6、使能更新中断,由于用到了中断,注意中断控制器的配置; 7、使能计数器; 8、编写中断服务程序** ###1、打开定时器时钟源 定时器的时钟源可以是内部的也可以是外部的,这里以内部时钟源为例。内部时钟源是CK_TIMER,通过时钟树我们可以看到定时器0的CK_TIMER是挂在APB2上的,第一步先打开它。 ![](https://cf04.ickimg.com/bbsimages/202010/b5afece69f7aff2901ab9d80f8f4f1c9.png) 配置的寄存器是APB2使能寄存器,bit11使能定时器0。手册中介绍说这个位是定时器0复位,感觉有点奇怪。 ![](https://cf04.ickimg.com/bbsimages/202010/68e3c9b0f7ac688aca202fe442fe43c2.png) 代码如下所示: ![](https://cf04.ickimg.com/bbsimages/202010/6928c4c7ac42705668760b41798f8892.png) ###2、设置定时器时钟的预分频 可以对CK_TIMER的时钟频率进行预分频,降低时钟源频率,预分频器是16位的,可以将时钟源进行1-65536的分频。分频后得到PSC_CLK时钟,通过它来驱动计数器计数。设置预分频系数的寄存器是预分频寄存器 (TIMERx_PSC): ![](https://cf04.ickimg.com/bbsimages/202010/f7dea64ab8990a38de98e2a5392e7a87.png) 计数器时钟等于CK_TIMER除以 (PSC+1),该寄存器带有缓冲器,能够在运行时改变,每次当更新事件产生时,PSC的值被装入当前预分频寄存器。 代码如下所示,宏TIMER0_BASE是0x40012C00。APB2的时钟是108M,CK_TIMER的也是108M,这里我们想要一个1M的时钟,所以设置PSC预分频值107,最终将CK_TIMER(107+1)分频。 ![](https://cf04.ickimg.com/bbsimages/202010/f87327e2f9d75b8943cf707716bbfae9.png) ###3、设置计数方向、对齐模式、时钟分频 定时器0有三种计数方式:向上计数、向下计数和中央对齐计数。向上计数就是从0加计数到自动重载值,然后再从0开始。向下计数是从自动重载值开始减计数到0,然后再从自动重载值开始。中央对齐是交替从0开始向上计数到自动重载值,然后再向下计数到0。这里的分频是用来产生DTS时钟的,死区发生器和数字滤波器会用到DTS时钟,我们以后边再说。操作的寄存器是控制寄存器0(TIMERx_CTL0),bit4设置计数方向,bit[5:6]设置模式,bit[8:9]设置DTS分频系数。 ![](https://cf04.ickimg.com/bbsimages/202010/47788cafd307cc9869e13c7c75327e9e.png) 这里如果bit[5:6]是中央对齐模式(非0),则bit4是只读的,表明现在的计数方向。我这里设置向上计数、边沿对齐、不分频,其实就是默认的0。代码如下: ![](https://cf04.ickimg.com/bbsimages/202010/d0aa27b63ce9df7698df1542498a83f8.png) ###4、设置自动重载值和重复计数值 计数器自动重载值决定了计数器的计数范围,也就是计数周期,计数器到达指定的数后会自动更新该值。寄存器为计数器自动重载寄存器 (TIMERx_CAR) ,是一个16位的寄存器。 ![](https://cf04.ickimg.com/bbsimages/202010/c473e616aad13b966943fb34b3f89ac2.png) 重复计数决定计数器经过多少(N+1)个计数周期后触发更新事件,计数器计完一个周期该值减1,减到0触发更新事件。寄存器是重复计数寄存器 (TIMERx_CREP),是8位寄存器。注意,该寄存器本身的值不随计数周期发生变化,应该是有其他机制来减数和重载,手册没有细说。 ![](https://cf04.ickimg.com/bbsimages/202010/b10521d77ba73511ebc68aca5b03b2db.png) 代码如下,这里设置重载值为100,也就是一个计数周期0.1ms;重复值为9(10次,所以设置9),最终1ms产生一个更新事件。 ![](https://cf04.ickimg.com/bbsimages/202010/fd4fbef3f2aa31976a3f0a4604225fde.png) ###5、触发软件更新事件更新寄存器的值 通过向软件事件产生寄存器 (TIMERx_SWEVG)的指定位写1可以产生一些软件事件,这里我们要让各种寄存器恢复到计数初始状态,所以设置更新事件,bit0写1产生更新事件。 ![](https://cf04.ickimg.com/bbsimages/202010/99bb27f98db0d979c0fdf3c6a10a9d1e.png) 代码如下: ![](https://cf04.ickimg.com/bbsimages/202010/11d80515564a9247771f22f66eb1876f.png) ###6、使能更新中断 [上一篇文章我们已经介绍了中断的使用](https://www.icxbk.com/article/detail?aid=1775 "上一篇文章我们已经介绍了中断的使用"),所以这里我们使用定时器中断。中断相关的配置寄存器是DMA和中断使能寄存器(TIMERx_DMAINTEN),bit0就是更新中断使能。 ![](https://cf04.ickimg.com/bbsimages/202010/fae817a3ba7e86eccff81c9ef9a1a57e.png) 代码如下,我们前面设置1ms产生一个更新事件,所以代码跑起来后1ms将会产生一个更新中断: ![](https://cf04.ickimg.com/bbsimages/202010/7d540980b169f6b68b6bafc7ab85ce90.png) 用到中断不要忘记中断控制器相关的配置,这里使用了官方的sdk库,[详细内容可以查看我的上一篇文章](https://www.icxbk.com/article/detail?aid=1775 "详细内容可以查看我的上一篇文章")。 ![](https://cf04.ickimg.com/bbsimages/202010/fe2791400f0c174809981aef2f822d37.png) ###7、使能计数器 最后就是打开计数器,它也在控制寄存器0(TIMERx_CTL0)中设置,bit0置1计数器使能。 ![](https://cf04.ickimg.com/bbsimages/202010/4187bb20a84dc95976bd8e982c800d9a.png) 代码如下: ![](https://cf04.ickimg.com/bbsimages/202010/66beede03d1220363778a3a7c31106c9.png) ###8、编写中断服务程序 定时器更新中断服务程序如下所示,这里我们判断中断是否为更新中断,然后清除标志,然后让变量update自加,来统计中断次数。 ![](https://cf04.ickimg.com/bbsimages/202010/bebd7d6c58024692edd7d0c78b83478d.png) 我这里这个中断中不能使用printf,原因未知。 ###应用实战 下面我们利用这个中断来实现一个my_delay延时毫秒函数。代码如下所示: ![](https://cf04.ickimg.com/bbsimages/202010/050b84dc7ec636fc502165ab4586da39.png) 代码很简单就不细说了,这里要强调的是update变量一定要加volatile关键字,否则编译器会优化这里的time1,认为它是多余的。或者可以实现一个获取update值的函数。 运行效果如下: ![](https://cf04.ickimg.com/bbsimages/202010/1dfc5d014bd8c3ef301802dd6f40f972.png) 可以看到,这里延时1秒,update大概多1002个数,考虑到代码的开销,这个延时是准确的,说明我们对定时器0的设置是ok的。 ok,关于定时器基本的计数计时功能就介绍到这里了,下一篇介绍一下pwm和输入捕获。 ![](https://cf04.ickimg.com/bbsimages/202010/91afef13626bfe316e9393ebbbe69644.jpg) ##bilibili:科G栈
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
gcrisis
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交