📄 020_smbus.c
字号:
#include "020_SmBus.h"
#include "C8051F020.H"
#include "020_IO_PORT.H"
#include <intrins.h>
bit GBV_smbus_wr; //读写控制位
unsigned char GCV_slave_addr; //从机地址
unsigned char GCV_slave_subaddr_num; //从机子地址数
unsigned int GIV_slave_subaddr; //从机子地址
unsigned char GCV_slave_data_num; //从机数据长度
unsigned char xdata *GPV_slave_data_array; //读写数据指针
//读写FRAM函数
void fram_wr_fun(bit B_wr, //读写控制位
unsigned int subaddr, //读写从机子地址
unsigned char length_of_data, //数据长度
unsigned char *P_to_wr_array) //读写指针
{
GBV_smbus_wr = B_wr;
GIV_slave_subaddr = subaddr;
GCV_slave_data_num = length_of_data;
GPV_slave_data_array = P_to_wr_array;
GCV_slave_addr = 0xa0;
GCV_slave_subaddr_num = 2;
STO = 0;
STA = 1;
}
//读写WDT_RTC函数
void wdt_rtc_wr_fun(bit B_wr, //读写控制位
unsigned int subaddr, //读写从地址
unsigned char length_of_data, //数据长度
unsigned char *P_to_wr_array) //读写指针
{
GBV_smbus_wr = B_wr;
GIV_slave_subaddr = subaddr;
GCV_slave_data_num = length_of_data;
GPV_slave_data_array = P_to_wr_array;
GCV_slave_addr = 0xd0;
GCV_slave_subaddr_num = 1;
STO = 0;
STA = 1;
}
void SMBUS_ISR(void) interrupt 7
{
#define SEND_STA 0X08
#define SEND_RE_STA 0X10
#define SEND_ADDR_W_REC_ACK 0X18
#define SEND_ADDR_W_REC_NACK 0X20
#define SEND_DATA_REC_ACK 0X28
#define SEND_DATA_REC_NACK 0X30
#define COMPETE_FAIL 0X38
#define SEND_ADDR_R_REC_ACK 0X40
#define SEND_ADDR_R_REC_NACK 0X48
#define REC_DATA_SEND_ACK 0X50
#define REC_DATA_SEND_NACK 0X58
SBUF0 = SMB0STA;
switch(SMB0STA)
{
//08 起始位已发出,清除STA,然后判断条件相应发出读或写地址,送入SMB0DAT
case SEND_STA:
{
STA = 0;
//发送从机+读写地址
if(!GBV_smbus_wr)
{SMB0DAT = GCV_slave_addr;
}
else
{SMB0DAT= GCV_slave_addr|0x01;
}
SI = 0;
break;
}
//10 重复起始位已发出,清除STA,然后判断条件相应发出读或写地址,送入SMB0DAT
case SEND_RE_STA:
{
STA = 0;
SMB0DAT = GCV_slave_addr;
SI = 0;
break;
}
//18 写地址已发送并收到应答,相应送出从地址或者数据到SMB0DAT,或者停止传输或者重复起始
case SEND_ADDR_W_REC_ACK:
{
//如果从机子地址为2位,则先发送高位,子地址数减1
if (GCV_slave_subaddr_num >= 2)
{
GCV_slave_subaddr_num = 1;
SMB0DAT = (unsigned char)(GIV_slave_subaddr >> 8);
}
//如果从机子地址为1位,则发送低位即,子地址数减1
else if (GCV_slave_subaddr_num == 1)
{
GCV_slave_subaddr_num = 0;
SMB0DAT = (unsigned char)GIV_slave_subaddr;
}
//没有子地址,则结束传输操作
else
{
STO = 1;
STA = 0;
_nop_();
}
SI = 0;
break;
}
//20 写地址已发送并收到非应答,发送重复起始位或者结束本次传输
case SEND_ADDR_W_REC_NACK:
{
//结束本次传输
STO = 1;
STA = 0;
SI = 0;
break;
}
//28 数据已发送并收到应答,发送下个数据或者停止传输或者重复起始条件。
case SEND_DATA_REC_ACK:
{
//两种可能:写操作写出子地址,读操作写出子地址
//为1则为读操作
if (GBV_smbus_wr)
{
//如果从机子地址为1位,则发送低位即,子地址数减1
if (GCV_slave_subaddr_num == 1)
{
GCV_slave_subaddr_num = 0;
SMB0DAT = (unsigned char)GIV_slave_subaddr;
}
//从机子地址发送完毕,则开始发送重复起始位
else
{
//STO = 1;
//STA = 1;
//从机地址变读
GCV_slave_addr |= 0x01;
//重复起始
SMB0CN |= 0X30;
}
}
//否则为写操作
else
{
//如果从机子地址为1位,则发送低位即,子地址数减1
if (GCV_slave_subaddr_num == 1)
{
GCV_slave_subaddr_num = 0;
SMB0DAT = (unsigned char)GIV_slave_subaddr;
}
//从机子地址发送完毕,则开始发送字节
else if (GCV_slave_data_num > 0)
{
SMB0DAT = *GPV_slave_data_array;
GCV_slave_data_num--;
GPV_slave_data_array++;
}
//数据发送完毕,则结束传输过程
else
{
STO = 1;
STA = 0;
_nop_();
}
}
SI = 0;
break;
}
//30 数据已发送并收到非应答,停止传输或者重复起始条件。
case SEND_DATA_REC_NACK:
{
//结束本次传输
STO = 1;
SI = 0;
break;
}
//38 竞争失败,保存当前数据
case COMPETE_FAIL:
{
_nop_();
SI = 0;
break;
}
//40 读地址已发送并收到应答,如果只接收1个字节,则AA位清0,否则等待接收数据
case SEND_ADDR_R_REC_ACK:
{
//如果只接收1个字节,则AA位清0,否则AA置1,允许应答
if (GCV_slave_data_num == 1)
{
AA = 0;
}
else
{
AA = 1;
}
SI = 0;
break;
}
//48 读地址已发送并收到非应答,发送重复起始位或者结束本次传输
case SEND_ADDR_R_REC_NACK:
{
//结束本次传输操作
STO = 1;
STA = 0;
SI = 0;
break;
}
//50 数据字节已收到并已发送完毕应答,读回SMB0DAT,等待下个字节,并判断,下个字节如果为最后一个字节,则AA位清0
case REC_DATA_SEND_ACK:
{
if (GCV_slave_data_num > 0)
{
//读取数据
*GPV_slave_data_array = SMB0DAT;
GPV_slave_data_array++;
GCV_slave_data_num--;
//下个字节如果为最后一个字节,则AA位清0
if (GCV_slave_data_num == 1)
{
AA = 0;
}
}
else
{
//结束传输
STO = 1;
STA = 0;
}
SI = 0;
break;
}
//58 数据字节已收到并已发送完毕非应答,则结束传输
case REC_DATA_SEND_NACK:
{
_nop_();
//读取数据
*GPV_slave_data_array = SMB0DAT;
//结束传输
STO = 1;
STA = 0;
SI = 0;
break;
}
default:
{
//结束传输
STO = 1;
SI = 0;
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -