定时器学习

 

文件夹

说明

依据数据手冊可知CC2530总共同拥有4个定时器,可是定时器2被系统占用,可用的仅仅有三个,分别为定时器1/3/4

Timer在协议栈的代码位置为hal_timer.c,hal_timer.h,4个定时器的ID分别为

/* Timer ID definitions */

#define HAL_TIMER_0               0x00   
// 8bit timer

#define HAL_TIMER_1               0x01   
// 16bit Mac timer

#defineHAL_TIMER_2               0x02   //
8bit timer

#define HAL_TIMER_3               0x03   
// 16bit timer

#define HAL_TIMER_MAX             4      
// Max number of timer

宏定义中的TIMER_ID并不是硬件中的定时器1,而是经过函数halTimerRemap映射,将HAL层自己定义的timerID映射为硬件的HW
TIMER ID

映射的结果为

* @brief  Maps API HAL_TIMER_ID to HW Timer ID.

*         HAL_TIMER_0 --> HW Timer 3 8bit

*         HAL_TIMER_2 --> HW Timer 4 8bit

*         HAL_TIMER_3 --> HW Timer 1 16bit

有两个方法达到定时的目的,一个是协议栈函数,一个直接寄存器操作

协议栈函数使用

在OSAL的main函数中 HalDriverInit();既有对timer的初始化HalTimerInit();该函数对各个定时器进行了初始化,首先对全部定时器清中断,然后设置时钟和预分频,最后设置定时器的Channel
structure.

假设用户想使用定时器须要自己设置某一个寄存器的变量,并实现相关回调函数,最后调用HalTimerStart来启动定时器.

设置初始化定时器

函数是uint8HalTimerConfig
(uint8 timerId, uint8 opMode, uint8 channel, uint8 channelMode,bool intEnable, halTimerCBack_t cBack)

各个參数的意思

* @param  timerId - Id of the timer

*         opMode - Operation mode操作方式共3种

*         channel - Channel where the counter operates on选择通道,相应IO口

*         channelMode - Mode of that channel通道的模式

*         intEnable -可中断

*         cBack - Pointer to the callback function 中断函数

演示样例:

HalTimerConfig(HAL_TIMER_0,HAL_TIMER_MODE_CTC,HAL_TIMER_CHANNEL_SINGLE,HAL_TIMER_CH_MODE_OUTPUT_COMPARE,TRUE,timer_callback);

此处的TimerID为HAL_TIMER_0,可是实际上使用的并不是这个,而是经过函数halTimerRemap映射,将HAL层自己定义的timerID映射为硬件的HW
TIMER ID映射的结果为

* @brief  Maps API HAL_TIMER_ID to HW Timer ID.

*         HAL_TIMER_0 --> HW Timer 3 8bit

*         HAL_TIMER_2 --> HW Timer 4 8bit

*         HAL_TIMER_3 --> HW Timer 1 16bit

回调函数(中断服务函数)

演示样例中的最后一个參数既是回调函数,回调函数能够决定定时的长短,每中断一次本函数被调用一次,例如以下代码

/*中断服务函数*/

volatile unsigned int n = 0; //一个volatile的全局变量

//确保本条指令不会因编译器的优化而省略,且要求每次直接读值

void timer_callback(uint8 timerId, uint8 channel, uint8 channelMode)

{

n++; 
//每次调用此函数,n加1

if(n ==5000) { 
//当n加到一个自己定义的数值后,就运行相关任务,然后将n清零

//改变这个值就可以控制定时的长短

/*do something...*/

HalUARTWrite(0,"20000000000\n",13); 
//定时到后运行任务

n =0;//又一次定时

}

/*TODO...*/

return;

}

启动定时器

重点函数HalTimerStart(uint8
timerId, uint32 timePerTick),參数定义

* @param  timerId     
- ID of the timer

*         timerPerTick - number of micro sec per tick, (ticks x prescale) / clock= usec/tick

第一个是定时器的ID,第二个未理解,可是数值越小,定时器时间间隔越小.

实例:

HalTimerStart (HAL_TIMER_0,65536);

停止定时器

函数HalTimerStop(uint8
timerId),指定timerID就可以停止某一个定时器

实例:HalTimerStop(HAL_TIMER_0)

/*中断服务函数*/

volatile unsigned int n = 0,stop=0;

void timer_callback(uint8 timerId, uint8 channel, uint8 channelMode)

{

n++;

if(n == 5000) {

HalUARTWrite(0,"20000000000\n",13);

LED1 = ~LED1;

stop++;

if(stop == 10) 
//将会在led灯闪烁5次之后关闭定时器

HalTimerStop(HAL_TIMER_0);

n =0;

}

return;

}

寄存器操作

本段參考网蜂团队的第二章”基础实验”的2.4定时器

分为两种方式:查询模式,中断模式,相比查询模式中断模式更节省cpu资源,效率更高!

查询方式

CC2530的 T1定时器(16位)我们须要配置三个寄存器
T1CTL, T1STAT。IRCON。

IO口配置请留意第一节教程内容。

各寄存器功能例如以下表所看到的:(具体參考
CC2530 datasheet.pdf)

T1CTL(0XE4)Timer1 
控制寄存器:

Bit3:Bit2 : 定时器时钟分频倍数选择:

00:不分频 01:8分频 10:
32分频 11:128分频

Bit1:Bit0 :  定时器模式选择:

00: 暂停

01: 自己主动重装 0X0000-0XFFFF

10: 比較计数 0X0000-T1CC0

11: PWM 
方式

T1STAT(0XAF)Timer1 
状态寄存器:

Bit5:  OVFIF 定时器溢出中断标志,在计数器达到计数终值时置位
1.

Bit4:   定时器 1 
通道 4 中断标志位

Bit3:   定时器 1 
通道 3 中断标志位

Bit2:   定时器 1 
通道 2 中断标志位

Bit1:   定时器 1 
通道 1 中断标志位

Bit0:   定时器 1 
通道 0 中断标志位

IRCON(0XC0) 中断标志位寄存器,仅仅要轮询此标志位就可以

实现代码

/**************************************

程序描写叙述:通过定时器 T1查询方式控制

LED1周期性闪烁

**************************************/

#include <ioCC2530.h>

#define uint unsigned int

#define uchar unsigned char

//定义控制 LED灯的port

#define LED1 P1_0     //定义
LED1为 P10口控制

//函数声明

void Delayms(uint xms);   //延时函数

void InitLed(void);       //初始化
P1口

void InitT1();             //初始化定时器
T1

/****************************

//延时函数

*****************************/

void Delayms(uint xms)    //i=xms 
即延时 i毫秒

{

uint I,j;

for(i=xms;i>0;i--)

for(j=587;j>0;j--);

}

/***************************

主函数

***************************/

void main(void)

{

uchar count;

InitLed();        //调用初始化函数

InitT1();                 //初始化定时器

while(1)                 //轮询查看IRCON寄存器的状态

{

if(IRCON>0) //查询方式

{

IRCON=0;

if(++count==1)         //约 1s周期性闪烁

{

count=0;

LED1 = !LED1;         //LED1
闪烁

}

}

}

/****************************

//初始化程序

*****************************/

void InitLed(void)

{

P1DIR |= 0x01;    //P1_0
定义为输出

LED1 = 1;         //LED1
灯初 始化熄灭

}

//定时器初始化

void InitT1() //系统不配置工作时钟时使用内部
RC振荡器。即16MHz

{

T1CTL = 0x0d;   //128
分频,自己主动重装 0X0000-0XFFFF

}

重点:系统在不配置工作频率时默觉得 2分频,即
32M/2=16M,所以定时

器每次溢出时 T=1/(16M/128)*65536≈0.5s, 所以总时间Ta=T*count=0.5*1=0.5S

切换 1次状态。所以看起来是
1S闪烁 1次。

中断方式(使用定时器3)

CC2530的 T3定时器主要是配置三个寄存T3CTL,T3CCTL0,T3CC0,T3CCTL1,T3CC1。

T3CTL(0XCB) Timer3 控制寄存器:

Bit7:Bit5 :  定时器时钟分频倍数选择:

000:不分频,001:2分频,010:4分频,
011:8分频,100:16分频,101:32分频,110:64分频,111:128分频

Bit4 :   T3 起止控制位

Bit3 :   溢出中断掩码 0:关溢出中断 1:开溢出中断

Bit2 :   清计数值 高电平有效

Bit1:Bit0: T3模式选择

00:自己主动重装 0X00-0XFF

01: DOWN (从
T3CC0 到 0X00计数一次)

10: 模计数(重复从 0X00
到 T3CC0 计数)

11: UP/DOWN(重复从
0X00到 T3CC0 计数再到 0X00)

T3CCTL0(0XCC) T3   
通道 0 捕获/ 比較控制寄存器:

Bit6:  T3通道 0 
中断掩码 0:关中断 1:开中断

Bit5: Bit3 : T3 
通道 0 比較输出模式选择

Bit2: T3通道 0 模式选择: 0:捕获 1 
:比較

Bit1: Bit0:    T3
通道 0 捕获模式选择

00   没有捕获 01    
上升沿捕获

10 下降沿捕获     11     边沿捕获

T3CC0(0XCD) T3
通道 0  捕获/ 比較值寄存器

T3CCTL1(0XCE) T3 
通道 1 捕获/ 比較控制寄存器:

Bit6:  T3通道1 中断掩码 0:关中断 1:开中断

Bit5: Bit3 : T3 
通道 1 比較输出模式选择

Bit2: T3通道 1 模式选择: 0:捕获 1 
:比較

Bit1: Bit0:    T3
通道 1 捕获模式选择

00   没有捕获 01    
上升沿捕获

10 下降沿捕获 11     边沿捕获

T3CC1(0XCF)   T3
通道 1  捕获/ 比較值寄存器

与上例 T1定时器查询方式的差别就是此处使用
T3定时器(8位)。中断方式。

寄存器配置例如以下:

T3CTL |= 0x08 ;  //开溢出中断

T3IE  = 1;  //开总中断和
T3中断

T3CTL |=0XE0;   //128
分频,128/16000000*N=0.5S,N=65200

T3CTL &= ~0X03;      //自己主动重装 00->0xff65200/256=254(次)

T3CTL |=0X10;   //启动

EA = 1;  //开总中断

代码实现

//定时器初始化

void InitT3()

{

T3CTL |= 0x08 ;   //开溢出中断

T3IE = 1;   //开总中断和
T3中断

T3CTL|=0XE0;   //128
分频,128/16000000*N=0.5S,N=65200

T3CTL &= ~0X03;   //自己主动重装
00->0xff  65200/256=254(次)

T3CTL |=0X10;   //启动

EA = 1;    //开总中断

}

中断函数

/************************************

中断函数

************************************/

#pragma vector = T3_VECTOR    //定时器
T3

__interrupt void T3_ISR(void)

{

IRCON = 0x00;   //清中断标志,也可由硬件自己主动完毕

if(++count>254)  //254
次中断后 LED取反。闪烁一轮(约为 0.5秒时间)

{

count = 0;  //
计数清零

LED1=~LED1; //led闪烁

}

}

Main函数

/***************************

//主函数

***************************/

void main(void)

{

InitLed();      //调用初始化函数

InitT3();

while(1){ }

}

CC2530定时器使用的更多相关文章

  1. CC2530定时器1的模模式中断

    CC2530定时器1的模模式中断void timer1SInit(void){ T1CCTL0 = 0; T1CTL &= ~0x0F; //clear register T1CTL |= 0 ...

  2. CC2530定时器3的输入捕获中断

    CC2530定时器3的输入捕获中断 使用的是tim3的通道1的输入捕获P1_7口.//GPIO配置成复用功能,同时设置P1_7为输入.void irCaptureGpioInit(void){ P1S ...

  3. CC2530定时器

    一.定时/技术器的基本原理 定时/计数器,是一种能够对内部时钟信号或外部输入信号进行计数,当计数值达到设定要求时,向CPU提出中断处理请求,从而实现定时或者计数功能的外设.         定时/计数 ...

  4. CC2530定时器的应用

    [例1]利用定时器计数实现5中彩灯的变化形式,基于模模式的.两个标志位,一个是定时器计数,一个是彩灯的状态. #include "ioCC2530.h" #define D3 P1 ...

  5. CC2530定时器模模式最大值计算

    首先假设 频率: f 分频系数: n 间隔定时: s 周期: T 模模式最大值: N 因为 T = 1 / f 所以 s = ( n / f ) * N  =  n * N / f 由此可得 计算模模 ...

  6. 实验三 CC2530平台上CC2530平台上定时器组件的

    实验三 CC2530平台上CC2530平台上定时器组件的TinyOS编程 实验目的: 加深和巩固学生对于TinyOS编程方法的理解和掌握 让学生初步掌握CC2530定时器的PWM功能,及其TinyOS ...

  7. zigbee学习之路(六):Time3(查询方式)

    一.前言 通过上次的学习,相信大家对cc2530单片机的定时器的使用有了一定的了解,今天我们来介绍定时器3的使用,为什么介绍定时器3呢,因为它和定时器4功能是差不多的,所以学会定时器3,就基本掌握了c ...

  8. CC2530学习路线-基础实验-定时器控制LED灯亮灭(3)

    目录 1. 前期预备知识 1.1 定时器中断触发 1.2 相关寄存器 1.3 寄存器相关问题 1.4 T1.T3定时器初始化流程 2 程序及代码 THE END 1. 前期预备知识 1.1 定时器中断 ...

  9. 【CC2530强化实训03】定时器间隔定时实现按键长按与短按

    [CC2530强化实训03]定时器间隔定时实现按键长按与短按 [题目要求] 虽然用普通的延时函数能够实现按键长按与短按的判别,但是在实际的工程应用和项目开发中并不好用也不灵活.更多得是借助定时器的间隔 ...

随机推荐

  1. 【转】一篇关于32位Linux内核使用大内存的文章——Hugemem Kernel Explained  &nb

    红旗DC系列Linux操作系统(x86平台)中带有四类核心: UP (支持单内核) SMP (支持多内核) hugemem Icc* (用intel C编译器编译的核心) 其中hugemem核心往往引 ...

  2. 玩转 Jupyter Notebook (CentOS)

    Jupyter Notebook 简介 Jupyter Notebook 是一个开源的 Web 应用程序,可以用来创建和共享包含动态代码.方程式.可视化及解释性文本的文档.其应用于包括:数据整理与转换 ...

  3. 页面打开pdf格式文件的方法

    <embed width=500 height=300 fullscreen=yes src="1.pdf" />

  4. HDU——T 1075 What Are You Talking About

    http://acm.hdu.edu.cn/showproblem.php?pid=1075 Time Limit: 10000/5000 MS (Java/Others)    Memory Lim ...

  5. 发送邮件被退回,提示: Helo command rejected: Invalid name 错误

    我自己配置的 postfix + dovecot server, 配置了outlook 后, 相同的账号. 在有的电脑上能收发成功, 在有的电脑上发送邮件就出现退信.提示 Helo command r ...

  6. javaWeb自己定义可排序过滤器注解,解决Servlet3.0下@WebFilter注解无法排序问题

    com.lwl.anno 凝视类型 @WebFilterSort 须要用的jar包 http://download.csdn.net/detail/u013202238/9431110 用该注解注冊的 ...

  7. [转]C语言预处理命令详解

    转载:https://www.cnblogs.com/clover-toeic/p/3851102.html 一  前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的 ...

  8. QCAD Plugin 开发

    QCAD Plugin 开发 eryar@163.com Abstract. QCAD是基于GPL协议的开源CAD软件,核心功能基于Qt使用C++开发,界面及其交互使用Javascript脚本进行开发 ...

  9. vim 基础学习之查找

    普通模式下 /->正向查找 n-向下查找 N-向上查找 ?->反向查找 N-向下查找 n-向上查找 <C-r><C-w> <C-r>-引用,例如引用寄存 ...

  10. 使用Redis配置JAVA_环境

    配置环境变量 1.安装完成后,右击"我的电脑",点击"属性",选择"高级系统设置": 2.选择"高级"选项卡,点击&qu ...