#include <stdio.h>//包含文件
#include <reg52.h>
#include <intrins.h>
#include<serial.h>
#include"i2c.h"
#define Byte unsigned char//宏定义
#define uint unsigned int
#define uchar unsigned char
#define device_16bit_Waddress 0xa0//器件写数据地址24c256
#define device_16bit_Raddress 0xa1//器件读数据地址24c256
#define device_8bit_Waddress 0xa2 //定义PCF8563的写数据地址
#define device_8bit_Raddress 0xa3 //定义PCF8563的读数据地址
sbit SCL= P3^5;
sbit SDA =P3^4;
/*sbit SCL= P1^5;
sbit SDA =P1^6;*/
/*延时子程序,大概10ms左右*/
void delay()
{
uint i,j;
for(i=0;i<10;i++)
{
for(j=0;j<1000;j++)
{
;
}
}
}
/*开始I2C数据发送或接收*/
void Start_I2C()//在时钟线为高,数据线从高电平跳到低电平时,开始传送
{
SDA=1; //数据先
_nop_(); //延时一段时间
_nop_();
SCL=1; //时钟线为高,等数据线下降才开始
_nop_();
_nop_();
_nop_();
_nop_();
SDA=0; //数据线下降拉,启动了
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
}
/*结束数据传送*/
void Stop_I2C()
{
SDA=0; //时钟线为高时,数据线上升沿为结束信号
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
}
/*发送字节子程序,入口参数为要发送的数据,无返回变量,分8位进行发送*/
void Sent_Byte(Byte Data)
{
Byte BitCount; //定义发送的位数
for(BitCount=0;BitCount<8;BitCount++)
{
_nop_();
_nop_();
if((Data<<BitCount)&0x80) SDA=1;//移位判断发送的数据是1还是0
else SDA=0;
_nop_();
_nop_();
SCL=1; //置位SCL,通知从器件开始接收数据,SCL上升沿发数据
_nop_(); //SCL为1,数据线电平不能变
_nop_();
_nop_();
_nop_();
SCL=0; //钳住总线,等下次接收
}
}
/*应答子程序,无入口参数,返回值是应答位*/
bit Ack_Check()
{
SDA=1; //先置时钟线为高,第九位数据过来会强行把数据线拉低
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
F0=SDA; //将数据线上的该位保存到F0中
SCL=0;
if(F0==1)
return 1;//没有应答,返回1,否则返回0
else return 0;
}
/*接收字节子函数,先接收高位,再接收低位无入口参数,返回值是一个无符号型的一个8位的数*/
Byte Rec_Byte()
{
Byte BitCount, RecData=0;
for(BitCount=0;BitCount<8;BitCount++)
{
SDA=1; //数据线先给1的话,如果从器件发0给主器件
_nop_(); //SDA会拉低,那主器件接收到的为0,否则不拉低,接收到的为1
_nop_(); //这相当释放数据总线一样
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
F0=SDA; //用F0来保存当前数据线上的值
SCL=0;
if(F0)
{
RecData=RecData<<1;
RecData=RecData|0x01;
}
else RecData=RecData<<1;
}
return(RecData);
}
/*发送数据子函数,入口参数是16位的器件地址和要发送的数据,无返回值*/
Sent_Data16(uint address,Byte Data)
{
bit ack_temp; //响应寄存位
uchar addr_H,addr_L;
addr_H=(uchar)(address>>8);
addr_L=(uchar)(address&0x00ff) ;
Start_I2C(); //启动传送
Sent_Byte(device_16bit_Waddress);//先发送器件地址
ack_temp=Ack_Check(); //接收应答位
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
Sent_Byte(addr_H); //再发送内存地址高八位
ack_temp=Ack_Check(); //接收应答位
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
Sent_Byte(addr_L); //再发送内存地低八位
ack_temp=Ack_Check(); //接收应答位
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
Sent_Byte(Data); //发送数据
ack_temp=Ack_Check(); //接收应答位
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
Stop_I2C(); //停止
}
/*接收数据子程序,入口参数是从器件的16位内存地址,返回值是读到的值*/
Byte Rec_Data16(uint address)
{
Byte RecByte; //定义接收到的数
bit ack_temp; //响应位
uchar addr_H,addr_L;
addr_H=(uchar)(address>>8);
addr_L=(uchar)(address&0x00ff) ;
Start_I2C(); //开化信号
Sent_Byte( device_16bit_Waddress);//先进行一次伪写操作
ack_temp=Ack_Check(); //接收应答位
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
Sent_Byte(addr_H); //再发送内存地址
ack_temp=Ack_Check();
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
Sent_Byte(addr_L); //再发送内存地址
ack_temp=Ack_Check();
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
Start_I2C(); //再一次启动信号
Sent_Byte( device_16bit_Raddress);//发送器件读地址
ack_temp=Ack_Check();
if(ack_temp==0)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}
RecByte=Rec_Byte(); //接收数据
/*ack_temp=Ack_Check();//一个字节一个字节读不需要应答
if(ack_temp==1)
{
SendCommString("ACK OK\r\n");
}
else {
SendCommString("ACK ERROR\r\n");
}*/
Stop_I2C(); //停止信号
return(RecByte);
}
/*发送数据子函数,入口参数是8位器件地址和要发送的数据,无返回值*/
Sent_Data8(Byte address,Byte Data)
{
bit ack_temp; //响应寄存位
Start_I2C(); //启动传送
Sent_Byte(device_8bit_Waddress);//先发送器件地址
ack_temp=Ack_Check(); //接收应答位
Sent_Byte(address); //再发送内存地址
ack_temp=Ack_Check(); //接收应答位
Sent_Byte(Data); //发送数据
ack_temp=Ack_Check(); //接收应答位
Stop_I2C(); //停止
}
/*接收数据子程序,入口参数是8位从器件的内存地址,返回值是读到的值*/
Byte Rec_Data8(address)
{
Byte RecByte; //定义接收到的数
bit ack_temp; //响应位
Start_I2C(); //开化信号
Sent_Byte(device_8bit_Waddress);//先进行一次伪写操作
ack_temp=Ack_Check(); //接收应答位
Sent_Byte(address); //再发送内存地址
ack_temp=Ack_Check();
Start_I2C(); //再一次启动信号
Sent_Byte(device_8bit_Raddress );//发送器件读地址
ack_temp=Ack_Check();
RecByte=Rec_Byte(); //接收数据
ack_temp=Ack_Check();
Stop_I2C(); //停止信号
return(RecByte);
}
main()
{
Byte i, m[4];
serial_init();
T0_init();
SendCommString("serial ok\r\n");
Sent_Data16(0x0020,2);//向从器件地址发四个数据
delay();
Sent_Data16(0x0021,4);
delay();
Sent_Data16(0x0022,6);
delay();
Sent_Data16(0x0023,8);
delay();
m[0]=Rec_Data16(0x0020);//将接收到的数据保存在一个数组中
m[1]=Rec_Data16(0x0021);
m[2]=Rec_Data16(0x0022);
m[3]=Rec_Data16(0x0023);
ES=0;
for(i=0;i<4;i++) //通过串行口对接收到的数显示
{
SBUF=m[i];
while(!TI); //串行发送
TI=0;
}
ES=1;
while(1); //等待
}
模拟I2C读写24C256和24C02
5星 · 超过95%的资源 需积分: 50 164 浏览量
2009-09-08
10:02:17
上传
评论 1
收藏 18KB RAR 举报
liu30989315
- 粉丝: 1
- 资源: 4
最新资源
- 基于QT+QML+C++实现的仿 Windows10 画图3D 的颜色选择器+源码
- 32代码四驱简易电动小车蓝牙控制、语音控制、寻光、巡线、避障(内含语音模块为天问ASR-PRO开发板与32单片机串口通信的代码)
- 基于STM32的计步器的设计
- 基于Qt与STM32平台开发的汽车车机系统上位机
- 基于MQTT的智能宠物投喂系统
- 312749069629470selfieU重绘.apk
- http%3A%2F%2Fimg.wsdl.vivo.com.cn%2Fappstore%2Fdeveloper%2Ficon%2F201412%2F201412231038336
- 主要记录B站up主莫烦matplotlib教程中的代码.zip
- Java SE Development Kit 8u411 Windows x64 Installer
- 用于科学绘图的 Matplotlib 样式.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
- 3
前往页