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