蓝桥杯单片机学习过程记录(十七)第九届彩灯控制器

蓝桥杯单片机学习过程记录(十七)第九届彩灯控制器


错误提示:
WARNING L5: CODE SPACE MEMORY OVERLAP
地址重叠。两个定时器重名,interrupt都用了1,一直报警告。
然后不得不说,从历年省赛来看,单片机是越来越难了,从开始到完成差不多正好比赛时间,包括吃饭啊啥的,比往届感觉要难,中间出了一个问题,因为审题不清楚,一开始只用了一个eep进行存储状态,后来分析,应该是4个模式下的小灯分别对应着一个流转间隔,又重新改了一下,头都大了,4个寄存器用数组来表示,但是重复的东西太多,超级繁琐,后续慢慢学习进行改进,放进函数里应该会好很多。用了两个定时器,一个控制小灯模式和亮度,另一个控制设置时得闪烁。在进行设置模式的流转间隔时,分别用中间变量进行存储。

应用内容:
数码管、LED小灯
独立按键、定时器
EEPROM寄存器存写读取
滑动变阻器IIC的读取

主函数:

//第九届彩灯控制
#include<STC15F2K60S2.H>
#include<iic.h>
sbit s7=P3^0;
sbit s6=P3^1;
sbit s5=P3^2;
sbit s4=P3^3;
unsigned char led_count;
unsigned char flag_yemian=1,s6_flag,flag_set;
char led_mode=1,count_mode,led_mode_temp,led_light_mode=1;
unsigned char seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
unsigned char eep[4];
unsigned char yi,er,san,si,wu,liu,qi,ba;
unsigned char t_0,t,t_1;
int dianya,eep_temp,count_eep;
void allinit();
void delayms(int ms);
void display_12(yi,er);
void display_34(san,si);
void display_56(wu,liu);
void display_78(qi,ba);
void key_scan();
void Timer0Init();
void Timer1Init();
unsigned char iic_read();
unsigned char eep_read(add);
void eep_write(add,dat);
void led_light();
void main(){
 //初始化
 allinit();
 Timer0Init();Timer1Init();
 EA=1;ET0=1;ET1=1;
 //四个寄存器
 eep[0]=eep_read(0x10);eep[1]=eep_read(0x20);
 eep[2]=eep_read(0x40);eep[3]=eep_read(0x80);
 yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
 while(1){
  dianya=iic_read();
  dianya=dianya*2;
  //亮度等级判断
  led_light();
  //eep中间暂存
  eep_temp=count_eep+eep;
  //设置页面模式及间隔
  if(flag_yemian==1){
   //选择模式
   if(s6_flag==1){
    //模式中间暂存
    led_mode_temp=(led_mode+count_mode)%4;
    if(led_mode_temp==0)
      led_mode_temp=4;
    if(flag_set==0){
     //亮
     switch(led_mode_temp){
      case 1: yi=10;er=led_mode_temp;san=10;si=11;wu=eep[0]/10;liu=eep[0]%10;qi=0;ba=0;break;
      case 2: yi=10;er=led_mode_temp;san=10;si=11;wu=eep[1]/10;liu=eep[1]%10;qi=0;ba=0;break;
      case 3: yi=10;er=led_mode_temp;san=10;si=11;wu=eep[2]/10;liu=eep[2]%10;qi=0;ba=0;break;
      case 4: yi=10;er=led_mode_temp;san=10;si=11;wu=eep[3]/10;liu=eep[3]%10;qi=0;ba=0; break;
     }
    }
    //灭
    else {
     switch(led_mode_temp){
      case 1: yi=11;er=11;san=11;si=11;wu=eep[0]/10;liu=eep[0]%10;qi=0;ba=0;break;
      case 2: yi=11;er=11;san=11;si=11;wu=eep[1]/10;liu=eep[1]%10;qi=0;ba=0;break;
      case 3: yi=11;er=11;san=11;si=11;wu=eep[2]/10;liu=eep[2]%10;qi=0;ba=0;break;
      case 4: yi=11;er=11;san=11;si=11;wu=eep[3]/10;liu=eep[3]%10;qi=0;ba=0; break;
     }
    }
   }
   //流转间隔设置
   else if(s6_flag==2){
    led_mode=led_mode_temp;
    if(flag_set==0){
     //进行边界的判断大于4小于12
     switch(led_mode_temp){
      case 1: yi=10;eep_temp=eep[0]+count_eep;if(eep_temp>12) {eep_temp=12;count_eep=0;}
          else if(eep_temp<4){ eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=eep_temp/10;liu=eep_temp%10;qi=0;ba=0;break;
      case 2: yi=10;eep_temp=eep[1]+count_eep;if(eep_temp>12) {eep_temp=12;count_eep=0;}
          else if(eep_temp<4) {eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=eep_temp/10;liu=eep_temp%10;qi=0;ba=0;break;
      case 3: yi=10;eep_temp=eep[2]+count_eep;if(eep_temp>12) {eep_temp=12;count_eep=0;}
          else if(eep_temp<4) {eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=eep_temp/10;liu=eep_temp%10;qi=0;ba=0;break;
      case 4: yi=10;eep_temp=eep[3]+count_eep;if(eep_temp>12) {eep_temp=12;count_eep=0;}
          else if(eep_temp<4) {eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=eep_temp/10;liu=eep_temp%10;qi=0;ba=0;break;
     }
    }
    else {
     switch(led_mode_temp){
      case 1: yi=10;eep_temp=eep[0]+count_eep;if(eep_temp>12){ eep_temp=12;count_eep=0;}
          else if(eep_temp<4){ eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=11;liu=11;qi=0;ba=0;break;
      case 2: yi=10;eep_temp=eep[1]+count_eep;if(eep_temp>12) {eep_temp=12;count_eep=0;}
          else if(eep_temp<4) {eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=11;liu=11;qi=0;ba=0;break;
      case 3: yi=10;eep_temp=eep[2]+count_eep;if(eep_temp>12) {eep_temp=12;count_eep=0;}
          else if(eep_temp<4) {eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=11;liu=11;qi=0;ba=0;break;
      case 4: yi=10;eep_temp=eep[3]+count_eep;if(eep_temp>12) {eep_temp=12;count_eep=0;}
          else if(eep_temp<4) {eep_temp=4;count_eep=0;}er=led_mode_temp;san=10;si=11;wu=11;liu=11;qi=0;ba=0;break;
     }
    }
   }
   //熄灭数码管
   else if(s6_flag==0){
     yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
   }
  }
  key_scan();
  display_12(yi,er);
  display_34(san,si);
  display_56(wu,liu);
  display_78(qi,ba);
 } 
}

按键设置

//按键
void key_scan(){
 //s7控制小灯开关
 if(s7==0){
  delayms(5);
  if(s7==0){
   if(led_mode==0){
    led_mode=1;led_count=0;
   }
   else{
    led_mode=0;
    P2=0X80;P0=0XFF;
   }
  }
  while(!s7);
 }
 //s6控制设置选择
 else if(s6==0){
  delayms(5);
  if(s6==0){
   if(flag_yemian==1){
    if(s6_flag==0){
     s6_flag=1;
    }
    else if(s6_flag==1){
     s6_flag=2;
    }
    else if(s6_flag==2){
     //设置完成进行保存写入寄存器
     switch(led_mode){
      case 1:eep[0]=eep_temp;eep_write(0x10,eep[0]);break;
      case 2:eep[1]=eep_temp;eep_write(0x20,eep[1]);break;
      case 3:eep[2]=eep_temp;eep_write(0x40,eep[2]);break;
      case 4:eep[3]=eep_temp;eep_write(0x80,eep[3]);break;
     }
     s6_flag=0;
     count_mode=0;count_eep=0;
    }
   }
  }
  while(!s6);
 }
 //s5控制加
 else if(s5==0){
  delayms(5);
  if(s5==0){
   if(flag_yemian==1){
    if(s6_flag==1){
     count_mode++;
    }
    else if(s6_flag==2){
     count_eep++;
    }
   }
  }
  while(!s5);
 }
 //s4控制减,在非设置时查看亮度
 else if(s4==0){
  delayms(5);
  if(s4==0){
   if(flag_yemian==1){
    if(s6_flag==1){
     count_mode--;
    }
    else if(s6_flag==2){
     count_eep--;
    }
   } 
  }
  while(!s4){
   if(s6_flag==0){
    yi=11;er=11;san=11;si=11;
    wu=11;liu=11;qi=10;ba=led_light_mode;
    display_12(yi,er);
    display_34(san,si);
    display_56(wu,liu);
    display_78(qi,ba);
   }
  }
 }
}

定时器判断和亮度等级判断

//定时器0设置,数码管闪烁控制
void time_0() interrupt 1{
 t_0++;
 if(t_0==160){
  t_0=0;
  if(flag_set==0)
   flag_set=1;
  else flag_set=0;
 }
}
//定时器1设置,模式控制亮度和流转间隔
void time_1() interrupt 3{
 t_1++;
 t++;
 if(t==5)
  t=0;
  //模式1
  if(led_mode==1){
   //控制亮度
   if(t<led_light_mode){
    P2=0X80;P0=~(0X01<<led_count);P2=P2&0X1F;
   }
   else{
    P2=0X80;P0=0xff;
   }  
   //控制流转间隔
   if(t_1==20*eep[0]){
    t_1=0;
    P2=0X80;P0=~(0X01<<led_count);P2=P2&0X1F;
    led_count++;
    if(led_count==8){led_count=0;led_mode++;}
   }
  }
  else if(led_mode==2){
   //亮度
   if(t<led_light_mode){
    P2=0X80;P0=~(0X80>>led_count);P2=P2&0X1F;
   }
   else{
    P2=0X80;P0=0xff;
   }
   //流转间隔
   if(t_1==20*eep[1]){
    t_1=0;
    P2=0X80;P0=~(0X80>>led_count);P2=P2&0X1F;
    led_count++;
    if(led_count==8){
     led_count=0;
     led_mode++;
    }
   }
  }
  else if(led_mode==3){
   //亮度
   if(t<led_light_mode){
    P2=0X80;P0=~((0X80>>led_count)|(0x01<<led_count));P2=P2&0X1F;
   }
   else{
    P2=0X80;P0=0xff;
   }
   //流转间隔
   if(t_1==20*eep[2]){
    t_1=0;
    P2=0X80;P0=~((0X80>>led_count)|(0x01<<led_count));
    led_count++;
    if(led_count==4){
     led_count=0;
     led_mode++;
    }
   }
  }
  else if(led_mode==4){
   //亮度
   if(t<led_light_mode){
    P2=0X80;P0=~((0X10<<led_count)|(0x08>>led_count));P2=P2&0X1F;
   }
   else{
    P2=0X80;P0=0xff;
   }
   //流转间隔
   if(t_1==20*eep[3]){
    t_1=0;
     P2=0X80;P0=~((0X10<<led_count)|(0x08>>led_count));
    led_count++;
    if(led_count==4){
     led_count=0;
     led_mode++;
    }
   }
  }
  if(led_mode>4)
   led_mode=1;
}
//亮度等级
void led_light(){
 if(dianya<125){
   led_light_mode=1;
  }
 else if(dianya<250){
   led_light_mode=2;
  }
 else if(dianya<375){
   led_light_mode=3;
  }
 else{
  led_light_mode=4;
 }
}

iic通信,eep读取和写入

//eep读取
unsigned char eep_read(add){
 unsigned char temp;
 IIC_Start();
 IIC_SendByte(0xa0);
 IIC_WaitAck();
 IIC_SendByte(add);
 IIC_WaitAck();
 IIC_Stop();
 IIC_Start();
 IIC_SendByte(0xa1);
 IIC_WaitAck();
 temp=IIC_RecByte();
 IIC_Stop();
 return temp;
}
//eep写入
void eep_write(add,dat){
 IIC_Start();
 IIC_SendByte(0xa0);
 IIC_WaitAck();
 IIC_SendByte(add);
 IIC_WaitAck();
 IIC_SendByte(dat);
 IIC_WaitAck();
 IIC_Stop();
}
//读取外部电压Rb2
unsigned char iic_read(){
 unsigned int 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;
}

初始化等设置

//定时器0,5ms
void Timer0Init(void)  
{
 AUXR |= 0x80;  
 TMOD &= 0xF0;  
 TL0 = 0x00; 
 TH0 = 0x28; 
 TF0 = 0; 
 TR0 = 1;  
}
//定时器1,5ms
void Timer1Init(void)  
{
 AUXR |= 0x40;  
 TMOD &= 0x0F;  
 TL1 = 0x00; 
 TH1 = 0x28; 
 TF1 = 0; 
 TR1 = 1;  
}
void allinit(){
 P2=0XA0;P0=0X00;
 P2=0XC0;P0=0XFF;P2=0XE0;P0=0XFF;
 P2=0X80;P0=0XFF;
}
void delayms(int ms){
 int q,w;
 for(q=0;q<ms;q++)
  for(w=0;w<845;w++);
}
void display_12(yi,er){
 P2=0XC0;P0=0X01;P2=0XE0;P0=seg[yi];
 delayms(1);
 P2=0XC0;P0=0X02;P2=0XE0;P0=seg[er];
 delayms(1);
}
void display_34(san,si){
 P2=0XC0;P0=0X04;P2=0XE0;P0=seg[san];
 delayms(1);
 P2=0XC0;P0=0X08;P2=0XE0;P0=seg[si];
 delayms(1);
}
void display_56(wu,liu){
 P2=0XC0;P0=0X10;P2=0XE0;P0=seg[wu];
 delayms(1);
 P2=0XC0;P0=0X20;P2=0XE0;P0=seg[liu];
 delayms(1);
}
void display_78(qi,ba){
 P2=0XC0;P0=0X40;P2=0XE0;P0=seg[qi];
 delayms(1);
 P2=0XC0;P0=0X80;P2=0XE0;P0=seg[ba];
 delayms(1);
 P2=0XC0;P0=0XFF;P2=0XE0;P0=0XFF;
 delayms(1);
}
发布了38 篇原创文章 · 获赞 41 · 访问量 6858

猜你喜欢

转载自blog.csdn.net/weixin_44747240/article/details/104422398