蓝桥杯单片机学习总结(Day 8 eeprom应用-开机次数存储)

标题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的应用,掌握存入取出信息的方式 。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值