(一)I^2 C总线控制原理:
1.数据有效性规定:
所以如图,当SCL为高电平的时候,SDA数据稳定不改变,当SCL为低电平的时候,看时序图SDA才允许改变。
2. 这是启示和终止,和上面没有太大关系。(上面只说有效信号)
数据传输可能产生的三种状况:
4. 主机在传送数据时的几种方式:
(S表示其实信号,P表示终止信号),白A表示从机的应答,阴影A表示主机的应答,—A表示非应答(代表即将结束接受),应答之后主(从)机再发送下一段数据*
方式一:
方式二:
方式三:非应答之后再次进行S初始信号发送,改变数据传输方向
从机地址==固定部分+可编程部分(决定可以访问的从机数目)
对于延时的解释:从SCL和SDA变成1或者变零所需要持续的时间。
应答可根据上述情况写出:
每个字节==八位二进制数,传输都是一个字节一个字节传输的。
(二)AT24CXX存储器戏芯片工作原理:
(四)编写代码使四个按键
k1(按下时读取数据),
k2(保存k1读取的的数据),
k3(数据递增1),
k4(数据清零)
并用数码管后四位显示这个过程:
main.c文件
#include "reg52.h"
#include "I^2C.h"
typedef signed char int8;
typedef signed int int16;
typedef signed long int32;
typedef unsigned char uint8; //字符型
typedef unsigned int uint16;
typedef unsigned long uint32;
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
char num=0;
uint8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uint16 disp[4];
void delay(uint16 x_ms) //延时毫秒
{
uint16 i, j;
for (i = x_ms; i > 0; i--)
for (j = 114; j > 0; j--);
}
void keybord() //独立按键
{
if(k1==0) //写
{
delay(4);
if(k1==0)
{
AT24C02Write(1,num);
}
while(!k1);
}
if(k2==0) //读取存储位
{
delay(4);
if(k2==0)
{
num=AT24C02Read(1);
}
while(!k2);
}
if(k3==0) //加一
{
delay(4);
if(k3==0)
{
num++;
if(num>255)
{
num=0;
}
}
while(!k3);
}
if(k4==0) //清零
{
delay(4);
if(k4==0)
{
num=0;
}
while(!k4);
}
}
void datapros()
{
disp[0]=smgduan[num/1000];//千位
disp[1]=smgduan[num%1000/100];//百位
disp[2]=smgduan[num%1000%100/10];//个位
disp[3]=smgduan[num%1000%100%10];
}
void DigDisplay()
{
uint16 i;
for(i=0;i<4;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=1;LSB=1;LSC=0; break;//显示第0位
case(1):
LSA=0;LSB=1;LSC=0; break;//显示第1位
case(2):
LSA=1;LSB=0;LSC=0; break;//显示第2位
case(3):
LSA=0;LSB=0;LSC=0; break;//显示第3位
}
P0=disp[i];//发送数据
delay(5); //间隔一段时间扫描
P0=0x00;//消隐
}
}
void main(void)
{
while(1)
{
keybord();
datapros(); //数据处理函数
DigDisplay();//数码管显示函数
}
}
I2C.c文件
#include"I^2C.h"
void delay10us() //延迟十毫秒,误差 0us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
void I2C_Start() //起始信号
{
SDA=1;
delay10us();
SCL=1;
delay10us();
SDA=0;
delay10us();
SCL=0;
delay10us();
}
void I2C_Stop() //终止信号
{
SDA=0;
delay10us();
SCL=1;
delay10us();
SDA=1;
delay10us();
//接下来变为0不需要管,因为得到终止信号程序截至
// SDA=0;
// delay10us();
}
//********《发送字节的函数》********//
unsigned char I2C_SendBye(unsigned char dat)
{
unsigned int i,m;
for(i=0;i<8;i++) //通过循环即可将八位字节数据输入
{
SDA=dat>>7; //输入最高一位
dat=dat<<1; //依次将最高位数左移到第一位
delay10us();
SCL=1;
delay10us();
SCL=0; //只有在SCL为0时数据可进行有效变动
delay10us();
}
SDA=1; //将SDA和SCL释放出来,都都置为1
delay10us();
SCL=1;
while(SDA) //(1).应答时SDA是0,是0时退出循环,return 1;
{
m++;
if(m>200)
{
SCL=0; //拉低时终止条件,无论应答或者非应答
delay10us();
return 0;//(2).SDA不为0,证明产生非应答,返回1
}
}
SCL=0;
delay10us();
return 1;
}
//**********《接受字节函数》**********//
unsigned char I2C_ReadBye()
{
unsigned char i=0,dat=0;
SDA=1; //初始时先置1,看接受过程中是否有会变0
delay10us();
for(i=0;i<8;i++)
{
SCL=1; //保持SCL=1时数据稳定不能改变,保证读取
delay10us();
dat=dat<<1; //【dat=0, 移位后为00】【01移位后10】......
dat=dat|SDA; //【00或运算后01】 【10或运算后11】......
delay10us();
SCL=0; //算完后置为0
delay10us();
}
return dat;
}
//*****《对AT24C02写入数据》*****// // 在那个地址 ,写入什么数据//
void AT24C02Write(unsigned char addr,unsigned char dat)
{
//起始信号
I2C_Start();
//器件地址(函数内部包含应答无需再写)
I2C_SendBye(0XA0);
//首地址(函数内部包含应答无需再写)
I2C_SendBye(addr);
//发送数据
I2C_SendBye(dat);
//停止信号
I2C_Stop();
}
//*****《对AT24C02数据进行读取,(先写后读)》******//
unsigned char AT24C02Read(unsigned char addr)
{
unsigned char num;
//(写)起始信号
I2C_Start();
//器件地址(函数内部包含应答无需再写)
I2C_SendBye(0XA0); //0是写
//首地址
I2C_SendBye(addr);
//(读)转向要重新写起始信号
I2C_Start();
//读取器件地址(函数内部包含应答无需再写)
I2C_SendBye(0XA1); //1是读
num=I2C_ReadBye(); //读取一位字节
//停止信号
I2C_Stop();
return num;
}
I2C.h文件
#ifndef _I2C_H
#define _I2C_H
#include sbit SCL=P2^1; sbit SDA=P2^0; void I2C_Start(); void I2C_Stop(); unsigned char I2C_SendBye(unsigned char dat); unsigned char I2C_ReadBye(); void AT24C02Write(unsigned char addr,unsigned char dat); //写 unsigned char AT24C02Read(unsigned char addr); //读 #endif
上一篇:51单片机~DS18B20温度传感器
下一篇:51单片机~串口通信
推荐阅读最新更新时间:2024-11-04 23:45