基于小蜜蜂老师的进阶与冲刺

一、24C02基础介绍

1.1 AT24C02功能概述

24C02是一个2K Bit的串行EEPROM存储器,内部含有256个字节。在24C02里面有一个8字节的页写缓冲器。该设备的工作电压为1.8V到6.0V,芯片的第7引脚WP为写保护引脚,将该引脚接地允许正常的读写。

1.2 设备地址

同样AT24C02也是IIC通信在IIC总线上一次可以同时挂载8个该设备通过A0 A1 A2来进行设备的选择

设备地址可以分为固定地址和可编程两部分 其中固定地址为1010

可编程地址的A0 A1 A2在该平台默认接的低电平 所以进行写操作时地址为0xa0 进行读操作时地址为0xa1

1.3 读写操作中的应答信号

在写操作中,24C02每接收一个8位字节后会产生一个应答信号。在读操作中,24C02在发送一个8位数据后会释放SDA线并监视应答信号。一旦收到应答信号,将继续发送数据。如果主机没有发送应答信号,从机则停止发送数据且等待一个停止信号。

1.4 字节写操作

24C02接收完设备地址后,产生应答信号;然后接收8位内存字节地址,产生应答信号,接着接收一个8位数据,产生应答信号;最后主机发送停止信号,字节写操作结束

1.5 页写操作

24C02有一个8字节的页写缓冲器,也就是说可以一次连续写入8个字节到缓冲器,然后由缓冲器一次性写到EEPROM。页写操作初始化与字节写操作相同,只是主机不会在写完第一个数据后就发送停止信号,而是在24C02应答后,接着发送7个数据。

需要注意的是,24C02接收到每个数据后,其字节地址的低3位会自动加1,高位地址不变,维持在当前页内。当内部产生的字节地址到达该页边界时,随后的数据将写入该页的页首,先前的写入的数据将会被覆盖

1.6 当前地址读操作

24C02内部的地址寄存器会保存着上次读/写操作最后一个地址加1的值。只要芯片有电,该地址就一直保存着。如果上次读/写操作的地址为N,那么当前地址读操作就从N+1开始。当读到最后一个字节(即255处),地址会回转到0

1.7 字节读操作

主机首先发送起始信号,接着发送设备地址和它想要读取的数据内存字节地址,执行一个伪写操作。在24C02应答主机之后,主机重新发送起始信号和从设备地址,进行读操作。24C02响应并发送应答信号,然后输出所要求的一个8位字节数据。主机接收完这个8位数据后,产生一个“非应答”信号,最后发送停止条件,字节读操作结束。

1.8 连续读操作

在24C02发送完一个8位字节数据之后,主机产生一个应答信号来响应,告知24C02要求读取更多的数据,直到读完最后一个数据,主机向24C02发送一个“非应答”信号,然后发送一个停止信号,结束此操作。

/********************************************
Date:2022-1-14
Author:小殷同学
Learn From:B 站小蜜蜂老师
*********************************************/

#include "reg52.h"
#include "iic.h"

unsigned char dat1 = 0;
unsigned char dat2 = 0; 
unsigned char dat3 = 0;

//共阳数目管段码
//0-f  0xbf代表 -
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
                                                               0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf};

//---------------------------------简单延时函数-------------------------
void Delay(unsigned int t)
{
     while(t--);
}

//-------------------------------74HC138初始化---------------------------
void Init_74HC138(unsigned char n)
{
     switch(n)
    {
         case 4:P2 = P2| 0x1f; P2 = 0x80; break;
        case 5:P2 = P2| 0x1f; P2 = 0xa0; break;
        case 6:P2 = P2| 0x1f; P2 = 0xc0; break;
        case 7:P2 = P2| 0x1f; P2 = 0xe0; break;
        case 0:P2 = P2| 0X1f; P2 = 0x00; break; //所有锁存器都不选择
    }
}

//----------------------------------系统初始化---------------------------
void InitSystem(void)
{
      Init_74HC138(5);
     P0 = 0x00;             //关闭继电器与蜂鸣器
     Init_74HC138(4);
     P0 = 0xff;   //关闭led
}



//---------------------------------数码管安位显示--------------------------
void SMG_DisplayBit(unsigned char pos ,unsigned char dat)
{
         Init_74HC138(6);
        P0 = 0x01 << pos ;//位选
        Init_74HC138(7);
        P0 = dat;        //段码
}

//-------------------------------关闭所有数码管---------------------------
void SMG_CLOSEALL(unsigned char dat)
{
     Init_74HC138(6);
     P0 = 0xff; //选中所有数码管
     Init_74HC138(7);
     P0 = dat; //关闭
}

//----------------------------时间显示函数----------------------------
void Time_Display(void)
{
     SMG_DisplayBit(0,SMG_Duan[dat1/10]);
     Delay(100);
     SMG_DisplayBit(1,SMG_Duan[dat1%10]);
     Delay(100);
     
     SMG_DisplayBit(2,SMG_Duan[16]);
     Delay(100);
     SMG_DisplayBit(3,SMG_Duan[dat2/10]);
     Delay(100);
     SMG_DisplayBit(4,SMG_Duan[dat2%10]);
     Delay(100);
     SMG_DisplayBit(5,SMG_Duan[16]);
     Delay(100);
     SMG_DisplayBit(6,SMG_Duan[dat3/10]);
     Delay(100);
     SMG_DisplayBit(7,SMG_Duan[dat3%10]);
     Delay(100);
     SMG_CLOSEALL(0xff);
     Delay(100);     
}


//---------------------------------24C02写操作-----------------------------
void Write_24C02(unsigned char addr,unsigned char dat)
{
    IIC_Start();        //IIC总线起始信号                    
    IIC_SendByte(0xa0);     //24C02的写设备地址
    IIC_WaitAck();        //等待从机应答    
    IIC_SendByte(addr);     //内存字节字节
    IIC_WaitAck();         //等待从机应答    
    IIC_SendByte(dat);     //写入目标数据
    IIC_WaitAck();        //等待从机应答    
    IIC_Stop();        //IIC总线停止信号    
}


//---------------------------------24C02读操作-----------------------------
unsigned char Read_24C02(unsigned char addr)
{
    unsigned char temp; //存储读取数据
    IIC_Start();        //IIC总线起始信号                    
    IIC_SendByte(0xa0);     //24C02的写设备地址
    IIC_WaitAck();        //等待从机应答    
    IIC_SendByte(addr);     //内存字节字节
    IIC_WaitAck();         //等待从机应答    
    

    IIC_Start();        //IIC总线起始信号                    
    IIC_SendByte(0xa1);     //24C02的读设备地址
    IIC_WaitAck();        //等待从机应答    
    temp = IIC_RecByte();     //读取数据
    IIC_SendAck(1); //非应答信号
    IIC_Stop();        //IIC总线停止信号        
    return temp;
}


//--------------------------------24C02读写操作--------------------------
void Read_Write_24C02(void)
{
        dat1 =  Read_24C02(0x01);
        dat2 =  Read_24C02(0x03);
        dat3 =  Read_24C02(0x05);

        dat1 += 1;
        dat2 += 1;
        dat3 += 1;
        
        if(dat1 > 10)
        {
             dat1 = 0;
        }
        if(dat2 > 20)
        {
             dat2 = 0;
        }
        if(dat3 > 30)
        {
             dat3 = 0;
        }

     Write_24C02(0x01,dat1);
     Delay(200);
     Write_24C02(0x03,dat2);
     Delay(200);
     Write_24C02(0x05,dat3);
     Delay(200);
}

void main(void)
{
    InitSystem();
    Read_Write_24C02();
     while(1)
    {
        Time_Display();
    }
}

二。智能照明控制器

#include "reg52.h"
#include "iic.h"


/********************************************
Date:2022-1-15
Author:小殷同学
Learn From:B 站小蜜蜂老师
*********************************************/


//led 灯定义
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;

unsigned char Rd1 = 0; //记录光敏实时数值
unsigned char Rd1_old = 0; //记录历史光敏值
unsigned char Level = 0; //记录灯光实时等级
unsigned char Level_old = 0; //记录灯光历史等级

//按键定义
sbit S4 = P3^3;
sbit S5 = P3^2;

//共阳数目管段码
//0-f  0xbf代表 -
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
                                                               0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf};





//---------------------------------简单延时函数-------------------------
void Delay(unsigned int t)
{
     while(t--);
}

//-------------------------------74HC138初始化---------------------------
void Init_74HC138(unsigned char n)
{
     switch(n)
    {
         case 4:P2 = P2| 0x1f; P2 = 0x80; break;
        case 5:P2 = P2| 0x1f; P2 = 0xa0; break;
        case 6:P2 = P2| 0x1f; P2 = 0xc0; break;
        case 7:P2 = P2| 0x1f; P2 = 0xe0; break;
        case 0:P2 = P2| 0X1f; P2 = 0x00; break; //所有锁存器都不选择
    }
}

//----------------------------------系统初始化---------------------------
void InitSystem(void)
{
      Init_74HC138(5);
     P0 = 0x00;             //关闭继电器与蜂鸣器
     Init_74HC138(4);
     P0 = 0xff;   //关闭led
}



//---------------------------------数码管安位显示--------------------------
void SMG_DisplayBit(unsigned char pos ,unsigned char dat)
{
         Init_74HC138(6);
        P0 = 0x01 << pos ;//位选
        Init_74HC138(7);
        P0 = dat;        //段码
}

//-------------------------------关闭所有数码管---------------------------
void SMG_CLOSEALL(unsigned char dat)
{
     Init_74HC138(6);
     P0 = 0xff; //选中所有数码管
     Init_74HC138(7);
     P0 = dat; //关闭
}

//----------------------------光敏数据读取函数----------------------------
void Read_Rd1_Data()
{
    IIC_Start();          //IIC起始信号
    IIC_SendByte(0x90);     //写入设备地址
    IIC_WaitAck();         //等待应答
    IIC_SendByte(0x01);     //写入通道 AIN1
    IIC_WaitAck();         //等待应答
    IIC_Stop();            //IIC停止信号

    IIC_Start();        //IIC起始信号
    IIC_SendByte(0x91);     //读取设备地址
    IIC_WaitAck();        //等待应答
    Rd1 = IIC_RecByte(); //读取数据
    IIC_SendAck(1);        //非应答
    IIC_Stop();            //IIC停止信号
}

//--------------------------------光敏等级Led控制---------------------------
/*
        等级1:255 <= 光照数据 < 200,L1点亮。

       等级2:200 <= 光照数据 < 150,L1~L2点亮。

       等级3:150 <= 光照数据 < 100,L1~L4点亮。

       等级4:100 <= 光照数据 < 50,L1~L6点亮。

       等级5:50 <= 光照数据 < 0,L1~L8点亮。

*/
void Led_Level_Tackle(void)
{
    Init_74HC138(4);
    Read_Rd1_Data();
    if(Rd1 > 200 && Rd1 <= 250)
    {
      //L1 = 0;
        P0 = 0xfe;
        Level = 5;
    }
    else if(Rd1 > 150 && Rd1 <= 200) 
    {
         //L1 = L2 = 0;
        P0 = 0xfc;
        Level = 4;
    }
    else if(Rd1 > 100 && Rd1 <= 150) 
    {
         //L1 = L2 = L3 = L4 = 0;
        P0 = 0xf0;
        Level = 3;
    }
    else if(Rd1 > 50 && Rd1 <= 100) 
    {
         //L1 = L2 = L3 = L4 = L5 = L6 = 0;
        P0 = 0xc0;
        Level = 2;
    }
    else if(Rd1 > 0 && Rd1 <= 50) 
    {
         //L1 = L2 = L3 = L4 = L5 = L6 = L7 = L8 = 0;
        P0 = 0x00;
        Level = 1;
    }

}

//----------------------------------24c02写操作-----------------------------
void Write_24C02(unsigned char addr,unsigned char dat)
{
        IIC_Start();                    //IIC起始信号
        IIC_SendByte(0xa0);                //发送设备地址 写操作
        IIC_WaitAck();                    //等待应答
        IIC_SendByte(addr);                //发送写单元地址
        IIC_WaitAck();                    //等待应答
        IIC_SendByte(dat);                //发送目标数据
        IIC_WaitAck();                    //等待应答
        IIC_Stop();                        //IIC停止信号
}

//----------------------------------24c02读操作-------------------------------
unsigned char Read_24C02(unsigned char addr)
{
         unsigned  char temp;        //接收数据变量
        IIC_Start();                //IIC起始信号
        IIC_SendByte(0xa0);            //发送设备地址 写操作
        IIC_WaitAck();                //等待应答
        IIC_SendByte(addr);            //发送写单元地址
        IIC_WaitAck();                //等待应答

        IIC_Start();                //IIC起始信号
        IIC_SendByte(0xa1);            //发送设备地址 读操作
        IIC_WaitAck();                //等待应答
        temp = IIC_RecByte();        //接收数据
        IIC_SendAck(1);                //非应答
        IIC_Stop();                    //IIC停止信号
        return temp    ;                //返回数据
}

//----------------------------------数码管数据显示---------------------------
void SMG_Dispaly_New_Data(void)
{
     SMG_DisplayBit(0,SMG_Duan[16]);
     Delay(200);
     SMG_DisplayBit(1,SMG_Duan[Level]);
     Delay(200);
     SMG_DisplayBit(2,SMG_Duan[16]);
     Delay(200);
     SMG_DisplayBit(3,0xff);
     Delay(200);
     SMG_DisplayBit(4,0xff);
     Delay(200);
     SMG_DisplayBit(5,SMG_Duan[Rd1/100]);
     Delay(200);
     SMG_DisplayBit(6,SMG_Duan[Rd1/10%10]);
     Delay(200);
     SMG_DisplayBit(7,SMG_Duan[Rd1%10]);
     Delay(200);
}

//显示旧值
void SMG_Dispaly_Old_Data(void)
{
     SMG_DisplayBit(0,SMG_Duan[16]);
     Delay(200);
     SMG_DisplayBit(1,SMG_Duan[Level_old]);
     Delay(200);
     SMG_DisplayBit(2,SMG_Duan[16]);
     Delay(200);
     SMG_DisplayBit(3,0xff);
     Delay(200);
     SMG_DisplayBit(4,0xff);
     Delay(200);
     SMG_DisplayBit(5,SMG_Duan[Rd1_old/100]);
     Delay(200);
     SMG_DisplayBit(6,SMG_Duan[Rd1_old/10%10]);
     Delay(200);
     SMG_DisplayBit(7,SMG_Duan[Rd1_old%10]);
     Delay(200);
}
//---------------------------------------按键读写操作------------------------
//按下S4按键将当前的灯光控制等级和光敏电阻的数据保存到存储器24C02的0x01和0x02内存单元中。
// 按下S5按键时,读取存储在24C02的历史数据并显示在数码管上,松开S5按键后,恢复显示实时数据。
void Key_Tackle(void)
{
     if(S4 == 0)
     {
            Delay(20);
            if(S4 == 0)
            {
                 Write_24C02(0x01,Level);      //写入灯光等级
                Delay(200);
                Write_24C02(0x02,Rd1);            //写入光敏数值
                while(S4 == 0)
                {
                     SMG_Dispaly_New_Data();     //实时数据显示
                }
            }
     }

     if(S5 == 0)
     {
            Delay(20);
            if(S5 == 0)
            {
                 Level_old = Read_24C02(0x01);     //读取灯光等级
                Delay(200);
                Rd1_old   =  Read_24C02(0x02); //读取光敏数值
                while(S5 == 0)
                {
                    SMG_Dispaly_Old_Data();         //历史数据显示
                }
            }
     }
}
//-------------------------------------主函数----------------------------------
void main(void)
{
    InitSystem();          //系统初始化
     while(1)
    {
        
        Led_Level_Tackle();        //灯光等级获取
        SMG_Dispaly_New_Data();     //数码管实时显示
        Key_Tackle();          //按键切换
    }

}

三。PWM信号控制呼吸流水灯

#include "regx52.h"
#include "absacc.h"
 
sbit S7 = P3^0;
sbit S4 = P3^3;
 
unsigned char pwm = 0;          
unsigned char pwm_duty = 0;              
unsigned char times = 0;        
unsigned char led_go = 0;       
unsigned char stat_go = 0;      
unsigned char stat = 0;         
unsigned char key_puse = 0;     
 
unsigned char code SMG_duanma[18]=
        {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
         0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
 
void DelaySMG(unsigned int t)
{
    while(t--);
}
 
void DisplaySMG_Bit(unsigned char pos, unsigned char value)
{
    XBYTE[0xE000] = 0xff;
    XBYTE[0xC000] = 0x01 << pos;
    XBYTE[0xE000] = value;
}
 
void Display_Info(unsigned char pos, unsigned char duty)
{
    DisplaySMG_Bit(0, SMG_duanma[pos]);
    DelaySMG(500);
 
    DelaySMG(500);
    DisplaySMG_Bit(6, SMG_duanma[duty / 10]);
    DelaySMG(500);
    DisplaySMG_Bit(7, SMG_duanma[duty % 10]);    
    DelaySMG(500);
    
    DisplaySMG_Bit(0, 0xff);
    DisplaySMG_Bit(6, 0xff);
    DisplaySMG_Bit(7, 0xff);
}
 
void Init_Timer0()
{
    TMOD = 0x01;
    TH0 = (65535 - 1000) / 256;            
    TL0 = (65535 - 1000) % 256;
    
    ET0 = 1;
    EA = 1;
    TR0 = 1;
}
 
void Service_Timer0() interrupt 1
{
    TH0 = (65535 - 1000) / 256;
    TL0 = (65535 - 1000) % 256;
    
    if(stat_go == 0)                              
      {
        XBYTE[0x8000] = 0xe7;                        
        return;
      } 
    
        pwm++;                
  
      if(pwm <= pwm_duty)   
      {
    XBYTE[0x8000] = ~(0x01 << stat);       
      }
      else if(pwm <= 10)
      {
        XBYTE[0x8000] = 0xff;
      }
      else
      {
        XBYTE[0x8000] = ~(0x01 << stat);
    
        pwm = 0;
        if(key_puse == 0)     
        {
          times++;
        }
      }
}
 
void LED_Control()
{
  if(times == 5)          
  {
    times = 0;
    if(led_go == 0)       
    {
      pwm_duty = pwm_duty + 1;
      if(pwm_duty == 11)
      {
                pwm_duty = 10;
        led_go = 1;
      }
    }
    else if(led_go == 1)  
    {
      pwm_duty = pwm_duty - 1;
      if(pwm_duty == 255)
      {
                pwm_duty = 0;
        led_go = 0;
        
        if(stat_go == 1)      
        {
          stat++;
          if(stat == 8)
          {
            stat = 0;
          }
        }
        else if(stat_go == 2) 
        {
          stat--;
          if(stat == 255)
          {
            stat = 7;
          }
        }
      }
    }
  }
}
 
void Scan_Keys()
{
    if(S4 == 0)
    {
        DelaySMG(100);
        if(S4 == 0)
        {
            while(S4 == 0)
            {
                key_puse = 1;
            }
            key_puse = 0;
            
      stat_go++;            
      if(stat_go == 3)
      {
        stat_go = 1;
      }
        }
    }
    
    if(S7 == 0)
    {
        DelaySMG(100);
        if(S7 == 0)
        {
            while(S7 == 0)
            {
                key_puse = 1;
                Display_Info(stat + 1, pwm_duty * 10);
            }
            key_puse = 0;
        }
    }
}
 
void Init_System()
{
    XBYTE[0xA000] = 0xff;
    XBYTE[0xA000] = 0x00;
    XBYTE[0xE000] = 0xff;
    XBYTE[0xC000] = 0xff;
    
    Init_Timer0();
}
 
void main()
{
    Init_System();
    while(1)
    {
        LED_Control();
        Scan_Keys();
    }
}


四。超声波测距

#include "reg52.h"
#include "intrins.h"

/********************************************
Date:2022-1-19
Author:小殷同学
Base Learn From:B 站小蜜蜂老师
*********************************************/

sbit TX = P1^0;
sbit RX = P1^1;
unsigned int Time = 0;
unsigned int dis = 0;
#define somenop() {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
//共阳数目管段码
unsigned char month = 0;     //定义一个变量让其变化显示
//0-f  0xbf代表 -
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
                                                               0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf};


//---------------------------------简单延时函数-------------------------
void delay(unsigned int t)
{
     while(t--);
}


void Delay12us()                  //@12.000MHz 延时12us
{
    unsigned char i;
 
    _nop_();
    _nop_();
    i = 33;
    while (--i);
}

//-------------------------------74HC138初始化---------------------------
void Init_74HC138(unsigned char n)
{
     switch(n)
    {
         case 4:P2 = P2| 0x1f; P2 = 0x80; break;
        case 5:P2 = P2| 0x1f; P2 = 0xa0; break;
        case 6:P2 = P2| 0x1f; P2 = 0xc0; break;
        case 7:P2 = P2| 0x1f; P2 = 0xe0; break;
        case 0:P2 = P2| 0X1f; P2 = 0x00; break; //所有锁存器都不选择
    }
}

//----------------------------------系统初始化---------------------------
void InitSystem(void)
{
      Init_74HC138(5);
     P0 = 0x00;             //关闭继电器与蜂鸣器
     Init_74HC138(4);
     P0 = 0xff;   //关闭led
}



//---------------------------------数码管安位显示--------------------------
void SMG_DisplayBit(unsigned char pos ,unsigned char dat)
{
         Init_74HC138(6);
        P0 = 0x01 << pos ;//位选
        Init_74HC138(7);
        P0 = dat;        //段码
}


//-------------------------------关闭所有数码管----------------------
void SMG_CLOSEALL(unsigned char dat)
{
     Init_74HC138(6);
     P0 = 0xff; //选中所有数码管
     Init_74HC138(7);
     P0 = dat; //关闭
}

void SMG_Display_Dynamic(void)
{
        SMG_DisplayBit(0,0xff);
        delay(200);
        SMG_DisplayBit(1,0xff);
        delay(200);
        SMG_DisplayBit(2,0xff);
        delay(200);
        SMG_DisplayBit(3,0xff);
        delay(200);
        SMG_DisplayBit(4,0xff);
        delay(200);
        SMG_DisplayBit(5,SMG_Duan[dis/100]);
        delay(200);
        SMG_DisplayBit(6,SMG_Duan[dis/10%10]);
        delay(200);
        SMG_DisplayBit(7,SMG_Duan[dis%10]);
        delay(200);
        SMG_CLOSEALL();
        delay(200);
}


//--------------------------------------发出声波----------------------------------
void SendWave(void)
{
    unsigned char i;
    for(i = 0; i < 8;i++)
    {
        TX = 1;
        somenop();
        TX = 0;
         somenop();     
    }
}
//------------------------------------超声波测距----------------------------------
void Ultrasonic_Dis(void)
{
    TMOD &= 0x0f; //定时器1模式0 13位最大值8192
    TH1 = 0x00;
    TL1 = 0x00;
    TF1  = 0; //溢出标志位
    TR1 = 0;
    SendWave();     //发送声波信号
    TR1 = 1;//启动定时
    while(RX == 1 && TF1 == 0);    //等待超声波信号返回或者等到测量超出范围  返回RX = 0
    TR1 = 0;//停止计时
    if(TF1 == 1) //溢出了还没有返回信号
    {
         TF1 = 0;
        dis = 999;
    }
    else
    {
          //接收到了返回信号 将定时时间合成16位
         Time = (TH1 << 8) | TL1; //总时间
         //dis = ((Time / 10) * 17) / 100 + 3;
         dis = Time * 0.0172;    
    }
}
//------------------------------------------------------------------------------------
void Delay_SMG(    unsigned char t)
{
     while(t--)
    {
        SMG_Display_Dynamic();
    }
}


void main(void)
{
    InitSystem();
     while(1)
    {
         Ultrasonic_Dis();
         Delay_SMG(50);
    }
}

五,模拟冲刺1

#include "reg52.h"
#include "iic.h"


/*****************************************************
*第十三届省赛模拟
*Date:2022-3-27
*Author:小殷
*****************************************************/


//独立按键定义
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

//LED定义
sbit LED1 = P0^0;
sbit LED2 = P0^1;
sbit LED3 = P0^2;
sbit LED4 = P0^3;
sbit LED5 = P0^4;

unsigned int Frequent = 0 ,f_data = 0,count = 0,count_flag = 0;   //频率相关变量
unsigned int Period = 0;    //周期
unsigned int Voltage_Rd1 = 0,Voltage_Rb2 = 0,Voltage = 0; //电压
unsigned int old_voltage  = 0,old_frequent = 0;
unsigned char led_flag = 0; //0 代表开启  1 代表关闭
unsigned char channel = 1,interface = 1 ; //通道编号  和显示界面
unsigned char time_flag = 0; //1s标志
unsigned char s7_press = 0,s_count = 0,s7_mode = 0; //按键长按下标志  ,计时变量  模式切换
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xbf,0xff};
unsigned char code smg_data_dot[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char led[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xff,0xff,0xff}; //led


void SMG_Display_V(void);
void SMG_Display_F(void);
void SMG_Display_T(void);

/**********************简单延时**********************/
void delay(unsigned char t)
{
     while(t--);
}


void delay_smg(unsigned char t)
{
     while(t--)
    {
         if(interface == 1)
        {
             SMG_Display_F();
        }
        else if(interface == 2)
        {
                SMG_Display_T();
        }
        else if(interface == 3)
        {
             SMG_Display_V();
        }

    }
}


/**********************锁存器操作********************/
void Init_74HC138(unsigned char n)
{
     switch(n)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
}

/*********************数码管安位操作*******************/
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     Init_74HC138(6);
    P0 = (0x01 << pos);
    Init_74HC138(7);
    P0 = dat;
    Init_74HC138(0);
}

/*************************关闭所有数码管***************/
void SMG_Close(void)
{
    Init_74HC138(6);
    P0 = 0xff;
    Init_74HC138(7);
    P0 = 0xff;
    Init_74HC138(0);
}    

/**********************系统初始化**********************/
void Init_System(void)
{
     Init_74HC138(4);
    P0 = 0xff;
    Init_74HC138(5);
    P0 = 0x00;
    Init_74HC138(0);
}

/***********************数码管功能显示******************/
void SMG_Display_F(void)
{
     SMG_DisplayBit(0,0x8e);  // F ->0111 0001 0x8e
    delay(200);
    if(Frequent > 999999)
    {
        SMG_DisplayBit(1,smg_data[Frequent/1000000]);
      delay(200);
    }
 if(Frequent > 99999)
    {
        SMG_DisplayBit(2,smg_data[Frequent/100000%10]);
     delay(200);
    }
     if(Frequent > 9999)
    {
        SMG_DisplayBit(3,smg_data[Frequent/10000%10]);
        delay(200);
    }
 if(Frequent > 999)
    {
        SMG_DisplayBit(4,smg_data[Frequent/1000%10]);
      delay(200);
    }
 if(Frequent > 99)
    {
         SMG_DisplayBit(5,smg_data[Frequent /100%10]);
         delay(200);
    }
 if(Frequent > 9)
    {
        SMG_DisplayBit(6,smg_data[Frequent /10%10]);
        delay(200);
    }

    SMG_DisplayBit(7,smg_data[Frequent %10]);
    delay(200);
    SMG_Close();

}

/*****************************周期显示***********************/
void SMG_Display_T(void)
{
    Period = 1.0/Frequent *1000000;
    SMG_DisplayBit(0,0xc8);  // >0001 0011  0xc8
    delay(200);
    if(Period > 999999)
    {
        SMG_DisplayBit(1,smg_data[Period/1000000]);
      delay(200);
    }
 if(Period > 99999)
    {
        SMG_DisplayBit(2,smg_data[Period/100000%10]);
     delay(200);
    }
     if(Period > 9999)
    {
        SMG_DisplayBit(3,smg_data[Period/10000%10]);
        delay(200);
    }
 if(Period > 999)
    {
        SMG_DisplayBit(4,smg_data[Period/1000%10]);
      delay(200);
    }
 if(Period > 99)
    {
         SMG_DisplayBit(5,smg_data[Period /100%10]);
         delay(200);
    }
 if(Period > 9)
    {
        SMG_DisplayBit(6,smg_data[Period /10%10]);
        delay(200);
    }

    SMG_DisplayBit(7,smg_data[Period %10]);
    delay(200);
    SMG_Close();
    
}

/*******************************电压显示**********************/
void SMG_Display_V(void)
{
    SMG_DisplayBit(0,0xc1);  // >1000 0011  0xc8
    delay(200);
    SMG_DisplayBit(1,0xbf); // -  
    delay(200);
    SMG_DisplayBit(2,smg_data[channel]);  
    delay(200);
    SMG_DisplayBit(3,0xff);  
    delay(200);
    SMG_DisplayBit(4,0xff);  
    delay(200);
    SMG_DisplayBit(5,smg_data_dot[Voltage/100]);  
    delay(200);
    SMG_DisplayBit(6,smg_data[Voltage/10%10]);  
    delay(200);
    SMG_DisplayBit(7,smg_data[Voltage%10]);  
    delay(200);
    SMG_Close();
    delay(200);
}
/******************************定时器初始化******************/
void Init_Timer(void)
{
     TMOD = 0x16; //定时器0计数 定时器1 计时
    TH0 = 0xff;
    TL0 = 0xff;
    TH1 = (65535-50000)/256; //50ms
    TL1 = (65535-50000)%256;
    ET0 = 1;
    ET1 = 1;
    TR0 = 1;
    TR1 = 1;
    EA  = 1;
}




unsigned char  Read_RD1(void)
{
     unsigned char temp  = 0;
     IIC_Start();
     IIC_SendByte(0x90);
     IIC_WaitAck();
     IIC_SendByte(0x01);   //光敏通道
     IIC_WaitAck();
     IIC_Stop(); 
     
     IIC_Start();
     IIC_SendByte(0x91);
     IIC_WaitAck();
     temp = IIC_RecByte();
     IIC_SendAck(1);
     IIC_Stop(); 
     return temp;
}



unsigned char  Read_RD2(void)
{
     unsigned char temp  = 0;
     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_SendAck(1);
     IIC_Stop(); 
     return temp;
}

/***************************按键处理*************************/
void KeyScans(void)
{
     if(S4 == 0)
    {
         delay_smg(20);
        if(S4 == 0)
        {
             while(S4 == 0); //等待按键松开
            if(interface == 1)
            {
                 interface = 2;
                SMG_Display_F();
            }
            else if(interface == 2)
            {
                 interface = 3;
                SMG_Display_T();
            }
            else if(interface == 3)
            {
                 interface = 1;
                SMG_Display_V();
            }
        }
    }

    if(S5 == 0)
    {
         delay_smg(20);
        if(S5 == 0)
        {
             while(S5 == 0); //等待按键松开
            if(channel == 1)
            {
                 channel = 3;
            }
            else if(channel == 3)
            {
                channel = 1;
            }
        }
    }

    if(S6 == 0)
    {
         delay_smg(20);
        if(S6 == 0)
        {
             while(S6 == 0); //等待按键松开
            old_voltage = Voltage ;         //保存旧值
        }
    }

    if(S7 == 0)
    {
         delay_smg(20);
        if(S7 == 0)
        {
            s7_press = 0;   //按键按下标志
            s_count = 0;
            while(S7 == 0); //等待按键松开
            if(s7_press == 1)       //长按
            {
                if(s7_mode == 0)    //模式切换变量 第一次长按关闭Led功能  再次长按打开led功能
                {
                     s7_mode = 1;
                    led_flag = 1;     //关闭led功能
                }
                else if(s7_mode == 1)
                {
                     s7_mode = 0;
                    led_flag = 0;        //打开led功能
                }    
            }
            else      //短按
            {
            old_frequent = Frequent;     //保存旧值
            }
        }
        

    }

}

/************************Led操作函数*************************/
void Led_Running(void)
{
     if(led_flag == 0)
    {    
        Init_74HC138(4); //选通Y4 进行LED 控制
        //通道3的实时电压数据大于缓存电压数据,指示灯L1点亮,否则熄灭
        if(Voltage > old_voltage )
        {
             //P0 = led[0];
            LED1 = 0;
        }
        else
        {
             LED1 = 1;
        }
        //实时频率值大于缓存频率数据,指示灯L2点亮,否则熄灭
         if(Frequent > old_frequent )
        {
            //P0 = led[1];
            LED2 = 0;    
        }
        else
        {
             LED2 = 1;
        }
         //处于频率界面,指示灯L3点亮,否则熄灭
        if(interface == 1)
        {
             //P0 = led[2];
            LED3 = 0;
        }
        else
        {
             LED3 = 1;
        }
        //处于周期界面,指示灯L4点亮,否则熄灭。
        if(interface == 2)
        {
             //P0 = led[3];
            LED4 = 0;
        }
        else
        {
             LED4 = 1;
        }
        //处于电压界面,指示灯L5点亮,否则熄灭
         if(interface == 3)
        {
             //P0 = led[4];
            LED5 = 0;
        }
        else
        {
             LED5 = 1;
        }
    }
    else if(led_flag == 1)
    {
        P0 = 0xff;
         Init_74HC138(4);    
    }
    //Init_74HC138(0);
}
/****************************主函数**************************/
void main(void)
{
     Init_System();
    Init_Timer();
    while(1)
    {
        KeyScans();
        switch(interface)
        {
             case 1:SMG_Display_F();break;
            case 2:SMG_Display_T();break;
            case 3:SMG_Display_V();break;
        }
         if(interface == 3)
        {
            switch(channel)
            {
              case 1: Voltage_Rd1 = Read_RD1();
                              Voltage = ( Voltage_Rd1/255.0 *5*100);//将其扩大100倍方便显示
                                break;
                case 3:    Voltage_Rb2 = Read_RD2();
                              Voltage = ( Voltage_Rb2/255.0 *5*100);//将其扩大100倍方便显示
                        break;
            }
        }

        Led_Running();

    }

}

void Server_Timer0() interrupt 1
{
     f_data++; 
}


void Server_Timer1() interrupt 3
{
    TH1 = (65535-50000)/256; //50ms
    TL1 = (65535-50000)%256;
    count++;
    s_count++;
    if(count == 20) //1s
    {
         Frequent = f_data;
        f_data = 0;
        count = 0;
    }

    //长按计时
    if(s_count == 20)
    {
         s7_press = 1;     //到达1s  s7press 置1
    }

}

#include "reg52.h"
#include "iic.h"

/**************************************
*第十三届蓝桥杯单片机省赛模拟
*Date:2022-3-29
*Author:小殷
***************************************/

sfr P4 = 0xc0;
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;

sbit L1 = P3^4;
sbit L2 = P3^5;
sbit L3 = P4^2;
sbit L4 = P4^4;


sbit  LED1 = P0^0;
sbit  LED2 = P0^1;

unsigned char s_press = 0,s_count = 0; //按键按下标志位和计时
unsigned char count = 0,led_flag = 0;    //计时  led标志位
unsigned int count_value = 0,count_value2 = 0;//按键值 和保存值
unsigned char interface = 1;    //界面
//数码管段码
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,
                                                                    0x82,0xF8,0x80,0x90,0xbf,0xff};


//1简单延时
void delay(unsigned int t)
{
     while(t--);
}

//操作锁存器
void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break; //Y4
        case 5:P2 = (P2 & 0x1f) | 0xa0;break; //Y5
        case 6:P2 = (P2 & 0x1f) | 0xc0;break; //Y6
        case 7:P2 = (P2 & 0x1f) | 0xe0;break; //Y7
        case 0:P2 = (P2 & 0x1f) | 0x00;break; //不选通任何一个
    }
        P2 = (P2 & 0x1f) | 0x00;
}

//数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//操作所有数码管
void SMG_All(unsigned char dat)
{
     P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}


//显示数码管数据 累加和减的数据
void SMG_Display_Data1(void)
{
 //0001 0001  ->0x88
     SMG_DisplayBit(0,0x88);
    delay(200);
    //    SMG_DisplayBit(0,0xff);
    SMG_DisplayBit(1,0xff);
    delay(200);
    SMG_DisplayBit(2,0xff);
    delay(200);
    SMG_DisplayBit(3,0xff);
    delay(200);
    SMG_DisplayBit(4,0xff);
    delay(200);
    //3位数码管来显示键值
    if(count_value > 99)
    {
        SMG_DisplayBit(5,smg_data[count_value/100]);
         delay(200);
    }
    if(count_value > 9)
    {
            SMG_DisplayBit(6,smg_data[count_value/10%10]);
            delay(200);
    }
    
    SMG_DisplayBit(7,smg_data[count_value%10]);
    delay(200);
    SMG_All(0xff);
    delay(200);
}


//系统初始化
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}

//回显数据显示
void SMG_Display_Data2(void)
{
 //1001 0001 ->0x89
     SMG_DisplayBit(0,0x89);
    delay(200);
    //    SMG_DisplayBit(0,0xff);
    SMG_DisplayBit(1,0xff);
    delay(200);
    SMG_DisplayBit(2,0xff);
    delay(200);
    SMG_DisplayBit(3,0xff);
    delay(200);
    SMG_DisplayBit(4,0xff);
    delay(200);
    //3位数码管来显示键值
    if(count_value > 99)
    {
        SMG_DisplayBit(5,smg_data[count_value2/100]);
         delay(200);
    }
    if(count_value > 9)
    {
            SMG_DisplayBit(6,smg_data[count_value2/10%10]);
            delay(200);
    }
    
    SMG_DisplayBit(7,smg_data[count_value2%10]);
    delay(200);
    SMG_All(0xff);
    delay(200);
}


//EEPROM写操作
void Write_AT24C02(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();
}

//读操作
unsigned char Read_AT24C02(unsigned char addr)
{
     unsigned int temp = 0;
    IIC_Start();
    IIC_SendByte(0xa0);
    IIC_WaitAck();
    IIC_SendByte(addr);
    IIC_WaitAck();

    IIC_Start();
    IIC_SendByte(0xa1);
    IIC_WaitAck();
    temp = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    return temp;
}


void Key_Scan(void)
{
    H3 = 0;
    H1 = H2 = H4 = 1;
    L1 =  L2 = L3 = L4 = 1;
    //S9        回显
    if(L3 == 0)
    {
         delay(20);
        if(L3 == 0)
        {
             while(L3 == 0){
            if(interface == 1)
            {
                 interface = 2; //界面切换
                SMG_Display_Data1();    
            }
            else if(interface == 2)
            {
                 interface = 1;
                SMG_Display_Data2();
            }
        }
        }
    }
    //S5 减
    else if(L4 == 0)
    {
         delay(20);
        if(L4 == 0)
        {
            
             while(L4 == 0)     
            {
                SMG_Display_Data1();
            }
             //在计数界面下进行键值的减
            if(interface == 1)
            {
                    count_value--;
            }
        
        }
    }

    H4 = 0;
    H1 = H2 = H3 = 1;
    L1 =  L2 = L3 = L4 = 1;
    //S8    存储
    if(L3 == 0)
    {
         delay(20);
        if(L3 == 0)
        {
            //每次按下时将计时和标志位清零
            s_press = 0;
            s_count = 0;
             while(L3 == 0)    
            {
                    SMG_Display_Data1();
            }    
            if(s_press == 1)     //长按标志
            {
                 count_value = 0;            //计数清零
            }
            //短按
            else
            {
                if(interface == 1)
                {
                     //count_value2 = count_value;        //保存当前值
                    Write_AT24C02(0x00,count_value);
                }
            }
        
        }
    }
    //S4  加
    else if(L4 == 0)
    {
         delay(20);
        if(L4 == 0)
        {        
            
                 while(L4 == 0)
                {
                     SMG_Display_Data1();
                }
                //在计数界面下 进行键值的累加
                if(interface == 1)
                {
                    count_value++;
                }
        }
    }

}


//dac数据
void Read_DAC(float dat)
{
     IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    IIC_SendByte(0x43);
    IIC_WaitAck();
    IIC_SendByte(dat);
    IIC_WaitAck();
    IIC_Stop();
}




//电压显示
void Voltage_Tackle(void)
{
     //为5非0 整数倍     DAC->4  ELSE DAC ->1
    if((count_value % 5)== 0)
    {
         Read_DAC(204); //数字转模拟      0-5  ->0-255
        //5/255 = 4/x    4x51 = 204
    }
    else
    {
         Read_DAC(51);
    }
}

void Led_Tackle(void)
{
    if(interface == 1)
    {
         LED1 = 0;
    }
    else
    {
         LED1 = 1;
    }
    if(count_value > count_value2)
    {
             if(led_flag == 0)
            {
                 LED2 = 0;
            }
            else if(led_flag == 1)
            {
                 LED2 = 1;
            }
    }
    Init_74HC138(4);
}


void Init_Timer(void)
{
     TMOD = 0x01;
    TH0 = (65535-50000)/256;         //50ms
    TL0 = (65535-50000)%256;
    ET0 = 1;
    TR0 = 1;
    EA  = 1;
}
//主函数
void main(void)
{
    Init_System();
    Init_Timer();
    while(1)
    {
        Key_Scan();
         switch(interface)
        {
             case 1:SMG_Display_Data1();break;
            case 2:
                        count_value2 = Read_AT24C02(0x00);
                        SMG_Display_Data2();break;
        }
        Led_Tackle();
        Voltage_Tackle();
        
    }
}


void Server_Timer0() interrupt 1
{
     TH0 = (65535-50000)/256;         //50ms
    TL0 = (65535-50000)%256;
    count++;
    s_count++;
    if(count == 4) //0.2s 开启led标志位
    {
        count = 0;
         if(led_flag == 0)
        {
             led_flag = 1;
        }
        else if(led_flag == 1)
        {
             led_flag = 0;
        }
    }

    if(s_count == 40) //定时2s
    {
         s_press = 1; //长按标志位置1 代表已进入长按模式
    } 

}

六,巩固练习

一、灯闪烁与数码管计数

#include "reg52.h"


sbit LED1 = P0^0;
sbit LED2 = P0^1;
sbit LED8 = P0^7;
unsigned char led_stat = 0xff;
unsigned char value1 = 0,value2 = 0;
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};


void SMG_Display_Data(void);//1.简单延时

void delay(unsigned int t)
{
     while(t--);
}


void Delay_s(unsigned int t)
{
  while(t--)
  {
    SMG_Display_Data();                //在延时期间保持数码管刷新
  }
}
//2.锁存器初始化
void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;//Y4输出0,LED控制
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;//Y5输出0,蜂鸣器和继电器控制
        case 6:P2 = (P2 & 0x1f) | 0xc0;break; //Y6输出0,数码管位选
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;//Y7输出0,数码管段码
        case 0:P2 = (P2 & 0x1f) | 0x00;break;//所有锁存器不选择
    }
        P2 = (P2 & 0x1f) | 0x00;//所有锁存器不选择
}

//3.数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos); //数码管的段位
    Init_74HC138(6);
    P0 = dat;           //数码管显示内容
    Init_74HC138(7);
}

//4.操作所有数码管
void SMG_All(unsigned char dat)
{
     P0 = 0xff;        //数码管的段位
    Init_74HC138(6);
    P0 = dat;         //数码管显示内容
    Init_74HC138(7);
}

//5.系统初始化
void Init_System(void)
{
     P0 = 0xff;      //关闭所有led
    Init_74HC138(4);
    P0 = 0x00;     //关闭蜂鸣器和继电器
    Init_74HC138(5);
    SMG_All(0xff); //关闭所有数码管
}

//6.数码管数据显示
void SMG_Display_Data(void)
{
    SMG_DisplayBit(0,smg_data[value1]);
    delay(200);
    SMG_DisplayBit(1,0xff);
    delay(200);
    SMG_DisplayBit(2,0xff);
    delay(200);
    SMG_DisplayBit(3,0xff);
    delay(200);
    SMG_DisplayBit(4,0xff);
    delay(200);
    SMG_DisplayBit(5,0xff);
    delay(200);
    SMG_DisplayBit(6,smg_data[value2/10]);
    delay(200);
    SMG_DisplayBit(7,smg_data[value2%10]);
    delay(200);
    SMG_All(0xff);
    delay(200);    
}


//7.led操作
void Led_Tackle(void)
{
     led_stat &= ~0x80;  //led8电亮
    P0 = led_stat;
    Init_74HC138(4);
    Delay_s(200);

    led_stat |= 0x80;   //熄灭
    P0 = led_stat;
    Init_74HC138(4);
    Delay_s(200);

    value2++;
    if(value2 == 100)
    {
         value2 = 0;
    }

    //led1 和led2 灯同时翻转
    if((led_stat & 0x03) == 0x03)
    {
         led_stat &= ~0x03;
    }
    else
    {
         led_stat |= 0x03;
    }
    P0 = led_stat;
    Init_74HC138(4);
    value1++;
    if(value1 > 9)
    {
         value1 = 0;
    } 
}

void main(void)
{
    Init_System();
    while(1)
    {
        Led_Tackle();
        SMG_Display_Data();     
    }
}

二、24C02基本读写操作

#include "reg52.h"
#include "iic.h"

unsigned char dat1,dat2,dat3;
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};

//1.简单延时
void delay(unsigned int t)
{
     while(t--);
}

//2.锁存器操作
void Init_74HC138(unsigned char n)
{
     switch(n)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
    P2 = (P2 & 0x1f) | 0x00;
}

//3.数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
    P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//关闭所有数码管
void SMG_Close(void)
{
     P0 = 0xff;
    Init_74HC138(6);
    P0 = 0xff;
    Init_74HC138(7);
}

//4.系统初始化
void Init_System(void)
{
    Init_74HC138(0);
     P0 = 0x00;
    Init_74HC138(5);
    P0 = 0xff;
    Init_74HC138(4);
}

//5.数码管数据显示
void SMG_Display_Data(void)
{
     SMG_DisplayBit(0,smg_data[dat1/10]);
    delay(200);
    SMG_DisplayBit(1,smg_data[dat1%10]);
    delay(200);
    SMG_DisplayBit(2,0xbf);
    delay(200);
    SMG_DisplayBit(3,smg_data[dat2/10]);
    delay(200);
    SMG_DisplayBit(4,smg_data[dat2%10]);
    delay(200);
    SMG_DisplayBit(5,0xbf);
    delay(200);
    SMG_DisplayBit(6,smg_data[dat3/10]);
    delay(200);
    SMG_DisplayBit(7,smg_data[dat3%10]);
    delay(200);
    SMG_Close();
    delay(200);
}


//6.at24c02数据写
void AT24C02_Write(unsigned char addr,unsigned char dat)
{    
    IIC_Start();         //起始信号
    IIC_SendByte(0xa0);  //EEPROM的写设备地址
    IIC_WaitAck();       //等待从机应答
    IIC_SendByte(addr);  //内存单元地址
    IIC_WaitAck();      //等待从机应答
    IIC_SendByte(dat);   //内存写入数据
    IIC_WaitAck();      //等待从机应答
    IIC_Stop();       //停止信号
}

//7.at24c02数据读
unsigned char AT24C02_Read(unsigned char addr)
{
      unsigned char tmp = 0;
      //首先,进行一个伪写操作
      IIC_Start();          //起始信号
      IIC_SendByte(0xa0);    //EEPROM的写设备地址
      IIC_WaitAck();        //等待从机应答
      IIC_SendByte(addr);    //内存单元地址
      IIC_WaitAck();        //等待从机应答
      //然后,开始字节读操作
      IIC_Start();          //起始信号
      IIC_SendByte(0xa1);    //EEPROM的读设备地址
      IIC_WaitAck();        //等待从机应答
      tmp = IIC_RecByte();  //读取内存中的数据
      IIC_SendAck(1);        //产生非应答信号
      IIC_Stop();            //停止信号
      return tmp;
}

//8.数据处理
void Read_Write_Data(void)
{
     //先读取数据
    dat1 =     AT24C02_Read(0x01);
    dat2 =  AT24C02_Read(0x03);
    dat3 =     AT24C02_Read(0x05);


    dat1  = dat1 +1;
    dat2  = dat2 +2;
    dat3  = dat3 + 3 ;
    if( dat1 > 10)
    {
         dat1 = 0;
    }
    if(dat2  > 20)
    {
         dat2 = 0;
    }
    if(dat3  > 30)
    {
         dat3 = 0;
    }

    //将数据写回去
    AT24C02_Write(0x01,dat1);
    delay(1000);
    AT24C02_Write(0x03,dat2);
    delay(1000);
    AT24C02_Write(0x05,dat3);
    delay(1000);

}
void main(void)
{
     Init_System();
    Read_Write_Data();
    while(1)
    {             
         SMG_Display_Data();
    }
}

三、24C02存储按键触发次数

#include "iic.h"
#include "reg52.h"

sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

unsigned char s4_value = 0,s5_value = 0,s6_value = 0;
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};
//1.简单延时
void delay(unsigned int t)
{
     while(t--);
}

//2.锁存器初始化
void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
    P2 = (P2 & 0x1f) | 0x00;
}

//3.数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//4.操作所有数码管
void SMG_All(unsigned char dat)
{
     P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}
//5.系统初始化
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}

//6.数码管显示数据
void SMG_Display_Data(void)
{
     SMG_DisplayBit(0,smg_data[s4_value/10]);
    delay(200);
    SMG_DisplayBit(1,smg_data[s4_value%10]);
    delay(200);
    SMG_DisplayBit(2,0xbf);
    delay(200);
    SMG_DisplayBit(3,smg_data[s5_value/10]);
    delay(200);
    SMG_DisplayBit(4,smg_data[s5_value%10]);
    delay(200);
    SMG_DisplayBit(5,0xbf);
    delay(200);
    SMG_DisplayBit(6,smg_data[s6_value/10]);
    delay(200);
    SMG_DisplayBit(7,smg_data[s6_value%10]);
    delay(200);
    SMG_All(0xff);
    delay(200);

}

//7.at24c02写数据
void AT24C02_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();
}

//8.at24c04读数据
unsigned char AT24C02_Read(unsigned char addr)
{
    unsigned char temp = 0;
    IIC_Start();
    IIC_SendByte(0xa0);
    IIC_WaitAck();
    IIC_SendByte(addr);
    IIC_WaitAck();

    IIC_Start();
    IIC_SendByte(0xa1);
    IIC_WaitAck();
    temp = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    return temp;
}

//9.系统上电后,先从24C04存储器的0x00、0x01和0x02这三个地址单元读取数据
void AT24C02_Data_Init(void)
{
     s4_value =     AT24C02_Read(0x00);
    delay(1000);
    s5_value =  AT24C02_Read(0x01);
    delay(1000);
    s6_value =  AT24C02_Read(0x02);
    delay(1000);

}

//10.按键控制
void Key_Scans(void)
{
 if(S4 == 0)
 {
        delay(20);
        if(S4 == 0)
        {
             while(S4 == 0);
            s4_value++;
            if(s4_value > 13)
            {
                 s4_value = 0;
            }
            AT24C02_Write(0x00,s4_value);
        }
 }
 
 if(S5 == 0)
 {
        delay(20);
        if(S5 == 0)
        {
             while(S5 == 0);
            s5_value++;
            if(s5_value > 13)
            {
                 s5_value = 0;
            }
            AT24C02_Write(0x01,s5_value);
        }
     }
    
    if(S6 == 0)
 {
        delay(20);
        if(S6 == 0)
        {
             while(S6 == 0);
            s6_value++;
            if(s6_value > 13)
            {
                 s6_value = 0;
            }
            AT24C02_Write(0x02,s6_value);
        }
 }                
}
void main(void)
{
    Init_System();
    AT24C02_Data_Init();
    while(1)
    {
        SMG_Display_Data() ;
        Key_Scans();
    }
     
}

四、采样可变电阻电压与光敏电阻电压

#include "iic.h"
#include "reg52.h"

sbit S4 = P3^3;
unsigned char channel = 1;
unsigned int adc_value = 0,adc_volt = 0;
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};
unsigned char code smg_dot[] ={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

//1.简单延时
void delay(unsigned int t)
{
     while(t--);
}

//2.锁存器初始化
void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
        P2 = (P2 & 0x1f) | 0x00;
}

//数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//操作所有数码管
void SMG_All(unsigned char dat)
{
  P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//系统初始化
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}

//数码管数据显示
void SMG_Display_Data(void)
{
     SMG_DisplayBit(0,0xbf);
    delay(200);
    SMG_DisplayBit(1,smg_data[channel]);
    delay(200);
    SMG_DisplayBit(2,0xbf);
    delay(200);
    SMG_DisplayBit(3,0xff);
    delay(200);
    SMG_DisplayBit(4,0xff);
    delay(200);
    SMG_DisplayBit(5,smg_dot[adc_volt/100]);
    delay(200);
    SMG_DisplayBit(6,smg_data[adc_volt/10%10]);
    delay(200);
    SMG_DisplayBit(7,smg_data[adc_volt%10]);
    delay(200);
    SMG_All(0xff);
    delay(200);
}

//PCF8591数据读取
void PCF8591_Read_Data(unsigned char channel)
{
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    if(channel == 1)
    {
         IIC_SendByte(0x01);    
    }
    else if(channel == 3)
    {
         IIC_SendByte(0x03);    
    }
    IIC_WaitAck();
    IIC_Stop();

    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();
    adc_value = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    adc_volt = adc_value * (5.0/255)*100;        //扩大100倍方便显示         
}

//按键操作
void Key_Tackle(void)
{
     if(S4 == 0)
    {
         delay(20);
        if(S4 == 0)
        {
             while(S4 == 0)
            {
                 if(channel == 1)
                {
                     channel = 3;
                }
                else if(channel == 3)
                {
                     channel = 1;
                }
                PCF8591_Read_Data(channel);
              SMG_Display_Data();
            }

        }
    }
}

//主函数
void main(void)
{
     Init_System();
     while(1)
    {
        
        Key_Tackle();
        PCF8591_Read_Data(channel);
        SMG_Display_Data();
    }
}

七,巩固练习2

一、按键长按短与短按

#include "reg52.h"

//定义S4按键
sbit S4 = P3^3;
unsigned char t_count = 0,s_press = 0,value =28;    //计时,按键长按标志,数值
unsigned char code smg_data[18]={0xc0,0xf9,
    0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
    0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};    //段码




//简单延时
void delay(unsigned int t)
{
    while(t--);
}

//锁存器初始化
void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
        P2 = (P2 & 0x1f) | 0x00;
}

//操作所有数码管
void SMG_All(unsigned char dat)
{    
    P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}


//数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//数码管显示数据
void SMG_Display_Data(void)
{
    SMG_DisplayBit(0,0xff);
    delay(200);
    SMG_DisplayBit(1,0xff);
    delay(200);
    SMG_DisplayBit(2,0xff);
    delay(200);
    SMG_DisplayBit(3,0xff);
    delay(200);
    SMG_DisplayBit(4,0xff);
    delay(200);
    SMG_DisplayBit(5,0xff);
    delay(200);
    SMG_DisplayBit(6,smg_data[value/10]);
    delay(200);
    SMG_DisplayBit(6,0xff);
    delay(200);
    SMG_DisplayBit(7,smg_data[value%10]);
    delay(200);
    SMG_DisplayBit(7,0xff);
    SMG_All(0xff);
    delay(200);
}





//系统初始化
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}


//按键处理
void Key_Scan(void)
{
     if(S4 == 0)
    {
        delay(20);
        if(S4 == 0)
        {
            //这里一定注意要将标志位和计时清零
            s_press = 0;
            t_count = 0;
             while(S4 == 0)
            {
                 SMG_Display_Data();
            }
            if(s_press == 1) //长按模式
            {
                 value = 0;
            }
            else      //短按模式
            {
                value++;
                if(value > 99)
                {
                     value = 0;
                }
            }
            
        }
    }
}

//定时器初始化
void Init_Timer(void)
{
     TMOD = 0x01;
    TH0  =(65535-10000)/256;    //10ms
    TL0  =(65535-10000)%256;
    ET0  = 1;
    TR0  = 1;
    EA   = 1;
}
//主函数
void main(void)
{
     Init_System();
    Init_Timer();
    while(1)
    {
         Key_Scan();
        SMG_Display_Data();
    }
}

//定时器中断处理

void Server_Timer0() interrupt 1
{
     TH0 = (65535-10000)/256;
    TL0 = (65535-10000)%256;
    t_count++;
    if(t_count == 100) //1s
    {
         s_press = 1;  //长按标志
    }
}

二、采样光敏与可调电阻电压

#include "reg52.h"
#include "iic.h"

unsigned char rd1_value = 0,rd2_value = 0; //光敏与电阻采样变量
unsigned int smg_value1 = 0,smg_value2 =0; //数码管显示
//不带小数点段码
unsigned char code smg_data[18]={0xc0,0xf9,
    0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
    0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//带小数点段码
unsigned char code smg_data_dot[10]={0x40,0x79,
    0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

//简单延时
void delay(unsigned int t)
{
     while(t--);
}

//锁存器初始化
void Init_74HC138(unsigned char channel)
{
    switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
        P2 = (P2 & 0x1f) | 0x00;
}

//数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//操作所有数码管
void SMG_All(unsigned char dat)
{
     P0  = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}


//数码管数据显示
void SMG_Display_V(void)
{
    //光敏电压显示
     SMG_DisplayBit(0,smg_data_dot[smg_value1/100]);
     delay(200);
     SMG_DisplayBit(0,0xff);
     delay(200);
     SMG_DisplayBit(1,smg_data[smg_value1/10%10]);
     delay(200);
     SMG_DisplayBit(1,0xff);
     delay(200);
     SMG_DisplayBit(2,smg_data[smg_value1%10]);
     delay(200);
     SMG_DisplayBit(2,0xff);
     delay(200);
     SMG_DisplayBit(3,0xff);
     delay(200);
     SMG_DisplayBit(4,0xff);
     delay(200);
     //电阻电压显示
     SMG_DisplayBit(5,smg_data_dot[smg_value2/100]);
     delay(200);
     SMG_DisplayBit(5,0xff);
     SMG_DisplayBit(6,smg_data[smg_value2/10%10]);
     delay(200);
     SMG_DisplayBit(6,0xff);
     delay(200);
     SMG_DisplayBit(7,smg_data[smg_value2%10]);
     delay(200);
     SMG_DisplayBit(7,0xff);
     delay(200);
     SMG_All(0xff);
     delay(200);
}

//读取光敏数据
void Read_AD1(void)
{
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();    
    IIC_SendByte(0x01);
    IIC_WaitAck();
    IIC_Stop();
    
    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();    
    rd1_value = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    smg_value1 = rd1_value * (5.0/255) * 100;
}

//读取电阻数据
void Read_AD2(void)
{
     
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();    
    IIC_SendByte(0x03);
    IIC_WaitAck();
    IIC_Stop();
    
    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();    
    rd2_value = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    smg_value2 = rd2_value * (5.0/255) * 100;
}


//系统初始化
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}


//主函数
void main(void)
{
     Init_System();
    while(1)
    {
            Read_AD1();
            Read_AD2();
            SMG_Display_V();
    }
}

三、基于PCF8591的DAC模拟电压输出

#include "reg52.h"
#include "iic.h"


sbit S4 = P3^3;    //引脚定义
unsigned char mode = 1; //输出模式
unsigned int volt_value = 0,ad_value = 0;     //数码管显示电压、采样变量
//不带小数点段码
unsigned char code smg_data[18]={0xc0,0xf9,
    0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
    0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//带小数点段码
unsigned char code smg_data_dot[10]={0x40,0x79,
    0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};


//简单延时
void delay(unsigned int t )
{
     while(t--);
}

//锁存器初始化
void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
        P2 = (P2 & 0x1f) | 0x00;
}

//数码管安位操作
void  SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//操作所有数码管
void SMG_All(unsigned char dat)
{
     P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//数码管数据显示
void SMG_Display_Data(void)
{
     SMG_DisplayBit(0,0xbf);
     delay(200);
     SMG_DisplayBit(0,0xff);
     delay(200);
     SMG_DisplayBit(1,smg_data[mode]);
     delay(200);
     SMG_DisplayBit(1,0xff);
     delay(200);
     SMG_DisplayBit(2,0xbf);
     delay(200);
     SMG_DisplayBit(2,0xff);
     delay(200);
     SMG_DisplayBit(3,0xff);
     delay(200);
     SMG_DisplayBit(4,0xff);
     delay(200);
     SMG_DisplayBit(5,smg_data_dot[volt_value/100]);
     delay(200);
     SMG_DisplayBit(5,0xff);
     delay(200);
     SMG_DisplayBit(6,smg_data[volt_value/10%10]);
     delay(200);
     SMG_DisplayBit(6,0xff);
     delay(200);
     SMG_DisplayBit(7,smg_data[volt_value%10]);
     delay(200);
     SMG_DisplayBit(7,0xff);
     delay(200);
     SMG_All(0xff);
     delay(200);

}    

//PCF8591数据读取
void Read_ADC(void)
{
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    IIC_SendByte(0x43);
    IIC_WaitAck();
    IIC_Stop();

    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();
    ad_value = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    volt_value = ad_value * (5.0/255)* 100;
}

void Read_DAC(float dat)
{
     IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    IIC_SendByte(0x43);
    IIC_WaitAck();
    IIC_SendByte(dat);
    IIC_WaitAck();
    IIC_Stop();
}



//系统初始化
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}


//按键处理
void Key_Scans(void)
{
     if(S4 == 0)
    {
         delay(20);
        if(S4 == 0)
        {
             while(S4 == 0)
            {
                     SMG_Display_Data();
            }
            if(mode == 1)
            {
                 mode = 2;
            }
            else if(mode == 2)
            {
                 mode = 3;
            }
            else if(mode == 3)
            {
                mode = 1;
            }

        }
    }
}
//主函数
void main(void)
{
     Init_System();
    while(1)
    {
            Key_Scans();
            switch(mode)
            {
                 case 1:Read_DAC(102);volt_value = 2*100;break;
                case 2:Read_DAC(204);volt_value = 4*100;break;
                case 3:Read_ADC();Read_DAC(ad_value);break;
            }
            SMG_Display_Data();
    }

}

八,电压信号探测器

#include "reg52.h"
#include "iic.h"

sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

unsigned int adc_volt = 0,volt = 0;     //采集电压 和数码管显示变量
unsigned int param_volt = 300,alarm_count = 0;//电压参数 、计数参数
unsigned char alarm_flag = 0,flash_flag = 0;//报警标志 、闪烁标志
unsigned char led_stat = 0xff;    //led状态
unsigned int t_count = 0;//计时
unsigned char interface = 0;     //界面切换
unsigned char code smg_data[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80};
unsigned char code smg_data_dot[]={0xc0-0x80,0xf9-0x80,0xa4-0x80,0xb0-0x80,0x99-0x80,0x92-0x80,0x82-0x80,0xf8-0x80,0x80-0x80};
void delay(unsigned int t)
{
     while(t--);
}

void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break; 
    }
        P2 = (P2 & 0x1f) | 0x00; 
}

void SMG_All(unsigned char dat)
{
     P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}


void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}


void Read_ADC(void)
{
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    IIC_SendByte(0x03);
    IIC_WaitAck();
    IIC_Stop();

    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();
    adc_volt = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    //数据处理
    volt = adc_volt * (5.0/255)*100;
}


void SMG_Display_Data(void)
{
    SMG_DisplayBit(1,0xff);
    delay(200);
    SMG_DisplayBit(2,0xff);
    delay(200);
    SMG_DisplayBit(3,0xff);
    delay(200);
    SMG_DisplayBit(4,0xff);
    delay(200);
    if(interface == 0)
    {
            //U 1000 0011 0xc1
         SMG_DisplayBit(0,0xc1);
        delay(200);
        SMG_DisplayBit(5,smg_data_dot[volt/100]);
        delay(200);
        SMG_DisplayBit(6,smg_data[volt/10%10]);
        delay(200);
        SMG_DisplayBit(7,smg_data[volt%10]);
        delay(200);
    }
    else if(interface == 1)
    {
        //P 0011 0001 0x8c
        SMG_DisplayBit(0,0x8c);
        delay(200);
        SMG_DisplayBit(5,smg_data_dot[param_volt/100]);
        delay(200);
        SMG_DisplayBit(6,smg_data[param_volt/10%10]);
        delay(200);
        SMG_DisplayBit(7,smg_data[param_volt%10]);
        delay(200);
    }
    else if(interface == 2)
    {
         //S 
        SMG_DisplayBit(0,0x92);
        delay(200);
        SMG_DisplayBit(5,0xff);
        delay(200);
        if(alarm_count > 9)
        {
            SMG_DisplayBit(6,smg_data[alarm_count/10]);
            delay(200);
        }
        SMG_DisplayBit(7,smg_data[alarm_count%10]);
        delay(200);
    }
    SMG_All(0xff);
    delay(200);
}

void Key_Scans(void)
{
    //S4界面切换
     if(S4 == 0)
    {
         delay(20);
        if(S4 == 0)
        {
             while(S4 == 0)
            {
                SMG_Display_Data();
            }
                 if(interface == 0)
                {
                     interface = 1;
                }
                else if(interface == 1)
                {
                    interface = 2;
                }
                else if(interface == 2)
                {
                     interface = 0;
                }
            }
    }
    //电压参数减0.5v每次
    if(S5 == 0)
    {
         delay(20);
        if(S5 == 0)
        {
             while(S5 == 0)
            {
                 SMG_Display_Data();
            }
            if(interface == 1)
            {
                  param_volt -= 50; //扩大100倍 分别显示处理
                 if(param_volt == 0)//边界处理
                 {
                         //减到最小值后 变成最大
                        param_volt = 500;
                 }
            }
        }
    }

        //电压参数加0.5v每次
    if(S6 == 0)
    {
         delay(20);
        if(S6 == 0)
        {
             while(S6 == 0)
            {
                 SMG_Display_Data();
            }
            if(interface == 1)
            {
                  param_volt += 50; //扩大100倍 分别显示处理
                 if(param_volt == 500)//边界处理
                 {
                         //加到最大值后变成最小值
                        param_volt = 0;
                 }
            }
        }
    }
}

void Led_Tackle(void)
{
     if(volt < param_volt)
    {     
        if(alarm_flag == 0)
        {
             alarm_flag = 1; //报警标志
        }
    }
    else
    {
         alarm_flag = 0;
        flash_flag = 0;
        t_count = 0;
        alarm_count = 0;
        led_stat |= 0xff;
        P0 = led_stat;
        Init_74HC138(4);
    }
}
void Init_Timer(void)
{
     TMOD = 0x01;
    TH0  = (65535-50000)/256;
    TL0  = (65535-50000)%256;
    ET0  = 1;
    TR0  = 1;
    EA   = 1;
}
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}

void main(void)
{
      Init_System();
     Init_Timer();
     while(1)
     {
             Read_ADC();
            Key_Scans();
            SMG_Display_Data();
            Led_Tackle();
     }
}

void Server_Timer0() interrupt 1
{
     TH0  = (65535-50000)/256;
    TL0  = (65535-50000)%256;
    //启动报警
    if(alarm_flag == 1)
    {
         t_count++;
         if(t_count % 20 == 0) //1s
         {
                 //还未到达最值计数值
                if(alarm_count != 99)
                {
                     alarm_count++; 
                }
                //秒闪标志
                if(flash_flag == 1)
                {
                    if(led_stat & 0x80 == 0x80)
                    {    
                        led_stat &= (~0x80); //点亮L8
                    }
                    else
                    {
                         led_stat |= 0x80; //熄灭L8
                    }
                }
         }

         if(t_count > 120) //超过6s
         {
                led_stat &= (~0x07);  //点亮L1 L2 L 3
                flash_flag = 1;
         }
         else if(t_count > 80) //超过4s
         {
                led_stat &= (~0x03);
         }
         else if(t_count > 40) //超过2s
         {
                led_stat &= (~0x01); //L1亮
         }
         else
         {
                led_stat = 0xff;//关闭LED
         }
             P0 = led_stat;
             Init_74HC138(4);
    }    
}
#include "reg52.h"
#include "iic.h"

sbit S5 = P3^2;
sbit S4 = P3^3;
unsigned int temp = 0;
unsigned char led_stat = 0xff; //led 状态
unsigned char adc_volt= 0,old_volt = 0; //电压采集
unsigned int volt = 0;    //数码管显示电压
unsigned char old_grade = 0,grade = 0; //灯光等级
//0-9 段码
unsigned char code smg_data[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80};
//0.-9.段码
unsigned char code smg_data_dot[]={0xc0-0x80,0xf9-0x80,0xa4-0x80,0xb0-0x80,0x99-0x80,0x92-0x80,0x82-0x80,0xf8-0x80,0x80-0x80};

//简单延时
void delay(unsigned int t)
{
     while(t--);
}

//锁存器初始化
void Init_74HC138(unsigned char channel)
{
     switch(channel)
    {
         case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break; 
    }
        P2 = (P2 & 0x1f) | 0x00; 
}

//操作所有数码管

void SMG_All(unsigned char dat)
{
     P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}
//数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
     P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}


//数码管数据显示
void SMG_Display_V(void)
{
     SMG_DisplayBit(0,0xbf);
    delay(200);
    SMG_DisplayBit(1,smg_data[grade]);
    delay(200);
    SMG_DisplayBit(2,0xbf);
    delay(200);
    SMG_DisplayBit(3,0xff);
    delay(200);
    SMG_DisplayBit(4,0xff);
    delay(200);
    SMG_DisplayBit(5,smg_data_dot[volt/100]);
    delay(200);
    SMG_DisplayBit(6,smg_data[volt/10%10]);
    delay(200);
    SMG_DisplayBit(7,smg_data[volt%10]);
    delay(200);
    SMG_All(0xff);
    delay(200);
}


//读取光敏通道电压
void Read_ADC(void)
{
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    IIC_SendByte(0x01);
    IIC_WaitAck();
    IIC_Stop();
    SMG_Display_V();
    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();
    adc_volt = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    //数据处理
    volt = adc_volt * (5.0/255)*100;
    SMG_Display_V();
}




//灯光控制
void Led_Working(void)
{
     Read_ADC();
    //等级0 全部灯熄灭
    if(volt <= 500 && volt > 450)
    {
         grade = 0;
         led_stat = 0xff;
    }
    //等级1 L1 点亮
    else if(volt <= 450 && volt > 400)
    {
         grade = 1;
        led_stat = 0xfe;
    }
    //等级2  L1-L2 亮
    else if(volt <= 400 && volt > 350)
    {
        grade = 2;
         led_stat = 0xfc;
    }
    //等级3 L1-L3 亮
    else if(volt <= 350 && volt > 300)
    {
        grade = 3;
        led_stat = 0xf8;
    }

        //等级4 L1-L4 点亮
    else if(volt <= 300 && volt > 250)
    {
         grade = 4;
        led_stat = 0xf0;     
    }
    //等级5  L1- L5 亮
    else if(volt <= 250 && volt > 200)
    {
         grade = 5;
        led_stat = 0xe0;
    }
    //等级6 L1-L6 亮
    else if(volt <= 200 && volt > 150)
    {
        grade = 6;
        led_stat = 0xc0;  
    }
     //等级7 L1-L7 亮
    else if(volt <= 150 && volt > 100)
    {
         grade = 7;
        led_stat = 0x80; 
    }
    //等级8 L1-L8 亮
    else if(volt <= 50 && volt > 0)
    {
        grade = 8;
        led_stat = 0x00;;
    }

    P0 = led_stat;
    Init_74HC138(4);
}


//AT24C02处理
void Write_AT24C02(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();
}

//读AT24C02
unsigned int Read_AT24C02(unsigned char addr)
{
    IIC_Start();
    IIC_SendByte(0xa0);
    IIC_WaitAck();
    IIC_SendByte(addr);
    IIC_WaitAck();

    IIC_Start();
    IIC_SendByte(0xa1);
    IIC_WaitAck();
    temp = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    return temp;
}

//保存当前数据
void Save_To_24C02(void)
{
      Write_AT24C02(0x01,grade);
     SMG_Display_V();
     Write_AT24C02(0x02,volt);
     SMG_Display_V();
}


//读取历史数据
void Read_From_24c02(void)
{
        old_grade = Read_AT24C02(0x01);
        delay(500);
        old_volt = Read_AT24C02(0x02);
        delay(500);
        grade = old_grade;
        volt     = old_volt;
}
//按键处理
void Key_Scans(void)
{
     if(S4 == 0)
    {
         delay(20);
        if(S4 == 0)
        {
            Save_To_24C02();
             while(S4 == 0)
            {
                 Led_Working();
            }
            
        }
    }

    if(S5 == 0)
    {
        delay(20);
        if(S5 == 0)
        {
            //关闭所有灯光
             led_stat = 0xff;
            P0 = led_stat;
            Init_74HC138(4);
            //读取数据
            Read_From_24c02();
            while(S5 == 0)
            {
                  SMG_Display_V();    
            }

        }
    }
}
//系统初始化
void Init_System(void)
{
     P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
    SMG_All(0xff);
}



//主函数
void main(void)
{
    Init_System();
    while(1)
    {
    
         Led_Working();
         Key_Scans();
    }

}
#include "reg52.h"
#include "iic.h"

/******************************************************************
*第十三届蓝桥杯省赛软件部分实现                                      *
*Author:小殷童鞋                                                   *
*Date:2022-12-13                                                  *      
*******************************************************************/
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;

unsigned int f_count = 0,count = 0,period = 0;   //频率  显示频率  周期变量
unsigned char Rd_Data = 0,Rd_Volt = 0, channel = 1; //通道模拟数据 电压 和通道变量
unsigned char interface = 1;     //界面
unsigned int old_volt = 0,old_f = 0; //缓存电压和频率
unsigned char long_press_flag = 0,t_count = 0,press_count = 0; //长按标志 计时  长按次数变量
unsigned char led_flag = 1,led_status = 0xff,old_led_status = 0xff;//led启动标志 led状态 led旧状态变量
//共阳
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
                                 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf}; //数码管段码

unsigned char code smg_dot[] ={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //带小数点
//简单延时
void delay(unsigned int t)
{
    while(t--);
}
//744HC138初始化
void Init_74HC138(unsigned char dat)
{
    switch(dat)
    {
        case 4:P2 = (P2 & 0x1f) | 0x80;break;
        case 5:P2 = (P2 & 0x1f) | 0xa0;break;
        case 6:P2 = (P2 & 0x1f) | 0xc0;break;
        case 7:P2 = (P2 & 0x1f) | 0xe0;break;
        case 0:P2 = (P2 & 0x1f) | 0x00;break;
    }
    P2 = (P2 & 0x1f) | 0x00;
}

//数码管按位操作
void SMG_DisplayByBit(unsigned char pos,unsigned char dat)
{
    P0 = (0x01 << pos);
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//操作所有数码管
void Controal_All_SMG(unsigned char dat)
{
    P0 = 0xff;
    Init_74HC138(6);
    P0 = dat;
    Init_74HC138(7);
}

//数码管数据显示频率
void SMG_Display_Frequent(void)
{
    SMG_DisplayByBit(0,SMG_Duan[15]);
    delay(200);
    if(count > 999999)
    {
        SMG_DisplayByBit(1,SMG_Duan[count/1000000]);
        delay(200);
    }
    if(count > 99999)
    {
        SMG_DisplayByBit(2,SMG_Duan[count/100000%10]);
        delay(200);
    }
    if(count > 9999)
    {
        SMG_DisplayByBit(3,SMG_Duan[count/10000%10]);
        delay(200);
    }
    if(count > 999)
    {
        SMG_DisplayByBit(4,SMG_Duan[count/1000%10]);
        delay(200);
    }
    if(count > 99)
    {
        SMG_DisplayByBit(5,SMG_Duan[count/100%10]);
        delay(200);
    }
    
    if(count > 9)
    {
        SMG_DisplayByBit(6,SMG_Duan[count/10%10]);
        delay(200);
    }    
    SMG_DisplayByBit(7,SMG_Duan[count%10]);
    delay(200);
    Controal_All_SMG(0xff);
    delay(200);
    
}


//周期显示
void SMG_Display_Period(void)
{
    SMG_DisplayByBit(0,~0x37);
    delay(200);
    if(count > 999999)
    {
        SMG_DisplayByBit(1,SMG_Duan[period/1000000]);
        delay(200);
    }
    if(count > 99999)
    {
        SMG_DisplayByBit(2,SMG_Duan[period/100000%10]);
        delay(200);
    }
    if(count > 9999)
    {
        SMG_DisplayByBit(3,SMG_Duan[period/10000%10]);
        delay(200);
    }
    if(count > 999)
    {
        SMG_DisplayByBit(4,SMG_Duan[period/1000%10]);
        delay(200);
    }
    if(count > 99)
    {
        SMG_DisplayByBit(5,SMG_Duan[period/100%10]);
        delay(200);
    }
    
    if(count > 9)
    {
        SMG_DisplayByBit(6,SMG_Duan[period/10%10]);
        delay(200);
    }    
    SMG_DisplayByBit(7,SMG_Duan[period%10]);
    delay(200);
    Controal_All_SMG(0xff);
    delay(200);
    
}


//PCF8591电压采集
void PCF8591_Volt_Rd1(unsigned char channel)
{
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();
    if(channel == 1)
    {
        IIC_SendByte(0x01);    //光敏
    }
    else if(channel == 3)
    {
        IIC_SendByte(0x03);    //电压
    }
    IIC_WaitAck();
    IIC_Stop();
    
    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();
    Rd_Data = IIC_RecByte();
    IIC_SendAck(1);
    IIC_Stop();
    Rd_Volt = Rd_Data * (5.0/255)  * 100;    //扩大100倍方便显示    
}



//数码管电压显示数据
void SMG_Display_Volt(void)
{
    SMG_DisplayByBit(0,~0x3e);
    delay(200);
    SMG_DisplayByBit(1,0xbf);
    delay(200);
    SMG_DisplayByBit(2,SMG_Duan[channel]);       //通道编号
    delay(200);
    SMG_DisplayByBit(3,0xff);
    delay(200);
    SMG_DisplayByBit(4,0xff);
    delay(200);

    SMG_DisplayByBit(5,smg_dot[Rd_Volt/100]);    //电压
    delay(200);
    SMG_DisplayByBit(6,SMG_Duan[Rd_Volt/10%10]);
    delay(200);
    SMG_DisplayByBit(7,SMG_Duan[Rd_Volt%10]);
    delay(200);
    Controal_All_SMG(0xff);
    delay(200);    
}

//按键控制
void Key_Scans(void)
{
    if(S4 == 0)
    {
        delay(20);
        if(S4 == 0)
        {
            while(S4 == 0)
            {
                //在按键一直按下时 避免数码管熄灭  根据相应的界面显示相应的数据
                if(interface == 1)
                {
                    SMG_Display_Frequent();
                }
                else if(interface == 2)
                {
                    SMG_Display_Period();
                }
                else if(interface == 3)
                {
                    SMG_Display_Volt();                                                         
                }
            }
            if(interface == 1)
            {
                interface = 2;
            }
            else if(interface == 2)
            {
                interface = 3;
            }
            else if(interface == 3)
            {
                interface = 1;
            }
        }
    }
    
    if(interface == 3)
    {
        
        //S5通道切换
        if(S5 == 0)
        {
            delay(20);
            if(S5 == 0)
            {                
                while(S5 == 0)
                {
                    PCF8591_Volt_Rd1(channel);
                    SMG_Display_Volt();
                }
                if(channel == 1)
                      {
                        channel = 3;
                    }
                    else if(channel == 3)
                    {
                        channel = 1;
                    }
                
            }
        }
    }
    
    //S6缓存channel 电压
    if(S6 == 0)
    {
        delay(20);
        if(S6 == 0)
        {
            t_count = 0;
            long_press_flag = 0;

            while(S6 == 0)
            {
                //在按键一直按下时 避免数码管熄灭  根据相应的界面显示相应的数据
                if(interface == 1)
                {
                    SMG_Display_Frequent();
                }
                else if(interface == 2)
                {
                    SMG_Display_Period();
                }
                else if(interface == 3)
                {
                    SMG_Display_Volt();                                                         
                }
                
                if(long_press_flag == 1) //长按
                {
                    if(press_count == 0)
                    {
                        press_count = 1;
                        led_flag = 0;  //禁用LED 全部熄灭
                        old_led_status = led_status; //缓存Led状态
                        P0 = 0xff;
                        Init_74HC138(4);
                    }
                    else if(press_count == 1)
                    {
                        //恢复LED功能
                        press_count = 0;
                        led_status = old_led_status; //将缓存的LED状态重新赋值给led_status
                        led_flag = 1;                //启用LED功能
                    }
                    
                }
                else{
                    if(channel == 3)
                    {
                        old_volt = Rd_Volt;
                    }
                }
                
            }
            
        }
    }
    
    
    //S7缓存频率
    if(S7 == 0)
    {
        delay(20);
        if(S7 == 0)
        {
            while(S7 == 0)
            {
                //在按键一直按下时 避免数码管熄灭  根据相应的界面显示相应的数据
                if(interface == 1)
                {
                    SMG_Display_Frequent();
                }
                else if(interface == 2)
                {
                    SMG_Display_Period();
                }
                else if(interface == 3)
                {
                    SMG_Display_Volt();                                                         
                }
            }
            old_f = count;     //将实时采集的频率count的值缓存到old_f变量中
        }
    }
}

//定时器初始化
void Init_Timer(void)
{
    TMOD = 0x16;  //定时器0计数 定时器1定时
    TH0  = 0xff;
    TL0  = 0xff;
    TH1  = (65535 - 50000)/256;  //高八位50ms
    TL1  = (65535 - 50000)%256;    
    ET0  = 1;
    ET1  = 1;
    TR0  = 1;
    TR1  = 1;
    EA   = 1;
}

//系统初始化
void Init_System(void)
{
    Init_74HC138(0);
    Controal_All_SMG(0xff);
    P0 = 0xff;
    Init_74HC138(4);
    P0 = 0x00;
    Init_74HC138(5);
}


//主函数
void main(void)
{
    Init_System();          //系统初始化
    Init_Timer();           //定时器初始化
    while(1)
    {
        PCF8591_Volt_Rd1(channel);
        Key_Scans();
        switch(interface)
        {
            case 1:SMG_Display_Frequent();break;
            case 2:SMG_Display_Period();break;
            case 3:SMG_Display_Volt();break;
        }
        if(led_flag == 1)
        {
            if(old_volt < Rd_Volt) //L1 open
            {
                led_status =  0xfe;     //0111 1111
            }
            if(old_f < count)
            {
                led_status &= 0xfd;       //1011 1111
            }
            if(interface == 1)
            {
                led_status &= 0xfb;    //1101  1111
            }
            if(interface == 2)
            {
                led_status &= 0xf7;  //1110 1111
            }
            if(interface == 3)
            {
                led_status &= 0xef; //1111  0111
            }
            P0 = led_status;
            Init_74HC138(4);
        }
    }
}


void Timer0_Server() interrupt 1
{
    f_count++;
}

void Timer1_Server() interrupt 3
{
    static unsigned char t = 0;
    TH1  = (65535 - 50000)/256;  //高八位50ms
    TL1  = (65535 - 50000)%256;    
    t++;
    t_count++;
    if(t == 20)  //1s
    {
        count = f_count;
        period = (1.0/count) * 1000000;
        f_count = 0;
        t = 0;
    }
    if(t_count >= 20) //超过或等于1s
    {
        long_press_flag = 1;
    }
}
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值