别的话也不多说,一起来看看第九届(2018)的题目吧。
题目
这次的题目依然还是用到了三大模块(数码管、LED、按键),还用到了EEPROM和模拟输入(ADC),也都是一些常见的外设,只要平常都练习过,也就不难,最重要的还是编程逻辑。
1 数码管显示
数码管有两个界面需要显示一个是设置状态的界面,还有一个是亮度等级界面。设置状态界面由运行模式和流转间隔组成。
2 LED显示
这次的LED是重点,不仅有四种运行模式还有四个亮度等级。四种运行模式就设置数组,然后循环运行。四个亮度等级就是把ADC 0到255分成四份,在哪个等级,LED就相应的亮多久,这样就会有视觉上的亮度等级,具体看代码。
3 按键模块
使用的是独立按键,s7是LED的启动和停止,s6定义一个变量mode1,为0时数码管关闭(此时按s4显示亮度等级),为1时显示运行模式1以及流转间隔,为2时运行模式1闪烁按s5或s4进行加减,为3时流转间隔闪烁按s5或s4进行加减。
4 EEPROM
就是改写底层驱动代码部分(IIC),在运行完加减后把流转间隔保存到其中去,在延时5ms。
5 ADC
就是改写底层驱动代码部分(IIC)。
IIC.c
#include"IIC.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
unsigned char Read_AD()
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
void write_eeprom(unsigned char add,unsigned char da)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(da);
IIC_WaitAck();
IIC_Stop();
}
unsigned char Read_eeprom(unsigned char add)
{
unsigned char da;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
da=IIC_RecByte();
IIC_Stop();
return da;
}
IIC.h
#ifndef _IIC_H_
#define _IIC_H_
#include<stc15f2k60s2.h>
#include<intrins.h>
void IIC_Delay(unsigned char i);
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
unsigned char Read_AD();
void write_eeprom(unsigned char add,unsigned char da);
unsigned char Read_eeprom(unsigned char add);
#endif
init.h
#include"init.h"
#include"jm.h"
#define u8 unsigned char
#define u16 unsigned int
#define state_0 0
#define state_1 1
#define state_2 2
static u8 segadder=0,key_state;
extern u8 mode1,a;
u8 seg[]={11,11,11,11,11,11,11,11};
u8 tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
u8 key_press,key_num,value;
void close_init() //关闭无关外设
{
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xa0;P04=0;P06=0;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=0x00;P2&=0x1f;
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
}
void display() // 数码管显示函数
{
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=1<<segadder;P2&=0x1f;
P2=(P2&0x1f)|0xe0;P0=tab[seg[segadder]];P2&=0x1f;
if(++segadder==8) segadder=0;
}
u8 read_key() //独立按键
{
key_press=P3&0x0f;
switch(key_state)
{
case state_0:
if(key_press!=0x0f)
key_state=state_1;
break;
case state_1:
if(key_press!=0x0f)
{
if((key_press&0x08)==0)
{
if(mode1==0&&a==1)
{
jm3();
a=0;
}
key_num=4;
}
if((key_press&0x04)==0) key_num=5;
if((key_press&0x02)==0) key_num=6;
if((key_press&0x01)==0) key_num=7;
key_state=state_2;
}
else
key_state=state_0;
break;
case state_2:
if(key_press==0x0f)
{
if(mode1==0&&a==0)a=1;
key_state=state_0;
}
break;
}
value=key_num;
key_num=0;
return value;
}
void Timer0Init(void)
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
TR0 = 1;
EA = 1;
ET0 = 1;
}
init.h
#ifndef _INIT_H_
#define _INIT_H_
#include<stc15f2k60s2.h>
void close_init();
void display();
unsigned char read_key();
void Timer0Init(void);
#endif
jm.h
#include"jm.h"
#include"IIC.h"
#define u8 unsigned char
#define u16 unsigned int
extern bit sp,mode_flag,val_flag; // extern表示此变量是在别处定义的,要在此处引用
extern u8 seg[],mode1,RB2_value;
extern u8 val1,val2,val3,val4,val_count;
u8 mode12[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //模式1,2的数组
u8 mode34[]={0x7e,0xbd,0xdb,0xe7}; //模式3,4的数组
u8 mode=1,i=0,j=7,x=0,y=3,mode2=1;
void Delay5ms()
{
unsigned char i, j;
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
void jm3() //亮度等级显示函数
{
seg[0]=11;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=11;
seg[5]=11;
seg[6]=10;
seg[7]=RB2_value;
}
void jm4() //s4的功能
{
if(mode1==2)
{
if(--mode==0)mode=4;
}
if(mode1==3)
{
if(mode==1)val1-=10;
if(val1<=40)val1=40;
write_eeprom(0x10,val1);
Delay5ms();
if(mode==2)val2-=10;
if(val2<=40)val2=40;
write_eeprom(0x20,val2);
Delay5ms();
if(mode==3)val3-=10;
if(val3<=40)val3=40;
write_eeprom(0x40,val3);
Delay5ms();
if(mode==4)val4-=10;
if(val4<=40)val4=40;
write_eeprom(0x80,val4);
Delay5ms();
}
}
void jm5() //s5的功能
{
if(mode1==2)
{
if(++mode==5)mode=1;
}
if(mode1==3)
{
if(mode==1)val1+=10;
if(val1>=120)val1=120;
write_eeprom(0x10,val1);
Delay5ms();
if(mode==2)val2+=10;
if(val2>=120)val2=120;
write_eeprom(0x20,val2);
Delay5ms();
if(mode==3)val3+=10;
if(val3>=12)val3=120;
write_eeprom(0x40,val3);
Delay5ms();
if(mode==4)val4+=10;
if(val4>=120)val4=120;
write_eeprom(0x80,val4);
Delay5ms();
}
}
void jm6()
{
if(mode1==0) //数码管关闭
{
seg[0]=11;
seg[1]=11;
seg[2]=11;
seg[3]=11;
seg[4]=11;
seg[5]=11;
seg[6]=11;
seg[7]=11;
}
if(mode1==1) //显示运行模式1以及流转间隔
{
seg[0]=10;
seg[1]=1;
seg[2]=10;
seg[3]=11;
seg[4]=val1/100;
seg[5]=val1/10%10;
seg[6]=val1%10;
seg[7]=0;
}
if(mode1==2) //运行模式1闪烁
{
if(mode_flag==1)
{
seg[0]=10;
seg[1]=mode;
seg[2]=10;
seg[3]=11;
if(mode==1)
{
seg[4]=val1/100;
seg[5]=val1/10%10;
seg[6]=val1%10;
seg[7]=0;
}
if(mode==2)
{
seg[4]=val2/100;
seg[5]=val2/10%10;
seg[6]=val2%10;
seg[7]=0;
}
if(mode==3)
{
seg[4]=val3/100;
seg[5]=val3/10%10;
seg[6]=val3%10;
seg[7]=0;
}
if(mode==4)
{
seg[4]=val4/100;
seg[5]=val4/10%10;
seg[6]=val4%10;
seg[7]=0;
}
}
else
{
seg[0]=11;
seg[1]=11;
seg[2]=11;
seg[3]=11;
}
}
if(mode1==3) //流转间隔闪烁
{
if(mode_flag==1)
{
if(mode==1)
{
seg[4]=val1/100;
seg[5]=val1/10%10;
seg[6]=val1%10;
seg[7]=0;
}
if(mode==2)
{
seg[4]=val2/100;
seg[5]=val2/10%10;
seg[6]=val2%10;
seg[7]=0;
}
if(mode==3)
{
seg[4]=val3/100;
seg[5]=val3/10%10;
seg[6]=val3%10;
seg[7]=0;
}
if(mode==4)
{
seg[4]=val4/100;
seg[5]=val4/10%10;
seg[6]=val4%10;
seg[7]=0;
}
}
else
{
seg[4]=11;
seg[5]=11;
seg[6]=11;
seg[7]=11;
}
}
}
void jm7()
{
if(sp==1) //打开LED
{
if(mode2==1&&val_flag==0)
{
P2=(P2&0x1f)|0x80;
P0=mode12[i];
P2&=0x1f;
}
if(mode2==1&&val_flag==1)
{
val_flag=0;
if(++i==8)
{
i=0;
mode2=2;
val_count=0;
}
}
if(mode2==2&&val_flag==0)
{
P2=(P2&0x1f)|0x80;
P0=mode12[j];
P2&=0x1f;
}
if(mode2==2&&val_flag==1)
{
val_flag=0;
if(--j==-1)
{
j=7;
mode2=3;
val_count=0;
}
}
if(mode2==3&&val_flag==0)
{
P2=(P2&0x1f)|0x80;
P0=mode34[x];
P2&=0x1f;
}
if(mode2==3&&val_flag==1)
{
val_flag=0;
if(++x==4)
{
x=0;
mode2=4;
val_count=0;
}
}
if(mode2==4&&val_flag==0)
{
P2=(P2&0x1f)|0x80;
P0=mode34[y];
P2&=0x1f;
}
if(mode2==4&&val_flag==1)
{
val_flag=0;
if(--y==-1)
{
y=3;
mode2=1;
val_count=0;
}
}
}
else
{
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
}
}
jm.h
#ifndef _JM_H_
#define _JM_H_
#include<stc15f2k60s2.h>
void jm3();
void jm4();
void jm5();
void jm6();
void jm7();
void Delay5ms();
#endif
main.c
#include"init.h"
#include"IIC.h"
#include"jm.h"
#define u8 unsigned char
#define u16 unsigned int
extern u8 mode2;
u8 a,b,num,mode1=0,RB2=0,RB2_value=0,RB2_count=0,e_count=0;
bit sp=0,mode_flag=0,val_flag=1,e_flag=0;
u16 mode_count=0,val_count=0;
u8 val1=40,val2=40,val3=40,val4=40;
void main()
{
close_init();
Timer0Init();
while(1)
{
RB2=Read_AD();
num=read_key();
switch(num)
{
case 4:
jm4();
break;
case 5:
jm5();
break;
case 6:
if(++mode1==4)mode1=0;
a=1;
break;
case 7:
sp^=1;
b=1;
break;
}
num=0;
if(a==1)jm6();
if(b==1)jm7();
if(RB2>=0&&RB2<64)RB2_value=1; //把ADC的值分成四个等级
if(RB2>=64&&RB2<128)RB2_value=2;
if(RB2>=128&&RB2<192)RB2_value=3;
if(RB2>=192&&RB2<=255)RB2_value=4;
if(e_flag==1) //读取EEPROM中的值
{
e_flag=0;
val1=Read_eeprom(0x10);
val2=Read_eeprom(0x20);
val3=Read_eeprom(0x40);
val4=Read_eeprom(0x80);
}
}
}
void Timer0() interrupt 1
{
display();
val_count++;
if(mode1==2||mode1==3)
{
if(++mode_count==800)
{
mode_count=0;
mode_flag^=1;
}
}
if((val_count==val1*10)&&mode2==1)
{
val_count=0;
val_flag=1;
}
if((val_count==val2*10)&&mode2==2)
{
val_count=0;
val_flag=1;
}
if((val_count==val3*10)&&mode2==3)
{
val_count=0;
val_flag=1;
}
if((val_count==val4*10)&&mode2==4)
{
val_count=0;
val_flag=1;
}
if(++RB2_count<=RB2_value) jm7(); //亮度等级越大,LED亮的越久
else if((RB2_count>RB2_value)&&(RB2_count<=4))
{
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
}
else if(RB2_count>4)RB2_count=0;
if(++e_count==200)
{
e_count=0;
e_flag=1;
}
}
最后,有什么写的不好的地方,还希望大家指正,或者有更好的意见和想法都可以讨论。