CC2530定时器使用
定时器学习
文件夹
说明
依据数据手冊可知CC2530总共同拥有4个定时器,可是定时器2被系统占用,可用的仅仅有三个,分别为定时器1/3/4
Timer在协议栈的代码位置为hal_timer.c,hal_timer.h,4个定时器的ID分别为
|
/* Timer ID definitions */ #define HAL_TIMER_0 0x00 #define HAL_TIMER_1 0x01 #defineHAL_TIMER_2 0x02 // #define HAL_TIMER_3 0x03 #define HAL_TIMER_MAX 4 |
宏定义中的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++; if(n ==5000) { //改变这个值就可以控制定时的长短 /*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) 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 //定义 //函数声明 void Delayms(uint xms); //延时函数 void InitLed(void); //初始化 void InitT1(); //初始化定时器 |
|
/**************************** //延时函数 *****************************/ void Delayms(uint xms) //i=xms { 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() //系统不配置工作时钟时使用内部 { T1CTL = 0x0d; //128 } |
重点:系统在不配置工作频率时默觉得 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; //开总中断和 T3CTL|=0XE0; //128 T3CTL &= ~0X03; //自己主动重装 T3CTL |=0X10; //启动 EA = 1; //开总中断 } |
中断函数
|
/************************************ 中断函数 ************************************/ #pragma vector = T3_VECTOR //定时器 __interrupt void T3_ISR(void) { IRCON = 0x00; //清中断标志,也可由硬件自己主动完毕 if(++count>254) //254 { count = 0; // LED1=~LED1; //led闪烁 } } |
Main函数
|
/*************************** //主函数 ***************************/ void main(void) { InitLed(); //调用初始化函数 InitT3(); while(1){ } } |
CC2530定时器使用的更多相关文章
- CC2530定时器1的模模式中断
CC2530定时器1的模模式中断void timer1SInit(void){ T1CCTL0 = 0; T1CTL &= ~0x0F; //clear register T1CTL |= 0 ...
- CC2530定时器3的输入捕获中断
CC2530定时器3的输入捕获中断 使用的是tim3的通道1的输入捕获P1_7口.//GPIO配置成复用功能,同时设置P1_7为输入.void irCaptureGpioInit(void){ P1S ...
- CC2530定时器
一.定时/技术器的基本原理 定时/计数器,是一种能够对内部时钟信号或外部输入信号进行计数,当计数值达到设定要求时,向CPU提出中断处理请求,从而实现定时或者计数功能的外设. 定时/计数 ...
- CC2530定时器的应用
[例1]利用定时器计数实现5中彩灯的变化形式,基于模模式的.两个标志位,一个是定时器计数,一个是彩灯的状态. #include "ioCC2530.h" #define D3 P1 ...
- CC2530定时器模模式最大值计算
首先假设 频率: f 分频系数: n 间隔定时: s 周期: T 模模式最大值: N 因为 T = 1 / f 所以 s = ( n / f ) * N = n * N / f 由此可得 计算模模 ...
- 实验三 CC2530平台上CC2530平台上定时器组件的
实验三 CC2530平台上CC2530平台上定时器组件的TinyOS编程 实验目的: 加深和巩固学生对于TinyOS编程方法的理解和掌握 让学生初步掌握CC2530定时器的PWM功能,及其TinyOS ...
- zigbee学习之路(六):Time3(查询方式)
一.前言 通过上次的学习,相信大家对cc2530单片机的定时器的使用有了一定的了解,今天我们来介绍定时器3的使用,为什么介绍定时器3呢,因为它和定时器4功能是差不多的,所以学会定时器3,就基本掌握了c ...
- CC2530学习路线-基础实验-定时器控制LED灯亮灭(3)
目录 1. 前期预备知识 1.1 定时器中断触发 1.2 相关寄存器 1.3 寄存器相关问题 1.4 T1.T3定时器初始化流程 2 程序及代码 THE END 1. 前期预备知识 1.1 定时器中断 ...
- 【CC2530强化实训03】定时器间隔定时实现按键长按与短按
[CC2530强化实训03]定时器间隔定时实现按键长按与短按 [题目要求] 虽然用普通的延时函数能够实现按键长按与短按的判别,但是在实际的工程应用和项目开发中并不好用也不灵活.更多得是借助定时器的间隔 ...
随机推荐
- 学习推荐《精通Python网络爬虫:核心技术、框架与项目实战》中文PDF+源代码
随着大数据时代的到来,我们经常需要在海量数据的互联网环境中搜集一些特定的数据并对其进行分析,我们可以使用网络爬虫对这些特定的数据进行爬取,并对一些无关的数据进行过滤,将目标数据筛选出来.对特定的数据进 ...
- 【Henu ACM Round#15 D】Ilya and Escalator
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 概率DP; 设f[i][j]表示前i个单位时间,j个人进入房间的概率是多少 然后想一下和i-1秒的时候要怎么转移就可以了. i-1秒 ...
- ASP.Net简单的交互案例
控制器 using System; using System.Collections.Generic; using System.Linq; using System.Web; using Syste ...
- 变量get、set设置
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 平板电脑上完美体验Windows 8 (视频)
平板电脑上完美体验Windows 8 (视频) 目前,计算机产业正面临重大变革,三网融合,云计算,物联网正加速终端产品的融合.4C融合成为终端产品的未来发展趋势,是4C融合的代表性产品,它破了传统的W ...
- ajax关于主流中的异类:应对Opera(四)
修改示例以支持Opera <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> ...
- java种instanceof方法和getclass方法的区别
在比较一个类是否和另一个类属于同一个类实例的时候,我们通常可以采用instanceof和getClass两种方法通过两者是否相等来判断,但是两者在判断上面是有差别的,下面写个测试类. public c ...
- C_数组详解
数组: 一 一维数组 1.1 一维数组的定义: 类型符 数组名[常量表达式]; int a[10]; 说明: 1.数组的命名规则遵循标识符命名规则. 2.定义时需要指定元素的个数.方括号里的常量表达式 ...
- Python 学习 第三天 课后总结:
PYTHON学习第三天课后总结: 1,注释:就是对代码起到说明注解的作用. 注释分为单行注释与多行注释. 单行注释:只注释一行代码在需要注释的所在行的行首使用#号来注释此行,注意#与代码之间需要 ...
- 调用中行接口针对返回报文(xml形式)做相关处理
最近在对接中行银行接口,在获取返回报文的时候遇到一些问题,现在在这里做个总结 TIP: 在返回报文之前,要对前置机的URL请求,在这期间遇到一个坑,还是通过查看日志才发现问题 在填写转账信息的时候要求 ...