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

PIC16F877A单片机 (IIC总线)

1 基本原理

1.1 IIC总线

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
需要注意的是,高四位对于同种芯片而言,都是一样的。例如AT24C02芯片的高四位固定为1010。

1.2 AT24C02芯片

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

2 源代码


/*---------------------函数功能:
		IIC总线 AT24C02

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


#include<pic.h>// 调用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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值