南昌航空大學實驗報告
二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信號。
