【第 1 题】 按键控制灯光

【第 1 题】 按键控制灯光

题目

新建 IAR 工程文件,完成按键控制 Zigbee 单片机上的 LED 的亮灭功能,模拟酒店楼道灯的控制效果,考核选手 ZigBee 单片机基础知识的掌握。具体任务要求如下:

  • 程序开始运行; D4 灯闪烁,D3、D5、D6 灯灭;
  • 按下模块上的“SW1”键松开后,实现 D5、D6 灯亮 2 秒后自动熄灭(期间再次按下后,顺延亮);
  • 重复上述第二个步骤。
    补充说明:
  • 在这块 ZigBee 板的小辣椒上贴上题号(如:任务三第 1 题则写题 1), 将这块ZigBee 板 装在答题区上 ,接上电源,待裁判评判。
  • 参赛选手打开“竞赛资料\任务 3\ ZigBee 模块板硬件原理图.pdf 文档”进行参考。
  • ZigBee 模块板所采用的芯片为 TI CC2530F256 芯片,头文件为 “ioCC2530.h”
  • 寄存器描述 如下表所示。
寄存器描述
寄存器功能描述
P1SEL
(0XF4)
功能选择7:0P1.7到P1.0功能选择
0:通用I/O
1:外设功能
P1DIR
(0XFE)
端口方向7:0P1.7 到 P1.0 的 I/O 口方向
0:输入
1:输出

解题思路

IAR新建工程并配置。
好多同学不明白顺延亮是什么意思,我的理解是类比电梯门:

  1. 进入电梯之后没人去按开门键2秒后电梯门就会自动关闭。
  2. 如果突然有人要上电梯里面的人需要按一下开门键让电梯门顺延关闭,也就是电梯门打开重新计时2秒后关闭。
  3. 如果你在电梯里等人,需要一直按下开门键让电梯门一直开着,直到你等的那个人上电梯之后松开电梯开门键,松开按键之后电梯门才会计时2秒后关闭。

代码

//-------------------------------------------------------------------
// 库文件
//-------------------------------------------------------------------
#include "ioCC2530.h"

//-------------------------------------------------------------------
// 常  量
//-------------------------------------------------------------------
#define D4 (P1_1)
#define D3 (P1_0)
#define D6 (P1_4)
#define D5 (P1_3)

#define SW1 (P1_2)

//-------------------------------------------------------------------
// 变  量
//-------------------------------------------------------------------
unsigned char flag200ms = 0;		// 定时200ms标志位 用于D4闪烁
unsigned char flag2s = 0;			// 定时2s标志位 用于D5、D6熄灭

unsigned char keySta = 1;			// 按键状态

unsigned char lightPeriod = 0;		// 亮灯期间 
unsigned char putoffPeriod = 0;		// 顺延期间

//-------------------------------------------------------------------
// 函  数
//-------------------------------------------------------------------
void halTimer1Config(unsigned int ms);
void halKeyScan();
void halKeyDirver();

void LeD56Light();
void putoffLight();

//-------------------------------------------------------------------
// 函数名   halTimer1Config
//
// 简  述   定时器1设置周期
//
// 参  数   ms(1~500ms)
//
// 返回值   无
//-------------------------------------------------------------------
void halTimer1Config(unsigned int ms)
{
 	unsigned long compare_up;					// 临时变量 向上比较
	compare_up = 16000000 / 128;				// 时钟频率 16MHZ / 128分频
	// s(定时时间) / T(时钟周期) = k(最大计数值)
	// 1 / f(时钟频率) = T(时钟周期)
	// s(定时时间) * f(时钟频率) /  = k(最大计数值)
	compare_up = (compare_up * ms) / 1000;		// ms / 1000 * f = k
	// cmpare_up = 65536 - cmpare_up; 			// 51单片机算法
	
	T1CC0L = (unsigned char)(compare_up);		// 定时器1通道0捕获/比较值低位
	T1CC0H = (unsigned char)(compare_up >> 8);	// 定时器1通道0捕获/比较值高位
	T1CCTL0 |= 0X04;							// 定时器1通道0比较模式
	T1CTL |= (0X0C)|(0X02);						// 定时器1 128分频 模模式
	T1IE = 1;									// IEN1.1/T1IE 定时器1中断使能
}

//-------------------------------------------------------------------
// 函数名   halKeyScan
//
// 简  述   按键SW1扫描消抖 8次扫描
//
// 参  数   无
//
// 返回值   无
//-------------------------------------------------------------------
void halKeyScan()
{
 	static unsigned char keybuf = 0xff;			// 缓存
	keybuf = (keybuf << 1) | SW1;
	if(keybuf == 0x00)
		keySta = 0;
	else if( keybuf == 0xff )
		keySta = 1;
	else
	{}
}

//-------------------------------------------------------------------
// 函数名   halKeyDriver
//
// 简  述   按键驱动函数 分配按键动作
//
// 参  数   无
//
// 返回值   无
//-------------------------------------------------------------------
void halKeyDriver()
{
 	static unsigned char backup = 1;		// 按键上次状态
	if( lightPeriod == 1 )
	{
	 	if( keySta == 0 )					
		{
		 	putoffLight();					// 亮灯期间按下按键 顺延亮
		}
		else
		{
		 	putoffPeriod = 0;				// 按键弹起顺延期间结束 计时2s后熄灭LED 
		}
	}
	else
	{
		if( backup != keySta )
		{
			if( keySta == 1 )
			{
				LeD56Light();				// 没有亮灯时按下点亮LeD56 进入亮灯期间
			}
			backup = keySta;				// 保存按键状态
		}
	}
}

//-------------------------------------------------------------------
// 函数名   Led56Light
//
// 简  述   按键动作点亮LeD56进入亮灯期间
//
// 参  数   无
//
// 返回值   无
//-------------------------------------------------------------------
void LeD56Light()
{
	D5 = 1;
	D6 = 1;
	lightPeriod = 1;			// 亮灯期间ing..
}

//-------------------------------------------------------------------
// 函数名   putoffLight
//
// 简  述   按键动作 顺延亮 进入顺延期间
//
// 参  数   无
//
// 返回值   无
//-------------------------------------------------------------------
void putoffLight()
{
	D5 = 1;
	D6 = 1;
	putoffPeriod = 1;			// 顺延期间ing..
}

//-------------------------------------------------------------------
// 函数名   main
//
// 简  述   主函数
//
// 参  数   无
//
// 返回值   无
//-------------------------------------------------------------------
void main(void)
{
	// LED与引脚对应关系
	// LED1 == D4 == P1_1
	// LED2 == D3 == P1_0
	// LED3 == D6 == P1_4
	// LED4 == D5 == P1_3
	
	// P1SEL复位值0x00 默认为通用I/O口所以省略 
	// 设置D4、D5、D6 通用输出 D3没用到
	P1DIR |= (1<<1)|(1<<4)|(1<<3);
	
	//程序开始运行:D4灯闪烁 D6、D5灯灭,D3没有设置不会亮
	D6 = 0;D5 = 0;
	
	halTimer1Config(10);		// 设置定时器1定时10ms
	EA = 1;						// 开启总中断
	
	while(1)
	{
		halKeyDriver();			// 按键驱动函数
		
		// 满足题意 运行时D4灯闪烁 间隔200ms(自定义)
		if( flag200ms == 1 )
		{
			flag200ms = 0;
			D4 = ~D4;
		}
		
		// 亮灯期间 2s时间到 关灯
		if( lightPeriod == 1 && flag2s == 1 )
		{
			flag2s = 0;
			D6 = 0;
			D5 = 0;
			lightPeriod = 0;
		}
		
	}
}

#pragma vector = T1_VECTOR
__interrupt void T1_ISR(void)
{
  	static unsigned char tmr200ms = 0;
	static unsigned char tmr2s = 0;
	
	tmr200ms++;
	if( tmr200ms >= 20 )
	{
		tmr200ms = 0;
		flag200ms = 1;
		if( lightPeriod == 1  && putoffPeriod == 0 )	// 在亮灯期间 并且 没有在顺延期间开始2s计时
		{
			tmr2s++;
			if(tmr2s >= 10)
			{
				tmr2s = 0;
				flag2s = 1;
			}
		}
		else
		{
			tmr2s = 0;
		}
	}
	halKeyScan();			// 按键扫描
}
//-------------------------------------------------------------------
// 作  者   :   MCU-51王
// 修改日期 :   2019年9月4日 10:43:05
//-------------------------------------------------------------------

顺延流程图

画的不是很好大概是这个意思 ?

Created with Raphaël 2.2.0 while(1){ 点亮状态? 顺延状态? 按键松开? 顺延状态结束 }//伪代码 计时清0 D56点亮状态 计时+1 2s时间到? D56熄灭状态 按键按下? 进入顺延状态 按键按下? yes no yes no yes no yes no yes yes
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值