本帖最后由 ohy3686 于 2017-10-19 14:58 编辑
【CC2530入门教程-强化练习B】利用PWM实现灯光亮度调节
硬件背景:LED1灯连接到CC2530的P1_0引脚,SW按键连接到CC2530的P0_1引脚。
题目要求:用定时器器1的模模式,实现0.1ms的间隔定时,并由此产生PWM信号输出,通过SW按键控制PWM占空比的变化, 实现LED1灯光从暗逐渐到亮,再从亮逐渐到暗的亮度控制。实现思路:
1. 定义必要的延时函数Delay()和端口初始化函数Init_Port(),在端口初始化函数中,初始化LED1灯和SW按键的相关端口寄存器。
2. 定义定时器1初始化函数Init_Timer1(),使用内部的16MHz晶振的8分频作为时钟输入信号,采用模模式,实现0.1ms的间隔定时。
3. 在定时中断服务函数Timer1_Sevice()中,实现PWM信号输出的相关程序。
4. 设计键盘扫描程序Scan_Keys(),实现PWM占空比的变化控制。
5. 在main()函数中,通过扫描按键控制PWM的占空比,实现对LED1的亮度控制。
参考源码:
#include "ioCC2530.h"
#define LED1 P1_0
#define SW P0_1
unsigned char pwm_period = 100; //定义PWM的周期
unsigned char pwm_duy = 90; //定义PWM的占空比
unsigned char t_count = 0; //间隔定时次数累计
unsigned char flag_dir = 0; //占空比变化方向标志
/*======================延时函数==========================
功能:根据输入参数实现延时
设计:广东职业技术学院 欧浩源
时间:2017年10月19日
========================================================*/
void Delay(unsigned int time)
{
while(time--);
}
/*==================端口初始化函数======================
功能:初始化LED1和SW按键
将P1_0设置为通用I/O端口的输出模式
将P0_1设置为通用I/O端口的输入模式,上拉
关闭LED1灯
设计:广东职业技术学院 欧浩源
时间:2017年10月19日
========================================================*/
void Init_Port()
{
P1SEL &= ~0x01; //将P1_0设置为通用I/O端口
P1DIR |= 0x01; //将P1_0设置为输出方式
P0SEL &= ~0x02; //将P0_1设置为通用I/O端口
P0DIR &= ~0x02; //将P0_1设置为输入方式
LED1 = 1; //输出1--关灯,输出0--开灯
}
/*=================定时器1初始化函数=====================
功能:初始化定时器1
使用内部16MHz晶振,定时周期1ms,
使用模模式,开启通道0的输出比较模式,
分频系数8,打开相应的定时中断
设计:广东职业技术学院 欧浩源
时间:2017年10月19日
========================================================*/
void Init_Timer1()
{
/*=内部16MHz晶振8分频定时0.1ms的最大计数值为0x00c8=*/
T1CC0L = 0xc8; //设置最大计数值的低8位
T1CC0H = 0x00; //设置最大计数值的高8位
T1CCTL0 |= 0x04; //开启通道0的输出比较模式
T1IE = 1; //使能定时器1中断
T1OVFIM = 1; //使能定时器1溢出中断
EA = 1; //使能总中断
T1CTL = 0x06; //分频系数是8,模模式
}
/*================定时器1中断服务函数====================
功能:1ms间隔定时中断服务函数
对间隔定时次数进行累加,即t_count++
t_count的计数值到达pwm_duy,高电平变为低电平
t_count的计数值到达pwm_period,低电平变为高电平
一个PWM周期结束,t_count清0 ,开始下一个PWM计数
设计:广东职业技术学院 欧浩源
时间:2017年10月19日
========================================================*/
#pragma vector = T1_VECTOR
__interrupt void Timer1_Sevice()
{
T1STAT &= ~0x01; //清除定时器1通道0中断标志
t_count++; //对间隔定时次数进行累加
if(t_count == pwm_duy) //高电平周期到
{
LED1 = 0; //输出低电平
}
else if(t_count == pwm_period) //低电平周期到
{
LED1 = 1; //输出高电平
t_count = 0; //间隔定时累加清0
}
}
/*==================按键扫描处理函数======================
功能:扫描SW按键是否按下,如有按下信号先做去抖动处理
确认为SW按键动作后,
改变PWM的占空比,每次减少10个单位
当减少到占空比的边沿时,每次增加10个单位
如此往复,实现PWM占空比的来回变化
等待按键松开后,退出扫描程序
设计:广东职业技术学院 欧浩源
时间:2017年10月19日
========================================================*/
void Scan_Keys()
{
if(SW == 0)
{
Delay(100); //按键去抖动处理
if(SW == 0)
{
if(flag_dir == 0)
{
pwm_duy -= 10; //改变PWM的占空比
if(pwm_duy == 10) //如果占空比到达边沿
{
flag_dir = 1; //改变占空比的变化方向
}
}
else if(flag_dir == 1)
{
pwm_duy += 10; //改变PWM的占空比
if(pwm_duy == 90) //如果占空比到达边沿
{
flag_dir = 0; //改变占空比的变化方向
}
}
while(SW == 0);
}
}
}
/*=====================主函数===========================*/
void main()
{
Init_Port(); //初始化I/O端口
Init_Timer1(); //初始化定时器1
while(1)
{
Scan_Keys(); //扫描按键
}
}
|