题目:
问题描述
拿到第一眼,我们应该先在脑海中想一想,如何编写代码,建议使用PDF来看题目,可以在上面做标记。
我们可以先开始写一套模板,包括(独立按键、数码管、LED灯、初始化)等,可以在模板的基础上写我们需要完成的程序。
接下来让我们看看基本的代码模板如何写吧
#include <STC15F2K60S2.H>
void choose(u8 channle) //选择通道
{
switch(channle)
{
case 4: //LED
P2 |= 0x80;
break;
case 5: //蜂鸣器继电器
P2 |= 0xa0;
break;
case 6: //数码管位选
P2 |= 0xc0;
break;
case 7: //数码管段选
P2 |= 0xe0;
break;
}
P2 &= ~0xe0;
}
/*题目中需要独立按键,所以矩阵按键我就不列出来了,有需要的小伙伴可以关注我看矩阵按键的文章*/
u8 key_statue =0; //独立按键
u8 KEY_scan()
{
u8 temp =0; //保存返回的值
P3 |= 0x0f; //选取P3,让它后四位拉高电阻输出高电平
temp = ~P3 & 0x0f; //P3为低电平
if(temp)
{
if(key_statue == 0)
{
key_statue = 1;
return 0;
}
else if(key_statue == 1)
{
key_statue = 2;
if(P30 == 0)
{
temp = 7;
}
if(P31 == 0)
{
temp = 6;
}
if(P32 == 0)
{
temp = 5;
}
if(P33 == 0)
{
temp = 4;
}
return temp;
}
else if(key_statue == 2)
{
return 0;
}
}
else
{
key_statue =0;
return 0;
}
return 0;
}
/************* 本地常量声明 **************/
u8 code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //
u8 P_SMG = 0; // 15是F,题目中要求第一个显示F
u8 SMGs1[8]={15,16,16,16,16,16,16,16}; //频率 通过题目要求,我们知道数码管有2种显示方式
//25显示U
u8 SMGs2[8]={25,16,16,16,16,16,16,16}; //电压 //16是不显示,为了不让数码管混乱,我们采取16
u8 *SMGs = SMGs1; //指针,用于数码管的切换,我们先默认为SMGs1
void SMGs_show()
{
P0 = 0x00;
choose(6);
P0 = ~t_display[SMGs[P_SMG]];
choose(7);
P0 = T_COM[P_SMG];
choose(6);
if(++P_SMG>=8)
{
P_SMG = 0;
}
}
u8 led_statue = 0x00; //定义一个变量,便于后面更改
void LED()
{
P0 = ~led_statue; //取返,LED灯全灭
choose(4);
}
/*****************接下来我们采用定时器的方式,用于读取LED、数码管************/
u16 cnt_1s =0;
u8 cnt_100ms =0;
void timer0isr() interrupt 3
{
LED();
SMGs_show();
cnt_1s++;
cnt_100ms++;
}
进一步编写:
有了基本的代码,我们可以进一步的来写。
/***********8题目中有N555测频率,我们先来完成它**************/ void Timer0Init(void) { AUXR |= 0x80; TMOD &= 0xF0; TMOD |= 0x04; TL0 = 0x00; TH0 = 0x00; TF0 = 0; TR0 = 1; } u16 freq = 0; //频率 /*根据之前写的,我们修改一下*/ void timer0isr() interrupt 3 { u16 temp; //temp来保存频率的值 LED(); SMGs_show(); cnt_1s++; cnt_100ms++; if(cnt_1s >= 1000) { cnt_1s = 0; TR0 = 0; temp = TH0; //合成一个int的函数 temp <<= 8; temp |= TL0; TL0 = 0x00; TH0 = 0x00; TR0 = 1; freq = temp; } } void main() { u8 key_vaule = 0; u8 temp = 0; u8 disp_mode = 1; // 0<- 频率 1<-电压 P2 = 0x00; //初始化(LED、蜂鸣器,继电器) P0 = 0x00; choose(5); P0 = 0xff; choose(4); Timer1Init(); Timer0Init(); while(1) { if(cnt_100ms >=10) { cnt_100ms = 0; /* 输入 */ key_vaule = KEY_scan(); /* 处理 */ if(key_vaule == 4) //按键切换模式 { disp_mode = !disp_mode; } if(disp_mode == 0) { SMGs = SMGs1; if(freq >= 100000) //未用到的数码管位将不显示 SMGs1[2] = freq / 100000; else SMGs1[2] = 16; if(freq >= 10000) SMGs1[3] = freq / 10000 % 10; else SMGs1[3] = 16; if(freq >= 1000) SMGs1[4] = freq / 1000 % 10; else SMGs1[4] = 16; if(freq >= 100) SMGs1[5] = freq / 100 % 10; else SMGs1[5] = 16; if(freq >= 10) SMGs1[6] = freq / 10 %10; else SMGs1[6] = 16; SMGs1[7] = freq % 10; } else { //暂时不写 } } } } /**************************接下来我们写入电压**********************/ void main() { u8 key_vaule = 0; u16 volt = 0; //保存100倍电压 u8 temp = 0; u8 disp_mode = 1; // 0<- 频率 1<-电压 u8 out_mode = 0; // 0<- 固定 1<-可变 P2 = 0x00; P0 = 0x00; choose(5); P0 = 0xff; choose(4); Timer1Init(); Timer0Init(); while(1) { if(cnt_100ms >=10) { cnt_100ms = 0; /* 输入 */ key_vaule = KEY_scan(); temp = read_8591(); //temp来保存读取的值 volt = (float)read_8591() / 255.0f * 500.0f; /* 处理 */ if(key_vaule == 4) { disp_mode = !disp_mode; } if(key_vaule == 5) { out_mode = !out_mode; } /* 输出 */ if(out_mode == 0) //测量电压值,0为固定,L1灭 { write_8591(102);//2V led_statue &= ~0x10; } else { write_8591(temp); //测量电压值,1为随数码管的值变化,电压变化,L1亮 led_statue |= 0x10; } //write_8591(temp); if(disp_mode == 0) { //上文频率 } else { SMGs = SMGs2; //电压显示 SMGs2[5] = volt / 100 +32; SMGs2[6] = volt / 10 %10; SMGs2[7] = volt % 10; } if(disp_mode == 0) //频率 //根据题意,我们知道LED灯的亮灭 { led_statue |= 0x02; //L2亮 led_statue &= ~0x01; //L1灭 } else //电压 { led_statue |= 0x01; //L1亮 led_statue &= ~0x02; //L2灭 } } } } /*********************************LED、数码管*****************/ u8 led_en = 1; u8 smg_en = 1; void SMGs_show() { P0 = 0x00; choose(6); if(!smg_en) //按键让LED { return; } P0 = ~t_display[SMGs[P_SMG]]; choose(7); P0 = T_COM[P_SMG]; choose(6); if(++P_SMG>=8) { P_SMG = 0; } }
写到这里基本上快写完了,剩下的LED灯我们也快速完成它
if(volt <150 || (volt >= 250 && volt < 350)) { led_statue &= ~0x04; } else { led_statue |= 0x04; } if(freq <1000 || (freq >= 5000 && freq < 10000)) { led_statue &= ~0x08; } else { led_statue |= 0x08; }
最后我们写入IIC—8591的驱动文件
u8 read_8591()
{
u8 temp = 0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
IIC_RecByte();
IIC_SendAck(0);
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void write_8591(u8 level)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(level);
IIC_WaitAck();
IIC_Stop();
}
本文结束了,大家多看看,总的来说还是挺简单的,本题涉及到N555、PCF8591、数码管、独立按键主要的模块,大家还需要掌握最基础的LED,单个模块还算简单,组合一起就需要大家思考思考了。