标题1:read_eeprom()、write_eeprom()函数的介绍
标题2:实例讲解
标题3:实验总结
read_eeprom()、write_eeprom()函数的介绍
read_eeprom()向AT24C02中某地址中读取数据,write_eeprom()向AT24C02某地址中存入数据,该数据不会随着电源的断开而导致数据丢失,因此我们可以利用这点来记录开机次数。
实例讲解:
#include <STC15F2K60S2.H>
#include "i2c.h"
sbit p27 = P2 ^ 7;
sbit p26 = P2 ^ 6;
sbit p25 = P2 ^ 5;
code unsigned char tab[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff};
unsigned char buf[8]={10,10,10,10,10,10,10,10};
unsigned char com=0;
void display();
void cls_buzz()
{
P2=(P2&0x1f)|0xa0;
P0=0x00;
P2&=0x1f;
}
//关闭LED
void cls_led()
{
P2=(P2&0x1f)|0x80;
P0=0xff;
P2&=0x1f;
}
//定时器初始化
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
//10ms延时
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
//主函数
void main()
{
unsigned char count=0;
cls_buzz();
cls_led();
Timer0Init();
ET0=1;
count=read_epprom(0x00); //向AT24C02中读取上一次的count数据
count++;
Delay10ms();
write_eeprom(0x00,count); //向AT24C02中地址为0x00存入数据
Delay10ms();
EA=1; //中断服务函数开启
if(count>=100)
buf[5]=count/100;
else
buf[5]=10;
if(count>=10)
buf[6]=count%100/10;
else
buf[6]=10;
buf[7]=count%10;
while(1);
}
//中断服务函数
void Timer0_Proc()
{
display();
}
//数码管处理
void display()
{
//消影
p27=1; //因为eeprom的应用中有P2引脚的使用,因此在此处不能直接对整个P2口处理
p26=1;
p25=1;
P0=0xff;
P27=0;
P26=0;
P25=0;
//位选
p27=1;
p26=1;
p25=0;
P0=(1<<com);
p27=0;
p26=0;
p25=0;
//段选
p27=1;
p26=1;
p25=1;
P0=tab[buf[com]];
p27=0;
p26=0;
p25=0;
//刷新
if(++com==8)
com=0;
}
i2c.c及其i2c.h代码如下:
i2c.c:
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
/** 定义I2C总线时钟线和数据线 */
sbit scl = P2^0;
sbit sda = P2^1;
/**
* @brief I2C总线中一些必要的延时
*
* @param[in] i - 延时时间调整.
* @return none
*/
void i2c_delay(unsigned char i)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(i--);
}
/**
* @brief 产生I2C总线启动条件.
*
* @param[in] none
* @param[out] none
* @return none
*/
void i2c_start(void)
{
sda = 1;
scl = 1;
i2c_delay(DELAY_TIME);
sda = 0;
i2c_delay(DELAY_TIME);
scl = 0;
}
/**
* @brief 产生I2C总线停止条件
*
* @param[in] none
* @param[out] none.
* @return none
*/
void i2c_stop(void)
{
sda = 0;
scl = 1;
i2c_delay(DELAY_TIME);
sda = 1;
i2c_delay(DELAY_TIME);
}
/**
* @brief I2C发送一个字节的数据
*
* @param[in] byt - 待发送的字节
* @return none
*/
void i2c_sendbyte(unsigned char byt)
{
unsigned char i;
//
EA = 0; //关闭中断,避免因为中断而影响总写读写的时序,导致读写失败。
for(i=0; i<8; i++){
scl = 0;
i2c_delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
i2c_delay(DELAY_TIME);
scl = 1;
byt <<= 1;
i2c_delay(DELAY_TIME);
}
EA = 1;
//
scl = 0;
}
/**
* @brief 等待应答
*
* @param[in] none
* @param[out] none
* @return none
*/
unsigned char i2c_waitack(void)
{
unsigned char ackbit;
scl = 1;
i2c_delay(DELAY_TIME);
ackbit = sda; //while(sda); //wait ack
scl = 0;
i2c_delay(DELAY_TIME);
return ackbit;
}
/**
* @brief I2C接收一个字节数据
*
* @param[in] none
* @param[out] da
* @return da - 从I2C总线上接收到得数据
*/
unsigned char i2c_receivebyte(void)
{
unsigned char da;
unsigned char i;
//
EA = 0;
for(i=0;i<8;i++){
scl = 1;
i2c_delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
i2c_delay(DELAY_TIME);
}
EA = 1;
//
return da;
}
/**
* @brief 发送应答
*
* @param[in] ackbit - 设定是否发送应答
* @return - none
*/
void i2c_sendack(unsigned char ackbit)
{
scl = 0;
sda = ackbit; //0:发送应答信号;1:发送非应答信号
i2c_delay(DELAY_TIME);
scl = 1;
i2c_delay(DELAY_TIME);
scl = 0;
sda = 1;
i2c_delay(DELAY_TIME);
}
/**
* @brief 读写操作过程中一些必要的延时
*
* @param[in] i - 指定延时时间
* @return - none
*/
void operate_delay(unsigned char t)
{
unsigned char i;
while(t--){
for(i=0; i<112; i++);
}
}
/**
* @brief 向AT24C02(add)中写入数据val
*
* @param[in] add - AT24C02存储地址
* @param[in] val - 待写入AT24C02相应地址的数据
* @return - none
*/
void write_eeprom(unsigned char add,unsigned char val)
{
i2c_start();
i2c_sendbyte(0xa0);
i2c_waitack();
i2c_sendbyte(add);
i2c_waitack();
i2c_sendbyte(val);
i2c_waitack();
i2c_stop();
operate_delay(10);
}
/**
* @brief 从AT24C02(add)中读出数据da
*
* @param[in] add - AT24C02存储地址
* @param[out] da - 从AT24C02相应地址中读取到的数据
* @return - da
*/
unsigned char read_eeprom(unsigned char add)
{
unsigned char da;
i2c_start();
i2c_sendbyte(0xa0);
i2c_waitack();
i2c_sendbyte(add);
i2c_waitack();
i2c_start();
i2c_sendbyte(0xa1);
i2c_waitack();
da = i2c_receivebyte();
i2c_sendack(1);
i2c_stop();
return da;
}
i2c.h:
/**
* @file i2c.h
* @brief 51单片机通过I0模拟I2C总线
* @author GhpZhu
* @date 2012/8/21
* @version A001
* @par Copyright (c):
* All User
* @par History:
* version: author, date, desc\n
*/
#ifndef __I2C_H
#define __I2C_H
void i2c_delay(unsigned char i);
void i2c_start(void);
void i2c_stop(void);
void i2c_sendbyte(unsigned char byt);
unsigned char i2c_waitack(void);
unsigned char i2c_receivebyte(void);
void i2c_sendack(unsigned char ackbit);
void write_eeprom(unsigned char add,unsigned char val);
unsigned char read_eeprom(unsigned char add);
void init_pcf8591(void);
unsigned char adc_pcf8591(void);
#endif
实验总结:
在有大量的引脚需要引用的情况下,为了防止相互影响可以不对整个口进行处理,而是使用sbit命名单独对某些引脚处理,熟练掌握eeprom的应用,掌握存入取出信息的方式 。