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

📄 i2c.c

📁 单片机C语言程序设计.日历时钟用液晶显示
💻 C
字号:
#include <c8051f020.h>
//------------------------------------------------------------------------------------
// Global CONSTANTS
//------------------------------------------------------------------------------------

#define 	WRITE	0x00						// SMBus WRITE command
#define		READ 	0x01						// SMBus READ command

//SMBus状态:MT=主发送器;MR=主接受器
#define	SMB_BUS_ERROR	0x00			// (所以模式)总线错
#define	SMB_START		0x08			// (主发送器和主接受器)开始条件已发送
#define	SMB_RP_START	0x10			// (主发送器和主接受器)重复开始条件已发送
#define	SMB_MTADDACK	0x18			// (主发送器)从地址+W 已发送,收到ACK									
#define	SMB_MTADDNACK	0x20			// (主发送器)从地址+W 已发送,收到NACK								
#define	SMB_MTDBACK		0x28			// (主发送器)数据字节已发送,收到ACK
#define	SMB_MTDBNACK	0x30			// (主发送器)数据字节已发送,收到NACK
#define	SMB_MTARBLOST	0x38			// (主发送器)竞争失败
#define	SMB_MRADDACK	0x40			// (主接受器)从地址+R已发送,收到ACK									
#define	SMB_MRADDNACK	0x48			//	(主接受器)从地址+R已发送,收到NACK										
#define	SMB_MRDBACK		0x50			// 	 (主接受器)数据字节已收到,ACK已发出
#define	SMB_MRDBNACK	0x58			// 	 (主接受器)数据字节已收到,NACK已发出

//--------------------------------------------------------------------
//全局变量
//--------------------------------------------------------------------
unsigned char COMMAND; 			// 在SMBus 中断服务程序中用于
								// 保存从地址+ R/W 位。
unsigned char *I2CDataBuff;		// 保持SMBus 要发送的数据字节				
								// 或刚收到的数据
unsigned char NByte;	 		// 数据字节数
								// 高地址字节、低地址字节或数据字节
unsigned char HIGH_ADD, LOW_ADD;// EEPROM 存储器地址的高、低字节
bit SM_BUSY; 					// 该位在发送或接收开始时被置1,
								// 操作结束后由中断服务程序清0
bit Attrib;						// 地址字节数 1为双字节,0为单字节

//------------------------------------------------------------------------------------
// Function PROTOTYPES
//------------------------------------------------------------------------------------

void SMBus0_Init(void)
{
	SMB0CN = 0x44; 				// 允许SMBus 在应答周期发送ACK
	SMB0CR = -80; 				// SMBus 时钟频率= 100kHz.
	EIE1 |= 2; 					// SMBus 中断允许
	EA = 1; 					// 全局中断允许
	SM_BUSY = 0; 				// 为第一次传输释放SMBus。
}

// SMBus 中断服务程序
void SMBUS_ISR (void) interrupt 7
{
                               // SMBus 状态码(SMB0STA 寄存器)
	switch (SMB0STA)
	{ 	
                             // 主发送器/接收器:起始条件已发送
                             // 在该状态发送的COMMAND 字的R/W 位总是为0(W),
                             // 因为对于读和写操作来说都必须先写存储器地址。
		case SMB_START:
			SMB0DAT = (COMMAND & 0xFE); // 装入要访问的从器件的地址
			STA = 0; 					// 手动清除START 位
			break;
                            // 主发送器/接收器:重复起始条件已发送。
                            // 该状态只应在读操作期间出现,在存储器地址已发送并得到确认之后
		case SMB_RP_START:
			SMB0DAT = (COMMAND | 0x01);	// COMMAND 中应保持从地址 + R.
			STA = 0;
			break;
                            // 主发送器: 从地址+ WRITE 已发送,收到ACK。
		case SMB_MTADDACK:
			SMB0DAT = HIGH_ADD;
			break;	
                           // 主发送器: 数据字节已发送         收到ACK
		case SMB_MTDBACK:
			if( Attrib )			  // 如果为 2 字节地址
			{
				Attrib  = 0;		  // 清标志位
				SMB0DAT = LOW_ADD;	  // 发低字节地址
				break;
			}
			else if( COMMAND & 0x01 ) // 如果为读操作
			{
				STA = 1;			  // 重复起始条件
				break;
			}
			else if( NByte )		  // 如果未写完数据,继续写直到NByte=0;
			{
				SMB0DAT = *I2CDataBuff;
				I2CDataBuff++;
				NByte--;			
				break;
			}
			else
			{
				STO = 1;	
				SM_BUSY = 0;		  
			}
			break;
                                      // 主发送器 从地址 + WRITE 已发送 收到NACK
                                      // 从器件不应答发送STOP + START 重试
		case SMB_MTADDNACK:
                                      // 主发送器 数据字节已发送        收到NACK
                                      // 从器件不应答发送STOP + START 重试
		case SMB_MTDBNACK:
                                      // 主发送器竞争失败
                                      // 不应出现如果出现重新开始传输过程
		case SMB_MTARBLOST:
			STO = 1;			
			STA = 1;
			break;
                                     // 主接收器从地址 + READ 已发送,收到ACK
		case SMB_MRADDACK:
			AA = 1;                      // 在应答周期ACK
			if (!NByte)
			{	
				STO = 1;	
				SM_BUSY = 0;			 // 释放SMBus
			}
			break;
                                       // 主接收器从地址 + READ 已发送收到NACK
                                       // 从器件不应答发送重复起始条件重试
		case SMB_MRADDNACK:
			STA = 1;
			break;				   
                                        // 收到数据字节ACK 已发送
                                        // 该状态不应出现因为AA 已在前一状态被清0 如果出现发送停止条件
		case SMB_MRDBACK:
			if ( NByte )
			{
				*I2CDataBuff = SMB0DAT;		
				I2CDataBuff++;
				NByte--;			
			}
			if (!NByte)	
				AA= 0;
			break;
                                        // 收到数据字节 NACK 已发送
                                        // 读操作已完成读数据寄存器后发送停止条件
		case SMB_MRDBNACK:
			STO = 1;
			SM_BUSY = 0;               // 释放SMBus
			break;
// 在本应用中所有其它状态码没有意义通信复位
		default:
			STO = 1;                   // 通信复位
			SM_BUSY = 0; 
			break;
		}
	SI=0;                              // 清除中断标志
}

⌨️ 快捷键说明

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