📄 c8051f120-i2c-simulate.c
字号:
// 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 + -