www.pudn.com > fm31256.rar > 020_SMBus.c
#include "020_SmBus.h" #include "C8051F020.H" #include "020_IO_PORT.H" #includebit 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; } } }