通过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: ...
随机推荐
- 你真的会用UIButton吗? UIButton详细介绍
本节知识点: 什么是UIButton UIButton的状态 UIButton的属性设置 UIButton基本使用步骤 UIButton的代码创建与常用属性设置 重写按钮的某个状态属性的 setter ...
- 通过pod导入第三方框架
项目导入第三方框架的时候,如果直接拖到项目中的话还需要去修改某些设置以及导入头文件等,当项目比较大的时候这个方法就比较笨拙了,我们可以通过pod来简化这写流程: 在使用pod之前我们需要安装Cocoa ...
- Redis & Sentinel 安装脚本
#!/bin/bash # 判断是否为root用户,不是root用户提示退出 if [[ $EUID -ne 0 ]]; then echo "This script. must be ...
- fedora 23中配置tftp-server
fedora 23中配置tftp-server */--> fedora 23中配置tftp-server Table of Contents 1. 简介 2. tftp安装 3. 启动和允许 ...
- LVM的添加与删除
#############################创建 fdisk -l查看分区情况 fdisk /dev/xvdb pvcreate /dev/xvdb1 vgextend VolGroup ...
- uiatuomator命令启动apk,与查找多个相同控件
背景:在做项目时,发现使用uiatuomator中遇到了一些问题,现在把解决方法和思路分享出来 案列1:使用命令去启动要运用的apk包 在做自动化时,需要通过命令去启动APK的包,我使用的是sdk中自 ...
- mig_ddr4_ultrascale
http://china.xilinx.com/support/documentation-navigation/design-hubs/dh0061-ultrascale-memory-interf ...
- jQuery 黑白插件
1 add jQuery and plug in to the page <script src="js/jquery.min.js"></script> ...
- VS打包
同学让帮忙打包个VC的程序,程序比较简单,是带access数据库的统计查询软件,之前用Visual Studio 6.0自带的Package & Deployment Wizard 工具打包过 ...
- C++实现元组
一般我们使用struct时需要在头文件中定义,例如 struct Example { int a; char b; ... }; 这样将数据打包好必须在程序运行之前将其定义好,如果有需求在程序运行时添 ...