51单片机入门实验代码——IIC协议读写EEPROM操作

实验功能为:系统运行时, 数码管右 3 位显示 0,按 K1 键将数据 写入到 EEPROM 内保存, 按 K2 键读取 EEPROM内保存的数据, 按K3 键显示数据加 1, 按K4 键显示数据清零,最大能写入的数据是 255。

学习视频:22.8-I2C-EEPROM实验--软件编程--创建多文件工程_哔哩哔哩_bilibili

首先第一步操作:对文件进行管理

  有如下几个文件夹:

《Public》 存放常规设置的接口和常用的函数,比如延时函数。

《APP》 存放IO设备相关设置的接口和调用函数 。

《User》 存放main.c; 

《Public》包含public.h.c 和public.h。代码如下:
// public.h

#ifndef _public_H
#define _public_H

#include "reg52.h"
 
typedef unsigned int u16;                     // 定义类型 u16代表int类型
typedef unsigned char u8;                     // 定义类型 u8代表char类型

void delay10us(u16 ten_us);                   // 包含延时程序

#endif




// public.c

#include "public.h"

void delay10us(u16 ten_us)        
{
	while(ten_us--);
}
		
《APP》包含key.ckey.h(按键函数)、smg.csmg.h(数码管函数)、iic.ciic.h(IIC协议函数)、24c02.c24c02.h(EEPROM读取函数)。代码分别如下:
key.ckey.h(按键函数)
// key.c

#include "key.h"

u8 key_scan(u8 mode)             
{
	static u8 key = 1;          
	
	if(mode) key = 1;           
	
	if(key = 1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))   
	{
			delay10us(1000);
			key = 0;
		
			if(KEY1==0)
				return KEY1_PRESS;
			else if(KEY2==0)
				return KEY2_PRESS;
			else if(KEY3==0)
				return KEY3_PRESS;
			else if(KEY4==0)
				return KEY4_PRESS;
	}
	else if(KEY1==1 && KEY2==1 && KEY3==1 && KEY4==1)  
	{
		key = 1;
	}
	return KEY_UNPRESS;
}



// key.h

#ifndef _key_H
#define _key_H

#include "public.h"
 
sbit KEY1 = P3^1;        
sbit KEY2 = P3^0;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;
 
#define KEY1_PRESS  1                     // 定义返回值函数
#define KEY2_PRESS  2
#define KEY3_PRESS  3
#define KEY4_PRESS  4
#define KEY_UNPRESS 0

u8 key_scan(u8 mode);                     // 包含按键扫描函数

#endif
smg.csmg.h(数码管函数):
// smg.c

#include "smg.h"

u8 gsmg_code[18] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
									0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40};  

void smg_display(u8 det[],u8 pos)       // 数码管显示函数,输入要显示数组的首地址 及 数码管控制位
{
	u8 i = 0; 
	u8 pos_temp = pos-1;
	for(i=pos_temp;i<8;i++)            
	{
		switch(i)
		{
			case 0: LSC = 1;LSB = 1;LSA = 1;  break;   
			case 1: LSC = 1;LSB = 1;LSA = 0;  break;  
			case 2: LSC = 1;LSB = 0;LSA = 1;  break;  
			case 3: LSC = 1;LSB = 0;LSA = 0;  break;  
			case 4: LSC = 0;LSB = 1;LSA = 1;  break;  
			case 5: LSC = 0;LSB = 1;LSA = 0;  break; 
			case 6: LSC = 0;LSB = 0;LSA = 1;  break;  
			case 7: LSC = 0;LSB = 0;LSA = 0;  break;  
		}
		
		SMG_A_DP_PORT = gsmg_code[det[i-pos_temp]];
		delay10us(500);                
		SMG_A_DP_PORT = 0x00;      
	}
}



// smg.h

#ifndef _smg_H
#define _smg_H

#include "public.h"

#define SMG_A_DP_PORT P0   
sbit LSA = P2^2;                   
sbit LSB = P2^3;                    
sbit LSC = P2^4;                    

extern u8 gsmg_code[18];
void smg_display(u8 det[],u8 pos);
#endif
iic.ciic.h(IIC协议函数):
// iic.c

#include "iic.h"

void iic_start(void)                      // IIC 起始信号
{
	IIC_SCL=1;
	IIC_SDA=1;
	delay10us(1);
	IIC_SDA=0;
	delay10us(1);
}

void iic_stop(void)                       // IIC 终止信号
{
	IIC_SCL=1;
	IIC_SDA=0;
	delay10us(1);
	IIC_SDA=1;
	delay10us(1);
}

void iic_ack(void)                        // IIC 应答信号
{
	IIC_SCL=0;
	IIC_SDA=0;
	delay10us(1);
	IIC_SCL=1;
	delay10us(1);
	IIC_SCL=0;
}

void iic_nack(void)                      // IIC 未应答信号
{
	IIC_SCL=0;
	IIC_SDA=1;
	delay10us(1);
	IIC_SCL=1;
	delay10us(1);
	IIC_SCL=0;
}

u8 iic_wait_ack(void)                    // IIC 等待应答信号
{
	u8 time_temp = 0;
	
	IIC_SCL=1;
	delay10us(1);
	while(IIC_SDA)
	{
		time_temp++;
		if(time_temp>100)
		{
			iic_stop();
			return 1;
		}
		IIC_SCL=0;
		return 0;
	}
	
}

void iic_write_byte(u8 dat)            // IIC 写入一个字节
{
	u8 i = 0;
	IIC_SCL=0;
	for(i=0;i<8;i++)
	{
		if((dat&0x80)>0)
			IIC_SDA=1;
		else
			IIC_SDA=0;
		
		dat<<=1;
		IIC_SCL=1;
		delay10us(1);
		IIC_SCL=0;
		delay10us(1);
	}
}

u8 iic_read_byte(u8 ack)               // IIC 读出一个字节
{
	u8 i = 0;
	u8 receive = 0;
	
	for(i=0;i<8;i++)
	{
		IIC_SCL=0;
		delay10us(1);
		IIC_SCL=1;
		delay10us(1);
		receive<<=1;
		if(IIC_SDA) receive++;	
	}
	if(!ack) iic_nack();
	else iic_ack();
	
	return receive;
}


// iic.h

#ifndef _iic_H
#define _iic_H

#include "public.h"

sbit IIC_SCL = P2^1;
sbit IIC_SDA = P2^1;

void iic_start(void);
void iic_stop(void);
void iic_ack(void);
void iic_nack(void);
u8 iic_wait_ack(void);
void iic_write_byte(u8 dat);
u8 iic_read_byte(u8 ack);
#endif
24c02.c24c02.h(EEPROM读取函数):
// 24c02.c

#include "24c02.h"
#include "iic.h"

void at24c02_write_one_byte(u8 addr, u8 dat)         // EEPROM写入函数
{
	iic_start();
	iic_write_byte(0xa0);
	iic_wait_ack();
	iic_write_byte(addr);	
	iic_wait_ack();
	iic_write_byte(dat);	
	iic_wait_ack();
	iic_stop();
	delay10us(1000);  
}


u8 at24c02_read_byte(u8 addr)                       // EEPROM读出函数
{
	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;
}



// 24c02.h

#ifndef  _24c02_H
#define  _24c02_H

#include "public.h"

void at24c02_write_one_byte(u8 addr, u8 dat);
u8 at24c02_read_byte(u8 addr);
#endif
《User》包含main.c,代码如下:
#include "public.h" 
#include "key.h"                               // 包含与独立按键相关函数
#include "smg.h"                               // 包含与数码管相关函数
#include "24c02.h"                             // 包含与EEPROM读取相关函数

#define EEPROM_ADDRESS 0
void main()
{
	u8 key_temp = 0;
	u8 save_value = 0;
	u8 save_buf[3];
	while(1)
	{
	  key_temp=key_scan(0);
		if(key_temp==KEY1_PRESS)                 // 若按键1按下,则将数据写入EEPROM
		{
			at24c02_write_one_byte(EEPROM_ADDRESS,save_value);
		}
		else if(key_temp==KEY2_PRESS)            // 若按键2按下,则读出EEPROM的数据
		{
			save_value=at24c02_read_byte(EEPROM_ADDRESS);
		}
		else if(key_temp==KEY3_PRESS)            // 若按键3按下,则将数据加一
		{
			save_value++;
			if(save_value==255) save_value=255;
		}
		else if(key_temp==KEY4_PRESS)            // 若按键4按下,则将数据置零
		{
			save_value=0;
		}
		save_buf[0]=save_value/100;
		save_buf[1]=save_value%100/10;
		save_buf[2]=save_value%100%10;
		smg_display(&save_buf[0],6);             // 数码管显示数据
	}

}

以上内容,学习参考所用。如有侵权,Call我必删。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值