新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 51单片机工程实践--第3章 74HC595+ULN200

51单片机工程实践--第3章 74HC595+ULN200

作者: 时间:2016-11-25 来源:网络 收藏

void timer0_interrupt(void) interrupt 1
{
ET0 = 0;
EA = 0; // 经测试 这里不关闭定时器中断也没有问题 鸿哥这里关闭定时器中断不知道是PIC单片机的特点还是其它原因

key_scan(); // 按键扫描函数

if(buzzer_time_cnt) // 控制蜂鸣器声音的长短
{
BUZZER_OUT = 0; // 开启蜂鸣器
--buzzer_time_cnt; // 蜂鸣器声音长短的计数延时
}
else
{
BUZZER_OUT = 1; // 关闭蜂鸣器
}

TH0 = 0xfe;
TL0 = 0x33;

ET0 = 1;
EA = 1; // 前面关闭定时器中断,这里当然需要开启
}

void interrupt_init(void)
{
TMOD = TMOD | 0x01;
TMOD = TMOD & 0xFD;

TH0 = 0xfe;
TL0 = 0x33; // 定时0.5ms
TR0 = 1;

ET0 = 1; // 开启外部中断
EA = 1; // 开启总中断
}

void key_scan(void)
{

switch(key_step)
{
case 1:// 按键扫描 1、2 号按键
KEY_OUT1 = 0;// 按键列扫描 第一列输出低电平
KEY_OUT2 = 1;// 第二列输出高电平
delay_cnt2 = 0; // 延时计数器清零
key_step++;// 切换到下一个步骤运行

break;

case 2:
delay_cnt2++;
if(delay_cnt2>CNT_DELAY_CNT2)// 小延时,但不是去抖动延时 保证列输出信号稳定
{
delay_cnt2 = 0;
key_step++;// 切换到下一个步骤运行
}

break;

case 3:
if((1==KEY_IN1)&&(1==KEY_IN2))// 如果没有按键按下,则2个IO输入都是高电平
{
key_step++;// 如果没有按键按下,下一个中断扫描另外2个按键
key_lock1 = 0;// 按键自锁标志清零
delay_cnt1 = 0;// 按键去抖动延时计数器清零,此处设计很巧妙
}
else if((0==KEY_IN1)&&(1==KEY_IN2)&&(0==key_lock1))
{

++delay_cnt1;// 延时计数器

if(delay_cnt1>CNT_DELAY_CNT1)// 延时计数器超过阀值
{
delay_cnt1 = 0;
key_lock1 = 1;// 自锁按键置位,避免一直触发,只有松开按键,才会被清零
key_sec = 1;// 触发 1 号按键
}
}

else if((1==KEY_IN1)&&(0==KEY_IN2)&&(0==key_lock1))
{
++delay_cnt1;
if(delay_cnt1>CNT_DELAY_CNT1)
{
delay_cnt1 = 0;
key_lock1 = 1;// 自锁按键置位,避免一直触发,只有松开按键,才会被清零
key_sec = 2;// 触发 2 号按键
}
}

break;

case 4:// 扫描 3、4 号按键
KEY_OUT1 = 1;// 第一列输出高电平
KEY_OUT2 = 0;// 按键列扫描,第二列输出低电平
delay_cnt2 = 0;// 延时计数器清零
key_step++;// 切换到下一步运行

break;

case 5:
delay_cnt2++;
if(delay_cnt2>CNT_DELAY_CNT2)// 小延时,但不是去抖动延时 保证列输出信号稳定
{
delay_cnt2 = 0;
key_step++;// 切换到下一步运行
}

break;

case 6:
if((1==KEY_IN1)&&(1==KEY_IN2))
{
key_step++;
key_lock1 = 0;
delay_cnt1 = 0;
}
else if((0==KEY_IN1)&&(1==KEY_IN2)&&(0==key_lock1))
{
++delay_cnt1;
if(delay_cnt1>CNT_DELAY_CNT1)
{
delay_cnt1 = 0;
key_lock1 = 1;
key_sec = 3;// 触发 3 号按键
}
}
else if((1==KEY_IN1)&&(0==KEY_IN2)&&(0==key_lock1))
{
++delay_cnt1;
if(delay_cnt1>CNT_DELAY_CNT1)
{
delay_cnt1 = 0;
key_lock1 = 1;
key_sec = 4;// 触发 4 号按键
}
}

break;
}

if(key_step>6)// 判断,第一组与第二组按键反复轮流扫描
{
key_step = 1;
}
}

void key_service(void)
{
switch(key_sec)
{
case 1:// 1 号按键
relay_status_clear();// 把relay_status清零
relay_status_set_1();// 把relay_status对应的第一个继电器启动
relay_drive();// 把relay_status的状态通过595驱动出来
buzzer_time_cnt = CNT_BUZZER_TIME;
key_sec = 0;// 处理完相应按键程序后,把按键选择变量清零,避免一直触发

break;

case 2: // 2 号按键
relay_status_clear();// 把relay_status清零
relay_status_set_2();// 把relay_status对应的第一个继电器启动
relay_drive();// 把relay_status的状态通过595驱动出来
buzzer_time_cnt = CNT_BUZZER_TIME;
key_sec = 0;

break;

case 3:// 3 号按键
relay_status_clear();// 把relay_status清零
relay_status_set_3();// 把relay_status对应的第一个继电器启动
relay_drive();// 把relay_status的状态通过595驱动出来
buzzer_time_cnt = CNT_BUZZER_TIME;
key_sec = 0;

break;

case 4:// 4 号按键
relay_status_clear();// 把relay_status清零
relay_status_set_4();// 把relay_status对应的第一个继电器启动
relay_drive();// 把relay_status的状态通过595驱动出来
buzzer_time_cnt = CNT_BUZZER_TIME;
key_sec = 0;

break;
}
}

void relay_status_clear(void)
{
relay_status = 0;
}

void relay_status_set_1(void)
{
relay_status |= 0x0001;
}

void relay_status_set_2(void)
{
relay_status |= 0x0002;
}

void relay_status_set_3(void)
{
relay_status |= 0x0004;
}

void relay_status_set_4(void)
{
relay_status |= 0x0008;
}

void relay_drive(void)
{
u8 tempdata = 0;
//u16 relay_status_temp = 0;

HC595_SCK_OUT = 0;
HC595_RCK_OUT = 0;

//relay_status_temp = relay_status;

for(tempdata=0; tempdata<16; tempdata++)
{
if(relay_status & 0x8000)
{
HC595_SI_OUT = 1;
}
else
{
HC595_SI_OUT = 0;
}

HC595_SCK_OUT = 0;
_nop_();
_nop_();
HC595_SCK_OUT = 1;
_nop_();
_nop_();
relay_status <<= 1;
}

HC595_RCK_OUT = 0;
_nop_();
_nop_();
HC595_RCK_OUT = 1;
_nop_();
_nop_();

HC595_SCK_OUT = 0;// 拉低,增强抗干扰
HC595_RCK_OUT = 0;
HC595_SI_OUT = 0;
}

void delay(void)
{
u8 t = 0;

for(t=0; t<0x0F; t++)
{;}
}


上一页 1 2 下一页

评论


技术专区

关闭