蓝桥杯第11届省赛(7.5号第一批)

本次蓝桥杯省赛中,一道涉及单片机的题目成为焦点。题目中的下降沿刷新事件处理需格外注意,稍有不慎可能导致错误。参赛者需熟练掌握相关代码编写,如timer.c/h、smg.c/h、keybord.c/h、iic.c/h及main.c等文件的应用。

题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

这次的题目就是有一个细节,下降沿刷新事件比较的有意思,稍微不注意可能就会写错,其他也是中规中矩的考,和之前出现的都差不多

timer.c

#include <timer.h>

/**
* @Function       Timer0Init
* @author         STC_isp
* @date           2020/7/7
* @Description:   定时器0的初始化
* @param          void
* @return         void
* @History        无
*/

void Timer0Init(void)  //1毫秒@12.000MHz
{
 AUXR &= 0x7F;  //定时器时钟12T模式
 TMOD &= 0xF0;  //设置定时器模式
 TL0 = 0x18;  //设置定时初值
 TH0 = 0xFC;  //设置定时初值
 TF0 = 0;  //清除TF0标志
 TR0 = 1;  //定时器0开始计时
 EA=ET0=1;
}

timer.h

#ifndef _TIMER_H_
#define _TIMER_H_

#include <STC15F2K60S2.H>

void Timer0Init(void);

#endif

smg.c

#include <smg.h>

unsigned char code smgduan[24]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90
,0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10
,0XC1,0X8C,0XC8,0XFF};
//U:20 P:21 N:22 灭:23

unsigned char dspbuf[8];

/**
* @Function       smg_display
* @author         Barry
* @date           2020/7/7
* @Description:   数码管的显示函数
* @param          void
* @return         void
* @History        无
*/
void smg_display(void)
{
 static unsigned char i=0;
 
 P2=(P2&0X1F)|0XE0;
 P0=0XFF;
 P2&=0X1F; 
 
 P2=(P2&0X1F)|0XC0;
 P0=(1<<i);
 P2&=0X1F; 
 
 P2=(P2&0X1F)|0XE0;
 P0=smgduan[dspbuf[i]];
 P2&=0X1F; 
 
 if(++i==8)
  i=0;
}

smg.h

#ifndef _SMG_H_
#define _SMG_H_

#include <STC15F2K60S2.H>

extern unsigned char dspbuf[8];

void smg_display(void);

#endif

keybord.c

#include <keybord.h>

unsigned char i=0,key_value,key_sum=0,key_press;

/**
* @Function       keybord_read
* @author         Barry
* @date           2020/7/7
* @Description:   矩阵键盘行列扫描
* @param          void
* @return         void
* @History        无
*/
void keybord_read(void)
{
  P3=0XF0;
  P42=P44=1;
 if(P44==0||P42==0||P35==0||P34==0)
 {
  for(i=0;i<4;i++)
  {
   P3=0XFF;
   P42=P44=1;
   P3&=~(1<<i);
   
   if(P44==0) key_value=4*i;
   else if(P42==0) key_value=4*i+1;
   else if(P35==0) key_value=4*i+2;
   else if(P34==0) key_value=4*i+3;
  }
  if(++key_sum==1)
    key_press=1;
 }
 else
  key_sum=0;
}

keybord.h

#ifndef _KEYBORD_H_
#define _KEYBORD_H_

#include <STC15F2K60S2.H>

extern unsigned char key_value;
extern unsigned char key_press;

void keybord_read(void);

#endif

iic.c

#include <iic.h>
#include "intrins.h"

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}    

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

//总线启动条件
void IIC_Start(void)
{
 SDA = 1;
 SCL = 1;
 somenop;
 SDA = 0;
 somenop;
 SCL = 0; 
}
//总线停止条件
void IIC_Stop(void)
{
 SDA = 0;
 SCL = 1;
 somenop;
 SDA = 1;
}
//等待应答
bit IIC_WaitAck(void)
{
 SDA = 1;
 somenop;
 SCL = 1;
 somenop;
 if(SDA)    
 {   
  SCL = 0;
  IIC_Stop();
  return 0;
 }
 else  
 { 
  SCL = 0;
  return 1;
 }
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
 unsigned char i;
 for(i=0;i<8;i++)
 {   
  if(byt&0x80) 
  { 
   SDA = 1;
  }
  else 
  {
   SDA = 0;
  }
  somenop;
  SCL = 1;
  byt <<= 1;
  somenop;
  SCL = 0;
 }
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
 unsigned char da;
 unsigned char i;
 
 for(i=0;i<8;i++)
 {   
  SCL = 1;
  somenop;
  da <<= 1;
  if(SDA) 
  da |= 0x01;
  SCL = 0;
  somenop;
 }
 return da;
}
/**
* @Function       adc_read
* @author         Barry
* @date           2020/7/7
* @Description:   读取adc值
* @param          void
* @return         void
* @History        无
*/
unsigned char adc_read(void)
{
 unsigned char dat;
 
 IIC_Start(); 
 IIC_SendByte(0X90);
 IIC_WaitAck();
 IIC_SendByte(0X03);
 IIC_WaitAck();
 
 IIC_Start();
 IIC_SendByte(0X91);
 IIC_WaitAck();
 dat=IIC_RecByte();
 IIC_Stop();
 
 return dat;
}
/**
* @Function       eeprom_write
* @author         Barry
* @date           2020/7/7
* @Description:   写对应的数据到eeprom对应的地址
* @param 1        addr
* @param 2        dat
* @return         void
* @History        无
*/
void eeprom_write(unsigned char addr,unsigned char dat)
{
 IIC_Start();
 
 IIC_SendByte(0XA0);
 IIC_WaitAck();
 IIC_SendByte(addr);
 IIC_WaitAck();
 IIC_SendByte(dat);
 IIC_WaitAck(); 
 
 IIC_Stop();
}
/**
* @Function       eeprom_write
* @author         Barry
* @date           2020/7/7
* @Description:   从对应的eeprom地址读出对应的数据
* @param          addr
* @return         void
* @History        无
*/
unsigned char eeprom_read(unsigned char addr)
{
 unsigned char dat=0;
 
 IIC_Start();
 
 IIC_SendByte(0XA0);
 IIC_WaitAck();
 IIC_SendByte(addr);
 IIC_WaitAck(); 
 
 IIC_Start();
 IIC_SendByte(0XA1);
 IIC_WaitAck(); 
 dat=IIC_RecByte();
 IIC_Stop(); 
 
 return dat;
}

iic.h

#ifndef _IIC_H_
#define _IIC_H_

#include <STC15F2K60S2.H>

unsigned char adc_read(void);
void eeprom_write(unsigned char addr,unsigned char dat);
unsigned char eeprom_read(unsigned char addr);

#endif

main.c

/*********************************************

File name:    电压调节器
Author:       Barry
Version       1.0
Description:  2020/7/5 第11届蓝桥杯省赛第一场
Others:       无
Log:          无

*********************************************/
#include <STC15F2K60S2.H>
#include <timer.h>
#include <smg.h>
#include <keybord.h>
#include <iic.h>

//标志位
unsigned char flag_key;
unsigned char flag_adc;
unsigned char flag_smg=0;
unsigned char flag_1s;
unsigned char count_5s=0;      //5秒计时
unsigned char s12_count=0;  //s12按下的次数
long adc_dat;        
unsigned int v;          //v
unsigned int vp;         //vp
unsigned char vp_save;
unsigned char count=0;   //计数值
unsigned char error1=0,error2=0,error3=0;  //每个界面的误操作次数
unsigned char L1_temp,L2_temp,L3_temp;     //L1,L2,L3
unsigned char flag1=0,flag2=0,flag3=0,flag4=0;  //判断下降沿

/**
* @Function       all_init
* @author         Barry
* @date           2020/7/7
* @Description:   初始化,关闭蜂鸣器,LED,继电器等
* @param          void
* @return         void
* @History        无
*/
void all_init(void)
{
  P2=(P2&0X1F)|0XA0;
  P0=0X00;
  P2&=0X1F; 
  
  P2=(P2&0X1F)|0X80;
  P0=0XFF;
  P2&=0X1F; 
}
/**
* @Function       eeprom_init
* @author         Barry
* @date           2020/7/7
* @Description:   初始化eeprom,读出0X00的数据并处理
* @param          void
* @return         void
* @History        无
*/
void eeprom_init(void)
{
  if(eeprom_read(0X80)==0X55)
  {
    vp_save=eeprom_read(0X00);
   vp=vp_save*10;
  }
 else
 {
  eeprom_write(0X80,0X55);
  vp_save=0;
 }
}

/**
* @Function       main
* @author         Barry
* @date           2020/7/7
* @Description:   主函数
* @param          void
* @return         void
* @History        无
*/
void main(void)
{
 all_init();
 Timer0Init();
 eeprom_init();
  while(1)
 {
   /**********KEY**********/
  if(flag_key)
  {
    flag_key=0;
    keybord_read();
  }
  if(key_press)
  {
   key_press=0; 
    if(key_value==14)
    {
      if(++s12_count==3)
      s12_count=0;
     switch(s12_count)
     {
      case 0: flag_smg=0;error2=0;error3=0;break;
      case 1: flag_smg=1;error1=0;error3=0;break;
      case 2: 
       flag_smg=2;
       error1=0;
       error2=0;
       vp_save=vp/10;
       eeprom_write(0X00,vp_save);
     break;
      }
    }
    
   if(flag_smg==0)
   {
     if(key_value==14)
     error1=0;
    else 
     error1++;
   }
   
   if(flag_smg==1)
   {
     if(key_value==15)
     {
       if(vp<500)
     {
      vp+=50;
      error2=0;
     }
     else if(vp==500)
     {
      error2=0;
       vp=0;
     } 
     }
    else if(key_value==11)
    {
       if(vp>0)
      {
       vp-=50;
       error2=0;
      }
     else if(vp==0)
     {
      error2=0;
       vp=500;
     }           
    }
    else if(key_value!=11 && key_value!=15 && key_value!=14)
     error2++;
   }
   
   if(flag_smg==2)
   {
     if(key_value==10)
     {
      count=0;
      error3=0;    
     }
     else if(key_value!=10 && key_value!=14)
      error3++;
   }
  }
   /**********LED**********/
  if(v<vp)
  {
   if(flag_1s)
   {
     flag_1s=0;
    if(++count_5s>6)
      L1_temp=0XF8;  
    else
      L1_temp=0XF9;
   }
  }
  else 
  {
    L1_temp=0XF9;
    count_5s=0;
  }
  
  if(count%2==0)     //L2
      L2_temp=0XFA;
  else 
      L2_temp=0XF8; 
      
  if(error1>=3||error2>=3||error3>=3)  //L3
      L3_temp=0XF8; 
  else 
      L3_temp=0XFC; 
      
  P2=(P2&0X1F)|0X80;
  P0=(L1_temp|L2_temp|L3_temp);
  P2&=0X1F; 
   /**********ADC**********/
  if(flag_adc)
  {
    flag_adc=0;
   adc_dat=adc_read();
  }
  v=(unsigned int)(adc_dat*500/255);
  
   /**********count**********/
  if(v>vp)
  {
   flag1=1;
   flag3=1;
   flag4=0;
  }
  if(v<vp)
  {
   flag2=1;
   flag4=1;
   flag3=0;
  }
  if((flag1==1) && (flag2==1) && (flag3==0) && (flag4==1))
  {
     count++;
     flag1=0;
     flag2=0;   
  }
  /**********SMG**********/
  if(flag_smg==0)
  {
   dspbuf[0]=20;
   dspbuf[1]=23;
   dspbuf[2]=23;
   dspbuf[3]=23;
   dspbuf[4]=23;
   dspbuf[5]=v/100+10;
   dspbuf[6]=v%100/10;
   dspbuf[7]=v%10;
  }
  if(flag_smg==1)
  {
   dspbuf[0]=21;
   dspbuf[1]=23;
   dspbuf[2]=23;
   dspbuf[3]=23;
   dspbuf[4]=23;
   dspbuf[5]=vp/100+10;
   dspbuf[6]=vp%100/10;
   dspbuf[7]=vp%10;
  }   
  if(flag_smg==2)
  {
   dspbuf[0]=22;
   dspbuf[1]=23;
   dspbuf[2]=23;
   dspbuf[3]=23;
   dspbuf[4]=23;
   dspbuf[5]=23;
   dspbuf[6]=count/10;
   dspbuf[7]=count%10;
  }
 }
}
/**
* @Function       timer0_isr
* @author         Barry
* @date           2020/7/7
* @Description:   定时器0中断服务函数
* @param          void
* @return         void
* @History        无
*/
void timer0_isr(void) interrupt 1
{
 static unsigned char flag_key_time=0;
 static unsigned char flag_adc_time=0;
 static unsigned int flag_1s_time=0;
 
 if(++flag_key_time==30)
 {
   flag_key_time=0;
   flag_key=1;
 }
 
 if(++flag_adc_time==100)   //0.1S
 {
   flag_adc_time=0;
   flag_adc=1;
 } 
 
 if(++flag_1s_time==1000)
 {
   flag_1s_time=0;
   flag_1s=1;
 }
 smg_display();
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值