题目涉及考点总结
一,按键
采用状态扫描来编写,由于J5配置为BTN独立按键模式,所以代码有所更改,变得简单。
以前:
//-----------------------------------------------//状态扫描矩阵按键
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
unsigned char read_KBD(void)
{
static char key_state = 0;
unsigned char key_return=0, key_press;
unsigned char key1,key2;
P44=1;P42=1;P35=1;P34=1;P33=0;P32=0;P31=0;P30=0;
if(P44==0) key1=0x70;
else if(P42==0) key1=0xb0;
else if(P35==0) key1=0xd0;
else if(P34==0) key1=0xe0;
else key1=0xf0;
P44=0;P42=0;P35=0;P34=0;P33=1;P32=1;P31=1;P30=1;
if(P33==0) key2=0x07;
else if(P32==0) key2=0x0b;
else if(P31==0) key2=0x0d;
else if(P30==0) key2=0x0e;
else key2=0x0f;
key_press =key1|key2;
switch (key_state)
{
case key_state_0:
if (key_press!=0xff) key_state = key_state_1;
break;
case key_state_1:
if (key_press !=0xff)
{
if(key_press==0x77) key_return = 4;
if(key_press==0x7b) key_return = 5;
if(key_press==0x7d) key_return = 6;
if(key_press==0x7e) key_return = 7;
if(key_press==0xb7) key_return = 8;
if(key_press==0xbb) key_return = 9;
if(key_press==0xbd) key_return = 10;
if(key_press==0xbe) key_return = 11;
if(key_press==0xd7) key_return = 12;
if(key_press==0xdb) key_return = 13;
if(key_press==0xdd) key_return = 14;
if(key_press==0xde) key_return = 15;
if(key_press==0xe7) key_return = 16;
if(key_press==0xeb) key_return = 17;
if(key_press==0xed) key_return = 18;
if(key_press==0xee) key_return = 19;
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0xff) key_state = key_state_0;
break;
}
return key_return;
}
现在:
//-----------------------------------------------//状态扫描矩阵按键
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
unsigned char read_KBD(void)
{
static char key_state = 0;
unsigned char key_return=0, key_press;
P33=1;P32=1;P31=1;P30=1;
if(P33==0) key_press=0x07;
else if(P32==0) key_press=0x0b;
else if(P31==0) key_press=0x0d;
else if(P30==0) key_press=0x0e;
else key_press=0x0f;
switch (key_state)
{
case key_state_0:
if (key_press!=0x0f) key_state = key_state_1;
break;
case key_state_1:
if (key_press !=0x0f)
{
if(key_press==0x07) key_return = 4;
if(key_press==0x0b) key_return = 5;
if(key_press==0x0d) key_return = 6;
if(key_press==0x0e) key_return = 7;
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0x0f) key_state = key_state_0;
break;
}
return key_return;
}
二,NE555脉冲输入
1)通过调节滑动变阻器Rb3改变脉冲输出频率。
2)其信号输出接到P34引脚,并将定时器0设置成计数模式,对来自P34的外部脉冲进行计数。
三,PCF8591 ADC与DAC
四,定时器初始化
定时器0用来计数,定时器1用来定时。
void TimerInit(void) //1ms 晶振频率12Mhz
{
AUXR |= 0x40; //定时器1时钟1T模式 不分频
TMOD =0x04; //设置定时器模式 定时器0计数,定时器1定时 都是16位自动重装
TL1 = 0x20; //设置定时初值 计数值达到65536时,自动重装载TH0,TL0的值
TH1 = 0xD1; //设置定时初值
TL0=0X00;//计数器清零
TH0=0X00;
TF1 = 0; //清除TF1溢出标志
TR1 = 1; //定时器1开始计时
TF0 = 0; //清除TF0溢出标志
TR0 = 1; //启动计数器0
ET0=1;//溢出中断允许位
ET1=1;//溢出中断允许位
EA=1; //总开关
}
五,中断服务函数
void tm1_isr() interrupt 3 //中断号3的中断服务函数 中断号1:定时器0中断 中断号3:定时器1中断
1)每500ms统计一次定时器(计数器)0的计数值,因为是16位自动重装载,足够大,不会出现溢出重装。
if (count_t == 500)
{
count_t=0;
TR0=0; // 关闭定时器0,关闭了才能同时修改当前状态TH0,TL0和重装载TH0,TL0
DATA_f=(TH0*256+TL0)*2;// 脉冲频率=1s的脉冲次数 所以结果 *2
TH0=0;TL0=0; //重置TH0,TL0
TR0=1; //打开定时器0
}
2)每200ms进行一次模拟电压转换
if(count_ad==200)
{
count_ad=0;
ad_flag=1;
}
if(ad_flag==1) //200MS 放在main.c里面
{
ad_flag=0;
EA=0;
ad_data=read_pcf8591();
voltage=(u16)(ad_data*5/255.0f*100+0.5);//放大100倍的voltage
EA=1;
}
六,LED
因为涉及到不同的led的亮灭,所以我定义了一个变量来操作。
u8 led=0xff;
比如:
P0=0XFF;P2=0X80;P0=led;P2=0X00; // 开启573锁存器之前把P0置为0xff 当不使用的led会隐隐亮,建议加上第一个代码
led&=0xfe;led|=0x02; //我们操作led即可