蓝桥杯:模拟智能门锁

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
https://blog.csdn.net/xue11232/article/details/108281049?utm_medium=distribute.pc_category.none-task-blog-hot-18.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-18.nonecase&request_id=

方案一:

//主函数
#include <reg52.h>                     //用52头文件编程
#include <iic.h>                       //iic头文件
sfr P4=0xc0;                           //定义P4管脚
sbit C1=P3^0;                          //矩阵按键相关
sbit C2=P3^1;
sbit C3=P3^2;
sbit C4=P3^3;
sbit R1=P3^4;
sbit R2=P3^5;
sbit R3=P4^2;
sbit R4=P4^4;

unsigned char s16=0;                    //按键s16输入按键
unsigned char s12=0;                    //按键s12密码修改按键
unsigned char s8=0;                     //按键s8清除按键
unsigned char a1;                       //修改密码时的参数
unsigned char a2;
unsigned char a3;
unsigned char a4;
unsigned char a5;
unsigned char a6;

unsigned char b1=0;                      //
unsigned char b2=0;                      //输入完成的标志

unsigned char b3=0;                      //密码输入正确的标志
unsigned char b4=0;                      //密码输入错误的标志
unsigned char b5=0;                      //输入密码达到6位时的标志
unsigned char b6=0;                      //密码输入正确时,修改密码的标志

unsigned char c1=8;                      //读取上次存储密码第一位
unsigned char c2=8;                      //读取上次存储密码第二位
unsigned char c3=8;                      //读取上次存储密码第三位
unsigned char c4=8;                      //读取上次存储密码第四位
unsigned char c5=8;                      //读取上次存储密码第五位
unsigned char c6=8;                      //读取上次存储密码第六位

unsigned char c7;                        //首次上电的密码存储相关

unsigned char moshi=0;                   //显示的模式
unsigned char count_1;                   //中断计数
unsigned long mima=888888;
unsigned long mima_1=21;                 //密码第一位
unsigned long mima_2=21;                 //密码第二位
unsigned long mima_3=21;                 //密码第三位
unsigned long mima_4=21;                 //密码第四位
unsigned long mima_5=21;                 //密码第五位
unsigned long mima_6=21;                 //密码第六位

unsigned long mima_7=0;                  //密码错误时显示 原数
unsigned char num;                       //按键代表的数
unsigned char i;                         //选择第几位密码输入
unsigned char dat;                       //AT24C02写入的数据
unsigned char smg_buff[8];               //数码管缓存
unsigned char code SMG_Duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
                               0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0x8c,0x86,0xc8,0xff};
//数码管段选0 1 2 3 4 5 6 7 8 9 a b c d e f - . P E N 关闭

void Read_mima();
void Delay(unsigned int t)                 //延时函数
{
	while(t--);
}
void Init_system()                       //系统初始化函数
{
  P2=(P2 & 0x1f)|0x80;                   //关闭LED灯
	P0=0xff;
	
	P2=(P2 & 0x1f)|0xa0;                   //关闭继电器和蜂鸣器
	P0=0X00;
	P2=0x00;
}
//***********************************数码管显示基础函数***************************************
void Display_SMG(unsigned char value,unsigned char pos)
{
  P2=(P2 & 0x1f)|0xe0;
	P0=value;
	
	P2=(P2 & 0x1f)|0xc0;
	P0=0x01<<pos;
	P2=0x00;
}
void ALL_smg()                       //关闭所有数码管以防最后一个和其他亮度不一样
{
  P2=(P2 & 0x1f)|0xe0;
	P0=0xff;
	
	P2=(P2 & 0x1f)|0xc0;
	P0=0xff;
	P2=0x00;
}
void SMG_Display()
{
   Display_SMG(SMG_Duan[smg_buff[0]],0);
   Delay(500);
   Display_SMG(SMG_Duan[smg_buff[1]],1);
   Delay(500);
   Display_SMG(SMG_Duan[smg_buff[2]],2);
	Delay(500);
	Display_SMG(SMG_Duan[smg_buff[3]],3);
	Delay(500);
	Display_SMG(SMG_Duan[smg_buff[4]],4);
	Delay(500);
	Display_SMG(SMG_Duan[smg_buff[5]],5);
	Delay(500);
	Display_SMG(SMG_Duan[smg_buff[6]],6);
	Delay(500);
	Display_SMG(SMG_Duan[smg_buff[7]],7);
	Delay(500);
	//Display_SMG(0xff,0&1&2&3&4&5&6&7);
	ALL_smg();
	Delay(500);
	//***********************************************************************************
//********************************AT24C02写函数************************************

void Write_AT24C02Aadd(unsigned char addr,unsigned char dat)
{
  IIC_Start();
  Delay(1000);
  IIC_SendByte(0xa0);
  Delay(1000);
  IIC_WaitAck();
  Delay(1000);
  IIC_SendByte(addr);
  Delay(1000);
  IIC_WaitAck();
  Delay(1000);
  IIC_SendByte(dat);
  Delay(1000);
  IIC_WaitAck();
  Delay(1000);
  IIC_Stop();
  Delay(1000);
  //*****************************************************************************************
//*******************************AT24C02读函数*************************************
unsigned char Read_AT24C02_ADD(unsigned char addr)
{
  unsigned char temp;
  IIC_Start();
  Delay(1000);
  IIC_SendByte(0xa0);
  Delay(1000);
  IIC_WaitAck();
  Delay(1000);
  IIC_SendByte(addr);
  Delay(1000);
  IIC_WaitAck();
  
  IIC_Start();
  Delay(1000);
  IIC_SendByte(0xa1);
  Delay(1000);
  IIC_WaitAck();
  temp=IIC_RecByte();
  IIC_SendAck(1);
  IIC_Stop();
  
  return temp;

}
//**********************************************************************************
//***********************************矩阵按键函数*************************************
void Kry_stat()
{
   C1=0;C2=1;C3=1;C4=1;    //0 1 2 3
   if(R1==0)
   {
       Delay(500);
       if(R1==0)
       {
         num=3;i++;b1++;
       }
       while(R1==0)
       {
            SMG_Display();
       }
    }
    if(R2==0)
    {
      Delay(500);
      if(R2==0)
      {
        num=2;i++;b1++;
      }
      while(R2==0)
      {
        SMG_Display();
      }
    }
    if(R3==0)
    {
        Delay(500);
        if(R3==0)
        {
           num=1;i++;b1++;
        }
        while(R3==0)
        {
           SMG_Display();
        }
    }
    if(R4==0)
    {
      Delay(500);
      if(R4==0)
      {
         num=0;i++;b1++;
      }
      while(R4==0)
      {
         SMG_Display();
      }
    }
    C1=1;C2=0;C3=1;C4=1;        //4 5 6 7
    if(R1==0)
    {
      Delay(500);
      if(R1==0)
      {
        num=7;i++;b1++;
      }
      while(R1==0)
      {
         SMG_Display();
      }
    } 
    if(R2==0)
    {
        Delay(500);
        if(R2==0)
        {
            num=6;i++;b1++;
        }
        while(R2==0)
        {
           SMG_Display();
        }
    }
    if(R3==0)
    {
      Delay(500);
      if(R3==0)
      {
         num=5;i++;b1++;
      }
      while(R3==0)
      {
         SMG_Display();
      }
    }
    if(R4==0)
    {
        Delay(500);
        if(R4==0)
        {
            num=4;i++;b1++;
        }
        while(R4==0)
        {
           SMG_Display();
        }
    }
    C1=1;C2=1;C3=0;C4=1;       //    8 9  无效 无效
    if(R1==0)
    {
       Delay(500);
       if(R1==0)
       {
          
       }
       while(R1==0)
       {
          SMG_Display();
       }
    }
    if(R2==0)
    {
       Delay(500);
       if(R2==0)
       {
       
       }
       while(R2==0)
       {
          SMG_Display();
       }
    }
    if(R3==0)
    {
        Delay(500);
        if(R3==0)
        {
            num=9;i++;b1++;
        }
        while(R3==0)
        {
          SMG_Display();
        }
        
    }
    if(R4==0)
    {
       Delay(500);
       if(R4==0)
       {
          num=8;i++;b1++;
       }
       while(R4==0)
       {
          SMG_Display();
       }
    }
     C1=1;C2=1;C3=1;C4=0;         //无效 清除 修改 输入
     if(R1==0)
     {
         Delay(500);
         if(R1==0)
         {
             s16++;i=0;Read_mima();
         }
         while(R1==0)
         {
              SMG_Display();
         }
     }
     if(R2==0)
     {
       Delay(500);
       if(R2==0)
       {
          s12++;i=0;
       }
       while(R2==0)
       {
          SMG_Display();
       }
     }
     if(R3==0)
	{
	  Delay(500);
		if(R3==0)
		{
		  s8++;
		}
		while(R3==0)
		{
		  SMG_Display();
		}
	}
	if(R4==0)
	{
	  Delay(500);
		if(R4==0)
		{
		  
		}
		while(R4==0)
		{
		  SMG_Display();
		}
	}	
}
}
}
//***********************************************************************
//********************************按键处理函数***************************
void Key_Dispose()
{
    if(s16>=1)
    {
        moshi=1;
        switch(i)
        {
           case 1:
                  mima_1=num;a1=mima_1;
                  break;
           case 2:	
                  mima_2=a1;
                  mima_1=num;a2=mima_1;
                  break; 
           case 3:
                  mima_3=a1;mima_2=a2;mima_1=num;a3=mima_1;
                  break;
            case 4:
                   mima_4=a1;mima_3=a2;mima_2=a3;mima_1=num;a4=mima_1;
                   break;
             case 5:
				   mima_5=a1;mima_4=a2;mima_3=a3;mima_2=a4;mima_1=num;a5=mima_1;
			       break;
			
			case 6:
				  mima_6=a1;mima_5=a2;mima_4=a3;mima_3=a4;mima_2=a5;mima_1=num;b2=1;
		       	  break;          
        }
        if(i>=7) i=0;
    }
}
//*****************************************************************************
//**********************************数据处理函数********************************
void Stat_Dispose()
{
   if(s8==1)
   {
		s8=0;
	    i=0;
		mima_1=21;
	  	mima_2=21;
	  	mima_3=21;
	  	mima_4=21;
	  	mima_5=21;
		mima_6=21;
   }
}
 if(b2==1)
 {
    mima_7=mima_6*100000+mima_5*10000+mima_4*1000+mima_3*100+mima_2*10+mima_1;
    if(c1==mima_1 && c2==mima_2 && c3==mima_3 && c4==mima_4 && c5==mima_5 && c6==mima_6)
    {
        moshi=2;
        s16=0;
        P2=(P2 & 0x1f)|0xa0;
        P0=0x10;
        P2=0x00;
        b3=1;
        s12=0;
        b2=0;
        mima_1=21;
        mima_2=21;
        mima_3=21;
        mima_4=21;
        mima_5=21;
         mima_6=21;
    }
    else
    {
       moshi=3;
       s16=0;
       P2=(P2 & 0x1f)|0x80;
       P0=0XFE;
       P2=0x00;
       b4=1;
       b2=0;
       
    }
    i=0;
    
 }
 if(moshi==1)
 {
    P2=(P2 & 0x1f)|0x80;
    P0=0xbf;
    P2=0x00;
 }
 if(moshi==0)
 {
     P2=(P2 & 0x1f)|0x80;
     P0=0xff;
     P2=0x00; 
 }
 if(moshi==4)
 {
     P2=(P2 & 0x1f)|0x80;
     P0=0x7f;
     P2=0x00;
}
//*******************************************************************************
//******************************密码修改函数**************************************
void xiugai()
{
   if(b3==1)
   {
        if(s12>=1)
        {
            b3=0;
			b6=1;
			i=0;
        }
   }
   if(b6==1)
   {
      
   }
}

方案二:

timer.c
#include <timer.h>

void Timer0Init(void)  //1毫秒@11.0592MHz
{
 AUXR |= 0x80;  //定时器时钟1T模式
 TMOD &= 0xF0;  //设置定时器模式
 TL0 = 0xCD;  //设置定时初值
 TH0 = 0xD4;  //设置定时初值
 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[16]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,
 0XF8,0X80,0X90,0XBF,0XFF,0XC6,0X86,0XC8,0X8C}; 

//10:-  11:灭  12:C  13:E  14:N  15:P
unsigned char dspbuf[8];

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;
}

keybord.c

#include <keybord.h>
unsigned char i,key_value,key_press,key_sum=0;

void key_read(void)
{

}

AT24C02模块

AT24C01/02/04/08/16是一个1K/2K/4K/8K/16K位(AT24C02大小为256字节)串行CMOS E2PROM内部含有128/256/512/1024/2048个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗AT24C01有一个8字节页写缓冲器 AT24C02/04/08/16有一个16字节页写缓冲器该器件通过I2C总线接口进行操作有一个专门的写保护功能。

2、AT24C02特性

①、与 400KHz I2C 总线兼容
  ②、1.8 到 6.0 伏工作电压范围
  ③、低功耗 CMOS 技术
  ④、写保护功能 当 WP 为高电平时进入写保护状态
  ⑥、页写缓冲器
  ⑦、自定时擦写周期
  ⑧、1,000,000编程/擦除周期
  ⑨、可保存数据100年

硬件原理图

在这里插入图片描述

管脚描述

在这里插入图片描述
A0、A1、A2、三个脚不同的电平可以形成不同的地址,最多8种。原理图中A0、A1、A2、三个脚全部接地,也就是硬件决定不可更改,默认为A0=0、A1=0、A2=0。同时写保护脚WP(原理图中为HOLD),也是接地。因此默认也是关闭写保护的。

从器件地址

在这里插入图片描述

  1. A0、A1和A2对应器件的管脚1、2和3
  2. P0、P1、P2对应存储阵列地址字地址。
  3. R/W为读写方向位,1为读,0为写。

对应AT24C02硬件原理图而言,A0、A1、A2、三个脚被硬件接地,即A0=0、A1=0、A2=0。所以AT24C02读地址为1010 0001(0xA1),AT24C02写地址为1010 0000(0xA0)。

这里再简单的介绍一下P0、P1、P2的含义,对于AT24C02而言大小为256字节,而对于AT24C08而言大小为1024(4*256)字节。假如P0=0、P1=0,即代表选中第一个256字节的首地址,P0=0、P1=0,即代表选中第一个256的首地址,P0=1、P1=0,即代表选中第二个256的首地址,以此类推。

写周期限制

写周期时间是指从一个写时序的有效停止信号到内部编程/擦除周期结束的这一段时间。在写周期期间,总线接口电路禁能,SDA保持为高电平,器件不响应外部操作。
  简单的说就是,当向AT24C02执行写操作时,从发出写命令到写完成最多10ms。因此在写程序时,每次写操作后都延迟10ms以保证稳定。

读写操作时序

向指定地址写一个字节
在这里插入图片描述

*
函数功能:向AT24c02指定地址写一字节数据
*/
void At24c02_Write_OneByte(u8 addr,u8 data)
{
  IIC_Start();
  IIC_Write_Byte(At24c02_Write_Addr);//发送写地址0XA0
  if(IIC_Check_Ack())return ;
  IIC_Write_Byte(addr);
  if(IIC_Check_Ack())return ;
  IIC_Write_Byte(data);
  if(IIC_Check_Ack())return ;
  IIC_Stop();
  delay_ms(10);//确保写完成
}

向指定地址开始读数据

在这里插入图片描述

*
函数功能:向AT24c02指定地址开始读数据
*/
void At24c02_Read_Data(u8 addr,u8 *data,u8 len) 
{
 u8 i=0;
  IIC_Start();
  IIC_Write_Byte(At24c02_Write_Addr);//发送写地址0XA0
  if(IIC_Check_Ack())return ;
  IIC_Write_Byte(addr);//写数据的地址
  if(IIC_Check_Ack())return ;
  IIC_Start();
  IIC_Write_Byte(At24c02_Read_Addr);//发送读地址0XA1
  if(IIC_Check_Ack())return ;
  for(i=0;i<len;i++)
  {
   data[i]=IIC_Read_Byte();
   if(i==len-1)IIC_Send_Ack(1);
   else IIC_Send_Ack(0);
  }
  IIC_Stop(); 
}

页写

在这里插入图片描述
用页写 AT24C01可一次写入8个字节数据 AT24C02/04/08/16可以一次写入16个字节的数据,页写操作的启动和字节写一样,不同在于传送了一字节数据后并不产生停止信号,主器件被允许发送停止信号P,AT24C01 P=7,AT24C02/04/08/16 P=15个额外的字节,每发送一个字节数据后AT24C01/02/04/08/16 产生一个应答位并将字节地址低位加1,高位保持不变。如果在发送停止信号之前主器件发送超过P+1个字节地址计数器将自动翻转,先前写入的数据被覆盖。
  简单的说,AT24C01一页为8字节,AT24C01/02/04/08/16为16字节。对于AT24C02而言,在一页内,每写一个字节写指针+1,当大于16字节时,又回到第一个字节的位置,先前写入的数据将会被覆盖。

/*
函数功能:对AT24C02指定地址页内写数据
*/
void At24c02_Write_Page(u8 addr,u8 *data,u8 len)
{
  u8 i=0;
  IIC_Start();
  IIC_Write_Byte(At24c02_Write_Addr);//发送写地址0XA0
  if(IIC_Check_Ack())return ;
  IIC_Write_Byte(addr);//写数据的地址
  if(IIC_Check_Ack())return ;
  for(i=0;i<len;i++)
  {
   IIC_Write_Byte(*data++);/
   if(IIC_Check_Ack())return ;
  }
  IIC_Stop();
  delay_ms(10);
}

向指定地址跨页写数据

/*
函数功能:对AT24C02指定地址跨页写数据
*/
void At24c02_Write_Data(u8 addr,u8 *data,u8 len)
{
  u8 write_len=16-addr%16;//起始页剩下的空间
  if(write_len>len)write_len=len;
  while(1)
  {
   At24c02_Write_Page(addr,data,write_len);
   if(write_len==len)break;
   addr+=write_len;
   data+=write_len;
   len-=write_len;
   if(len>16)write_len=16;
   else write_len=len;
  }
}

型号是AT24C02的EEPROM分为32页,每一页可以存储8个字节的数据,若在同一页写入超过8字节,则超过的部分会被写在该页的起始地址(也就是一开始写好的部分会被覆盖).
为了把连续的缓冲区数组按页写入到 EEPROM,就需要对缓冲区进行分页处理.I2C_EE_BufferWrite()是根据输入的缓冲区大小参数 NumByteToWrite,计算出需要写入多少页,计算写入位置。
分页处理好之后,调用 I2C_EE_PageWrite(),这个函数是与 EEPROM进行I2C通讯的最底层函数(里面都是调用STM32库函数)
EEPROM写入 I2C_EE_BufferWrite();


u8 I2c_Buf_Write[256]; 
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite) 
{
  u8 NumOfPage = 0,NumOfSingle = 0,Addr =0,count = 0;
  /*计算出要写的页数和分页*/
  Addr = WriteAddr % I2C_PageSize;
  count = I2C_PageSize - Addr;
  NumOfPage = NumByteToWrite / I2C_PageSize;
  if(Addr == 0)
  {
    if(NumOfPage == 0)
    {
      I2C_EE_PageWrite(pBuffer,WriteAddr,NumOfSingle);
      I2C_EE_WaitEepromStandbyState(); //检测是否为Standby状态,才可以进行下一步操作
    }
    else
    {
       while(NumOfPage--)
       {
         I2C_EE_PageWrite(pBuffer,WriteAddr,I2C_PageSize);
         I2C_EE_WaitEepromStandbyState();
         WriteAddr += I2C_PageSize;
         pBuffer += I2C_PageSize;
       }
       if(NumOfSingle!=0)
       {
          I2C_EE_PageWrite(pBuffer,WriteAddr,NumOfSingle);
          I2C_EE_WaitEepromStandbyState();
       }
    }
  }
  else
  {
     if(NumOfPage == 0)
     {
       I2C_EE_PageWrite(pBuffer,WriteAddr,NumOfSingle);
       I2C_EE_WaitEepromStandbyState();
       
     }
     else
     {
       NumByteToWrite -= count;
       NumOfPage = NumByteToWrite / I2C_PageSize;
       NumOfSingle = NumByteToWrite % I2C_PageSize;
       if(count != 0)
       {
         I2C_EE_PageWrite(pBuffer,WriteAddr,count)
         I2C_EE_WaitEepromStandbyState();
         WriteAddr += count;
         pBuffer += count;
       }
               while(NumOfPage--)
        {
            I2C_EE_PageWrite(pBuffer,WriteAddr,I2C_PageSize);
            I2C_EE_WaitEepromStandbyState();
            WriteAddr += I2C_PageSize;
            pBuffer += I2C_PageSize;
        }

        if(NumOfSingle != 0)
        {
            I2C_EE_PageWrite(pBuffer,WriteAddr,NumOfSingle);
            I2C_EE_WaitEepromStandbyState();
        }
     }
  }
}

这里每次调用完 I2C_EE_PageWrite()后,都调用了一个I2C_EE_WaitEepromStandbyState();

void I2C_EE_WaitEepromStandbyState(void)
{
  vu16 SR1_Tmp = 0;
   do
    {
        I2C_GenerateSTART(I2C1, ENABLE);

        SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);

        I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
    }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));

    I2C_ClearFlag(I2C1, I2C_FLAG_AF);

    I2C_GenerateSTOP(I2C1, ENABLE);
}

这里是利用了 EEPROM在接收完数据后,启动了周期写入数据的时间内不会对主机的请求做出应答的特性,利用这个库函数循环发送起始信号,若检测到 EEPROM的应答,则说明 EEPROM已经完成上一步的数据写入,进入了Standby状态,可以进行下一步操作。

EEPROM进行I2C通讯的最底层函数I2C_EE_PageWrite()

void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite) 
{
  //确保SDA总线空闲时再做I2C通讯/ 
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
  //产生I2C的通讯起始信号S。
  I2C_GenerateSTART(I2C1, ENABLE);
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
  //把前面条件变异中赋值的变量 EEPROM_ADDRESS 地址通过I2C1接口发送出去,数据传输方向为ST32的 I2C发送数据
  //这里的 EEPROM_ADDRESS 地址是 EEPROM作为挂载在I2C总线上设备的寻址,并不是 EEPROM 内存存储矩阵的地址
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
//这里把数据传输到数据寄存器,再由I2C模块根据I2C协议发送出去,但是要注意这里的输入参数是WriteAddr,根据EEPROM的页写入时序,发送I2C的地址后的第一个数据,并不一定要写入EEPROM的数据,EEPROM的数据解释为将要对存储矩阵写入的地址,WRiteAddr是在I2C_EE_PageWrite()函数时作为参数输入的,在这个实列是由I2C_EE_BufferWrite()计算出来的.
I2C_SendData(I2C1, WriteAddr);
while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

while(NumByteToWrite--)
{
    //这里是向 EEPROM发送要写如的数据,根据 EEPROM 的页写入时序,这些数据被写入到前面发送的页地址中,如果连续写入超过一页的最大字节数(这里是8个),则多出来的数据会重新从该页的起始地址连续写入,覆盖前面的数据.
    I2C_SendData(I2C1, *pBuffer);

    pBuffer++;

    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMIT)TED));
}
//产生I2C的传输结束信号,完成一次I2C通讯.
I2C_GenerateSTOP(I2C1, ENABLE);

}

I2C事件检测:

在 I2C_EE_PageWrite里面还有很多的事件检测,这些都是必须的,根据STM32参考手册的序列图可以看到,在I2C的通讯过程中,会产生一系列的事件,出现时间后相应的寄存器中会产生标志位.

这个 EEPROM 的页写入就是根据 EEPROM的页写入时序来写的:
在这里插入图片描述
在 I2C_EE_PageWrite()函数中,先不管while语句的循环检测,就可以很清晰的看到整个代码流程就是 EEPROM 的页写入时序流程

https://blog.csdn.net/linzhihan7410/article/details/52099051?biz_id=102&utm_term=i2cWriteBuffer&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-2-52099051&spm=1018.2118.3001.4449

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值