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

📄 c8051f120-i2c-simulate.c

📁 c8051f120端口模拟的I2C,点亮PCF8574驱动的发光二极管
💻 C
📖 第 1 页 / 共 2 页
字号:

// Example software to demonstrate the C8051F12x SMBus interface in
// Master mode.
// - Interrupt-driven SMBus implementation
// - Only master states defined (no slave or arbitration)
// - 1-byte SMBus data holders used for each transmit and receive
// - Timer3 used by SMBus for SCL low timeout detection
// - SCL frequency defined by <SMB_FREQUENCY> constant
// - ARBLOST support included
// - Pinout:
//    P1.5 -> SDA (SMBus)
//    P1.4 -> SCL (SMBus)
//
//    P1.6 -> LED
//
//    all other port pins unused
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <c8051f120.h>                 // SFR declarations
#include <intrins.h>

#define uchar  unsigned char
#define uint   unsigned int
#define ulong  unsigned long

#define Crystal_Clock 22118400L        // External Crystal oscillator
                                       // frequency (Hz),MCU internal oscillator 24.5MHz
                                       // NOTE: This value will determine the
                                       // XFCN bits in ExtCrystalOsc_Init ()

#define SYSCLK       22118400L        //此处使用外部晶体振荡器频率,不分频

//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------


// 16-bit SFR declarations
sfr16    RCAP4    = 0xCA;              // Timer4 reload value
sfr16    TMR4     = 0xCC;              // Timer4 counter

sbit LED     = P1^6;                   // green LED: '1' = ON; '0' = OFF
sbit SW      = P3^7;                   // SW ='0' means switch pressed
sbit OUT1    = P4^1;

sbit SCL  = P1^4;                          // 将p1.4口模拟时钟口
sbit SDA  = P1^5;                         // 将p1.5口模拟数据口

bit bdata  ACK;
#define  NUM  10 	                    //	接收和发送缓存区的深度
uchar idata sendbuf[NUM];       // 数据发送缓冲区
uchar idata receivebuf[NUM];    // 数据接收缓冲区
bit   bdata SystemError;                // 从机错误标志位

              
//------------------------------------------------------------------------------------
// Function PROTOTYPES
//------------------------------------------------------------------------------------
void SYSCLK_Init (void);
void ExtCrystalOsc_Init (void);

void PORT_Init (void);

//void Timer0_ms (uint ms);								//定时器1作为1ms基准中断
//void Timer0_us (ulong us); 
      
void Delay1us(uchar us);
void Delay1ms(uchar T);

void I2C_start(void);
void I2C_stop(void);
//void slave_ACK(void);
//void slave_NOACK(void);
void check_ACK(void);
void I2CSendByte(uchar ch);
void writeNbyte(uchar slave_add, uchar n);

//--------------------------------------------------------------------------------------------------
// 函数名称: I2C_start()
// 函数功能: 启动I2C总线子程序
//--------------------------------------------------------------------------------------------------
void I2C_start(void)
{                  //时钟保持高,数据线从高到低一次跳变,I2C通信开始
	//EA  = 0;
	SDA = 1;
	SCL = 1; 
	   //Delay1us(1);
	Delay1us(5);      // 延时5us 
	SDA = 0;	
	   //Delay1us(1);
	Delay1us(5);
	SCL = 0;	
}

//--------------------------------------------------------------------------------------------------
// 函数名称: I2C_stop()
// 函数功能: 停止I2C总线数据传送子程序
//--------------------------------------------------------------------------------------------------
void I2C_stop(void)
{ 
	SDA = 0;   	   //时钟保持高,数据线从低到高一次跳变,I2C通信停止
	SCL = 0;
	Delay1us(5);
	SCL = 1;
	Delay1us(5);
	SDA = 1;
}

/*
//--------------------------------------------------------------------------------------------------
// 函数名称: slave_ACK
// 函数功能: 从机发送应答位子程序
//--------------------------------------------------------------------------------------------------
void slave_ACK(void)
{
	SDA = 0;      //数据线保持低,时钟线发生一次从高低的跳变 发送一个应答信号 
	Delay1us(5);
	SCL = 1;
	Delay1us(5);			
	//SDA = 1;
	SCL = 0;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: slave_NOACK
// 函数功能: 从机发送非应答位子程序,迫使数据传输过程结束
//--------------------------------------------------------------------------------------------------
void slave_NOACK(void)
{ 
	SDA = 1;      //数据线保持高,时钟线发生一次从高低的跳变 没有应答 
	Delay1us(5);
	SCL = 1;
	Delay1us(5);
	//SDA = 0;
	SCL = 0;
}
*/
//--------------------------------------------------------------------------------------------------
// 函数名称: check_ACK
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束
//--------------------------------------------------------------------------------------------------
void check_ACK(void)
{ 
	SDA = 1;      
	SCL = 1;
	Delay1us(5);
	ACK = 0;
	if(SDA == 1)    // 若SDA=1表明非应答,置位非应答标志ACK
		ACK = 1;
	SCL = 0;
}

//--------------------------------------------------------------------------------------------------
// 函数名称: I2CSendByte
// 入口参数: ch
// 函数功能: 发送一个字节
//--------------------------------------------------------------------------------------------------
void I2CSendByte(uchar ch)
{ 
	uchar idata n=8;     // 向SDA上发送一位数据字节,共八位
	while(n--)
	{ 
		if((ch&0x80) == 0x80)    // 若要发送的数据最高位为1则发送位1
		{
			SDA = 1;    // 传送位1
			SCL = 1;
			Delay1us(5);
			SCL = 0;    
		}
		else
		{  
			SDA = 0;    // 否则传送位0
			SCL = 1;
			Delay1us(5);
			SCL = 0;  
		}
		ch = ch<<1;    // 数据左移一位
	}
	/*
	SDA = 1;        //释放数据线,准备接收应答位
	SCL = 1;
	Delay1us(5);		
	if (SDA == 1 ) ACK=1;
    else  ACK=0;
  SCL = 0;	*/
}


/*-------------------------------------------------------------------------------- 
// 调用方式:uchar I2CReceive(void)
// 函数说明:
// 返回接收的数据
// 函数功能: 接收一字节子程序
---------------------------------------------------------------------------------*/ 
/*
uchar I2CReceiveByte(void) 
{ 
uchar i=8,data=0; 
SDA=1; 
while (i--) 
{ 
data<<=1; 
SCL=0;
Delay1us(5); 
SCL=1;
Delay1us(5);   //时钟做一次从低到高的跳变 可以接收数据 
data|=SDA; 
} 
SCL=0; 
return data; 
}
*/


//--------------------------------------------------------------------------------------------------
// 函数名称: writeNbyte
// 入口参数: slave_add从机地址,n要发送的数据个数
// 函数功能: 发送n位数据子程序
//--------------------------------------------------------------------------------------------------
void writeNbyte(uchar slave_add, uchar n)
{          
	uchar idata send_da,i=0;
	I2C_start();                // 启动I2C
	I2CSendByte(slave_add);     // 发送地址位
	check_ACK();                // 检查应答位
    if(ACK == 1)
	{ 
		SystemError=1;
		return;    								// 若非应答表明器件错误或已坏,置错误标志位SystemError
	}
	//while(n--)
	//{ 
	//send_da = sendbuf[i++];	
	Delay1us(5);								//[宜加时间间隔
	send_da = n; 
	I2CSendByte(send_da);
		check_ACK();    // 检查应答位
		if (ACK == 1)
		{
			SystemError=1;
			return;    // 若非应答表明器件错误或已坏,置错误标志位SystemError
		}
	//}
	I2C_stop();         // 全部发完则停止
}


//--------------------------------------------------------------------------------------------------
// 函数名称: receiveNbyte
// 入口参数: slave_add从机地址,n要接收的数据个数
// 函数功能: 接收n位数据子程序
//--------------------------------------------------------------------------------------------------
/*
void receiveNbyte(uchar idata slave_add, uchar n)
{ 
	uchar idata receive_da,i=0;
	I2C_start();
	I2CSendByte(slave_add);
	check_ACK();
	if(ACK == 1)
	{
		SystemError = 1;
		return;
	}
	while(n--)
	{ 
		receive_da=I2CreceiveByte();
		receivebuf[i++]=receive_da;
		slave_ACK();    // 收到一个字节后发送一个应答位
	}
	slave_NOACK();    // 收到最后一个字节后发送一个非应答位
	I2C_stop();
}
*/

void Delay1us(uchar us)
{
uchar i;
while (us)
{
   for(i=11;i>0;i--);
   --us;
}
}


void Delay1ms(uchar T) 
{ 
uchar i,j;
i=T;
for(;i>0;i--)
{
for(j=5;j>0;j--){ Delay1us(200);}

⌨️ 快捷键说明

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