书读少了,也没学过编程,抱着书啃程序太费力了。
照着书上做矩阵键盘扫描实验时,没做成书上的2*3键盘矩阵而是做成了3*3,将代码也做了相应修改,这个程序是带3秒无操作自动休眠的,任意键唤醒,可我写入程序调试时却遇到个很奇怪的问题,就是我自己加的那列键盘死活就是唤不醒休眠后的单片机,但第一次休眠后可以,反正就是不按那排按钮就正常,一按就不正常。后来将程序又从头检查了N遍,还是没发现有明显问题。最后尝试着去掉一句没看明白但觉得可能影响唤醒的语句,嘿!结果就好了!特来请教各位该语句是什么意思?在下面用红字标出来了……希望能尽量解释通俗点,没学过C的,呵呵,路还很长啊……
#include "iom48v.h"
#include "macros.h"
#include "delay.h"
#include "led_dis.h"
#define Key_X_1 PORTC = 0b11011111 //扫描第1行键
#define Key_X_2 PORTC = 0b11101111 //扫描第2行键
#define Key_X_3 PORTC = 0b11110111 //扫描第3行键
#define Key_Scan_Port PINC //定义用于扫描键盘的端口
#define Key_Y_1 0b11111011 //第1列上有键按下
#define Key_Y_2 0b11111101 //第2列上有键按下
#define Key_Y_3 0b11111110 //第3列上有键按下
#define Key_1 0x01
#define Key_2 0x02
#define Key_3 0x03
#define Key_4 0x04
#define Key_5 0x05
#define Key_6 0x06
#define Key_7 0x07
#define Key_8 0x08
#define Key_9 0x09
#define NoKey 0x00
#define LedDisPort PORTD
unsigned char Key_Scan (void)
{
/*-----------------------扫描第1行-----------------------*/
Key_X_1;
Delay_ms(1);
if ((Key_Scan_Port|Key_Y_1)==Key_Y_1)
return Key_1;
else if ((Key_Scan_Port|Key_Y_2)==Key_Y_2)
return Key_2;
else if ((Key_Scan_Port|Key_Y_3)==Key_Y_3)
return Key_3;
/*-----------------------扫描第2行-----------------------*/
Key_X_2;
Delay_ms(1);
if ((Key_Scan_Port|Key_Y_1)==Key_Y_1)
return Key_4;
else if ((Key_Scan_Port|Key_Y_2)==Key_Y_2)
return Key_5;
else if ((Key_Scan_Port|Key_Y_3)==Key_Y_3)
return Key_6;
/*-----------------------扫描第3行-----------------------*/
Key_X_3;
Delay_ms(1);
if ((Key_Scan_Port|Key_Y_1)==Key_Y_1)
return Key_7;
else if ((Key_Scan_Port|Key_Y_2)==Key_Y_2)
return Key_8;
else if ((Key_Scan_Port|Key_Y_3)==Key_Y_3)
return Key_9;
return NoKey;
}
unsigned char Key_Scan_Ant_Dither(void) //抗抖动的键盘扫描函数,扫描键盘并返回键值
{
unsigned char TmpKeyValue=NoKey;
TmpKeyValue=Key_Scan();
if (TmpKeyValue==NoKey)
return NoKey;
Delay_ms(20);
if (TmpKeyValue!=Key_Scan())
return NoKey;
return TmpKeyValue;
}
#pragma interrupt_handler pcint1_isr: iv_PCINT1
void pcint1_isr(void) //引脚电平变化中断PCINT1中断服务函数
{
SMCR&=0xFE; //禁止休眠功能,以免误触发
PCMSK1&=(~((1<<[s:9]CINT11)|(1<<[s:9]CINT10)|(1<<[s:9]CINT9))); //禁止引脚电平变化中断,以免影响键盘扫描程序的运行
PCICR&=(~(1<<[s:9]CIE1)); //就是这句了,书上也没说,网上也没查到资料[s:245] }
void main (void)
{
unsigned char KeyValue=NoKey;
unsigned int SleepTimer=0;
DDRC=0xF8; //将键盘的"行"设置为输出,键盘的"列"设置为输入并开启了输入端的内部上拉电阻
DDRB=0xFF;
DDRD=0xFF;
PORTC=0xFF;
PORTB=0x00;
PORTD=0xFF;
SEI(); //允许全局中断
LedDisPort=DisTab[0]; //上电后初始化显示"0"
while(1)
{
KeyValue=Key_Scan_Ant_Dither();
if (KeyValue!=NoKey) //当有按键按下时,显示该键的键值
{
LedDisPort=DisTab[KeyValue];
SleepTimer=0; //并清0休眠计时器
}
else //当没有按键按下时,计算连续未操作的时间
{
SleepTimer++; //休眠计时器自加以实现计时
if (SleepTimer >= 1500) //当连续3秒钟(近似值)没有按任何按键时,将进入休眠状态
{
SleepTimer=0; //清0休眠计时器,以便唤醒后继续计时
PORTC=0b11000111; //将键盘的行(PC5,PC4)设置为输出"0"状态
PORTD=0x00; //关闭数码管显示驱动以节省电能
PCMSK1|=((1<<[s:9]CINT10)|(1<<[s:9]CINT9)|(1<<[s:9]CINT8)); //使能PCINT9..11
PCICR|=(1<<[s:9]CIE1); //使能第一组引脚电平变化中断
SMCR=0x05; //设置掉电状态并使能休眠功能
asm("SLEEP"); //休眠单片机,进入掉电状态
PORTC=0xFF; //休眠唤醒后将PC端口重置回初始化状态
}
} //End Of Else
} //End Of While
}
200字以内,仅用于支线交流,主线讨论请采用回复功能。