打印

那位用c8051f020接过1307 smbus 通信

[复制链接]
2169|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chuandaoxy|  楼主 | 2008-1-6 18:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我用模拟的程序测试硬件没问题,但是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
}

相关帖子

沙发
hotpower| | 2008-1-6 19:27 | 只看该作者

就把它看成是有PEC校验的I2C即可

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

855

主题

1044

帖子

4

粉丝