单片机
返回首页

PIC16F877A单片机 (IIC总线+AT24C02芯片)

2022-01-10 来源:eefocus

1 基本原理

1.1 IIC总线

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

需要注意的是,高四位对于同种芯片而言,都是一样的。例如AT24C02芯片的高四位固定为1010。


1.2 AT24C02芯片

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2 源代码


/*---------------------函数功能:

IIC总线 AT24C02


-----------------------------------------*/


#include// 调用PIC16f87XA单片机的头文件

#include'delay.h'//调用延时子函数的头文件


__CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关

//__CONFIG(HS&WDTDIS&LVPDIS);


/*-----------宏定义--------------*/

#define  uint  unsigned int

#define  uchar unsigned char

#define  SDA     RC4 // IIC的数据线

#define  SCL     RC3 // IIC的时钟线


/*-----------子函数声明--------------*/

void IIC_start(void); // IIC启动信号函数

void IIC_end(void); // IIC终止信号函数


void write_1Byte(uchar buf);//向IIC总线写一个字节的函数

char read_1Byte(); //从IIC总线读一个字节的函数


void write_AT24C02(char address,char databuf); //向AT24C02芯片的指定地址写一个字节的数据

char read_AT24C02(char address); //从AT24C02芯片的指定地址读一个字节的数据




/*-----------主函数--------------*/

void main()

{

char bufdata;


// data direction register is TRISA. 

// Setting  a TRISA bit (= 1) will make the corresponding PORTA pi an input. 

// Clearing a TRISA bit (= 0) will make the corresponding PORTA pin an output.

TRISD=0x00; //RD作为输出口,作为LED灯的显示

PORTD=0x00; //LED的初值为0

delay(1000);


while(1)

{

bufdata=read_AT24C02(0x18);// 从AT24C02中地址0x18读出数据

PORTD=bufdata;

delay(1000);



bufdata=bufdata+1;

PORTD=bufdata;

delay(1000);



write_AT24C02(0x18,bufdata);//将+1的数据保存在0x18中

}

}









/*************IIC启动信号函数***************/

void IIC_start(void)

{

//为什么这样写,见IIC的时序图

SDA=1;

SCL=1;

asm('NOP');

asm('NOP');


SDA=0;

asm('NOP');

asm('NOP');


SCL=0;

asm('NOP');

asm('NOP');


}





/*************IIC终止信号函数***************/

void IIC_end(void)

{

SDA=0;

SCL=0;

asm('NOP');

asm('NOP');


SCL=1;

asm('NOP');

asm('NOP');


SDA=1;

asm('NOP');

asm('NOP');


SCL=0;//拉低

asm('NOP');

asm('NOP');


}





/*************向IIC总线写一个字节(8 bit)的函数***************/

void write_1Byte(uchar buf)

{

int k=0;

for(k=0;k<8;k++)

{

//将最高位写到SDA总线上去

//SDA=buf&0x80; // 等价于下面的if语句

if(buf&0x80) // 提取buf的最高位数据

SDA=1; //如果buf的最高位为1,就写1

else

SDA=0; //如果buf的最高位为0,就写0

asm('NOP');

asm('NOP');

SCL=1;

asm('NOP');


SCL=0; //时钟信号归零

asm('NOP');


buf=buf<<1; //左移一位,准备提取下一个待写的数据

}



// 每接收到一个字节的数据后,从机必须产生一个应答信号给主机。

// 应答器件在第9个时钟周期将SDA线拉低,表示已经接收了一个八位数据

TRISC4=1; //RC4作为输入,SDA引脚接的是RC4口   开始读数据,读SDA的值

asm('NOP');


SCL=1;

asm('NOP');

asm('NOP');

//if(RC4=0) //说明SDA=0,即成功接收

SCL=0;

TRISC4=0;

}





/*************向IIC总线读一个字节(8 bit)的函数***************/

char read_1Byte()

{

int k=0;

char t_byte=0x00;


TRISC4=1; //RC4作为输入,SDA引脚接的是RC4口     开始读数据,读SDA的值


for(k=0;k<8;k++)

{

t_byte=t_byte<<1; //左移一位

SCL=1;

asm('NOP');

asm('NOP');


//读 SDA的值

if(SDA=1) 

t_byte=t_byte|0x01;//写1 只对最低位有影响

else

t_byte=t_byte&0xfe;//写0


SCL=0;

asm('NOP');

asm('NOP');

}


TRISC4=0;


return t_byte; // 返回的是一个字节 eg:0x3f

}






/*************向AT24C02芯片的指定地址写一个字节的数据***************/

void write_AT24C02(char address,char databuf)

{

IIC_start(); //发送起始信号


//AT24C02芯片寄存器: 1010 A2 A1 A0 R/W_n  AT24C02芯片的高四位固定为1010

// A2A1A0:从机选择,一共可以接八个AT24C02芯片。  A2A1A0=000,选择第一个芯片。  R/W_n:读/写


//选择某一个从器件(确定用哪一个芯片)

write_1Byte(0xa0); //发送从器件地址000,选择第一个芯片。R/W_n=0,表示写

//指定该器件内部的某一个地址(确定芯片内部地址)

write_1Byte(address); //指定该芯片内部的某一个地址(一共有256个地址)

//向该芯片的指定地址里面写数据

write_1Byte(databuf); //向指定地址发送数据


IIC_end(); //发送结束信号

}





/*************从AT24C02芯片的指定地址读一个字节的数据***************/

char read_AT24C02(char address)

{

char buf;


//AT24C02芯片寄存器: 1010 A2 A1 A0 R/W_n  AT24C02芯片的高四位固定为1010

// A2A1A0:从机选择,一共可以接八个AT24C02芯片。  A2A1A0=000,选择第一个芯片。  R/W_n:读/写


IIC_start(); //发送起始信号

//选择某一个从器件(确定用哪一个芯片)

write_1Byte(0xa0); //发送从器件地址000,选择第一个芯片。R/W_n=0,表示写

//指定该器件内部的某一个地址(确定芯片内部地址)

write_1Byte(address); //指定该芯片内部的某一个地址(一共有256个地址)





//在传输过程中,当需要改变传送方向时(写<->读),起始信号IIC_start()和从机地址write_1Byte(0xa1)都被重复产生一次

//由于写变成读,所以需要下面两条指令

IIC_start(); //再次启动

//选择某一个从器件(确定用哪一个芯片)  此时要准备读数据

write_1Byte(0xa1); //发送从器件地址,选择第一个芯片。R/W_n=1,表示读

//读出该芯片指定地址的数据

buf=read_1Byte();



IIC_end(); //发送结束信号




return buf; // 返回的是一个字节 eg:0x3f

}

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

最新器件
精选电路图
  • 光控音效发生器电路

  • 优化电路板布局的简单方法

  • 一个简单的立体声平衡指示器电路

  • 分享一个电网倾角计电路

  • 使用NE555和磁簧开关的橱柜照明电路

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章