CC2530+定时器3与Delay_ms延时函数
前言
Delay
函数是开发中常用到的函数,可以用于按键消抖,LED闪烁,生成一定频率信号等(软件模拟通讯协议)。由于利用循环执行一定次数的空指令实现的延时函数在精度上并不能让人满意,而用定时器进行延时的精度更高。本章将基于CC2530的定时器3(8位定时器)实现Delay_ms
函数。
定时器3
跟定时器1
不同的是定时器3
和定时器 4
的所有定时器功能都是基于主要的 8 位计数器建立的。计数器在每个时钟边沿递增或递减
-
可以通过SFR寄存器 TxCNT 读取 8 位计数器的值,其中x指的是定时器号码,3或4。
-
通过设置 TxCTL 控制寄存器的值实现清除和停止计数器
模模式
当定时器运行在模模式,8位计数器在 0x00 启动,每个活动时钟边沿递增。当计数器达到寄存器TxCC0所含的最终计数值时,计数器复位到 0x00,并继续递增。如果设置了相应的中断屏蔽位TxCTL.OVFIM,就产生一个中断请求。
使用定时器T3的模模式,需要配置以下寄存器:
-
T3CTL:定时器3控制寄存器
-
T3CC0:保存最终的计数值
-
T3CCTL0:使用定时器3模计数时,必须使能 T3CCTL0.MODE =1
-
T3IF: 定时器3中断标志
-
T3IE: 定时器3中断使能
-
Note: 定时器3的使用也需要配置系统时钟,与定时器1的配置方式一致,不再赘述,详细可看基础篇02号文章
具体代码讲解
工程结构
Clock.c
#include <ioCC2530.h>
#include "Clock.h"/**
* @brief 设置系统时钟为32Mhz晶振
*/
void Oclk32_Init(void)
{CLKCONCMD &= ~0x40; // 设置系统时钟源为 32MHZ晶振while(CLKCONSTA & 0x40); // 等待晶振稳定 CLKCONCMD &= ~0x3f; // 定时器tick输出设置 设置系统主时钟频率为 32MHZ
}/**
* @brief 设置系统时钟为16Mhz晶振
*/
void Oclk16_Init(void)
{CLKCONCMD |= 0x40;while(!(CLKCONSTA & 0x40));CLKCONCMD |= 0x09;CLKCONCMD &= 0xC9;
}
Clock.h
#ifndef __CLOCK_H
#define __CLOCK_H
void Oclk32_Init(void);
void Oclk16_Init(void);
#endif
Timer3.c
#include <ioCC2530.h>
#include "timer3.h"
unsigned int remaintims;
/**
* @brief 开启定时器3
*/
void Timer3_On(void)
{T3CTL |= 0x10;
}/**
* @brief 关闭定时器3
*/
void Timer3_Off(void)
{T3CTL &= 0xEF;
}/**
* @brief 定时器3初始化函数 定时器中断
*/
void Timer3_Init(void)
{// 开启定时器3中断T3IF = 0; // 清除中断标志T3IE = 1; // 定时器1中断使能 IEN1EA = 1; // 使能全局中断// 定时器3参数配置 T3CTL |= 0xEE; //开溢出中断 128分频T3CC0 = 0xFA; // 250最终计数T3CCTL0 |= 0x04; // 设置输出模式Timer3_Off(); // 关闭定时器
}// 定时器T3中断服务函数 1ms
#pragma vector = T3_VECTOR
__interrupt void T3_ISR(void)
{T3IF = 0; // 清除中断标志位if(remaintims > 0){remaintims--; // 剩余计数时间 /ms}else{Timer3_Off(); // 关闭定时器}
}
定时器3中断函数详解
当remaintims
大于零时,每进入一次中断令其自减,当remaintims
自减到0时,关闭定时器。
Timer3.h
#ifndef __TIMER3_H
#define __TIMER3_H
void Timer3_Init(void);
void Timer3_On(void);
void Timer3_Off(void);
extern unsigned int remaintims;
#endif
Delay.c
#include <ioCC2530.h>
#include "delay.h"
#include "Clock.h"
#include "timer3.h"/**
* @brief 延时函数初始化
*/
void Delay_Init(void)
{Oclk32_Init(); // 时钟初始化 32MHZTimer3_Init(); // 定时器3 初始化
}/**
* @brief 延时函数 1ms
* @param ms: 延时时间 单位: ms
*/
void Delay_ms(unsigned int ms)
{remaintims = ms;Timer3_On(); // 启动定时器3while(remaintims > 0); // 等待延时结束
}
Delay_ms()
函数详解
将需要延时的时间ms
(单位毫秒),作为参数传入。函数内令remaintims
等于ms
, 开启定时器3
,由于定时器3
每1ms进入一次中断,并在每次中断函数中将remaintims
减一,while
等待remaintims
减到0,此时延时结束,退出函数。
Delay.h
#ifndef __DELAY_H
#define __DELAY_H
void Delay_Init(void);
void Delay_ms(unsigned int ms);
#endif
接下来,写一个流水灯检测一下刚实现的Delay_ms()
函数
LED.c
#include <ioCC2530.h>
#include "LED.h"
#include "delay.h"
unsigned int LED_Flag=0;
/**
* @brief 初始化LED
*/
void LED_Init(void)
{P1SEL &= ~0x03; P0SEL &= ~0x10;P1DIR |= 0x03; // P1_0 P1_1 设置为输出P0DIR |= 0x10; // P0_4 设置为输出LED1 = 1;LED2 = 1;LED3 = 1;
}/**
* @brief 关闭所有LED
*/
void LED_OFF(void)
{LED1 = 1;LED2 = 1;LED3 = 1;
}/**
* @brief 流水灯
*/
void LED_Flow(unsigned int ms)
{LED1 = ~LED1;Delay_ms(ms);LED2 = ~LED2;Delay_ms(ms);LED3 = ~LED3;Delay_ms(ms);
}
LED.h
#ifndef __LED_H
#define __LED_H
#define LED1 P1_0
#define LED2 P1_1
#define LED3 P0_4
extern unsigned int LED_Flag;
void LED_Init(void);
void LED_OFF(void);
void LED_Flow(unsigned int ms);
#endif
main.c
#include <ioCC2530.h>
#include "LED.h"
#include "delay.h"
#include "Clock.h"
void main(void)
{Delay_Init(); // Delay 初始化LED_Init(); // LED初始化while(1){LED_Flow(1000); // 流水灯 每过1s改变一个灯的状态}
}
结语
本章介绍了用CC2530的定时器3实现Delay_ms()
函数。