高分跪求PIC 单片机I2C总线的例程

高分跪求PIC 单片机I2C总线的例程,第1张

这是pic16f873单片机的i2c总线的例子,先把数据写到at24c02上,然后再读回来,给数码管显示

#include<pic.h>

#define uchar unsigned char

#define uint unsigned int

#define add 0xaa

__CONFIG(0x3B31)

const uchar ee_data[]={1,2,3,4,5,6}

uchar read_data[6]

const uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,

0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}

void delay(uint x)

void init()

void didi(uchar num)

void disp(uchar num1,uchar num2,uchar num3,uchar num4,uchar num5,uchar num6)

void write()

void read()

void main()

{

init()

write()

delay(100)

read()

while(1)

{

disp(read_data[0],read_data[1],read_data[2],read_data[3],read_data[4],read_data[5])

}

}

void delay(uint x)

{

uint a,b

for(a=xa>0a--)

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

}

void init()

{

TRISD=0

TRISA=0

TRISE0=0

// ADCON1=0x07

RE0=0

PORTD=0

PORTA=0

TRISC=0xff

SSPSTAT=0x80

SSPCON=0x38

SSPCON2=0

SSPADD=0x09

}

void write()

{

uchar i

SSPIF=0

SEN=1

while(!SSPIF)

SSPIF=0

SSPBUF=0xA0

while(!SSPIF)

SSPIF=0

SSPBUF=add

while(!SSPIF)

SSPIF=0

for(i=0i<6i++)

{

SSPBUF=ee_data[i]

while(!SSPIF)

SSPIF=0

}

PEN=1

while(!SSPIF)

SSPIF=0

}

void read()

{

uchar i

SSPIF=0

SEN=1

while(!SSPIF)

SSPIF=0

SSPBUF=0xA0

while(!SSPIF)

SSPIF=0

SSPBUF=add

while(!SSPIF)

SSPIF=0

SSPIF=0

RSEN=1

while(!SSPIF)

SSPIF=0

SSPBUF=0xA1

while(!SSPIF)

SSPIF=0

for(i=0i<6i++)

{

RCEN=1

while(!SSPIF)

read_data[i]=SSPBUF

while(!SSPIF)

SSPIF=0

if(i>=5)

{

ACKDT=1

}

else

{

ACKDT=0

}

ACKEN=1

while(!SSPIF)

SSPIF=0

}

PEN=1

while(!SSPIF)

SSPIF=0

}

void didi(uchar num)

{

uchar di_num

for(di_num=numdi_num>0di_num--)

{

RE0=1

delay(50)

RE0=0

delay(20)

}

}

void disp(uchar num1,uchar num2,uchar num3,uchar num4,uchar num5,uchar num6)

{

PORTD=table[num1]//显示第一正顷李个数码举迟管

PORTA=0x20//0010 0000

delay(2)

PORTD=table[num2]//显示第乎谨二个数码管

PORTA=0x10//0001 0000

delay(2)

PORTD=table[num3]//显示第三个数码管

PORTA=0x08//0000 1000

delay(2)

PORTD=table[num4]//显示第四个数码管

PORTA=0x04//0000 0100

delay(2)

PORTD=table[num5]//显示第五个数码管

PORTA=0x02//0000 0010

delay(2)

PORTD=table[num6]//显示第六个数码管

PORTA=0x01//0000 0001

delay(2)

}

贴个程序给你看看,,,单片机没有I2C总线接口,只能靠软件模拟

/*程序的I2C从器件地址为1010,片选地址为000*/

#include <reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

sbit SDA=P1^7

sbit SCL=P1^6

void Delay(uint us)

{

for(usus>0us--)

}

void start_iic() // 启动I2C总线

{

SDA=1 // 发送起始条件数据信号,启动时,

SCL=1 // 必需使数据线、时钟信号线处于高电平(空闲态)

Delay(10) // 使用I2C总线必需考虑保持时间和建立时间,故延时

SDA=0 //产生下降沿,发送起始信号

Delay(10)

SCL=0

}

void stop_iic()

{

SDA=0 //为产生上跳沿做准备

SCL=1 //打开时钟线

Delay(10)

SDA=1 //产生停止信号(上跳沿山和有效)

Delay(10)

SCL=0 //时钟线恢复无效态//

}

void ack_iic()

{

SDA=0 // 接受器件发送应答信号

SCL=1

Delay(10)

SCL=0

SDA=1 //应答信号低电平有效,故需将其重新置高电平

}

void nack_iic()

{

SDA=1 //主器件发非应答信号,通知AT24C08不再发送数据

SCL=1

Delay(10)

SCL=0

SDA=0 //非应答信号高电平有效,故需将其重新置低电平

}

Write_byte(uchar c)

{

uchar i

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

{

if(c&0x80)SDA=1

else SDA=0

SCL=1

Delay(10)

SCL=0 //因为当时钟线有效是,数据线必须保持稳定的电平,

c=c<<1 //要改变SDA电平,应先将SCL拉低

}

SDA=1 //释放I2C总线,准备接受应答信号

SCL=1

Delay(10)

if(SDA==1)F0=0 //没有接到应答位

else F0=1

SCL=0

}

uchar Read_byte()

{

uchar i

uchar r=0

SDA=1 //置数据线为输入方式

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

{

r=r<<1

SCL=1

Delay(10) //保证一定的电平保持时带正间

if(SDA==1)r++ //从高位开始,一位一位的读

SCL=0

}

return r

}

main()

{

uchar slave=0xa0 //I2C总线从器件地址(注意:硬件电路的接法要是片选地址为0,否则不能工作)

uchar Rslave=slave+1 //主器件发送读控制字字节

uchar addre=0x20 // 指定的写数据地址

uchar wbuf=0x23 //将要写进逗行盯addre的数据

uchar rbuf //存放读出的数据的临时变量

start_iic() //产生起始信号

Write_byte(slave) //发送从器件地址

if(F0==0)return 0 //检查应答位

Write_byte(addre) //发送目的地址

if(F0==0)return 0

Write_byte(wbuf) //发送8为数据

if(F0==0)return 0

stop_iic() //停止信号

/*8位的数据发送完毕*/

Delay(1000)

start_iic()

Write_byte(slave)

if(F0==0)return 0

Write_byte(addre)

if(F0==0)return 0

start_iic() //再次产生起始信号,不能少

Write_byte(Rslave) //送读控制字

if(F0==0)return 0

rbuf=Read_byte() //读出指定单元的内容

nack_iic() //非应答信号

stop_iic()

/*8位的数据读取完毕*/

TMOD=0x20 //串口调试

TL1=0xfd

TH1=0xfd

SCON=0x40

PCON=0x00

TR1=1

while(1)

{

SBUF=rbuf //放入缓冲

while(TI==0)

TI=0

Delay(10000)

}

}

先回答你的最后一问: 答 你说的很对,SCL脉冲永远都是由主机来提供,从机在SCL线蠢侍上永远都是输入状态。再回答你的第二问:答 你的第二句话是错误的。正确的说法是:I2C主机可以发送则洞SDA, 也可以从SDA上接收;从机可以根据主机的要求发送SDA数据,也可以从SDA上接收数据(当然这一过程要按照I2C通信协议规定的数据帧进行)发送和接收数据并不会改变主机和从机的区别。以上是I2C技术标准里规定死的,和单片机型号无关。最后回答你的第一个问题:答: 在弄清了I2C主机和从机的本质区别是看谁能提供SCL信号以后,我们再看看PIC单片机所谓 主模式---从模式是什么意思。早期的PIC单片机,没有I2C的硬件模块支持,要完成I2C的通信,必须通过两根普通I/O线,完全用软件来模拟。既然是软件模拟,自然孙档枯是可以模拟成主机运行,也可以模拟成从机。由于大量外围I2C器件都是制造成从机的,所以,软件模拟主机的情况居多。现今的PIC新型单片机,从物理硬件、中断、串行数据字节等,都有专门的I2C模块。这些模块如果是工作在从机状态下,就叫做从模式,工作在主机状态下,就是主模式。在一个I2C总线上,遵守一主多从的规定。


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

原文地址:https://54852.com/yw/8182325.html

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

发表评论

登录后才能评论

评论列表(0条)

    保存