通过I2C总线向EEPROM中写入数据,记录开机次数
没买板子之前,用protues画过电路图,实现了通过i2c总线向EEPROM中写入和读出数据。
今天,在自己买的板子上面写关于i2c总线的程序,有个地方忘了延时,调程序的时候很蛋疼。下面说说我对I2c总线的理解
i2c总线共有两根线,一根是时钟信号线,一根是数据线。这里我只实现了,指定EEPROM片内地址,并向其中写入一个字节。从EEPROM中指定地址读出一个字节。
写入过程
1.需要发一个启动信号
2.发送EEPROM设备地址
3.发送EEPROM片内地址
4.发送你要写入的数据
5.发送结束信号
读出过程:
1.发送启动信号
2.发送设备地址(注意这里是伪写 和写入过程前两个步骤一样 注意仔细看EEPROM文档)
3.发送EEPROM片内地址
4.发送启动信号(读数据需要启动两次)
5.发送设备地址(这里和读过程不同的是r/w位 前面是低电平 这里是高电平)
6.读取数据
7.发送结束信号
6.发送结束信号
当然单片机向总线写数据完成后,要注意检测应答信号,读取数据后,单片机应向设备发送,非应答信号或者叫应答非信号。
/*=================================================================================
功能:通过i2c总线向EEPROM中写入数据 并读回数据 验证I2C总线通信 实现记录开机次数
电路图:P2.0接SCL
P2.1接SDA
P1口接led发光二极管
P2.3接 数码管位选信号
P2.2接段选信号
P0口接数码管
注意理解设备发出的应答
和单片机发出的非应答或者叫应答非
两者使得通信完整 只不过方向不一样
====================================================================================*/
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define TIME_SET 50000 /* 一次定时时间 */ sbit scl = P2^;
sbit sda = P2^; bit ack; uchar code table[] = {
0x3F,0x06,0x5b,0x4f,0x66,0x6d,
0x7d,0x07,0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00
}; //led亮的数字 sbit wela = P2^;//位选信号
sbit dula = P2^;//段选
uchar times; void start(); /* 开始信号 */
void stop(); /* 结束信号 */
void write(uchar byte); /* 向EEPROM中写入一个字节 */
void delay(uchar time_delay); /* 延时函数 */
void write_address(uchar byte, uchar address); /* 根据地址向EEPROM中写入数据 */
uchar read_address(uchar address); /* 从指定地址读出数据 */
void no_ack(); /* 发送一个非应答信号 */
void display(uchar num_display); /* 显示开机次数 */
void init(); void main()
{
init();
times = read_address(0x50);
times += ;
write_address(times, 0x50);
display(times);
while();
}
/*==========================
功能:发送启动信号
输入:无
输出:启动信号 SDA负跳变
============================*/
void start()
{
sda = ;
// _nop_(); /* ? */
scl = ;
delay();
sda = ;
delay();
scl = ; /* scl为什么要拉低 */
delay(); /* ? */
}
/*==========================
功能:发送结束信号
输入:无
输出:启动信号 SDA正跳变
============================*/
void stop()
{
sda = ;
_nop_();
scl = ;
delay();
sda = ;
delay();
}
/*==============================================
功能:延时函数 time_delay = 10 延时大约0.5MS
输入:延时时间
输出:延时
================================================*/
void delay(uchar time_delay)
{
uchar i,j;
for(i = time_delay; i > ; i--)
for(j = time_delay; j > ; j --)
{}
}
/*=====================================
功能:向数据线上写一个字节 先写高位
输入:待写字节
输出:写到数据总线上
=======================================*/
void write(uchar byte)
{
uchar i = ; for(; i < ; i ++)
{
if((byte << i) & 0x80)
sda=;
else
sda = ;
delay(); /* 为啥要延时 */
scl = ;
delay();
scl = ;
}
delay(); sda = ;
delay();
scl = ;
delay();
if(sda == )
ack = ;
else
ack = ; scl = ;
} /*=========================================
功能:向指定地址写入一个字节数据
输入:address写入地址,byte写入字节数据
输出:无
===========================================*/
void write_address(uchar byte, uchar address)
{
start();
delay();
write(0xae); /* 写入设备地址 */
delay();
write(address);
delay();
write(byte); delay(); stop();
delay(); /* 延时很重要!!??? */
}
/*==========================
功能:从指定地址读出数据
输入:数据地址
输出:指定地址的数据
============================*/
uchar read_address(uchar address)
{
uchar i;
uchar result = ;
start(); write(0xae); /* 写入设备地址 */ write(address); start(); /* 第二次设置开始信号 */ write(0xaf); sda = ; for(i = ; i < ; i ++) /* 读出数据 */
{
scl = ;
delay();
scl = ;
delay();
result <<= ; /* result <<= 1? */
if(sda == )
result = result + ; delay();
}
scl = ; /* 为啥要拉低 */
delay(); no_ack(); /* 发送非应答信号 */ stop();
return result;
}
/*=======================
功能:初始化变量
输入:无
输出:初始化后的变量
========================*/
void init()
{
ack = ;
scl = ;
sda = ; times = ;
EA = ;
ET0 = ;
TH0 = ( - TIME_SET) / ;
TL0 = ( - TIME_SET) % ;
TR0 = ;
}
/*==========================
功能:发送一个非应答信号
输入:无
输出:非应答信号
============================*/
void no_ack()
{
sda = ;
delay();
scl = ;
delay();
scl= ;
delay();
}
/*======================
功能:定时器中断函数
输入:定时器0中断
输出:刷新数码管显示
========================*/
void timer0() interrupt
{
TH0 = ( - TIME_SET) / ;
TL0 = ( - TIME_SET) % ;
display(times);
}
/*==========================
功能:数码管显示开机次数
输入:开机次数
输出:数码管显示开机次数
============================*/
void display(uchar num_display)
{
uchar ge,shi;//个位和十位 ge = num_display % ;
shi = num_display / ;
//消影
P0 = 0xff;
wela = ;
wela = ;
P0 = ;
dula = ;
dula = ; //显示十位数字
P0 = 0xfe;
wela = ;
wela = ;
P0 = table[shi];
dula = ;
dula = ;
delay(); //消影
P0 = 0xff;
wela = ;
wela = ;
P0 = ;
dula = ;
dula = ; //显示个位数字
P0 = 0xfd;
wela = ;
wela = ;
P0 = table[ge];
dula = ;
dula = ;
delay();
}
通过I2C总线向EEPROM中写入数据,记录开机次数的更多相关文章
- 向post请求中写入数据,最终保存在了HttpWebRequest.Params中
一.向post请求中写入数据,最终保存在了HttpWebRequest.Params中: 1)如果存入的是IDictionary类型的字符串变量,如:“username=administrator”, ...
- PHP连接sqlserver的两种方法,向sqlserver2000中写入数据,中文乱码
项目环境是php5.3.28 项目用的ThinkPHP3.2.3 已经mysql5.5数据库,要和另一个项目对接,需要连接sqlsever2000数据库进行一些操作. 第一种用php自带扩展连接数据 ...
- 【转】从QDataStream向QByteArray中写入数据时的注意点(QT)
最近发现从QDataStream向QByteArray中写入数据常常是写不进去的,通过查看QT的源码: QDataStream &operator>>(QDataStream &a ...
- POI往word模板中写入数据
转: POI往word模板中写入数据 2018年03月24日 16:00:22 乄阿斗同學 阅读数:2977 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn ...
- Verilog利用$fdisplay命令往文件中写入数据
最近在做的事情是,用FPGA生成一些满足特定分布的序列.因此为了验证我生成的序列是否拥有预期的性质,我需要将生成的数据提取出来并且放到MATLAB中做数据分析. 但是网上的程序很乱,表示看不懂==其实 ...
- 复制excel表,往excel表中写入数据
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import jav ...
- POI向Excel中写入数据及追加数据
import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import ...
- 计算机二级-C语言-程序填空题-190117记录-对文件的处理,复制两个文件,往新文件中写入数据。
//给定程序的功能是,调用函数fun将指定源文件中的内容赋值到指定目标文件中,复制成功时函数返回1,失败时返回0,把复制的内容输出到终端屏幕.主函数中源文件名放在变量sfname中,目标文件名放在变量 ...
- lua向文件中写入数据,进行记录
function readfile(path) local file = io.open(path, "r") if file then local content = file: ...
随机推荐
- Android View的绘制机制流程深入详解(一)
本系列文章主要着重深入介绍Android View的绘制机制及流程,第一篇主要介绍并分析LayoutInflater的原理, 从而理解setContentView的加载原理.对于LayoutInfla ...
- 需要一个分页,花了一个钟写了一个,刚学js,不是很完美
<script src="js/jquery.min.js" ></script> <script type="text/javascrip ...
- 关于Git的stash命令
add 添加新文件到 Git 代码仓库的索引中 $ git add filename mv 移动或重命名文件 $ git mv old-filename new-filename rm 从工作目录和 ...
- php xml常用函数的集合(比较详细)
1.DOM 函数 a.DOMDocument-<load()作用:加载xml文件用法:DOMDocument-<load( string filename )参数:filename,xml ...
- hadoop的mapreduce过程
http://www.cnblogs.com/sharpxiajun/p/3151395.html 下面我从逻辑实体的角度讲解mapreduce运行机制,这些按照时间顺序包括:输入分片(input s ...
- 转:Unity3D的四种坐标系
World Space(世界坐标):我们在场景中添加物体(如:Cube),他们都是以世界坐标显示在场景中的.transform.position可以获得该位置坐标. Screen Space(屏幕坐标 ...
- Webbrowers控件的小技巧
我最近接触webbrowers 这个控件比较多,感觉用起来比较顺手吧.可以做很多操作. 貌似很多网络模拟有时候都内置这个控件或者类似的控件,但这样子速度就不能跟那些单纯用API 构建数据包比了. 我一 ...
- WCF编程系列(五)元数据
WCF编程系列(五)元数据 示例一中我们使用了scvutil命令自动生成了服务的客户端代理类: svcutil http://localhost:8000/?wsdl /o:FirstServic ...
- iOS RunTime的简单使用
1.根据指定规则根据runtime进行页面选择跳转 背景:要根据后台返回的数据 进行选择要跳转到哪一个ViewController // 这个规则肯定事先跟服务端沟通好,跳转对应的界面需要对应的参数 ...
- Xcode中,调试console窗口输出error: Couldn't materialize struct: the variable 'cell' has no location, it may have been optimized out的问题
Xcode中调试代码时,常常需要使用console窗口查看变量的信息,比如使用了如下的命令来输出有关UITableView中一个UITableViewCell的信息, po cell 令人感到意外的是 ...