功能呢就类似于倒计数秒表,四个独立按键控制四位数码管显示;s1控制数码管显示可调,s2=1、2、3、4时,加减键操作分别为个十百千位, 现在的问题是,当我按下加减键时,比如s2=1时,个位跟十百千位一直常亮,闪烁程序不会。当我不按下按键时,我没法确定我操作对象是哪一位数码管,所以求怎样添加闪烁程序。单片机P4口连接两个74hc753,一片控制段信号,控制位信号;P6.3 P6.4控制74HC753的选通,P1.4-P1.7四个独立按键s1.s2.s3.s4
附上程序:
#include
#define uchar unsigned char
#define ulong unsigned long
ulong n=180;
uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
#define DCTR0 P6OUT &= ~BIT4 //数码管段控制位信号置低
#define DCTR1 P6OUT |= BIT4 //数码管段控制位信号置高
#define WCTR0 P6OUT &= ~BIT3 //数码管位控制位信号置低
#define WCTR1 P6OUT |= BIT3 //数码管位控制位信号置高
#define DATAPORT P4OUT //数据口所在端口P4
#define DATASEL P4SEL //数据口功能寄存器,控制功能模式
#define DATADIR P4DIR
#define CTRPORT P6OUT //控制线所在的端口P6
#define CTRSEL P6SEL //控制口功能寄存器,控制功能模式
#define CTRDIR P6DIR //控制口方向寄存器
#define KEYPORT P1OUT //按键所在的端口P1
#define KEYSEL P1SEL //控制口功能寄存器,控制功能模式
#define KEYDIR P1DIR //控制口方向寄存器
#define KEYIN P1IN
void delay(int z)
{
int x,y;
for(x=z;x>0;x--)
for(y=10;y>0;y--);
}
void Port_Init()
{
DATASEL = 0x00; //设置IO口为普通I/O模式,此句可省
DATADIR = 0xFF; //设置IO口方向为输出
DATAPORT = 0xFF; //P4口初始设置为FF
CTRSEL = 0x00; //设置IO口为普通I/O模式,此句可省
CTRDIR |= BIT3 + BIT4; //设置IO口方向为输出,控制口在P63,P64
CTRPORT = 0xFF; //P6口初始设置为FF
KEYSEL = 0x00; //设置IO口为普通I/O模式,此句可省
KEYDIR = 0x0F; //高四位输入模式,低四位输出模式,外部上拉电阻
KEYPORT= 0xF0;
P2DIR=0xFF;
P2OUT=0xFF;
}
void Clock_Init()
{
uchar i;
BCSCTL1&=~XT2OFF; //打开XT2振荡器
BCSCTL2|=SELM1+SELS; //MCLK为8MHZ,SMCLK为8MHZ
do{
IFG1&=~OFIFG; //清楚振荡器错误标志
for(i=0;i<100;i++)
_NOP();
}
while((IFG1&OFIFG)!=0); //如果标志位1,则继续循环等待
IFG1&=~OFIFG;
}
void display()
{
uchar i,j,k,m;
m=n%1000%100%10;
k=n%1000%100/10;
j=n%1000/100;
i=n/1000;
DCTR1; //控制数码管段数据的74HC573的LE管脚置高
WCTR1; //控制数码管位的74HC573的LE管脚置高
DATAPORT=0xfe; //设置要显示的位,也就是哪一个数码管亮
WCTR0; //锁存位数据,下面送上段数据以后,就显示出来了
DATAPORT=table; //送要显示的数据,这里是键值
DCTR0; //锁存段数据,数码管亮一个时间片刻
delay(200);
DCTR1; //控制数码管段数据的74HC573的LE管脚置高
WCTR1;
DATAPORT=0xfd;
WCTR0;
DATAPORT=table[j];
DCTR0;
delay(200);
DCTR1; //控制数码管段数据的74HC573的LE管脚置高
WCTR1;
DATAPORT=0xfb;
WCTR0;
DATAPORT=table[k];
DCTR0;
delay(200);
DCTR1; //控制数码管段数据的74HC573的LE管脚置高
WCTR1;
DATAPORT=0xf7;
WCTR0;
DATAPORT=table[m];
DCTR0;
delay(200);
}
void keyscan()
{
static uchar a,b,c,d;
static int s1num,s3num,s4num;
static char s2num=-1;
if(P1IN==0xe0)
{
delay(5000);
if(P1IN==0xe0)
{
while(P1IN==0xe0);
s1num=s1num++;
s1num=s1num%2;
}}
switch(s1num)
{
case 1:
CCTL0 = ~CCIE;
if(P1IN==0xd0)
{
delay(5000);
if(P1IN==0xd0)
{
while(P1IN==0xd0);
s2num++;
s2num=s2num%4;
}
}
switch(s2num)
{
case 0: if(P1IN==0x70)
{
delay(5000);
if(P1IN==0x70)
{
while(P1IN==0x70);
//if((P1IN&0x80)
a++;
a=a%10;
n=a+b*10+c*100+d*1000;
}
}
if(P1IN==0xb0)
{
delay(5000);
if(P1IN==0xb0)
{
while(P1IN==0xb0);
a--;
if(a==255) a=9;
n=a+b*10+c*100+d*1000;
}
}//display(n); //控制数码管段数据的74HC573的LE管脚置高
break;
case 1: if(P1IN==0x70)
{
delay(5000);
if(P1IN==0x70)
{
while(P1IN==0x70);
//if((P1IN&0x80)
b++;
b=b%10;;
n=a+b*10+c*100+d*1000;
}
}
if(P1IN==0xb0)
{
delay(5000);
if(P1IN==0xb0)
{
while(P1IN==0xb0);
b--;
if(b==255) b=9;
n=a+b*10+c*100+d*1000;
}
}//display(n);
break;
case 2: if(P1IN==0x70)
{
delay(5000);
if(P1IN==0x70)
{
while(P1IN==0x70);
//if((P1IN&0x80)
c++;
c=c%10;
n=a+b*10+c*100+d*1000;
}
}
if(P1IN==0xb0)
{
delay(5000);
if(P1IN==0xb0)
{
while(P1IN==0xb0);
a--;
if(a==255) a=9;
n=a+b*10+c*100+d*1000;
}
}//display(n);
; break;
case 3: if(P1IN==0x70)
{
delay(5000);
if(P1IN==0x70)
{
while(P1IN==0x70);
//if((P1IN&0x80)
d++;
d=d%10;
n=a+b*10+c*100+d*1000;
}
}
if(P1IN==0xb0)
{
delay(5000);
if(P1IN==0xb0)
{
while(P1IN==0xb0);
d--;
if(d==255) d=9;
n=a+b*10+c*100+d*1000;
}
}//display(n);
break;
//display(n);
// break;
case -1: display(n); break;
}
break;
case 0: CCTL0 = CCIE;break;
}
}
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
n--;
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; //看门狗初始化
Clock_Init(); //时钟初始化
Port_Init();
CCTL0 = CCIE;
CCR0 = 4096;
TACTL = TASSEL_1+ID_3 + MC_1;
_EINT();
while(1)
{
keyscan();
display(n);
if(n==0)
{
CCTL0 = ~CCIE;
P2OUT=0x00;
delay(200000);
P2OUT=0xFF;
n=180;
}
}
}
我看了下键盘扫描函数应该单独写,而您呢,却写在case语句之后了。这样的写法。。。。
能力 太低啊,但是加减按键之前一定要判定s2num啊,想不出来还能怎么写
我个人建议啊,请把switch语句的判断和 键盘扫描函数(就是case后的语句分开)。实在不行,您可以先画个流程图出来。这样您的思路更加清晰一些的。不要怕浪费时间。
键盘扫描的函数里,我只是举个例子。比如在扫描函数中按下key1键,获取键值1,那么数码管显示1。这个我想你与其问。还不如去画个流程图,这样你写程序的时候就不怎么茫然了。