嵌入式——1138纯净版代码(定时器)


这些是我自己常用的代码,比官方的要简洁些,主要是自用,还有相关模块,使用代码。

具体文件可以去我github上下载。

Timer 总体特性

在 Stellaris 系列 ARM 内部通常集成有 2~4 个通用定时器模块(General-Purpose Timer
Module,GPTM),分别称为 Timer0、Timer1、Timer2 和 Timer3。它们的用法是相同的:每 个 Timer 模块都可以配置为一个 32 位定时器或一个 32 位 RTC 定时器;也可以拆分为两个16 位的定时/计数器 TimerA 和 TimerB,它们可以被配置为独立运行的定时器、事件计数器或 PWM。

Timer 模块具有非常丰富的功能:

32 位定时器模式:

„可编程单次触发(one-shot)定时器
„ 可编程周期(periodic)定时器
„ 实时时钟 RTC(Real Time Clock) „ 软件可控的事件暂停(用于单步调试时暂停计数,RTC 模式除外)

16 位定时器模式:

„ 带 8 位预分频器的通用定时器功能
„ 可编程单次触发(one-shot)定时器
„ 可编程周期(periodic)定时器
„ 软件可控的事件暂停

16 位输入捕获模式:

„ 输入边沿计数捕获
„ 输入边沿定时捕获

16 位 PWM 模式:

„ 用法简单的 PWM(Pulse-Width Modulation,脉宽调制)模式
„ 可通过软件实现 PWM 信号周期、占空比、输出反相等的控制

Timer 功能概述

Timer 模块的功能在总体上可以分成 32 位模式和 16 位模式两大类。在 32 位模式下,TimerA 和 TimerB 被连在一起形成一个完整的 32 位计数器,对 Timer 的各项操作,如装载
初值、运行控制、中断控制等,都用对 TimerA 的操作作为总体上的 32 位控制,而对 TimerB的操作无任何效果。在 16 位模式下,对 TimerA 的操作仅对 TimerA 有效,对 TimerB 的操作仅对 TimerB 有效,即对两者的操控是完全独立进行的。

每一个 Timer 模块对应两个 CCP 管脚。CCP 是“Capture Compare PWM”的缩写,意为“捕获/比较/脉宽调制”。在 32 位单次触发和周期定时模式下,CCP 功能无效(与之复用的 GPIO 管脚功能仍然正常)。在 32 位 RTC 模式下,偶数 CCP 管脚(CCP0、CCP2、CCP4等)作为 RTC 时钟源的输入,而奇数 CCP 管脚(CCP1、CCP3、CCP5 等)无效。在 16 位模式下,计数捕获、定时捕获、PWM 功能都会用到 CCP 管脚,对应关系是:Timer0A 对应CCP0、Timer0B 对应 CCP1,Timer1A 对应 CCP2、Timer1B 对应 CCP3,依此类推。

32 位单次触发/周期定时器

在这两种模式中,Timer 都被配置成一个 32 位的递减计数器,用法类似,只是单次触
发模式只能定时一次,如果需要再次定时则必须重新配置,而周期模式则可以周而复始地定
时,除非被关闭。在计数到 0x00000000 时,可以在软件的控制下触发中断或输出一个内部
的单时钟周期脉冲信号,该信号可以用来触发 ADC 采样。

32 位 RTC 定时器

在该模式中,Timer 被配置成一个 32 位的递增计数器。
RTC 功能的时钟源来自偶数 CCP 管脚的输入。在 LM3S101/102 里,RTC 时钟信号从专
门的“32KHz”管脚输入。输入的时钟频率应当为精准的 32.768KHz,在芯片内部有一个
RTC 专用的预分频器,固定为 32768 分频。因此最终输入到 RTC 计数器的时钟频率正好是1Hz,即每过 1 秒钟 RTC 计数器增 1。RTC计数器从 0x00000000 开始计满需要 232秒,这是个极长的时间,有 136 年!因此RTC真正的用法是:初始化后不需要更改配置(调整时间或日期时例外),只需要修改匹配寄存器的值,而且要保证匹配值总是超前于当前计数值。每次匹配时可产生中断(如果中断已被使能),据此可以计算出当前的年月日、时分秒以及星期。在中断服务函数里应当重新设置匹配值,并且匹配值仍要超前于当前的计数值。
注意:在实际应用当中一般不会真正采用 Timer 模块的 RTC 功能来实现一个低功耗万
年历系统,因为芯片一旦出现复位或断电的情况就会清除 RTC 计数值。取而代之的是冬眠
模块(Hibernation Module)的 RTC 功能,由于采用了后备电池,因此不怕复位和 VDD 断
电,并且功耗很低。

16 位单次触发/周期定时器

一个 32 位的 Timer 可以被拆分为两个单独运行的 16 位定时/计数器,每一个都可以被
配置成带 8 位预分频(可选功能)的 16 位递减计数器。如果使用 8 位预分频功能,则相当
于24位定时器。具体用法跟32位单次触发/周期定时模式类似,不同的是对TimerA和TimerB
的操作是分别独立进行的。

16 位输入边沿计数捕获

在该模式中,TimerA 或 TimerB 被配置为能够捕获外部输入脉冲边沿事件的递减计数
器。共有 3 种边沿事件类型:正边沿、负边沿、双边沿。
该模式的工作过程是:设置装载值,并预设一个匹配值(应当小于装载值);计数使能
后,在特定的 CCP 管脚每输入 1 个脉冲(正边沿、负边沿或双边沿有效),计数值就减 1;
当计数值与匹配值相等时停止运行并触发中断(如果中断已被使能)。如果需要再次捕获外
部脉冲,则要重新进行配置。

16 位输入边沿定时捕获

在该模式中,TimerA 或 TimerB 被配置为自由运行的 16 位递减计数器,允许在输入信
号的上升沿或下降沿捕获事件。
该模式的工作过程是:设置装载值(默认为 0xFFFF)、捕获边沿类型;计数器被使能后
开始自由运行,从装载值开始递减计数,计数到 0 时重装初值,继续计数;如果从 CCP 管
脚上出现有效的输入脉冲边沿事件,则当前计数值被自动复制到一个特定的寄存器里,该值
会一直保存不变,直至遇到下一个有效输入边沿时被刷新。为了能够及时读取捕获到的计数
值,应当使能边沿事件捕获中断,并在中断服务函数里读取。

16 位 PWM

Timer 模块还可以用来产生简单的 PWM 信号。在 Stellaris 系列 ARM 众多型号当中,
对于片内未集成专用 PWM 模块的,可以利用 Timer 模块的 16 位 PWM 功能来产生 PWM 信号,只不过功能较为简单。对于片内已集成专用 PWM 模块的,但仍然不够用时,则可以从Timer 模块借用。
在 PWM 模式中,TimerA 或 TimerB 被配置为 16 位的递减计数器,通过设置适当的装
载值(决定 PWM 周期)和匹配值(决定 PWM 占空比)来自动地产生 PWM 方波信号从相
应的 CCP 管脚输出。在软件上,还可以控制输出反相,参见函数 TimerControlLevel( )。

源码main函数

#include  "systemInit.h"
#include  <timer.h>


void Time_Init( void ) {
  SysCtlPeriEnable(SYSCTL_PERIPH_TIMER0);                 //  使能Timer模块
  TimerConfigure(TIMER0_BASE, TIMER_CFG_16_BIT_PAIR |     //  配置Timer为16位周期定时器
                 TIMER_CFG_A_PERIODIC);
  TimerPrescaleSet(TIMER0_BASE, TIMER_A, 99);             //  预先进行100分频
  TimerLoadSet(TIMER0_BASE, TIMER_A, 30000);              //  设置Timer初值,定时500ms
  TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);        //  使能Timer超时中断
  IntEnable(INT_TIMER0A);                                 //  使能Timer中断
  IntMasterEnable();                                      //  使能处理器中断
  TimerEnable(TIMER0_BASE, TIMER_A);                      //  使能Timer计数
}


//  主函数(程序入口)
int main(void){
  jtagWait();                                             //  防止JTAG失效,重要!
  clockInit();                                            //  时钟初始化:晶振,6MHz
  Time_Init();

  while(1){

  }
}


//  定时器的中断服务函数
void Timer0A_ISR(void)
{
  unsigned long ulStatus;

  ulStatus = TimerIntStatus(TIMER0_BASE, true);           //  读取中断状态
  TimerIntClear(TIMER0_BASE, ulStatus);                   //  清除中断状态,重要!

  if (ulStatus & TIMER_TIMA_TIMEOUT)                      //  如果是Timer超时中断
  {
  }
}


startup_ewarm.c

在这里插入图片描述
在这里插入图片描述

这些是要改的部分。

具体的就不讲解了,地址后期会附上。


文章作者: michaelming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 michaelming !
 上一篇
嵌入式——1138纯净版代码(12864液晶) 嵌入式——1138纯净版代码(12864液晶)
这些是我自己常用的代码,比官方的要简洁些,主要是自用,还有相关模块,使用代码。 具体文件可以去我github上下载。就是这款。   lcd12864简介  带中文字库的128X64是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含
2018-12-09
下一篇 
嵌入式——1138纯净版代码(自带按键) 嵌入式——1138纯净版代码(自带按键)
这些是我自己常用的代码,比官方的要简洁些,主要是自用,还有相关模块,使用代码。 具体文件可以去我github上下载。 这个没什么好讲的,就是自带的几个按键使用罢了。不想外接用这个。 源码main函数// 基于《Stellaris外设驱动库
2018-12-09
  目录