我用模拟的程序测试硬件没问题,但是smbus老是不通,那位做过点拨一下 下面是我的程序
问题在给1307里的寄存器付值后01-06,只能读出最后一次付的值
而且读不出01的值
老几位看看那里错了 #include <c8051f020.h> // SFR declarations
#include <absacc.h>
#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command
#define CHIP_SELECT 0xD0 // Device address for chip A
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit led=P3^0 ;
uchar Month; // 月 uchar Day; // 日 uchar Hour; // 时 uchar Minute; // 分 uchar Second; // 秒
uchar COMMAND; // 在SMBus 中断服务程序中用于保存从地址+ R/W 位。 uchar RESULT_BYTE; // 保持SMBus 要发送的数据字节或刚收到的数据 uchar BYTE_NUMBER; // 在中用于检查发送的是什么数据高地址字节、低地址字节或数据字节 uchar HIGH_ADD, LOW_ADD; // EEPROM 存储器地址的高、低字节
bit SM_BUSY; // 该位在发送或接收开始时被置1,操作结束后由中断服务程序清0
//////////////////////////////////
void Timer_Init() { CKCON = 0x20; TCON = 0x40; TMOD = 0x11; T2CON = 0x30; RCAP2L = 0xB2; RCAP2H = 0xFF; }
/////////////////////////////////////
void UART_Init() { SCON0 = 0x10; }
////////////////////////////////////
void SMBus_Init()
{ SMB0CN = 0x40;
SMB0CR = 0x91; }
////////////////////////////////////////
void Port_IO_Init() {
P0MDOUT = 0x03; P1MDOUT = 0x03; P3MDOUT = 0x01; XBR0 = 0x07; XBR2 = 0x40;
}
//////////////////////////////////////////////
void Oscillator_Init() //24M { int i = 0; OSCXCN = 0x67; for (i = 0; i < 3000; i++); // Wait 1ms for initialization while ((OSCXCN & 0x80) == 0); OSCICN = 0x88; }
/////////////////////////////////////////////////////////////
void Interrupts_Init() { IP = 0x10; EIE1 = 0x02;
}
/////////////////////////////////////////////////////////////
void Init_Device(void) { Timer_Init(); UART_Init(); //SMBus_Init(); Port_IO_Init(); Oscillator_Init(); Interrupts_Init(); }
//////////////////////////////////////////////////////////////
// SMBus 字节写函数----------------------------------------------------- // 向给定存储器地址写一个字节,out_byte = 待写数据,byte_address = 待写存储器地址(2 字节),chip_select = 待写EEPROM 芯片的器件地址 void SM_Send (char chip_select, uint byte_address, char out_byte)
{ while (SM_BUSY); // 等待SMBus 空闲 SM_BUSY = 1; // 占用SMBus(设置为忙) SMB0CN = 0x44; // SMBus 允许,应答周期发ACK BYTE_NUMBER = 2; // 2 地址字节 COMMAND = (chip_select | WRITE); // 片选+ WRITE HIGH_ADD = ((byte_address >> 8) & 0x00FF); // 高8 位地址 LOW_ADD = (byte_address & 0x00FF); // 低8 位地址 RESULT_BYTE = out_byte; // 待写数据 STA = 1; // 启动传输过程 }
////////////////////////////////////////////////////////////
// SMBus 随机读函数----------------------------------------------------- // 从给定存储器地址读一个字节,byte_address = 要读取的存储器地址,chip_select = 待读EEPROM 的器件地址
uchar SM_Receive (char chip_select, uint byte_address)
{ while (SM_BUSY); // 等待总线空闲 SM_BUSY = 1; //占用SMBus(设置为忙) SMB0CN = 0x44; // 允许SMBus,应答周期发ACK BYTE_NUMBER = 2; // 2 地址字节 COMMAND = (chip_select | READ); // 片选+ READ HIGH_ADD = ((byte_address >> 8) & 0x00FF); // 高8 位地址 LOW_ADD = (byte_address & 0x00FF); // 低8 位地址 STA = 1; // 启动传输过程 while (SM_BUSY); // 等待传输结束 return RESULT_BYTE; }
////////////////////////////////////////////////////////////////////
// SMBus states:
// MT = Master Transmitter
// MR = Master Receiver
#define SMB_BUS_ERROR 0x00 // (all modes) BUS ERROR #define SMB_START 0x08 // (MT & MR) START transmitted #define SMB_RP_START 0x10 // (MT & MR) repeated START #define SMB_MTADDACK 0x18 // (MT) Slave address + W transmitted; // ACK received #define SMB_MTADDNACK 0x20 // (MT) Slave address + W transmitted; // NACK received #define SMB_MTDBACK 0x28 // (MT) data byte transmitted; ACK rec'vd #define SMB_MTDBNACK 0x30 // (MT) data byte transmitted; NACK rec'vd #define SMB_MTARBLOST 0x38 // (MT) arbitration lost #define SMB_MRADDACK 0x40 // (MR) Slave address + R transmitted; // ACK received #define SMB_MRADDNACK 0x48 // (MR) Slave address + R transmitted; // NACK received #define SMB_MRDBACK 0x50 // (MR) data byte rec'vd; ACK transmitted #define SMB_MRDBNACK 0x58 // (MR) data byte rec'vd; NACK transmitted
//----------------------------------------------------------------------------------- //Global VARIABLES //----------------------------------------------------------------------------------- //char COMMAND; // Holds the slave address + R/W bit for // use in the SMBus ISR.
bit SM_BUSY; // This bit is set when a send or receive // is started. It is cleared by the // ISR when the operation is finished. uchar SMB_buf[56];
uchar SMB_num;
uchar SMB_ctr;
uchar start_adr;
//------------------------------------------------------------------------------------ // Function PROTOTYPES //------------------------------------------------------------------------------------ void SMBus_ISR (void); //------------------------------------------------------------------------------------ // MAIN Routine //------------------------------------------------------------------------------------ // // Main routine configures the crossbar and SMBus, and tests // the SMBus interface between the three EEPROMs
void main (void)
{ uchar i; // Used for testing purposes
WDTCN = 0xde; // disable watchdog timer
WDTCN = 0xad;
Init_Device();
EA = 1; // Global interrupt enable
SM_BUSY = 0; // Free SMBus for first transfer.
SM_Send (0xD0, 0x0000, 0x00);
SM_Send (0xD0, 0x0001, 0x59);
SM_Send (0xD0, 0x0002, 0x23);
SM_Send (0xD0, 0x0003, 0x04);
SM_Send (0xD0, 0x0005, 0x10);
SM_Send (0xD0, 0x0006, 0x08);
//SM_Send (0xD0, 0x003f, 0x00);
i=SM_Receive (0xD0, 0x0006);
//if (i==0x00)
//{led=~led; }
while(1); {}
} //------------------------------------------------------------------------------------ // Interrupt Service Routine //------------------------------------------------------------------------------------
// SMBus interrupt service routine:
void SMBUS_ISR (void) interrupt 7 { switch (SMB0STA){ // Status code for the SMBus (SMB0STA register)
// Master Transmitter/Receiver: START condition transmitted. // The R/W bit of the COMMAND word sent after this state will // always be a zero (W) because for both read and write, // the memory address must be written first. case SMB_START: //0x08 SMB0DAT = (COMMAND & 0xFE); // Load address of the slave to be accessed.写操作 STA = 0; // Manually clear START bit break;
// Master Transmitter/Receiver: Repeated START condition transmitted. // This state should only occur during a read, after the memory address has been // sent and acknowledged. case SMB_RP_START: //0x10 SMB0DAT = COMMAND; // COMMAND should hold slave address + R. STA = 0; break;
// Master Transmitter: Slave address + WRITE transmitted. ACK received. case SMB_MTADDACK: //0x18 SMB0DAT = start_adr; // Load memory address to be written.
break;
// Master Transmitter: Slave address + WRITE transmitted. NACK received. // The slave is not responding. Send a STOP followed by a START to try again. case SMB_MTADDNACK: //0x20 STO = 1; STA = 1; break;
// Master Transmitter: Data byte transmitted. ACK received. // This state is used in both READ and WRITE operations. Check BYTE_NUMBER // for memory address status - if only HIGH_ADD has been sent, load LOW_ADD. // If LOW_ADD has been sent, check COMMAND for R/W value to determine // next state. case SMB_MTDBACK: //0x28 if(SMB_num) { // If BYTE_NUMBER=1, LOW_ADD was just sent. if (COMMAND & 0x01){ // If R/W=READ, sent repeated START. STO = 0; STA = 1;
} else { SMB0DAT = SMB_buf[SMB_ctr]; // If R/W=WRITE, load byte to write. SMB_ctr++; SMB_num--; } } else{ // If BYTE_NUMBER=0, transfer is finished. STO = 1; SM_BUSY = 0; // Free SMBus } break;
// Master Transmitter: Data byte transmitted. NACK received. // Slave not responding. Send STOP followed by START to try again. case SMB_MTDBNACK: //0x30 STO = 1; STA = 1; break;
// Master Transmitter: Arbitration lost. // Should not occur. If so, restart transfer. case SMB_MTARBLOST: //0x38 STO = 1; STA = 1; break;
// Master Receiver: Slave address + READ transmitted. ACK received. // Set to transmit NACK after next transfer since it will be the last (only) // byte. case SMB_MRADDACK: //0x40 AA = 1; // ACK sent on acknowledge cycle. break;
// Master Receiver: Slave address + READ transmitted. NACK received. // Slave not responding. Send repeated start to try again. case SMB_MRADDNACK: //0x48 STO = 0; STA = 1; break;
// Data byte received. ACK transmitted. // State should not occur because AA is set to zero in previous state. // Send STOP if state does occur. case SMB_MRDBACK: //0x50 if(SMB_num>1) { // If BYTE_NUMBER=1, LOW_ADD was just sent. SMB_buf[SMB_ctr] = SMB0DAT; // If R/W=WRITE, load byte to write. SMB_ctr++; SMB_num--; AA=1; } else if(SMB_num ==1){ SMB_buf[SMB_ctr] = SMB0DAT; // If R/W=WRITE, load byte to write. SMB_ctr++; SMB_num--; AA=0; } break;
// Data byte received. NACK transmitted. // Read operation has completed. Read data register and send STOP. case SMB_MRDBNACK: //0x58 SMB_buf[SMB_ctr] = SMB0DAT; STO = 1; SM_BUSY = 0; // Free SMBus break;
// All other status codes meaningless in this application. Reset communication. default: STO = 1; // Reset communication. SM_BUSY = 0; break; }
SI=0; // clear interrupt flag }
|