⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 此源码利用单片机模拟实现IIC总线通信
💻 C
字号:
/*****************************************/
/* Copyright (c) 2005, 通信工程学院      */
/* All rights reserved.                  */
/* 作    者:戴 佳				  	     */
/*****************************************/

#include "I2C.h"

/* 延时约5微秒,对于12M时钟 */
void delay5us()
{
	uint i;
	for (i=0;i<5;i++)
		_nop_();	
}

/* 起始条件子函数 */
void start(void)
{
	SDA = 1;			// 启动I2C总线
	SCL = 1;
	delay5us();
	SDA = 0;
	delay5us();
	SCL = 0;
}

/* 停止条件子函数 */
void stop(void)
{
	SDA = 0;			// 停止I2C总线数据传送
	SCL = 1;
	delay5us();
	SDA = 1;
	delay5us();
	SCL = 0;
}

/* 发送应答子函数 */
void ack(void)
{
	SDA = 0;			// 发送应答位
	SCL = 1;
	delay5us();
	SDA = 1;
	SCL = 0;
}

/* 发送非应答子函数 */
void n_ack(void)
{
	SDA = 1;			// 发送非应答位
	SCL = 1;
	delay5us();
	SDA = 0;
	SCL = 0;
}

/* 应答位检查子函数 */
void checkack(void)
{ 
	SDA = 1;    		// 应答位检查(将p1.0设置成输入,必须先向端口写1)
	SCL = 1;
	nackFlag = 0;
	if(SDA == 1)    	// 若SDA=1表明非应答,置位非应答标志F0
		nackFlag = 1;
	SCL = 0;
}

/* 发送一个字节数据子函数 */
void sendbyte(uchar idata *ch)
{ 
	uchar idata n = 8;  
	uchar idata temp;
	temp = *ch;
	while(n--)
	{ 
		if((temp&0x80) == 0x80)    // 若要发送的数据最高位为1则发送位1
		{
			SDA = 1;    // 传送位1
			SCL = 1;
			delay5us();
			SDA = 0;
			SCL = 0;    
		}
		else
		{  
			SDA = 0;    // 否则传送位0
			SCL = 1;
			delay5us();
			SCL = 0;  
		}
		temp = temp<<1;    // 数据左移一位
	}
}


/* 接收一字节子程序 */
void recbyte(uchar idata *ch)
{
	uchar idata n=8;    // 从SDA线上读取一位数据字节,共8位
	uchar idata temp = 0;
	while(n--)
	{
		SDA = 1;
		SCL = 1;
		temp = temp<<1;    // 左移一位
		if(SDA == 1)
			temp = temp|0x01;    // 若接收到的位为1,则数据的最后一位置1
		else 
			temp = temp&0xfe;    // 否则数据的最后一位置0
		SCL=0;
	}
	*ch = temp;
}

/* 发送n字节数据子程序 */
void sendnbyte(uchar idata *sla, uchar n)
{          
	uchar idata *p;
	start();				// 发送启动信号
	sendbyte(sla);    		// 发送从器件地址字节
	checkack();    			// 检查应答位
    if(F0 == 1)
	{ 
		NACK = 1;
		return;    		// 若非应答表明器件错误或已坏,置错误标志位NACK
	}
	p = sbuf;
	while(n--)
	{ 
		sendbyte(p);
		checkack();    	// 检查应答位
		if (nackFlag == 1)
		{
			NACK=1;
			return;    	// 若非应答表明器件错误或已坏,置错误标志位NACK
		}
		p++;
	}
	stop();    			// 全部发完则停止
}

/* 接收n字节数据子程序 */
void recnbyte(uchar idata *sla, uchar n)
{ 
	uchar idata *p;
	start();			// 发送启动信号
	sendbyte(sla);		// 发送从器件地址字节
	checkack();			// 检查应答位
	if(nackFlag == 1)
	{
		NACK = 1;
		return;
	}
	p = rbuf;			// 接收字节存放在rbuf中
	while(n--)
	{ 
		recbyte (p);
		ack();    		// 收到一个字节后发送一个应答位
		p++;
	}
	n_ack();    		// 收到最后一个字节后发送一个非应答位
	stop();
}

/* 主函数,模拟实现I2C总线的数据收发 */
void main(void)
{
	uchar i,numbyte;

	numbyte = 8;

	/* 需发送的8字节数据 */
	for (i=0;i<numbyte;i++)
		sbuf[i] = i+0x11;
 
	SLAdd = 0x58;		// 从器件地址
	
   	sendnbyte(&SLAdd,numbyte);	// 向从器件发送存放在sbuf中的8字节数据

	for (i=0;i<10000;i++)
		delay5us();

	recnbyte(&SLAdd,numbyte);	// 由从器件接收8字节数据,存放在rbuf中

}





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -