您的位置:首页 > 编程语言

第十天: 定时器、看门狗、PWM、蜂鸣器、RTC原理及代码实战

2016-08-13 22:28 351 查看
什么是定时器
定时器是SoC中常见外设
定时器与计数器。计数器是用来计数的(每隔一个固定时间会计一个数);因为计数器的计数时间周期是固定的,因此到了一定时间只要用计数值 x
计数时间周期,就能得到一个时间段,这个时间段就是我们定的时间(这就是定时器了)

定时器/计数器作为SoC的外设,主要用来实现定时执行代码的功能。定时器相对于SoC来说,就好像闹钟相对于人来说意义一样。      
对于单核CPU,是单线程的,在同一时间内,只能做一件事情,就像人需要闹钟,SoC需要定时器一样

 
定时器有什么用
定时器可以让SoC在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断CPU,CPU会去处理中断并执行定时器中断的ISR.从而去执行预先设定好的时间,    
重点是产生中断的条件是定时器产生的,定时器产生的信号就是计时结束标志.

定时器就好像CPU
的一个秘书一样,这个秘书专门帮CPU计时,并到时间后提醒CPU要做某件事情.所以CPU有了定时器之后,只需预先自己xx时间之后必须要做的事情绑定到定时器中断ISR即可,到了时间之后定时器就会以中断的方式提醒CPU来处理这个事情。

定时器的原理
定时器计时其实是通过计数来实现的。定时器内部有一个计数器,这个计数器更加·根据一个时钟(这个时钟源来自于ARM的APB总线,然后经过内部时钟模块内部的分频器来分频得到)来工作。
每隔一个时钟周期,计数器就计一次,定时器的时间就是计数器计数值x时钟周期。

定时器内部有一个寄存器TCNT,计时开始时我们会把一个总的计数值(譬如300)放入TCNT寄存器中,然后每隔一个时钟周期(假设1ms)TCNT中的值会自动减1(硬件自动完成,不需要CPU软件去干预),直到TCNT中减为0的时候,TCNT就会触发定时器中断。

定时时间是由两个东西共同决定的:一个是TCNT中的计数值,一个是时钟周期。譬如上例中,定时周期就为300x1ms
= 300ms。

 
定时器和看门狗、RTC、蜂鸣器
这几个东西都是和时间有关的部件

看门狗其实就是一个定时器,只不过定时时间到了之后不只是中断,还可以复位CPU

RTC是实时时钟,它和定时器的差别就好像闹钟(定时器)和钟表(RTC)的差别一样。

蜂鸣器是一个发声设备,在我们ARM里面蜂鸣器是用定时器来驱动的。

 

S5PV210中的定时器

在S5PV210内部,一共有4类定时器件。这4类定时器件的功能、特征是不同的。
PWM定时器
这种是最常用的,平时所说的定时器一般指的是这个。像简单单片机(譬如51单片机)中的定时器也是这类。

为什么叫PWM定时器,因为一般SoC中产生PWM都是靠这个定时器模块的。

系统定时器
系统(指的是操作系统)定时器,系统定时器也是用来产生固定时间间隔(TCNTx时钟周期)信号的,称为systick,这个用来给操作系统提供tick信号。

产生systick作为操作系统的时间片(time
slice)的。
一般做操作系统移植的时候,这里不会由自己来做,一般原厂提供的基础移植部分就已经包含了,不用深究。

看门狗定时器本质也是一个定时器,和上面两个没有任何本质区别

看门狗定时器可以设置在时间到了的时候产生中断,也可以选择发出复位信号复位CPU。

看门狗定时器在实践中应用很多,尤其是工业领域(环境复杂、干扰多)机器容易出问题,而且出问题后果很严重,此时一般都会用看门狗来进行系统复位。
本章节用两节课对210的看门狗进行讲解和编程

实时时钟RTC(real
time clock)
区分时间段和时间点。时间段是相对的,两个时间点相减会得到一个时间段;而时间点是绝对的,是绝无仅有的一个时间点

定时器关注的是时间段(而不是时间点),定时器计时从开启定时启动的那一刻开始,到定的时间段结束为止产生中断;RTC中工作用的是时间点(xx年xx月xx日xx时xx分xx秒)。

RTC和定时的区别,就相当于是钟表和闹钟的的区别。

以数据手册为教材:

S5PV210 中的PWM定时器
1
为什么叫PWM定时器
叫定时器说明它本质上的原理是定时器

叫PWM定时器,是因为这些定时器天然是用来产生PWM波形的。

PWM定时器介绍
S5PV210有5个PWM定时器。其中0、1、2、3各自对应一个外部GPIO,可以通过这些对应的GPIO产生PWM波形信号并输出;timer4没有对应的外部GPIO(因此不是为了生成PWM波形而是为了产生内部定时器中断产生的)

S5PV210的5个PWM定时器的时钟源为
PCLK_PSYS,time0和time1共同使用一个预分频器、timer2、3、4共同使用一个预分频器;每个timer有一个专用的独立的分频器;预分频器和分频器构成了两级分频系统,将PCLK_PSYS两级分频后生成的时钟供给timer模块

框图解析

 
 

S5PV210的PWM定时器2
预分频器与分频器
两级分频是串联的,或者叫级联,所以两级分频的分频数是相乘
的。
两级分频的分频系数分别在TCFG0
和 TCFG1两个寄存器中设置;

预分频器有两个,prescaler0位timer0&timer1共用;prescaler1为timer2、3、4共用;两个prescaler都是8个bit位,因此prescaler
value 范围为0~255;所以预分频器的分频值范围为1~256
(注意实际分频值位prescaler value +1)。

分频器实质是一个MUX开关,多选一开关决定了走哪个分频系数路线。可以选择的有1/1,1/2,1/4,1/8,/1/16等

计算一下两级分频下来,分频最小为1/2,分频最大为1/4096等。

使用PCLK_PSYS为66MHz的情况下(默认时钟设置就是66MHz的),此时两级分频后的时钟周期范围为0.03us到62.061us;再结合TCNTB的值的设置的(范围为1~32次方),可知能定出来的时间最长为266548.27s(折合74小时多)

 
 
TCNT&TCMP、TCNTB&TCMPB、TCNTO
TCNT和TCNTB是相对应的,TCNB是有地址的寄存器,供程序员操作;TCNT在内部和TCNTB相对应,他没有寄存器地址,程序员不能编程访问这个寄存器

TCNT寄存器功能就是用来减一的,他是内部的不能读写,我们想TCNT中写要通过TCNTB往进写;读取TCNT寄存器中的值要通过读取相对应的TCNTO寄存器。

工作流程就是:我们事先算好TCNT寄存器中开始减的那个数(譬如300),然后将之写入TCNTB寄存器中,启动timer前,将TCNTB中的值刷到TCNT寄存器中(有一位寄存器专门用来操作刷数据过去的),刷过去后就可以启动定时器开始计时;在计时过程中如果想知道TCNT寄存器中的值减到多少了,可以读取相应的TCNTO寄存器来得知

定时功能只需要TCNT、TCNTB两个即可;TCNTO寄存器用来做一些捕获计时;TCMPB用来生成PWM波形。

自动重载和双缓冲(auto-reload and
double buffering)
定时器工作的时候,一次定时算一个工作循环。定时器默认是单个循环工作的,也就是说定时一次,计时一次,到期中断一次就完了。下次如果还要再定时中断,需要另外设置。

但是现实中用定时器来做到的时候往往是循环的最简单最笨的方法就是写代码反复充重置定时器寄存器的值(在每次中断处理的isr中再次给TCNTB中赋值,再次刷到TCNT中再次启动定时器),早期的单片机定时器就是这样的;但是现在的高级SoC中的定时器已经默认内置了这种循环定时工作模式就叫自动装载(auto-reload)机制。

自动装载机制就是当定时器初始化好开始计时后不用管了,它一个周期到了后会自己从TCNTB中再次装载值到TCNT中,再次启动定时器开始下个循环。

 

S5PV210的PWM定时器3
什么是PWM?
PWM(pulse
wide modulation   脉宽调制)

PWM波形是一个周期性波形,周期为T,在每个周期内波形是完全相同的。每个周期内由一个高电平和一个低电平组成

PWM波形有两个重要参数一个周期T,另一个是占空比duty(占空比就是一个周期内高电平的时间除以周期时间的商)

对于一个PWM波形知道了周期
T 和占空比duty,就可以算出这个波形的所有细节了。

PWM波形的用途很多:
通信上用PWM来进行脉宽调制对基波进行载波调制;在发光二级管LED照明领域可以用PWM波形来调制电流进行调光;用来驱动蜂鸣器等设备。

PWM波形的生成原理
PWM波形其实就是用时间来控制电平高低,所以用定时器来实现PWM波形是天经地义的

早期的简单单片机里(譬如51单片机)是没有专用的PWM定时器的,那时候我们需要自己结合GPIO和定时器来手工生产PWM波形(流程是这样的:先将GPIO引脚电平拉高、同时启动定时器定T*duty时间,时间到了在isr中将电平拉低,然后定时T*(1-duty)后再次启动定时器,然后时间到了后在isr中将电平拉高,然后再定时T*duty再次启动定时器······如此循环即可得到周期为T,占空比为duty的PWM波形)

后来因为定时器经常和PWM产生纠结一起,所以设计SoC的时候就直接把定时器和一个GPIO引脚内部绑定起来了,然后在定时器内部给我们设置了PWM产生的机制,可以更方便的利用定时器产生PWM波形。此时我们利用PWM定时器来产生PWM定时器来产生PWM波形在不用中断了。绑定了之后坏处就是GPIO引脚是固定的、死板的、不能随便换的;好处就是不用进入中断isr中,直接可以生成PWM

在S5PV210中,PWM波形产生有两个寄存器很关键,一个是TCNTB、一个是TCMPB。TCNTB决定PWM的周期,TCMPB决定了PWM波形的占空比

最终生成的PWM波形的周期是:TCNTBx时钟周期(PCLK_PSYS经过两极分频后得到的时钟周期)注意这个周期是PWM中高电平+低电平的总时间,不是其中之一.

最终生成的PWM波形的占空比:
TCMPB/TCNTB

输出电平翻转器
PWM定时器规定:
当TCNT>TCMPB时,为高电平,当TCNT<TCMPB时为低电平。
也可以规定,当TCNT>TCMPB时为低电平,当TCNT<TCNMPB为高电平。在这两种规定下,计算时TCMP寄存器的值会变化。

电平翻转器在电路上的实质就是一个电平取反的部件,在编程上反应为一个寄存器位。写零就关闭输出电平反转,写1
就开启输出电平反转。 
开启后和开启前输出电平刚好高低反转。(输出电平一反转30%的duty就变成70%了)

实战中到底是TCNT和TCMPB谁大谁小高电平还是低电平,一般不用理论分析,只要写个代码,然后用示波器实际看一下出来的波形就知道了;如果反了就直接开启电平翻转器即可

死区生成器
PWM有一个应用就是用在功率电路中用来对交流电压进行整流。整流时两路整流分别在正电平和付电平时导通工作,不能同时导通(同时导通会直接短路,瞬间的同时导通都会导致电路烧毁)大功率的开关电源、逆变器等设备广泛使用了整流技术。特别是逆变器,用SoC的GPIO输出的PWM波形来分别驱动两路整流的IGBT。

PWM波形用来做整理时要求不能同时高或低,因为会短路。但是实际电路是不理想的,不可能同时上升/下降沿,所以比较安全的做法是留死区。

死区这东西离不了也多不了,死区少了容易短路,死区多了控制精度低了

S5PV210提供了自带的死区生成器,但是基本用不上,一般都是关闭状态。

蜂鸣器和PWM定时器编程实践1
蜂鸣器的工作原理
蜂鸣器里面有2个金属片,离的很紧但没挨着;没电的时候两个片在弹簧本身张力作用下分开彼此平行;有电的时候两边分别充电,在异性电荷的吸引作用下两个片挨着;

我们只要以快速的频率给蜂鸣器的正负极:供电、断电。进行这样的循环,蜂鸣器的两个弹簧片就会挨着分开······形成敲击,发出声音。

因为人的耳朵能听见的声音频率有限制(20Hz-20000Hz),我们做实验时一般给个2KHz的频率,大部分人都能听到(听不到的就就近医院处理)。

频率高低会影响声音的音频,一般是音频越低声音听起来越低沉。音频越高声音越尖锐

根据以上分析,可以看出,只要用PWM波形的电压信号来驱动蜂鸣器,把PWM波形的周期T设置为要发出的声音信号的1/频率即可;PWM的占空比只要确保能驱动蜂鸣器即可(驱动能力问题,一般引脚启动能力都不够,所以蜂鸣器会额外用三极管放大电流来供电)。

原理图和硬件信息
查阅原理图可知,开发板地板上的蜂鸣器通过GPD0_2(XpwmTOUT2)引脚连接在SoC上。

GPD0_2引脚通过限流电阻接在三极管基极上,引脚有电蜂鸣器就会有电(三极管导通);引脚没电蜂鸣器就会没电(三极管关闭)。这些都是硬件问题,软件工程师不用管,软件工程师只要写程序控制GPD_2引脚的电平产生PWM波形即可。

GPD0CON (0xe02000A0),要把bit8~bit11设置为0b0010(功能选择为TOUT_2,就是把这个引脚设置为PWM输出功能)

从GPD0_2引脚可以反推出使用的是timer2这个定时器

相关的寄存器

蜂鸣器和PWM定时器编程实践2

基于uart_stdio
项目源码来添加PWM定时器驱动蜂鸣器实验
注意:PWM定时器来产生PWM波形时是不需要中断干预的。
 

看门狗定时器
什么是看门狗、有什么用
看门狗定时器和普通的定时器并无本质区别。定时器可以设定一个时间,在这个时间完成之前定时器不断计时,时间到的时候定时器会复位CPU(重启系统)。

系统正常工作的时候当然不希望被重启,但是系统受到干扰、极端环境等可能会产生异常工作或者不工作,这种状态可能会造成不良影响(至少是不工作),此时解决方案就是重启系统。

普通设备重启不是问题,但是有些设备人工重启存在困难。这时候我们希望系统能够自己检验自己是否已经跑飞,并且在意识到自己跑飞的时候,可以很快的(几个ms或者更短)自我重启。这个功能就要靠看门狗定时器来实现,

典型应用的情景是:
我们在应用程序中打开看门狗设备,初始化好给它一个时间,然后应用程序使用一个线程来喂狗,这个线程的执行时间安全短于看门狗的复位时间。当系统(或者应用程序)异常后,喂狗线程自然就不工作了,到时间看门狗就会复位。

补充:
实战中有时候为了绝对的可靠,我们并不会用SoC中自带的看门狗,而是使用专门的外置的看门狗芯片来实现看门狗。

S5PV210看门狗定时器的结构框图
PCLK_PSYS经过两级分频生成WDT的时钟周期,然后把要定的时间写到WDAT寄存器中,刷到WTCNT寄存器中去减1,减到
0 时(定时时间到)产生复位信号或者中断信号

典型应用中是配置为产生信号是

 
 

实时时钟RTC
何为实时时钟
real time clock,真实时间,就是所谓的xx年xx月x日x时x分x秒星期x

RTC是SoC中一个内部外设,RTC有自己独立的晶振提供RTC时钟源(32.768MHz),内部有一些寄存器用来记录时间(年月日分秒星期)。一般情况下为了在系统关机时时间仍然在走,还会给RTC提供一个电池供电。

S5PV210实时时钟的结构框图
时间寄存器 7

闹钟发生器

闹钟发生器
可以定时间,到时间会产生RTC
alarm interrupt ,通知系统闹钟定时到了

闹钟定时是定的时间点,而time定时是定的时间段

S5PV210实时时钟的主要寄存器
INTP
中断寄存器
RTCCON RTC控制寄存器

RTCALM ALMxxx
闹钟功能有关的寄存器
BCDxxx
时间寄存器

BCD码
RTC中所有的时间(年月日时分秒星期,包括闹钟)都是用BCD码编码的

BCD码本质上是对数字的一种编码,用来解决种问题:有
56 得到 0x56
(或者反过来)也就说我们希望十进制的56可以编码成56(这里的56不是十进制,而是两个数字
5 和 6

BCD码的作用在于可以将十进制数拆成组成这个十进制数的各个数字的编码,变成编码后就没有位数的限制了。譬如
我有一个很大的数12345678912334568,如果这个数纯粹当数字肯定超出了int
的范围,计算机无法直接处理,要想让计算机处理这个数,计算机首先得能表达这个数,表达的方式就是先把这个数转成相应的BCD码(12345678912334568)

BCD码可以在计算机中可以用十六进制的形式来表示。
也就是说十进制的56转成BCD码后是56,在计算机中用0x56来表达(暂时存储与运算)。

需要写两个函数,一个是BCD转十进制,一个是十进制转BCD。当我们要设置时间时(譬如要设置为23分),我们需要将这个23转成0x23然后再赋值给相应的寄存器BCDMIN;当我们从寄存器BCDMIN中读取一个时间时(譬如读取到的是0x59),需要将之当作BCD码转成十进制再去显示(0x59当做BCD码就是59,转成十进制就是59
,所以显示就是59分)

RTC编程实战
设置时间与读取显示时间
为了安全,默认情况下RTC读写是禁止的,此时写RTC的时间是不允许的;当我们要更改时间时,应该打开RTC的读写开关

读写RTC寄存器时,一定要注意BCD码和十进制的转换

年的问题。S5PV210中做了设定,BCDYEAR寄存器存的并不是完整的年数(譬如今年2015年),而是基于2000年的偏移量来存储的,譬如今年2015年实际存的就是15(2015-2000),还有些RTC芯片是以1970年为基点来记录的。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: