感知层编程实验四
南昌航空大学实验报告
二0二1年11月11日
课程名称: 感知层编程实验 实验名称:TIME编程
班级学号: 姓名: 同组人: 无
指导教师评定: 签名:
实验四 TIMER编程
实验目的:
- 加深和巩固学生对于CC2530定时器的理解和掌握
- 让学生初步掌握CC2530定时器的PWM功能,及其编程方法
- 提高学生的上机和编程过程中处理具体问题的能力
实验要求:
- 实验要求自己独立的完成;
- 编写和调试过程中出现的问题要做好记录,并事后总结到报告中
- 实验程序调试完成后, 用给定的平台进行测试,由老师检查测试结果,并给予相应的成绩
- 实验完成后,要上交实验报告。
实验内容:
- 开发一个新的应用,能够利用定时器使用LED灯周期性闪烁,及通过PWM功能实现无级调光。
- 首先使得LED灯可以周期性闪烁(利用定时器的计时功能);
- 利用定时器PWM功能控制LED的周期性渐亮、渐暗;
- 通过按键控制控制亮度变化,实现按下逐渐变亮,放开逐渐变暗。
- 在实验报告中分别给出上述三个阶段的源码。
实验环境:
集成开发环境为IAR
实验过程:
这次实验主要考察的定时器与PWM功能的设计,按照实验内容的要求分别在IAR上写好代码,连接板子烧录,观察实验现象。
实验代码:
第一部分
#include<ioCC2530.h>
#define LED1 P1_0 //定义LED1为P1_0口控制
#define LED2 P1_1 //定义LED2为P1_1口控制
#define KEY1 P0_1 //定义KEY1为P0_1口控制
void Delay(int n); //延时
void InitKEY(void); //初始化KEY控制IO口函数
void Delay(int n) //1ms
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<535;j++);
}
void InitKEY(void)
{
IEN1 |= 0x20; //端口0的总中断使能
P0IEN |= 0x02; //P0_1口的中断使能,即KEY1的按键中断
//PICTL |= 0x00; //端口中断触发延,默认所有端口都是上升沿
PICTL |= 0x01; //设置成端口0下降沿触发
IEN0 |= 0x80; //总中断开启
P0IFG = 0x00; //清除端口0的中断状态标志
}
void main(void)
{
P1DIR |= 0x03; //P1_0、P1_1定义为输出
LED1 = 1; //LED0灯初始化为关
LED2 = 1; //LED1灯初始化为关
InitKEY();
while(1) //死循环 等待按键中断
{
}
}
#pragma vector = P0INT_VECTOR //P0中断向量
__interrupt void P0_ISR(void)
{
if(0x02 == (P0IFG & 0x02)) //判断一下是否是P0_1即按键1的中断请求
{
for(int i = 0;;i++)
{
if(i%2==0)
{
LED2 = 1;
LED1 = !LED1;
}
else
{
LED1 = 1;
LED2 = !LED2;
}
Delay(1000);
}
}
IRCON &= ~0x20; //清除端口0的总中断状态标志
//P0IF = 0; //和上面的代码是一个意思
P0IFG &= ~0x02; //清除具体端口P0_1的中断状态标志
}
第二部分
#include <ioCC2530.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define LED1 P1_0 // P1.0口控制LED1
void Delay(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<535;j++);
}
void InitLed(void)
{
P1DIR |= 0x01; //P1.0定义为输出
LED1 = 0; //使LED1灯上电默认为熄灭
}
void Init_Clock()
{
CLKCONCMD &= ~0x40; //系统时钟源选择:外部32MHz 。
while(!(SLEEPSTA & 0x40));//等待晶振稳定
CLKCONCMD &= ~0x47; //128分频 CLKSPD不发分频
SLEEPCMD |= 0x04; //关闭不用的RC振荡器
}
void InitT1()
{
CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定为32M
CLKCONCMD &= ~0x07; //设置系统主时钟频率为32MHZ
CLKCONCMD |= 0x38;//时钟速度32 MHz 定时器标记输出设置[5:3]250kHz
PERCFG |= 0x40; //定时器1 的IO位置 1:备用位置2
P2SEL &= ~0x10; //定时器1优先
P2DIR |= 0xC0; //第1优先级:定时器1通道2-3
P1DIR |= 0xff; //端口1为输出
P1SEL |= 0x01; //timer1 通道2映射口P1_0
T1CC0H = 0x00; //1ms的周期时钟,频率为976.516HZ
T1CC0L = 0xff;
T1CCTL2 = 0x1c;// 模式选择 通道2比较模式
T1CTL = 0x02; //250KHz 1分频
}
void main(void)
{
InitLed();//调用初始化函数
InitT1(); //定时器初始化及pwm配置
Init_Clock(); //声明初始化时钟函数
while(1)
{
uchar m;
uchar array[11]={0xF7,0xE1,0xC8,0xAF,0x96,
0x7D,0x64,0x4B,0x32,0x19,0x0A};//占空比依次增大,LED逐渐变亮
for(m = 0; m < 11; m++)
{
T1CC2H = 0x00;//高位不变
T1CC2L = array[m];//依次改变占空比
Delay(200);
}
for(m = 10; m >0; m--)
{
T1CC2H = 0x00;//高位不变
T1CC2L = array[m];//依次改变占空比
Delay(200);
}
}
}
第三部分
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
#define LED1 P1_0 //定义LED1为P10口控制
#define KEY1 P0_1 //KEY1为P0.1口控制
void Delay(unsigned int t);
void InitIO(void);
void InitKey();
void main (void){
unsigned int CYCLE=600,PWM=0;//定义周期并赋值
InitIO();
InitKey();
while (1) {
if(KEY1==0){
//KEY1按下,一直按着
PWM++;
if(PWM>CYCLE){
PWM=CYCLE-1;
}
}else{
PWM--;
if(PWM<1){
PWM=1;
}
}
if(PWM==1){
LED1=0;
}else if(PWM==CYCLE){
LED1=1;
}else if(CYCLE>PWM){
LED1=1;
Delay(PWM);
LED1=0;
Delay(CYCLE-PWM);
}
}
}
void Delay(unsigned int t){//延时函数
while(t){
t--;
t++;
t--;
}
}
void InitIO(void){//初始化IO口程序
P1DIR |= 0x13; //P10、P11、P14定义为输出
}
void InitKey(){//按键初始化函数
P0SEL &= ~0x02; //设置P0.1为普通IO口
P0DIR &= ~0X02; //按键接在P0.1口上,设P0.1为输入模式
}
实验结果:
第一个:led灯呈现周期性闪烁
第二个:led灯自动渐亮渐灭
第三个:led灯最开始很暗,按下k1不动逐渐变亮,放开k1逐渐变暗。
实验总结:
这次实验主要存在点困难的是如何用定时器去设计pwm,通过给的资料加上老师上课讲的找到了设计思路。
通过这次实验加深和巩固我对于CC2530定时器的理解和掌握,以及学会了通过定时器设计一个pwm功能。
附录:
周期性闪烁的实现:在响应定时器的中断服务程序中切换LED的状态
PWM功能实现渐亮渐暗:
(1)根据板载LED选择合适的定时器及通道,要求所使用的定时器的通道的引脚与LED相连;
(2)选定定时器的工作模式,设置好预分频值,逐渐改变占空比以输出PWM信号
定时器各通道所使用的引脚:
T1CTL:
IRCON:
T1STAT:
定时器框图:
初值寄存器:设置计数周期
比较寄存器:设置占空比
使用CC2530输出PWM信号,在选定通道后,要选定相应工作模式,确定该模式下初值寄存器、比较寄存器分别是2530中的哪个寄存器。确定好周期,适时修改比较寄存器即可输出PWM信号。