目录
前言
本实验用于学习CC2530芯片:
- GPIO的配置方法及中断概念与方法
- Led驱动电路及开关Led的原理
- 定时器 T1 的配置与使用
一、实验相关电路图
由于发光二级管单向导电特性, 即只有在正向电压(二极管的正极接正,负极接负)下才能导通发光。P1.0 引脚接发光二极管D1的负极,所以 P1.0 引脚输出低电平 D1 亮, P1.0 引脚输出亮电平 D1 熄灭。
实验结果:定时器 T1 通过查询方式控制 LED1 周期性闪烁。
二、实验相关理论与寄存器
定时器 1 是一个独立的 16 位定时器,支持典型的定时/计数功能,比如输入捕获,输出比较和 PWM 功能。定时器有五个独立的捕获/比较通道。每个通道定时器使用一个 I/O 引脚。定时器用于范围广泛的控制和测量应用,可用的五个通道的正计数/倒计数模式将允许诸如电机控制应用的实现。
定时器 1 的功能如下:
- 五个捕获/比较通道
- 上升沿、下降沿或任何边沿的输入捕获
- 设置、清除或切换输出比较
- 自由运行、模或正计数/倒计数操作
- 可被 1, 8, 32 或 128 整除的时钟分频器
- 在每个捕获/比较和最终计数上生成中断请求
- DMA 触发功
1.定时/计数器的基本原理
定时/计数器,是一种能够对内部时钟信号或外部输入信号进行计数,当计数值达到设定要求时,则向 CPU 提出中断处理请求,从而实现定时或者计数功能的外设。
定时/计数器最基本的工作原理是进行计数。 不管是定时器还是计数器,本质上都是计数器,可以进行加 1(减 1)计数,每出现一个计数信号,计数器就会自动加 1(自动减 1),当计数值从 0 变成最大值(或从最大值变成 0)溢出时,定时/计数器就会向 CPU 提出中断请求。
2.CC2530 的定时/计数器
CC2530 共有 5 个定时/计数器,其中定时器 1 是一个 16 位的定时器,为 CC2530 中功能最全的一个定时/计数器,在应用中应优先选用。定时器 1 的工作模式有三种:
<1> 自由运行模式: 计数器从 0x0000 开始,在每个活动时钟边沿增加 1,当计数器达到0xFFFF 时溢出,计数器重新载入 0x0000 并开始新一轮的递增计数。该模式的计数周期是固定0xFFFF,当达到最终计数值 0xFFFF 时,标志位 IRCON.T1IF 和 T1STAT.OVFIF 被设置。
![](https://img-blog.csdnimg.cn/ff2ad90f9b5c4da3a57cc0d0f43e3447.png)
<2> 模模式: 计数器从 0x0000 开始,在每个活动时钟边沿增加 1,当计数器达到 T1CC0 寄存器保存的值时溢出,计数器又将从 0x0000 开始新一轮的递增计数, 模模式的计数周期可自行设定。
![](https://img-blog.csdnimg.cn/6c1e212e83234591b89c14e29f81f346.png)
<3> 正计数/倒计数模式: 计数器反复从 0x0000 开始,正计数到 TICC0 保存的最终计数值,然后再倒计数回 0x0000,当达到最终计数值时,标志位 T1IF 和 OVFIF 被设置。
![](https://img-blog.csdnimg.cn/81cf7c54cbb14b4498a48deab3bd5dc3.png)
3.CC2530 的定时/计数器中断系统
定时器有 3 种情况能产生中断请求:
<1> 计数器达到最终计数值(溢出或回到零)。
<2> 输入捕获事件。
<3> 输出比较事件(模模式时使用)。
使用模模式要特别注意,需要开启通道 0 的输出比较模式,否则计数器的值达到 T1CC0 后,是不会产生溢出中断的。
定时器 1 共有 5 对 T1CCxH 和 T1CCxL 寄存器,分别对应通道 0 到通道 4。在使用定时器 1 的定时功能时,会用到 T1CC0H 和 T1CC0L 两个寄存器存放最大计数值的高 8 位和低 8 位。最大计数值 = 定时时长 / 定时器计数周期。
举例:如何定时 100ms(0.1s) ?
系统在不配置工作频率时默认为 2 分频,32M/2=16M,则系统时钟为 16MHz,分频系数为128,要定时 0.1 秒,最大计数值为:
默认情况下系统时钟为 16MHz 时,16 位定时器每次溢出的值是 65536,溢出时间可以按此公式算出,T=1/(16M/128)*65536=0.524s
CC2530 的 T1 定时器(16 位)需要配置三个寄存器 T1CTL、 T1STAT、 IRCON。如下表所示(更详细的可参考数据手册):
寄存器 | 作用 | 描述 |
T1CTL(0xE4) | 定时器 1 的控制 | T1CTL (Bit 3:2) 分频器划分值,如下: 00: 暂停运行。 01: 自由运行,从0x0000到0xFFFF反复计数。 10: 模模式,从0x0000到T1CC0反复计数。 11: 正计数/倒计数,从 0x0000 到 T1CC0 反复计数并且从 T1CC0 倒计数到 0x0000。 |
T1STAT(0xAF) | 定时器 1 状态 | Bit5(OVFIF): 定时器/计数器溢出中断标志 Bit4: 定时器 1 通道 4 中断标志 Bit3: 定时器 1 通道 3 中断标志 Bit2: 定时器 1 通道 2 中断标志 Bit1: 定时器 1 通道 1 中断标志 Bit0: 定时器 1 通道 0 中断标志 |
IRCON(0xC0) | 中断标志4 | Bit1(T1IF): 定时器1中断标志。当定时器1中断发生时设为1并且当CPU向量指向中断服务例程时清除。 0: 无中断未决 1: 中断未决 |
按照表格寄存器的内容,对 Led1 和 定时器T1 进行配置:
Led1配置如下:
P1SEL &=~0x01; //配置P1.0为通用IO口
P1DIR |= 0x01; //配置 P1.0 为输出
定时器T1配置如下:
T1CTL = 0x0d; //128 分频,自动重装 0x0000-0xFFFF
T1STAT= 0x21; //通道 0,中断有效
本实验运行过程:通过T1CTL和T1STAT寄存器设置模式为通道0的自由运行模式时,系统开始从0x0000向0xFFFF计数,当达到0xFFFF时,产生溢出中断,标志位 IRCON.T1IF 被系统设为1,手动将 IRCON 归零后,计数器重新载入 0x0000 并开始新一轮的递增计数。
三、源码分析
/****************************************************************************
* 文 件 名: main.c
* 描 述: 定时器T1通过查询方式控制LED1每1s周期性闪烁
****************************************************************************/
#include <ioCC2530.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define LED1 P1_0 // P1.0口控制LED1
//设置LED灯相应的IO口 入口参数: 无 出口参数: 无
void InitLed(void)
{
P1DIR |= 0x01; //P1.0定义为输出
LED1 = 1; //使LED1灯上电默认为熄灭
}
//定时器初始化,系统不配置工作时钟时默认是2分频,即16MHz 入口参数: 无 出口参数: 无
void InitT1()
{
T1CTL = 0x0d; //128分频,自动重装 0x0000-0xFFFF
T1STAT= 0x21; //通道0,中断有效
}
//程序入口函数
void main(void)
{
uchar count=0;
InitLed(); //调用初始化函数
InitT1();
while(1)
{
if(IRCON > 0) //当进入该条语句时,说明已经计数一次0xFFFF(0.524s)了
{
IRCON=0;
if(count++ >= 1) //约1s周期性闪烁,示波器测大约为1025MS
{
count=0;
LED1 = !LED1; //LED1闪烁
}
}
}//count++ >=1规则为先判断后加1,所以while里每进行两次循环约为1s
}