模拟I2C读写24C256、PCF8563
更新时间:2023-07-17 10:46:01 阅读量: 实用文档 文档下载
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
主函数
#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的读数据地址
#define debug 0
/*sbit SCL= P3^5;
sbit SDA =P3^4;*/
/*sbit SCL= P1^5;
sbit SDA =P1^6;*/
sbit SCL= P3^4;
sbit SDA =P3^3;
/*延时子程序,大概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_();
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
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_();
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
_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;
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
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(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Sent_Byte(addr_H); //再发送内存地址高八位
ack_temp=Ack_Check(); //接收应答位
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
Sent_Byte(addr_L); //再发送内存地低八位
ack_temp=Ack_Check(); //接收应答位
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Sent_Byte(Data); //发送数据
ack_temp=Ack_Check(); //接收应答位
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
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(debug==1)
{
if(ack_temp==0)
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Sent_Byte(addr_H); //再发送内存地址
ack_temp=Ack_Check();
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Sent_Byte(addr_L); //再发送内存地址
ack_temp=Ack_Check();
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Start_I2C(); //再一次启动信号
Sent_Byte( device_16bit_Raddress);//发送器件读地址
ack_temp=Ack_Check();
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
SendCommString("ACK ERROR");
}
}
RecByte=Rec_Byte(); //接收数据
/*ack_temp=Ack_Check();//一个字节一个字节读不需要应答
if(ack_temp==1)
{
SendCommString("ACK OK");
}
else {
SendCommString("ACK ERROR");
}*/
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(); //接收应答位
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Sent_Byte(address); //再发送内存地址
ack_temp=Ack_Check(); //接收应答位
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
SendCommString("ACK ERROR");
}
}
Sent_Byte(Data); //发送数据
ack_temp=Ack_Check(); //接收应答位
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Stop_I2C(); //停止
}
/*接收数据子程序,入口参数是8位从器件的内存地址,返回值是读到的值*/
Byte Rec_Data8(address)
{
Byte RecByte; //定义接收到的数
bit ack_temp; //响应位
Start_I2C(); //开化信号
Sent_Byte(device_8bit_Waddress);//先进行一次伪写操作
ack_temp=Ack_Check(); //接收应答位
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Sent_Byte(address); //再发送内存地址
ack_temp=Ack_Check();
if(debug==1)
{
if(ack_temp==0)
{
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Start_I2C(); //再一次启动信号
Sent_Byte(device_8bit_Raddress );//发送器件读地址
ack_temp=Ack_Check();
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
RecByte=Rec_Byte(); //接收数据
ack_temp=Ack_Check();
if(debug==1)
{
if(ack_temp==0)
{
SendCommString("ACK OK");
}
else
{
SendCommString("ACK ERROR");
}
}
Stop_I2C(); //停止信号
return(RecByte);
}
main()
{
Byte xdata i, m[20];
serial_init();
T0_init();
if(debug==1)
{
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
SendCommString("serial ok");
}
Sent_Data16(0x0020,13);//向从器件地址发四个数据
delay();
Sent_Data16(0x0021,14);
delay();
Sent_Data16(0x0022,15);
delay();
Sent_Data16(0x0023,16);
delay();
m[0]=Rec_Data16(0x0020);//将接收到的数据保存在一个数组中
m[1]=Rec_Data16(0x0021);
m[2]=Rec_Data16(0x0022);
m[3]=Rec_Data16(0x0023);
ES=0;
TI=0;
for(i=0;i<4;i++) //通过串行口对接收到的数显示
{
SBUF=m[i];
while(!TI); //串行发送
TI=0;
}
ES=1;
/*Sent_Data8(0x00,1);//向从器件地址发四个数据
delay();
Sent_Data8(0x01,2);
delay();
Sent_Data8(0x02,3);
delay();
Sent_Data8(0x03,4);
delay();
m[0]=Rec_Data8(0x00);//将接收到的数据保存在一个数组中
m[1]=Rec_Data8(0x01);
m[2]=Rec_Data8(0x02);
m[3]=Rec_Data8(0x03);
ES=0;
TI=0;
for(i=0;i<4;i++) //通过串行口对接收到的数显示
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
{
SBUF=m[i];
while(!TI); //串行发送
TI=0;
}
ES=1;*/
while(1); //等待
}
串口部分:
#include "reg52.h"
#include "intrins.h"
#include "serial.h"
#define uchar unsigned char
#define uint unsigned int
uchar rec_data[30];//上位机传来的命令数据长度为:4(STAR)+4(TEST等)+3(010长度等)+data+2(CRC)+3(END),16+data,数据长度暂时定为30
uchar xdata send_data[120];//由于上传数据时data比较长,有数字通道数据和模拟通道数据还有开关量通道数据
uchar rec_over_flag;//接收串行口0和串行口1一帧数据结束标志
uchar xdata send_num,send_length;//232需要发送的数据的长度和还需要发送的长度 uchar rec_tail;//接受232数据时保存是接受第几个数据的变量
/*发送一帧232数据子程序*/
void SendCommString(unsigned char *base)
{
if (base[0]==0) return;
for (;;)
{
if (base[send_length]==0) break;
send_data[send_length]=base[send_length];
send_length++;
}
SBUF=send_data[0];
send_num=send_length;
while(send_length!=0);
}
/*串行口初始化函数*/
void serial_init()//初始化串行口函数,设置串行口波特率为9600,8位数据位,一位停止位,无校验位
{ //使用T1做波特率发生器
SCON|=0x50;//8位异步收发,允许串行口接收数据,TI和RI初始化为0
PCON=0x80; // SMOD = 1;
SCON = 0x50; // Mode 1, 8-bit UART, enable receiption 19200 TH1=0xfd;
TL1=0xfd;
模拟I2C总线读写24C256和PCF8563,扩展成读写一切I2C总线的设备
TR1=1;
TMOD|=0x20;//8Bit
ES=1;
EA=1;
}
/*定时器0初始化*/
void T0_init(void)
{
TMOD|=0x01;//初始化定时器0包括T0的工作方式为1,初值为定时10ms,开中断 TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
ET0=1;
}
/*定时器0中断服务函数*/
void t0_isp(void) interrupt 1
{
TF0=0;//定时器0中断标志清零
TR0=0;//关闭计数器
rec_over_flag=1;//10ms没有新数据,需要将接收到得数据打包
rec_data[rec_tail]=0;//结束标志
rec_tail=0;
}
/*串行口中断服务函数*/
void serial_isp(void )interrupt 4//串行口中断服务函数,接收上位机的命令或下位机的数据 {
if(RI)//接收到了新数据
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TR0=1;
RI=0;
rec_data[rec_tail]=SBUF;
rec_tail++;
}
if(TI)
{
TI=0;
send_length=send_length-1;
if(send_length!=0)
{
SBUF=send_data[send_num-send_length];
}
}
}
正在阅读:
校运会解说词02-17
2017年河南师范大学体育学院333教育综合之简明中国教育史考研冲刺密押题07-29
医用化学第一章 溶液的组成标度与渗透压05-18
垃圾渗滤液设计方案05-03
整合资源,建立湄洲湾经济开发区03-15
闪光眼镜项目可行性研究报告(技术工艺+设备选型+财务概算+厂区规划)方案设计01-24
浅谈银川市联通分公司的员工培训11-14
青春励志诗歌经典11-21
- 教学能力大赛决赛获奖-教学实施报告-(完整图文版)
- 互联网+数据中心行业分析报告
- 2017上海杨浦区高三一模数学试题及答案
- 招商部差旅接待管理制度(4-25)
- 学生游玩安全注意事项
- 学生信息管理系统(文档模板供参考)
- 叉车门架有限元分析及系统设计
- 2014帮助残疾人志愿者服务情况记录
- 叶绿体中色素的提取和分离实验
- 中国食物成分表2020年最新权威完整改进版
- 推动国土资源领域生态文明建设
- 给水管道冲洗和消毒记录
- 计算机软件专业自我评价
- 高中数学必修1-5知识点归纳
- 2018-2022年中国第五代移动通信技术(5G)产业深度分析及发展前景研究报告发展趋势(目录)
- 生产车间巡查制度
- 2018版中国光热发电行业深度研究报告目录
- (通用)2019年中考数学总复习 第一章 第四节 数的开方与二次根式课件
- 2017_2018学年高中语文第二单元第4课说数课件粤教版
- 上市新药Lumateperone(卢美哌隆)合成检索总结报告
- 读写
- PCF8563
- 模拟
- 24C256
- I2C
- 转速器盘夹具设计说明书
- 鄂人19号湖北省机关事业单位离退休人员计发离退休费等问题的实施意见
- 陶氏超滤产品技术手册(F)
- 2012年宁夏回族自治区药店名录大全
- 一年级上语文教案
- 剩余劳动力就业安置合同
- 5.2平面直角坐标系(1)
- 第六章 心境障碍患者的护理试题及答案
- 县长在全市安全生产约谈会上的表态发言
- 计算机模拟试卷4及答案
- 游戏中地图的即时生成算法
- 新桃园煤矿井口启封及排放瓦斯安全技术措施最新版
- 大学团课结业考试试题及参考答案
- 600456宝钛股份关于变更签字注册会计师项目合伙人项目质量控制复2021-03-02
- “买伊利纯牛奶_拿健康好礼”大型消费者推广案
- 感染性疾病科标准健康教育计划
- Asymptotic behavior of a nonisothermal viscous Cahn-Hilliard equation with inertial term
- 马坊小学2013年预算执行情况说明(上报)
- 600236广西桂冠电力股份有限公司关于持股5%以上股东增持股份达到12021-03-02
- 注射用重组人尿激酶原