51+stm32标准库+软件iic+24c02(EEPROM)驱动

EEPROM

EEPROM包括

iic总线;51单片机没有iic总线,软件模拟实现iic;根据时序,依次包括iic起始,终止,应答,非应答,等待应答,单个字节写入;单个字节数据读取,

at24c02;包括数据写入,数据读取;写入时序,读取时序

iic

iic总线时序

根据下图可知,最小延时时间在0.6us,因此下面延时大于0.6us即可

在这里插入图片描述

typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;
/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
	while(ten_us--);	
}

/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ms:ms延时时间
* 输    出    	 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
	u16 i,j;
	for(i=ms;i>0;i--)
		for(j=110;j>0;j--);
}

iic起始终止

代码采用模块化思想;将重复使用的起始过程;终止过程;应答等待;字节写;字写读;封装成函数;并且整体装到iic.c里;通过iic.h来调用;

在这里插入图片描述

首先是起始信号函数;void iic_start(),终止信号函数void iic_stop()

//51单片机没有iic总线;因此使用软件模拟iic总线
sbit IIC_SDA= P2^0;
sbit IIC_SCL= P2^1;

//IIC起始信号    SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号;
void iic_start()
{   
    IIC_SDA=1; 	
    delay_10us(1);
    
    IIC_SCL=1;
    delay_10us(1); //起始SCL,SDA高电平延时10us
    
    IIC_SDA=0;
    delay_10us(1); //拉低SDA,形成起始信号延时10us   
    
    IIC_SCL=0;     //SCL高电平数据稳定,低电平可写入数据
    delay_10us(1);
}

//iic结束信号    SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。
void iic_stop()
{  
    IIC_SDA=0;
    delay_10us(1);
    
    IIC_SCL=1;
    delay_10us(1); //结束信号初始电平SCL高电平,SDA低电平
    
    IIC_SDA=1;
    delay_10us(1);  
    //sda和scl都为高电平,释放iic总线
}

iic应答/非应答时序

在这里插入图片描述

接收器拉低SDA线表示应答,并在应答脉冲期间保持稳定的低电平。当主器件作接收器时,必须发出数据传输结束的信号给发送器,即它在最后一个字节之后的应答脉冲期间不会产生应答信号(不拉低SDA)。这种情况下,发送器必须释放SDA线为高以便主器件产生停止条件。

//iic   应答   从机SDA低电平;主机SCL  低电平>高>低
void iic_ack()
{
    IIC_SCL=0;
    IIC_SDA=0; 
    delay_10us(1);
    IIC_SCL=1; 
    delay_10us(1);
    IIC_SCL=0;   
}

//iic非应答    从机SDA高电平;主机SCL  低电平>高>低
void iic_noack()
{
    IIC_SCL=0;
    IIC_SDA=1; 
    delay_10us(1);
    IIC_SCL=1; 
    delay_10us(1);
    IIC_SCL=0; 
    
}

// :iic 应答等待
u8 iic_wait_ack()
{
    u8 time_wait=0;
    IIC_SCL=1;
    //IIC_SDA=1;//保SDA产生应答信号前处于高电平;若发数据最后一位为低电平;则可能会造成没有应答而主机认为从机已应答的情况;在应答等待中置为高电平或者在
    delay_10us(1);
    while(IIC_SDA)
    {
        time_wait++;
        if(time_wait>100)
        {
            iic_stop();
            return 1;
        }    
    }
     IIC_SCL=0;
     return 0;  
}

iic字节读写操作

在这里插入图片描述

void iic_write_byte(u8 dat)
{   
        u8 i=0;
        IIC_SCL=0;
        for(i=0;i<8;i++)
        {
            if((dat&0x80)>0)//判断最高位是否为1;为1写入1;为0写入0
            {
                IIC_SDA=1;
            }
            else
            {
                IIC_SDA=0;
            }
            dat<<=1;
            delay_10us(1);
            
            IIC_SCL=1;  //数据稳定
            delay_10us(1);
            
            IIC_SCL=0;  //下一次写入  
            delay_10us(1);             
        }
        
        IIC_SDA=1;      //拉高数据总线SDA电平,释放IIC总线//防止
        delay_10us(1); 

    
}
iic字节读
u8 iic_read_byte(u8 ack)
{
        u8 i=0;
        u8 receive=0;
        for(i=0;i<8;i++)
        {
            IIC_SCL=0;
            delay_10us(1);
            IIC_SCL=1;
            receive<<=1;
            if(IIC_SDA)receive++;   
            delay_10us(1); 
        }					 
        if (!ack)
        { 
            iic_noack();
        }
        else
        {
            iic_ack();  
        } 
        return receive;
}

AT24C02

在这里插入图片描述

/*******************************************************************************
* 函 数 名         : at24c02_write_one_byte
* 函数功能		   : 在AT24CXX指定地址写入一个数据
* 输    入         : addr:写入数据的目的地址 
					 dat:要写入的数据
* 输    出         : 无
*******************************************************************************/
void at24c02_write_one_byte(u8 addr,u8 dat)
{	   	  	    																 
   	iic_start();
    
    iic_write_byte(0XA0);   //打开写入开关
    iic_wait_ack();         //等待应答
    iic_write_byte(addr);   //发送地址
    iic_wait_ack(); 	
    iic_write_byte(dat);    //发送1个byte数据;
    iic_wait_ack();  
    iic_stop();             //停止
    delay_ms(10);
}

在这里插入图片描述

/*******************************************************************************
* 函 数 名         : at24c02_read_one_byte
* 函数功能		   : 在AT24CXX指定地址读出一个数据
* 输    入         : addr:开始读数的地址 
* 输    出         : 读到的数据
*******************************************************************************/
u8 at24c02_read_one_byte(u8 addr)
{				  
	u8 temp=0;  
    iic_start();
    iic_write_byte(0XA0);   //打开写入开关
    
    iic_wait_ack();         //等待应答
    
    iic_write_byte(addr);   //发送地址
    
    iic_wait_ack();
    
    iic_start();     
    
    iic_write_byte(0XA1);   //打开读
    
    iic_wait_ack();	        //等待应答
    
    temp=iic_read_byte(0);
    iic_stop();             //停止
	return temp;			//返回读取的数据  
}

数码管

数码管:连接74hc1380译码器;
数码管分共阴极共阳极段码;

//共阴极数码管显示0~F的段码数据
gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};	

74hc138译码器

​ 数码管共阴极;也就是负极连着74hc138;也就是说将Y0—Y7;赋予低电平即可点亮数码管;查看其真值表;可通过控制三个针脚控制8个输出针脚,

在这里插入图片描述

#define SMG P0	//使用宏定义数码管段码口

//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

//数码管位段选择
void smg(u8 wei,u8 duan)
{
  
    switch(wei)
    {
        case 0: LSC=1;LSB=1;LSA=1;break;//  LED 8
		case 1: LSC=1;LSB=1;LSA=0;break;//  LED 7
		case 2: LSC=1;LSB=0;LSA=1;break;//  LED 6
		case 3: LSC=1;LSB=0;LSA=0;break;//  LED 5
		case 4: LSC=0;LSB=1;LSA=1;break;//  LED 4
		case 5: LSC=0;LSB=1;LSA=0;break;//  LED 3
		case 6: LSC=0;LSB=0;LSA=1;break;//  LED 2
		case 7: LSC=0;LSB=0;LSA=0;break;//  LED 1
    } 
	SMG=gsmg_code[duan];//传送段选数据
	delay_10us(100);//延时一段时间,等待显示稳定
	//SMG=0x00;//消影    
}

原理图

在这里插入图片描述

独立按键和矩阵按键

按键检测的最佳防抖时间10ms

独立按键检测

//mode为0时连续检测,为1非连续

u8 Key_4Scan(u8 mode)
{
   static u8 key=1;

	if(mode)key=1;//连续扫描按键
	if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下
	{
		delay_10us(1000);//消抖
		key=0;
		if(KEY1==0)
			return KEY1_PRESS;       //1
		else if(KEY2==0)
			return KEY2_PRESS;       //2
		else if(KEY3==0)
			return KEY3_PRESS;       //3
		else if(KEY4==0)
			return KEY4_PRESS;	     //4   
	}
	else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)	//无按键按下
	{
		key=1;			
	}
	return KEY_UNPRESS;	//0	
}

矩阵按键检测——线翻转

u8 key_matrix_flip_scan(void)
{
	 static u8 key_value=0;
	KEY_MATRIX_PORT=0xff;

	KEY_MATRIX_PORT=0x0f;//给所有行赋值0,列全为1
	if(KEY_MATRIX_PORT!=0x0f)//判断按键是否按下
	{
		delay_10us(1000);//消抖
		if(KEY_MATRIX_PORT!=0x0f)
		{
			//测试列
			KEY_MATRIX_PORT=0x0f;
			switch(KEY_MATRIX_PORT)//保存行为0,按键按下后的列值	
			{
				case 0x07: key_value=0;break;
				case 0x0b: key_value=1;break;
				case 0x0d: key_value=2;break;
				case 0x0e: key_value=3;break;
			}
			//测试行
			KEY_MATRIX_PORT=0xf0;
			switch(KEY_MATRIX_PORT)//保存列为0,按键按下后的键值	
			{
				case 0x70: key_value=key_value;break;
				case 0xb0: key_value=key_value+4;break;
				case 0xd0: key_value=key_value+8;break;
				case 0xe0: key_value=key_value+12;break;
			}
			while(KEY_MATRIX_PORT!=0xf0);//等待按键松开	
		}
	}
	else
		key_value=17;		
	
	return key_value;		
}

EEPROM+SMG+独立按键+矩阵按键 实现简单密码锁

主函数

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

//初始显示0闪;输入密码解锁;key1按键确认,错误显示;三次后闪倒计时;   

独立按键:k1,确认输入;输入密码后;若正确,左数码管1,4,显示0,错误显示ff 
按键k3修改密码(若输入密码与之前相同,继续输入,若不同则退出),k2退出,此时需要再次输入密码

k2取消输入;k3,需要在输入密码后(解锁之后)更改密码;k4清除密码(复位)//将密码恢复至原始密码——00000000,即数组

矩阵按键1-16作为输入键输出0-f
*/

#include"public.h"
#include"SMG.h"
#include"KEY.h"
#include"IIC.h"
#include"AT24C02.h"

u8 ff=0;
u8 read[]={0,0,0,0,0,0,0,0};//读取数据的数组
u8 dat[]={0,0,0,0,0,0,0,0}; //数据写入数组

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

判断输入是否相同,相同返回1,不同返回0;
*//*/*/

bit compare_arrays() 
{
    u8 i=0;
    for ( i = 0;i<8; i++) 
    {
        if (read[i] != dat[i]) 
        {
            return 0;
        }
    }
    return 1;
}
/*/**********************************************
   函数名:at24c02_write_page(u8 dat[])
   功能: 连续写入8个bit,1页到数组dat
   输入:dat[8]
   输出:全局变量的数组dat[];
/************************************************/
void at24c02_write_page()//
{
    u8 x=0;
    for(x=0;x<8;x++)
    {
        at24c02_write_one_byte(x,dat[x]);
    } 
}

/*/**************************************************
   函数名:at24c02_read_page()
   功能: 连续读取8个bit,1页到数组dat
   输入:  无
   输出:全局变量的数组reda[];
/****************************************************/

void at24c02_read_page()
{
    u8 r=0;
    for(r=0;r<8;r++)
    {
        read[r]=at24c02_read_one_byte(r);    
    }   
}
  



//串口调试函数
//
//    void uart_init(u8 baud)
//    {
//        TMOD|=0X20; //设置计数器工作方式2
//        SCON=0X50; //设置为工作方式1
//        PCON=0X80; //波特率加倍
//        TH1=baud; //计数器初始值设置
//        TL1=baud;
//        ES=1; //打开接收中断
//        EA=1; //打开总中断
//        TR1=1; //打开计数器
//    }


void k16_one_scanf()//依次键入函数
{
    u8 i=0;
	u8 key=0;       //矩阵按键返回0-15
    key=key_matrix_flip_scan(); //返回值0-15
    if(key!=17) 
        {
            for(i=0;i<8;)
            {
                if(key!=17)
                {
                    dat[i]=key;    
                    smg(i,dat[i]);
                }
                    key=key_matrix_flip_scan(); //返回值0-f
                    if(key!=17)
                    {
                        i++;
                    } 
            }
        }       
}
/*/**************************************************
   函数名:confirmInput()
   功能: k1按键确认输入;并将值与eeprom中储存的值比较(reda[])若相同smg输出0;不同输出频闪11111111
   输入: dat[]
   输出:  
/****************************************************/

void changePassword();//重置密码函数声明
void confirmInput()
    
{    
    u8 key4=0;
    u8 i=0;
    bit a=1;
    at24c02_read_page();//读取eeprom中储存的数//存到read[]中 

    if(compare_arrays())
    {   
        at24c02_write_page(); 
        smg(3,10);
        delay_ms(1000);
        while(a)
        {
            key4=Key_4Scan(0);//无按键返回0,有按键1-4
            if(key4==2)
            {  
                for(i=0;i<8;i++)
                {
                    dat[i]=0;
                }
                a=0;break;
                
            }//按下k2返回
            
            if(key4==3)      //按下k3重置密码
            {
                smg(3,11);
                 a=0;
                changePassword();
                delay_ms(1000);
                
               
            }
            smg(3,0);
          
               
     
        }  
    }
    {ff++;
    if(ff==3)
    {
     while(ff)
     {  
        smg(ff--,15);
        delay_ms(2000);
        
     }  
    }
    }
}

//void cancelInput()
//{
//    
//}

//******************************************************************************按键检测没有一直在循环里
void changePassword()
{   

    u8 a=0;
    u8 i=0;
    u8 key4=0;
    bit x=1;
    while(x)
    {
        smg(3,12);
        k16_one_scanf();
        a=compare_arrays();
        key4=Key_4Scan(0);//无按键返回0,有按键1-4
        if(key4==2)x=0;//如果按键按了2,回退到确认函数;
        if(key4==1)
        {
            //输完需要再次确认键()
            if(!a)//判断是否与原密码相同相同重新输入
            {
                at24c02_write_page(); 
                smg(1,0);
                x=0;
                //数组只能在定义的时候才可以dat[]={0,0,0,0};之后只能一个一个赋值
                for(i=0;i<8;i++)
                {
                    dat[i]=0;
                }
                delay_ms(1000);

            }
        }
    }
    
    
    
}
void resetPassword()
{
    u8 i=0;
      for(i=0;i<8;i++)
            {
                dat[i]=0;
               
            }
     at24c02_write_page(); 

          delay_ms(2000);
}


void main()
{	

     u8 key=0;  //独立按键返回1-4
    //uart_init(0xfa);  //9600
	while(1)
	{ 
         //if(key!=17)SBUF=key;   
         //delay_ms(1000);
         k16_one_scanf();
        //初始化显示12,45,为0
         smg(0,0);
         smg(1,0);
         smg(4,0);
         smg(5,0);
         key=Key_4Scan(0);//无按键返回0,有按键1-4
         switch(key)
            {
                case 1:    confirmInput();                 break;   // 确认                        
                case 2:   smg(0,15);delay_ms(2000);     break;                       
                case 3:   smg(0,15);delay_ms(2000);     break;   
                case 4:   resetPassword();     break;                     
            }               
	}		
}
 
//void uart() interrupt 4 //串口通信中断函数
//{
    u8 rec_data;
    RI = 0; //清除接收中断标志位
    rec_data=SBUF; //存储接收到的数据
// //   SBUF=rec_data; //将接收到的数据放入到发送寄存器
//    while(!TI); //等待发送数据完成
//    TI=0; //清除发送完成标志位
//}

STM32F103x——IIC软件驱动标准库

在这里插入图片描述

#include "stm32f10x.h" 
//#include"iic.h"


#define ReadSDA GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)
//#define ReadSCL GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)

uint8_t read[]={0,0,0,0,0,0,0,0};//读取数据的数组
uint8_t dat[]={5,2,3,4,5,6,7,8}; //数据写入数组

void delay_us(u16 us)//uS微秒级延时程序(参考值即是延时数,72MHz时最大值233015)	
{ 
	uint32_t temp;
	SysTick->LOAD=(SystemCoreClock/1000000)*us;  //重装计数初值(当主频是72MHz,72次为1微秒)
	SysTick->VAL=0x00;        			//清空定时器的计数器
	SysTick->CTRL=0x00000005;			//时钟源HCLK,打开定时器
	do
	{
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&(1<<16)));	//等待时间到达  
	SysTick->CTRL=0x00000004;			//关闭定时器
	SysTick->VAL=0x00;        			//清空定时器的计数器
}
void delay(unsigned int i)
{
    while(i--);
}
void IIC_SCL(uint8_t BitValue)
{
	/*根据BitValue的值,将SCL置高电平或者低电平*/
	GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction)BitValue);
	//delay_us(10);
	/*如果单片机速度过快,可在此添加适量延时,以避免超出I2C通信的最大速度*/
	//...
}

void IIC_SDA(uint8_t BitValue)
{
	/*根据BitValue的值,将SDA置高电平或者低电平*/
	GPIO_WriteBit(GPIOB, GPIO_Pin_7, (BitAction)BitValue);
	//delay_us(10);
	/*如果单片机速度过快,可在此添加适量延时,以避免超出I2C通信的最大速度*/
	//...
}

//初始化SCL和 SDA分别是 PB6和 PB7
void Init_iic()
{
    //打开GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /*将SCL和SDA引脚初始化为开漏模式*/
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/*释放SCL和SDA*/
	IIC_SCL(1);
	IIC_SDA(1);
}

//起始终止/
//IIC起始信号    SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号;
void start()
{
    IIC_SCL(1);
	IIC_SDA(1);
    delay_us(2);
    
    IIC_SDA(0);
    delay_us(2);
    IIC_SCL(0);
    delay_us(2);
}
//iic结束信号    SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。
void stop()
{
    IIC_SDA(0);
    delay_us(2);
    IIC_SCL(1);
    delay_us(2);
    IIC_SDA(1);
    delay_us(2);
}
//iic   应答   从机SDA低电平;主机SCL  低电平>高>低

void iic_ack()
{
    IIC_SDA(0);
    delay_us(2);
    IIC_SCL(1); 
    delay_us(2);
    IIC_SCL(0);
    delay_us(2); 
    IIC_SDA(1);  
    delay_us(2);     
}

//iic非应答    从机SDA高电平;主机SCL  低电平>高>低
void no_ack()
{
    IIC_SDA(1);
    delay_us(2); 
    IIC_SCL(1);
    delay_us(2); 
    IIC_SCL(0); 
    delay_us(2); 
}
//iic 应答等待
uint8_t wait_ack()
{
    uint8_t time=0;
    
    IIC_SCL(1);
    delay_us(2);
    IIC_SDA(1);//保SDA产生应答信号前处于高电平;若发数据最后一位为低电平;则可能会造成没有应答而主机认为从机已应答的情况;在应答等待中置为高电平或者在
    delay_us(2);
    
    while(ReadSDA);
    {
    time++;
        if(time>100)
        {
         // led(4); 
        stop();            
        return 1;
        }
    }
    IIC_SCL(0);
    delay_us(2);
    //led(6);  
return 0;
}

//字节写
void write_byte(uint8_t dat)
{
    uint8_t i=0;
    IIC_SCL(0);
    for(i=0;i<8;i++)
    {
       IIC_SDA((dat&0x80)>>7);
       delay_us(2); 
       IIC_SCL(1);
       delay_us(2);  
       IIC_SCL(0);
        dat<<=1;
    }
    IIC_SDA(1);
   delay_us(2); 
}

//字节读取
uint8_t read_byte(uint8_t ack)
{
    uint8_t i=0;
    uint8_t receive=0;
     for(i=0;i<8;i++)
        {
            IIC_SCL(0);
            delay_us(1);
            IIC_SCL(1);
            receive<<=1;
            if(ReadSDA)receive++;   
            
            delay_us(2); 
        }
        if(!ack)
           no_ack();
        else
           iic_ack();
 
    return receive;        
}






/*******************************************************************************
* 函 数 名         : at24c02_write_one_byte
* 函数功能		   : 在AT24CXX指定地址写入一个数据
* 输    入         : addr:写入数据的目的地址 
					 dat:要写入的数据
* 输    出         : 无
*******************************************************************************/
void at24c02_write_one_byte(uint8_t addr,uint8_t dat)
{	   	  	    																 
    start();
    write_byte(0xA0);//写入地址指令
    wait_ack();
    write_byte(addr);//写入地址
    
    wait_ack();
    write_byte(dat);
    wait_ack();
    stop();
    delay_us(10000);

    
}


uint8_t at24c02_read_one_byte(uint8_t addr)
{				  
	uint8_t temp=0;  
    
    start();
    
    write_byte(0XA0);   //打开写入开关
    
    wait_ack();         //等待应答
    
    write_byte(addr);   //发送地址
    
    wait_ack();
    
    start();     
    
    write_byte(0XA1);   //打开读
    
    wait_ack();	        //等待应答
    
    temp=read_byte(0);
    stop();             //停止
	return temp;			//返回读取的数据  
}



void at24c02_write_page()//
{
    uint8_t x=0;
    for(x=0;x<8;x++)
    {
        at24c02_write_one_byte(x,dat[x]);
    } 
}

void at24c02_read_page()
{
    uint8_t r=0;
    for(r=0;r<8;r++)
    {
        read[r]=at24c02_read_one_byte(r);    
    }   
}







void GPIO_Configuration(void);
void led(uint8_t add);
void Key_Scan(void);

int main(void)
{
    Init_iic();
    GPIO_Configuration();
    while (1)
    {
        Key_Scan();
//        GPIO_ResetBits(GPIOB, GPIO_Pin_5);  

//        GPIO_SetBits(GPIOB, GPIO_Pin_5);  
//        delay_us(20);//2US
   }
     //return 0;
}
void led(uint8_t add)
{
    while(add--)
    {     
       GPIO_ResetBits(GPIOB, GPIO_Pin_5);  
       delay_us(65535);
       delay_us(65535);
       delay_us(65535);
       GPIO_SetBits(GPIOB, GPIO_Pin_5);  
       delay_us(65535);
       delay_us(65535);
       delay_us(65535);
    }
    
}
void Key_Scan(void)
{
    uint8_t a=1;
    uint8_t b=0;
    if (!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)) // 检测KEY0是否被按下
    {
        delay(0x800); // 延时消抖
        if (!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)) // 再次检测KEY0是否被按下
        {
            while(!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4));  //检测抬起
            led(3);
            //at24c02_write_page();
            at24c02_write_one_byte(0,6);
        }

    }
    else if (!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)) // 检测KEY1是否被按下
    {
        delay(0x800); // 延时消抖
        if (!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)) // 再次检测KEY1是否被按下
        {
            
           while(!GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)); 
           // led(1);            
            a=at24c02_read_one_byte(0);
            b++;
     
            led(a);
            
        }
    }
    else if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) // 检测KEY_UP是否被按下
    {
        delay(0x800); // 延时消抖
        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) // 再次检测KEY_UP是否被按下
        {
             while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0));
             led(a);
        }
    }   
}


void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);

    // 配置LED0、LED1和蜂鸣器的输出模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;// | GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    //GPIO_ResetBits(GPIOB, GPIO_Pin_8);
    GPIO_ResetBits(GPIOB, GPIO_Pin_5);
    //GPIO_SetBits(GPIOB, GPIO_Pin_8);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOE, GPIO_Pin_5);  
    
    // 配置按键KEY_UP、KEY1和KEY0的输入模式
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3 | GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPU;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    //上拉E,3,4
    GPIO_SetBits(GPIOE, GPIO_Pin_3);
    GPIO_SetBits(GPIOE, GPIO_Pin_4);
    
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPD;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
      // 下拉PA0
    //GPIO_ResetBits(GPIOA, GPIO_Pin_0);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值