⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 led_key.c

📁 单片机实现消息队列的例子
💻 C
字号:
/*************************************************/

/********************显示与键盘接口********/

/*************2002年12月13日*******************/

/************WROTE BY WANGSW********************/
#include "reg52x2.h"  
#include <intrins.h>

#include "define.h"

#include "led_key.h"

#define KEY_SHORT_INTERVAL		2
#define KEY_LONG_INTERVAL		40

sbit SDA = P1^0;			/*模拟串行转并行口,下降沿有效,输出为低电平可控点亮*/
sbit SCL = P1^1;			/*模拟串并行转换的时钟信号线*/

sbit KEY = P1^2;			/*键盘,低电平有效,检测位*/

sbit DISPLAY0 = P1^3;		/*EBIT4, 低电平有效*/
sbit DISPLAY1 = P1^4;		/*EBIT3*/
sbit DISPLAY2 = P1^5;		/*EBIT2*/
sbit DISPLAY3 = P1^6;		/*EBIT1*/

sbit LED = P1^7;			/*EBIT0,低电平有效*/

bool  LED_KEY_SIGN = FALSE;

byte data KeyCounter = 0;

byte data KeyIntervalSafeguard = 0;		/*用于连续两个按键速度过快导致按键混乱*/

byte data g_KeyStore = 0x00;

static byte code KeyMap[8] =				/*键盘转换*/
{
	KEY1, KEY2, KEY3, KEY4, KEY5, KEY6, KEY7, KEY8
};

static byte code LedDisplayMap[2][16] =
{
	{0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E},
	{0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0E}
};

static void SendData(byte value);

static byte KeyCheck(void);							/*键值检测*/
				

/******************************************************************************************
*函数名:		SendData
*参数:			value			需要进行串并转换的数据,是一字节8位数据
*返回值:		无
*描述:			把数据value按照从高位到低位串行发送到串并转换电路输
				入端,主要可以用来协助完成底层LED显示
*编写:			王绍伟
*版本信息:		V1.0			2003年8月15日
******************************************************************************************/
static void SendData(byte value)
{
	byte data counter;
	SCL = 1;
	for(counter = 0; counter < 8; counter++)
	{
		if(value & 0x80)  	/*判断数据*/
		{
			SDA = 1;
		}
		else
		{
			SDA = 0;
		}
		SCL = 0;					/*产生时钟动作*/
		SCL = 1;
		value = value << 1;
	}
}


/******************************************************************************************
*函数名:		KeyCheck
*参数:			无
*返回值:		counter			返回键值
				ERROR			返回出错信息
*描述:			通过扫描键盘返回按下的按键号
*编写:			王绍伟
*版本信息:		V1.0			2003年8月15日
******************************************************************************************/
static byte KeyCheck(void)
{
	byte counter;
	SDA = 1;			/*注意,原来数据为0,现在为1*/
	for(counter = 0; counter < 8; counter++)			/*r先将扫描线上都置为高电平*/
	{
		SCL = 0;					
		SCL = 1;
	}
	SDA = 0;										/*r然后逐行置为低电平,侦测P1.2(KEY反馈线)*/
	
	for(counter = 0; counter < 8; counter++)			/*需要修改计数值*/
	{
		SCL = 0;					
		SCL = 1;
		delay(1);								/*必须的延迟,否则数据出错*/
		if(!KEY)
		{
			return(counter);					/*r扫描出按下键就返回按下的键值并退出函数*/
		}
	}
	return(ERROR);				/*r若没有扫描到按下键就返回ERROR*/
}




/******************************************************************************************
*函数名:		led_key_led_control
*参数:			LedIndex		点亮的LED发光管号,其取值从1~8有效
*返回值:		无
*描述:			根据LedIndex的值决定选择点亮哪一只LED管
*编写:			王绍伟
*版本信息:		V1.0			2003年8月15日
******************************************************************************************/

extern void led_key_led_control(byte LedIndex)
{
	P1 = 0xFF;
	if(LedIndex)
	{
		LedIndex = 1 << (LedIndex - 1);		/*r当1左移(LedIndex-1)位后,发送到串并行转换电路*/
		SendData(~LedIndex);
		LED = 0;							/*r开启DP-51的Q1三极管,这样就可以开启LED管点亮*/
	}
	
	
}


/******************************************************************************************
*函数名:		led_key_led_display_control
*参数:			value			LED显示数码值
				boDp			是否显示小数点
				LedDisplayIndex	代表显示那一块LED
*返回值:		无
*描述:			对选择的LED模块让其显示一个数码的程序
*编写:			王绍伟
*版本信息:		V1.0			2003年8月15日
******************************************************************************************/
extern void led_key_led_display_control(byte LedDisplayIndex, bool boDp, byte value)
{
	byte i;
	i = boDp;
	P1 = 0xFF;
	SendData(LedDisplayMap[i][value]);		/*r发送LED显示数据到串并转换电路*/

	P1 &= ~(0x04 << LedDisplayIndex);
}


/******************************************************************************************
*函数名:		led_key_key_check
*参数:			无
*返回值:		无
*描述:			按键扫描判定程序		
*编写:			王绍伟
*版本信息:		V1.0			2003年8月15日
******************************************************************************************/
extern void led_key_key_check(void)			/*5*5=25mS*/
{
	byte i;

	P1 = 0xFF;					/*初始化原状态,以免引起错误*/
	SDA = 0;
	for(i = 0; i < 8; i++)		/*r基于DP-51硬件构造,先向扫描线上发送低电平*/
	{
		SCL = 0;
		SCL = 1;
	}
	
	if(KEY)					/*r检测反馈线,若无键按下,则KEY(P1.2)则会保持高电平,此时判定无键按下,退出键扫程序*/
	{
		KeyCounter = 0;
		return;
	}
				
	if(KeyIntervalSafeguard)	/*设置这段程序是为了让判定两次按键之间的时间间隔大于等于0.1s,此段程序在初始化后第一次按键时并不执行*/
	{
		KeyIntervalSafeguard--;
		return;
	}
		
	KeyCounter++;				/*r每25ms执行一次本程序,也就使KeyCounter自加1*/

	
	if(KeyCounter == KEY_SHORT_INTERVAL)		/*r若非保持持续按键状态(超过75ms),系统每50ms检测一次按键,若没有按键,退出;若有,发出消息*/
	{
		i = KeyCheck();
		if(i == ERROR)
		{
			return;
		}
		msg_queue_in(MSG_KEY, KeyMap[i]);
		KeyIntervalSafeguard = 3;				/*r确保系统在判定有按键按下后的0.1s内不会对按键的抖动作出多次按键判定*/
	}

	if(KeyCounter == KEY_LONG_INTERVAL)		/*r连续按键判定,如果持续按键超过一秒钟,若不松键,则接下去每经过0.1s,系统就认定又按了一次键*/
	{
		i = KeyCheck();
		if(i == ERROR)
		{
			return;
		}	
		msg_queue_in(MSG_KEY, KeyMap[i]);
		KeyCounter -= 4;
	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -