用I2C实现两单片机联机,接收程序怎么写?

用I2C实现两单片机联机,接收程序怎么写?,第1张

发送和接收差不多,

这里是个例子,有问题欢迎一起讨论

/*****************************************************

/* 文件名: I2C.h

/* 描述 : I2C.c的头文件

/* 编写环境 : Keil uVision 3 V3.51

/* 作者 : XX

/* 学校 : 广东XX大学

/* Email : lanhaospider@163.com

/* 版本 : V1.0

/* 编写日期 : 2008-3-30

/* 仅供学习参考

/* 芯片 : MCS-51 AT89S52

/* 晶振 : 11.0592MHz

/* 功能描述 : 模拟I2C总线的接口程序库,主机的程序

/* 应用 : 发送n个字节: 起始位->发送控制字节(类型标识符4位->

片选3位->读写位最后1位)->应答位->数据->应答...........应答->终止位

高位先到达,低位后到达

/****************************************************/

#include "reg51.h"/*根据不同主控芯片型号改写该套入*/

#include "intrins.h"

sbit SCL = P1^6 /*定义SCL线所在口,根据实践需要改写该定义*/

sbit SDA = P1^7 /*定义SDA线所在口,根据实践需要改写该定义*/

unsigned char idata error/*错误提示,全局变量*/

extern void Start_I2C(void)

extern void Stop_I2C(void)

extern void Ack_I2C(void)

extern void Send_Ack(void)

extern void Send_Not_Ack(void)

extern void Send_I2C(unsigned char send_byte)

extern unsigned char Receive_I2C(void)

/*****************************************************/

/* 文件名: I2C.c

/* 描述 : I2C通信程序

/* 编写环境 : Keil uVision 3 V3.51

/* 作者 : XX

/* 学校 : 广东XX大学

/* Email : lanhaospider@163.com

/* 版本 : V1.0

/* 编写日期 : 2008-3-30

/* 仅供学习参考

/* 芯片 : MCS-51 AT89S52

/* 晶振 : 11.0592MHz

/* 功能描述 : 模拟I2C总线的接口程序库,为主机的程序

/*****************************************************/

#include "I2C.h"

/**************************************************

调用方式 : void Start_I2C(void)

函数说明: 启动I2C总线

**************************************************/

void Start_I2C(void)

{

EA = 0 /*关总中断*/

SDA = 1 /*发送启动总线的数据信号*/

SCL = 1 /*发送启动总线的时钟信号*/

_nop_() /*保持数据线高,延时*/

_nop_()

_nop_()

_nop_()

_nop_()

SDA = 0 /*发送起始信号*/

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL = 0 /*时钟线高低跳变一次,I2C通信开始*/

}

/**************************************************

调用方式 : void Stop_I2C(void)

函数说明: 关闭I2C总线

**************************************************/

void Stop_I2C(void)

{

SCL = 0/*发送关闭总线的时钟信号*/

SDA = 0/*发送关闭总线的数据信号*/

_nop_()

_nop_()

_nop_() /*保持数据线低,延时*/

_nop_()

_nop_()

SCL = 1 /*时钟线一次低高跳变,I2C通信停止*/

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SDA = 1 /*发送I2C总线停止数据信号*/

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

EA = 1 /*开总中断*/

}

/**************************************************

调用方式 : void Ask_I2C(void)

函数说明: 主控程序等待从器件接收方式应答

**************************************************/

void Ack_I2C(void)

{

unsigned char errtimes = 0xFF

SDA = 1

SCL = 1

error = 0x10

while(SDA)

{

errtimes--

if(!errtimes)

{

Stop_I2C()

error = 0x11

return

}

}

SCL = 0

}

/**************************************************

调用方式 : void Send_Ask(void)

函数说明: 主控程序为接收方,从器件为发送方时,从

器件等待主器件应答

**************************************************/

void Send_Ack(void)

{

SDA = 0 /*保持数据线低,时钟线发生一次高低跳变 发送一个应答信号*/

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL = 1 /*时钟线保持低电平*/

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL = 0

}

/**************************************************

调用方式 : void Send_Not_Ask(void)

函数说明: 主控程序为接收方,从器件为发送方时,非应答信号

**************************************************/

void Send_Not_Ack(void)

{

SDA = 1 /*保持数据线高,时钟线发生一次高低跳变 没有应答*/

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL = 1 /*时钟线保持高电平*/

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL = 0

}

/**************************************************

调用方式 : void Send_I2C(unsigned char send_byte)

函数说明: 总线发送一个字节

**************************************************/

void Send_I2C(unsigned char send_byte)

{

unsigned char send_bit

for(send_bit = 8send_bit <= 0send_bit--)

{

SCL = 0

_nop_()

SDA = (send_byte &0x80)

send_byte<<=1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

}

SCL = 0

}

/**************************************************

调用方式 : unsigned char Receive_I2C(void)

函数说明: 从I2C总线上接收一个字节

**************************************************/

unsigned char Receive_I2C(void)

{

unsigned char receive_bit , receive_byte = 0

for(receive_bit = 8receive_bit <= 0receive_bit--)

{

SCL = 0

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

SCL = 1

_nop_()

_nop_()

_nop_()

_nop_()

_nop_()

receive_byte <<=1

receive_byte |= SDA

}

SCL = 0

return receive_byte

}

这是我写的模拟程序,只有一个发送函数和一个接收函数,EP为接收标志位,发送没有标志位,通过外部中断来发送起始信号,无应答与非应答,无结束信号,实测可以正常收发数据

#ifndef _IOPORTSEND_H__

#define _IOPORTSEND_H__

#include<reg52.h>

unsigned char DAT,EP=0//可以把DAT当作串口中的SBUF,主机发送完后接收机从DAT提取数据

sbit flag = P3^3//外部中断口

sbit ok = P2^7//起始信号发送口

sbit PCL = P2^6//时钟线

sbit PDA = P2^5//数据线

void delay() //延时函数控制波特率

{

unsigned char a,b

for(b=3b>0b--)

for(a=13a>0a--)

}

void PortInit()//中断配置

{

EA=1

EX1=1

IT1=1

}

void SendPort(unsigned char dat)//发送函数

{

unsigned char i

PCL=0

ok=1//通过ok来启动接收机的中断

ok=0

for(i=0i<8i++)//开始发送数据

{

PCL=0

delay()

if(dat&0x80)

PDA=1

else

PDA=0

PCL=1

delay()

dat<<=1

}

PCL=0

delay()

ok=1//ok置1以便下次发送时启动中断

PCL=1//发送完毕释放时钟线与数据线

PDA=1

}

void ReadPort()interrupt 2//接收函数,在中断函数中接收数据

{

unsigned char i

static unsigned int b

PCL=1

PDA=1//防止接收机的PCL口和PDA口影响数据的接收

for(i=0i<8i++)//开始接收数据

{

DAT<<=1

while(PCL==0)

b=0

while(PCL==1)

{

b++

if(b==1)

if(PDA)

DAT|=0x01

}

}

EP=1//接收完毕后置EP为1,需要在其他函数中清零

}

#endif

#include<at89x51.h>

#define uchar unsigned char

#define uint unsigned int

sbit SCL=P3^1

sbit SDA=P3^2

void delay(uint i)

{

uchar j

while(i--)

for(j=0j<100j++)

}

void write_add(uchar r)//r=1 读否则写

{

uchar i

uchar add_rw

if(r)

add_rw=0x91 //读

else

add_rw=0x90 //写

SCL=1 //START

SDA=1

SDA=0

SCL=0

for(i=0i<8i++) //ADDRESS

{

if(add_rw&0x80)

SDA=1

else SDA=0

SCL=1

SCL=0

add_rw=add_rw<<1

}

SDA=1

SCL=1

while(SDA) //等待应答

SCL=0

}

void write_data(uchar d)

{

uchar i

SCL=0

for(i=0i<8i++) //DATA

{

if(d&0x80)

SDA=1

else SDA=0

SCL=1

SCL=0

d=d<<1

}

SDA=1

SCL=1

while(SDA) //等待应答

SCL=0

}

void stop(void)

{

SCL=1

SDA=1

}

uchar read_data(uchar over)

{

uchar i,d

SCL=0

for(i=0i<8i++) //DATA

{

d=d<<1

SCL=1

if(SDA)

d=d|0x01

SCL=0

}

if(over) SDA=1

else SDA=0

SCL=1 //应答

SCL=0

SDA=0

return d

}

void write_cmd(uchar d)

{

uchar i,w_add=0x90

SCL=1 //START

SDA=1

SDA=0

SCL=0

for(i=0i<8i++) //ADDRESS

{

if(w_add&0x80)

SDA=1

else SDA=0

SCL=1

SCL=0

w_add=w_add<<1

}

SDA=1

SCL=1

while(SDA) //等待应答

SCL=0

SDA=0

for(i=0i<8i++) //DATA

{

if(d&0x80)

SDA=1

else SDA=0

SCL=1

SCL=0

d=d<<1

}

SDA=1

SCL=1

while(SDA) //等待应答

SCL=0

SDA=0

SCL=1

SDA=1

}

uchar read_tmp(void)

{

uchar h,l

write_add(0)

write_data(0xee)//转换

stop()

delay(1000)

write_add(0)

write_data(0xaa)//读温度

stop()

write_add(1)

h=read_data(0)

l=read_data(1)

stop()

return(h)

}

void main(void)

{

while(1)

P0=read_tmp()

}

显示部分我用的串口,你改改就可以了


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12095681.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存