📄 smbus.c
字号:
/***************************************Copyright (c)*************************************
**
/*--------------文件信息------------------------------------------------------------------
**文 件 名:SMBUS.C
**创 建 人:王胜
**日 期:2007年2月4日
**描 述:
** 本库函数可实现I2C总线一次读/写多个字节操作,将这两个文件复制到您的工程目录下,在
** 主函数中使用头文件包含语句 #include "SMBUS.h" 即可,其中包含三个函数:
**
** SMBUS初始化函数:
** void SMBus_Init(void);
**
** 多个字节数据的发送函数:
** void SMBUS_Puts(
** unsigned char chip,
** unsigned char wordadr,
** char *dat,
** unsigned char number
** );
**
** 多个字节数据的读取函数:
** void SMBUS_Gets(
** unsigned char chip,
** unsigned char wordadr,
** char *dat,
** unsigned char number
** );
**
** 输入变量定义如下:
** chip : 为I2C器件从地址,本实验板3个I2C器件(ZLG7290,24C02,PCF8563)的从地址定义
** (不包括R/W的控制)在头文件"SMBUS.h"中有定义。
** wordadr : 为I2C器件内部寄存器从器件子地址。
** dat : 为读/写数据指针,当为读取时,通过指针直接修改变量的值。
** number : 为每次读/写数据的字节数。
*******************************************************************************************/
#include <c8051f020.h>
//与SMBUS操作有关变量定义
bit SM_BUSY; //SMB0忙标志位.
unsigned char SMBMODE; //SMB0读写控制字CHIP_SELECT+R/W.
unsigned char SMB_num; //SMB0一次读写的字节数..
unsigned char start_adr; //SMB0读写字节在器件中的起始地址.
char *SMB_Dat; //SMBUS中断传输数据指针
/******************************************************************************************/
/*函数名称:SMBus_Init() */
/*函数功能:SMBus初始化函数 */
/*输入参数:无 */
/*输出参数:无 */
/******************************************************************************************/
void SMBus_Init(void)
{
SMB0CN = 0x44; //允许SMBUS, 应答返回AA(低电平有效)
SMB0CR = 0x00; //配置传送速度为42Kbit/s
EIE1 |= 0x02; //使能SMBUS中断
EIP1 |= 0x02; //设置SMBUS中断为高优先级
}
/******************************************************************************************/
/*函数名称:SMBUS_Puts() */
/*函数功能:SMBUS 总线综合发送函数,向从机发送number个字节的数据 */
/*入口参数:chip 从机地址(7位纯地址,不含读写位)
wordadr 从机的子地址
data 待发送的数据指针
number 发送数据的字节数 */
/*出口参数:无 */
/******************************************************************************************/
void SMBUS_Puts(unsigned char chip,unsigned char wordadr,char *dat,unsigned char number)
{
SI = 0;
SMB_num=number; // 确定写数据大小
while (SM_BUSY); // 若SMBUS忙碌就等待
SM_BUSY = 1; // SM_BUSY是忙碌标志位
SMBMODE=chip & 0xfe;
start_adr=wordadr; // 装载写字节起始地址
SMB_Dat= dat;
STO = 0;
STA = 1;
while (SM_BUSY);
}
/******************************************************************************************/
/*函数名称:SMBUS_Gets() */
/*函数功能:SMBUS 总线综合接收函数,从从机接收number个字节的数据 */
/*入口参数:chip 从机地址(7位纯地址,不含读写位)
wordadr 从机的子地址
*data 保存接收到的数据
number 读取数据的字节数 */
/*出口参数:无 */
/******************************************************************************************/
void SMBUS_Gets(unsigned char chip,unsigned char wordadr,char *dat,unsigned char number)
{
SI = 0;
SMB_num = number; //确定写数据大小
while (SM_BUSY); // 若SMBUS忙碌就等待
SM_BUSY = 1; // SM_BUSY是忙碌标志位
SMBMODE = chip | 0x01;
start_adr = wordadr; //装载写字节起始地址
SMB_Dat =dat;
STO = 0;
STA = 1;
while (SM_BUSY);
}
//SMBUS中断服务函数
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA)
{
case 0x08: //(MT & MR) 发送起始位
SMB0DAT = (SMBMODE & 0xFE); //发送从器件地址 + W
STA = 0;
break;
case 0x10: //(MT & MR) 重复起始位
SMB0DAT = (SMBMODE | 0x01); // 发送从器件地址 + R.
STA = 0;
break;
case 0x18: //(MT) 发送从地址 + W 后收到ACK
SMB0DAT = start_adr; // 发送SMB0读写字节在器件中的起始地址.
break;
case 0x20: //(MT) 发送从地址 + W 后收到NACK
STO = 1;
STA = 1;
break;
case 0x28: //(MT) 发送数据后收到ACK
if(SMB_num)
{
if (SMBMODE & 0x01) // 如果为读操作则重新启动总线.
{
STO = 0;
STA = 1;
}
else
{
SMB0DAT = *SMB_Dat; //如果为写操作则将数据写入SMB0DAT.
SMB_Dat++;
SMB_num--;
}
}
else //如果数据写入完毕则发送停止信号.
{
STO = 1;
SM_BUSY = 0;
}
break;
case 0x30: //(MT) 发送数据后收到NACK
STO = 1;
STA = 1;
break;
case 0x38 : //(MT)竞争失败
STO = 1;
STA = 1;
break;
case 0x40: //(MR) 发送从地址 + R 后收到 ACK
if(SMB_num==1) //如果只读一个字节则将应答位AA清0,
AA = 0; //收到数据以后不发送应答位
else
AA = 1; //如果读字节数大于1则收到数据以后发送应答位
break;
case 0x48: //(MR) 发送从地址 + R 后收到 NACK
STO = 0;
STA = 1;
break;
case 0x50: //(MR) 收到数据字节 后已发送ACK
if(SMB_num>2)
{
*SMB_Dat = SMB0DAT;
SMB_Dat++;
SMB_num--;
AA=1;
}
else if(SMB_num ==2)
{
*SMB_Dat = SMB0DAT;
SMB_Dat++;
SMB_num--;
AA=0;
}
break;
case 0x58: //(MR) 收到数据字节 后已发送NACK
*SMB_Dat = SMB0DAT;
STO = 1;
SM_BUSY = 0;
break;
default:
STO = 1;
SM_BUSY = 0;
break;
}
SI=0; // 清除中断标志
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -