这是我第二次写第九届的题目了,总体感觉还行,没有什么难点。第二次写第九届省赛赛题给我的感觉是:写代码的时候一定要保持头脑清晰,这样才能更高效地写代码(毕竟这比赛重逻辑)。好了,废话不多说,我直接贴代码了(全程使用状态机,减少脑髓流失)!
#include "STC15F2K60S2.H"
#include "iic.h"
#define u8 unsigned char
#define KEY_STATE_0 0
#define KEY_STATE_1 1
#define KEY_STATE_2 2
#define LED_0 0X00
#define LED_1 ((0x01)<<(1-1))
#define LED_2 ((0x01)<<(2-1))
#define LED_3 ((0x01)<<(3-1))
#define LED_4 ((0x01)<<(4-1))
#define LED_5 ((0x01)<<(5-1))
#define LED_6 ((0x01)<<(6-1))
#define LED_7 ((0x01)<<(7-1))
#define LED_8 ((0x01)<<(8-1))
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 code LED_COM[]={LED_0,LED_1,LED_2,LED_3,LED_4,LED_5,LED_6,LED_7,LED_8};//led显示操作码
static u8 key_state=KEY_STATE_0;//后面会用到独立按键,这个是按键的状态标志位
void Timer0Init(void) //1毫秒定时器中断
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
unsigned char KEY_SCAN()//按键扫描函数
{
u8 KEY=0;
u8 key_val=0;
P30=1;P31=1;P32=1;P33=1;
if(P30==0) KEY=7;
if(P31==0) KEY=6;
if(P32==0) KEY=5;
if(P33==0) KEY=4;
if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1)) KEY=0;
switch(key_state)
{
case KEY_STATE_0:
if(KEY!=0)
{
key_state=KEY_STATE_1;
}
break;
case KEY_STATE_1:
switch(KEY)
{
case 4: key_val=4; break;
case 5: key_val=5; break;
case 6: key_val=6; break;
case 7: key_val=7; break;
}
key_state=KEY_STATE_2;
break;
case KEY_STATE_2:
if(KEY==0)
{
key_state=KEY_STATE_0;
}
break;
}
return key_val;
}
/**********************************用到了17个外部变量*************************************/
bit key_flag=0;//按键读取标志位
u8 key_val=0;//按键的键值
u8 adc_val;//adc读取的值
u8 led_choose1=0;//选择的第一个led灯
u8 led_choose2=0;//选择的第二个led灯
u8 led_mode=1;//led模式
u8 led_mode_time[5];//每个led流转模式的间隔时间
u8 led_mode_smgdisplay=1;//运行模式编号 1、2、3、4
u8 smg_display_index=0;//0、数码管全部熄灭 1、模式编号 2、流转间隔 (123循环)
bit smg_diaplay_flag=0;//0: 数码管熄灭表示 1: 数码管打开表示
bit led_flag=0;//led显示标志位
static int led_count=0;//led计数器
u8 led_level=1;//led亮度等级 (1-4)
u8 smg_display[8];//数码管显示数组
u8 smg_display_mode_index=1;//1、正常显示模式 2、S4按下模式
bit smg_blink_flag=0;//数码管闪烁标志位置
/***********************************************************************************/
void main()
{
led_mode_time[1]=read_24c02(1);
led_mode_time[2]=read_24c02(2);
led_mode_time[3]=read_24c02(3);
led_mode_time[4]=read_24c02(4); //EEPROM读取键值
P2=0XA0;P0=0X00;P2=0X00; //关闭蜂鸣器
Timer0Init(); //定时器0中断
while(1)//下面是需要执行的函数
{
adc_val=read_adc(0x03); //读取adc的值
if(adc_val<=64)
{
led_level=1;
}
else if(adc_val<=128)
{
led_level=2;
}
else if(adc_val<=192)
{
led_level=3;
}
else if(adc_val<=255)
{
led_level=4;
}
//不同的adc的值对应不同的led亮度等级
if(key_flag) //定时器扫描按键进入
{
key_flag=0;
key_val=KEY_SCAN();
if((smg_display_index==0)&&(key_state==KEY_STATE_2))
{
if(key_val==4)
smg_display_mode_index=2;
}
else
{
smg_display_mode_index=1;
}
switch(key_val)
{
case 4:
if((smg_display_index==1)&&(led_mode_smgdisplay!=1)) //模式编号
{
led_mode_smgdisplay--;
}
if((smg_display_index==2)&&(led_mode_time[led_mode_smgdisplay]!=4))
{
led_mode_time[led_mode_smgdisplay]--;
write_24c02(led_mode_smgdisplay,led_mode_time[led_mode_smgdisplay]);
}
break;
case 5:
if((smg_display_index==1)&&(led_mode_smgdisplay!=4)) //模式编号
{
led_mode_smgdisplay++;
}
if((smg_display_index==2)&&(led_mode_time[led_mode_smgdisplay]!=12))
{
led_mode_time[led_mode_smgdisplay]++;
write_24c02(led_mode_smgdisplay,led_mode_time[led_mode_smgdisplay]);
}
break;
case 6:
smg_display_index++;
break;
case 7: led_flag=~led_flag; break;
}
}
if(smg_display_index==0)
{
smg_diaplay_flag=0;
}
if(smg_display_index==1)
{
smg_diaplay_flag=1;
}
if(smg_display_index==2)
{
smg_diaplay_flag=1;
}
if(smg_display_index==3)//数码管模式越界
{
smg_display_index=0;
}
if(smg_display_mode_index==1)//非特殊显示模式
{
if(smg_diaplay_flag)//数码管打开
{
smg_display[0]=t_display[17];
if(smg_display_index==1)//标号模式
{
if(smg_blink_flag)
{
smg_display[1]=t_display[led_mode_smgdisplay];
}
else
{
smg_display[1]=t_display[16];
}
}
else
{
smg_display[1]=t_display[led_mode_smgdisplay];
}
smg_display[2]=t_display[17];
smg_display[3]=t_display[16];
if(smg_display_index==2)//间隔时间显示模式
{
if(smg_blink_flag)
{
if(led_mode_time[led_mode_smgdisplay]>=10)
{
smg_display[4]=t_display[1];
}
else
{
smg_display[4]=t_display[16];
}
smg_display[5]=t_display[led_mode_time[led_mode_smgdisplay]%10];
smg_display[6]=t_display[0];
smg_display[7]=t_display[0];
}
else
{
smg_display[4]=t_display[16];
smg_display[5]=t_display[16];
smg_display[6]=t_display[16];
smg_display[7]=t_display[16];
}
}
else
{
if(led_mode_time[led_mode_smgdisplay]>=10)
{
smg_display[4]=t_display[1];
}
else
{
smg_display[4]=t_display[16];
}
smg_display[5]=t_display[led_mode_time[led_mode_smgdisplay]%10];
smg_display[6]=t_display[0];
smg_display[7]=t_display[0];
}
}
else//数码管关闭
{
smg_display[0]=t_display[16];
smg_display[1]=t_display[16];
smg_display[2]=t_display[16];
smg_display[3]=t_display[16];
smg_display[4]=t_display[16];
smg_display[5]=t_display[16];
smg_display[6]=t_display[16];
smg_display[7]=t_display[16];
}
}
else
{
smg_display[0]=t_display[16];
smg_display[1]=t_display[16];
smg_display[2]=t_display[16];
smg_display[3]=t_display[16];
smg_display[4]=t_display[16];
smg_display[5]=t_display[16];
smg_display[6]=t_display[17];
smg_display[7]=t_display[led_level];
}
}
}
void Timer0(void) interrupt 1 //1毫秒@11.0592MHz
{
static int key_count=0,P2_count=0,i=0,led_light_level=1,smg_blink=0;
key_count++;P2_count++;smg_blink++;
if(smg_blink==800)
{
smg_blink=0;
smg_blink_flag=~smg_blink_flag;
}
if(key_count==10)
{
key_count=0;
key_flag=1;
}
if(P2_count==1)
{
if(led_flag)
{
led_count++;
led_light_level++;
if(led_light_level==5)
{
led_light_level=1;
}
}
else
{
led_count=0;
led_choose1=0;
led_choose2=0;
led_mode=1;
}
}
if(led_light_level<=led_level)
{
P0=~(LED_COM[led_choose1]|LED_COM[led_choose2]);P2=0X80;P2=0X00;
}
else
{
P0=~0;P2=0X80;P2=0X00;
}
if(P2_count==2)
{
P2_count=0;
P2=0XC0;P0=0X00;P2=0X00;
P2=0XE0;P0=~smg_display[i];P2=0X00;
P2=0XC0;P0=T_COM[i];P2=0X00;
i++;
if(i==8) {i=0;}
}
if ((led_count==led_mode_time[1]*50)&&(led_mode==1))
{
led_count=0;
led_choose1=0;
led_choose2++;
if(led_choose2==8)
{led_mode=2;}
}
if ((led_count==led_mode_time[2]*50)&&(led_mode==2))
{
led_count=0;
led_choose1=0;
led_choose2--;
if(led_choose2==1)
{
led_mode=3;
}
}
if ((led_count==led_mode_time[3]*50)&&(led_mode==3))
{
led_count=0;
led_choose1++;
led_choose2=(9-led_choose1);
if(led_choose1==4)
{
led_mode=4;
}
}
if ((led_count==led_mode_time[4]*50)&&(led_mode==4))
{
led_count=0;
led_choose1--;
led_choose2=(9-led_choose1);
if(led_choose1==0)
{
led_choose2=1;
led_mode=1;
}
}
}
代码就是这么多,也就400多行代码。实测完成度100%。
这里没有贴“iic.c“和”iic.h“的代码,有需要的同学点击下面的链接: