打印
[MCU]

Example_2833xI2C_eeprom.c

[复制链接]
328|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhangmangui|  楼主 | 2019-12-27 23:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  • // TI File $Revision: /main/10 $   
  • // Checkin $Date: April 21, 2008   15:43:02 $   
  • //###########################################################################   
  • //   
  • // FILE:    Example_2833xI2c_eeprom.c   
  • //   
  • // TITLE:   DSP2833x I2C EEPROM Example   
  • //   
  • // ASSUMPTIONS:   
  • //   
  • //    This program requires the DSP2833x header files.   
  • //   
  • //    This program requires an external I2C EEPROM connected to   
  • //    the I2C bus at address 0x50.   
  • //   
  • //    As supplied, this project is configured for "boot to SARAM"   
  • //    operation.  The 2833x Boot Mode table is shown below.   
  • //    For information on configuring the boot mode of an eZdsp,   
  • //    please refer to the documentation included with the eZdsp,   
  • //   
  • //       $Boot_Table:   
  • //   
  • //         GPIO87   GPIO86     GPIO85   GPIO84   
  • //          XA15     XA14       XA13     XA12   
  • //           PU       PU         PU       PU   
  • //        ==========================================   
  • //            1        1          1        1    Jump to Flash   
  • //            1        1          1        0    SCI-A boot   
  • //            1        1          0        1    SPI-A boot   
  • //            1        1          0        0    I2C-A boot   
  • //            1        0          1        1    eCAN-A boot   
  • //            1        0          1        0    McBSP-A boot   
  • //            1        0          0        1    Jump to XINTF x16   
  • //            1        0          0        0    Jump to XINTF x32   
  • //            0        1          1        1    Jump to OTP   
  • //            0        1          1        0    Parallel GPIO I/O boot   
  • //            0        1          0        1    Parallel XINTF boot   
  • //            0        1          0        0    Jump to SARAM       <- "boot to SARAM"   
  • //            0        0          1        1    Branch to check boot mode   
  • //            0        0          1        0    Boot to flash, bypass ADC cal   
  • //            0        0          0        1    Boot to SARAM, bypass ADC cal   
  • //            0        0          0        0    Boot to SCI-A, bypass ADC cal   
  • //                                              Boot_Table_End$   
  • //   
  • // DESCRIPTION:   
  • //   
  • //    This program will write 1-14 words to EEPROM and read them back.   
  • //    The data written and the EEPROM address written to are contained   
  • //    in the message structure, I2cMsgOut1. The data read back will be   
  • //    contained in the message structure I2cMsgIn1.   
  • //   
  • //    This program will work with the on-board I2C EEPROM supplied on   
  • //    the F2833x eZdsp.   
  • //   
  • //   
  • //###########################################################################   
  • // Original Author: D.F.   
  • //   
  • // $TI Release: DSP2833x/DSP2823x C/C++ Header Files V1.31 $   
  • // $Release Date: August 4, 2009 $   
  • //###########################################################################   
  •    
  •    
  • #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File   
  •    
  • // Note: I2C Macros used in this example can be found in the   
  • // DSP2833x_I2C_defines.h file   
  •    
  • // Prototype statements for functions found within this file.   
  • void   I2CA_Init(void);   
  • Uint16 I2CA_WriteData(struct I2CMSG *msg);   
  • Uint16 I2CA_ReadData(struct I2CMSG *msg);   
  • interrupt void i2c_int1a_isr(void);   
  • void pass(void);   
  • void fail(void);   
  •    
  • #define I2C_SLAVE_ADDR        0x50   
  • #define I2C_NUMBYTES          4   
  • #define I2C_EEPROM_HIGH_ADDR  0x00   
  • #define I2C_EEPROM_LOW_ADDR   0x30   
  •    
  • // Global variables   
  • // Two bytes will be used for the outgoing address,   
  • // thus only setup 14 bytes maximum   
  • struct I2CMSG I2cMsgOut1={I2C_MSGSTAT_SEND_WITHSTOP,   
  •                           I2C_SLAVE_ADDR,   
  •                           I2C_NUMBYTES,   
  •                           I2C_EEPROM_HIGH_ADDR,   
  •                           I2C_EEPROM_LOW_ADDR,   
  •                           0x12,                   // Msg Byte 1   
  •                           0x34,                   // Msg Byte 2   
  •                           0x56,                   // Msg Byte 3   
  •                           0x78,                   // Msg Byte 4   
  •                           0x9A,                   // Msg Byte 5   
  •                           0xBC,                   // Msg Byte 6   
  •                           0xDE,                   // Msg Byte 7   
  •                           0xF0,                   // Msg Byte 8   
  •                           0x11,                   // Msg Byte 9   
  •                           0x10,                   // Msg Byte 10   
  •                           0x11,                   // Msg Byte 11   
  •                           0x12,                   // Msg Byte 12   
  •                           0x13,                   // Msg Byte 13   
  •                           0x12};                  // Msg Byte 14   
  •    
  •    
  • struct I2CMSG I2cMsgIn1={ I2C_MSGSTAT_SEND_NOSTOP,   
  •                           I2C_SLAVE_ADDR,   
  •                           I2C_NUMBYTES,   
  •                           I2C_EEPROM_HIGH_ADDR,   
  •                           I2C_EEPROM_LOW_ADDR};   
  •    
  • struct I2CMSG *CurrentMsgPtr;               // Used in interrupts   
  • Uint16 PassCount;   
  • Uint16 FailCount;   
  •    
  • void main(void)   
  • {   
  •    Uint16 Error;   
  •    Uint16 i;   
  •    
  •    CurrentMsgPtr = &I2cMsgOut1;   
  •    
  • // Step 1. Initialize System Control:   
  • // PLL, WatchDog, enable Peripheral Clocks   
  • // This example function is found in the DSP2833x_SysCtrl.c file.   
  •    InitSysCtrl();   
  •    
  •    
  • // Step 2. Initalize GPIO:   
  • // This example function is found in the DSP2833x_Gpio.c file and   
  • // illustrates how to set the GPIO to it's default state.   
  • // InitGpio();   
  • // Setup only the GP I/O only for I2C functionality   
  •    InitI2CGpio();   
  •    
  • // Step 3. Clear all interrupts and initialize PIE vector table:   
  • // Disable CPU interrupts   
  •    DINT;   
  •    
  • // Initialize PIE control registers to their default state.   
  • // The default state is all PIE interrupts disabled and flags   
  • // are cleared.   
  • // This function is found in the DSP2833x_PieCtrl.c file.   
  •    InitPieCtrl();   
  •    
  • // Disable CPU interrupts and clear all CPU interrupt flags:   
  •    IER = 0x0000;   
  •    IFR = 0x0000;   
  •    
  • // Initialize the PIE vector table with pointers to the shell Interrupt   
  • // Service Routines (ISR).   
  • // This will populate the entire table, even if the interrupt   
  • // is not used in this example.  This is useful for debug purposes.   
  • // The shell ISR routines are found in DSP2833x_DefaultIsr.c.   
  • // This function is found in DSP2833x_PieVect.c.   
  •    InitPieVectTable();   
  •    
  • // Interrupts that are used in this example are re-mapped to   
  • // ISR functions found within this file.   
  •    EALLOW;  // This is needed to write to EALLOW protected registers   
  •    PieVectTable.I2CINT1A = &i2c_int1a_isr;   
  •    EDIS;   // This is needed to disable write to EALLOW protected registers   
  •    
  • // Step 4. Initialize all the Device Peripherals:   
  • // This function is found in DSP2833x_InitPeripherals.c   
  • // InitPeripherals(); // Not required for this example   
  •    I2CA_Init();   
  •    
  • // Step 5. User specific code   
  •    
  •    // Clear Counters   
  •    PassCount = 0;   
  •    FailCount = 0;   
  •    
  •    // Clear incoming message buffer   
  •    for (i = 0; i < I2C_MAX_BUFFER_SIZE; i++)   
  •    {   
  •        I2cMsgIn1.MsgBuffer = 0x0000;   
  •    }   
  •    
  • // Enable interrupts required for this example   
  •    
  • // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1   
  •    PieCtrlRegs.PIEIER8.bit.INTx1 = 1;   
  •    
  • // Enable CPU INT8 which is connected to PIE group 8   
  •    IER |= M_INT8;   
  •    EINT;   
  •    
  •    // Application loop   
  •    for(;;)   
  •    {   
  •       //////////////////////////////////   
  •       // Write data to EEPROM section //   
  •       //////////////////////////////////   
  •    
  •       // Check the outgoing message to see if it should be sent.   
  •       // In this example it is initialized to send with a stop bit.   
  •       if(I2cMsgOut1.MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP)   
  •       {   
  •          Error = I2CA_WriteData(&I2cMsgOut1);   
  •          // If communication is correctly initiated, set msg status to busy   
  •          // and update CurrentMsgPtr for the interrupt service routine.   
  •          // Otherwise, do nothing and try again next loop. Once message is   
  •          // initiated, the I2C interrupts will handle the rest. Search for   
  •          // ICINTR1A_ISR in the i2c_eeprom_isr.c file.   
  •          if (Error == I2C_SUCCESS)   
  •          {   
  •             CurrentMsgPtr = &I2cMsgOut1;   
  •             I2cMsgOut1.MsgStatus = I2C_MSGSTAT_WRITE_BUSY;   
  •          }   
  •       }  // end of write section   
  •    
  •       ///////////////////////////////////   
  •       // Read data from EEPROM section //   
  •       ///////////////////////////////////   
  •    
  •       // Check outgoing message status. Bypass read section if status is   
  •       // not inactive.   
  •       if (I2cMsgOut1.MsgStatus == I2C_MSGSTAT_INACTIVE)   
  •       {   
  •          // Check incoming message status.   
  •          if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)   
  •          {   
  •             // EEPROM address setup portion   
  •             while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS)   
  •             {   
  •                // Maybe setup an attempt counter to break an infinite while   
  •                // loop. The EEPROM will send back a NACK while it is performing   
  •                // a write operation. Even though the write communique is   
  •                // complete at this point, the EEPROM could still be busy   
  •                // programming the data. Therefore, multiple attempts are   
  •                // necessary.   
  •             }   
  •             // Update current message pointer and message status   
  •             CurrentMsgPtr = &I2cMsgIn1;   
  •             I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY;   
  •          }   
  •    
  •          // Once message has progressed past setting up the internal address   
  •          // of the EEPROM, send a restart to read the data bytes from the   
  •          // EEPROM. Complete the communique with a stop bit. MsgStatus is   
  •          // updated in the interrupt service routine.   
  •          else if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_RESTART)   
  •          {   
  •             // Read data portion   
  •             while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS)   
  •             {   
  •                // Maybe setup an attempt counter to break an infinite while   
  •                // loop.   
  •             }   
  •             // Update current message pointer and message status   
  •             CurrentMsgPtr = &I2cMsgIn1;   
  •             I2cMsgIn1.MsgStatus = I2C_MSGSTAT_READ_BUSY;   
  •          }   
  •       }  // end of read section   
  •    
  •    }   // end of for(;;)   
  • }   // end of main   
  •    
  •    
  • void I2CA_Init(void)   
  • {   
  •    // Initialize I2C   
  •    I2caRegs.I2CSAR = 0x0050;        // Slave address - EEPROM control code   
  •    
  •    #if (CPU_FRQ_150MHZ)             // Default - For 150MHz SYSCLKOUT   
  •         I2caRegs.I2CPSC.all = 14;   // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz)   
  •    #endif   
  •    #if (CPU_FRQ_100MHZ)             // For 100 MHz SYSCLKOUT   
  •      I2caRegs.I2CPSC.all = 9;       // Prescaler - need 7-12 Mhz on module clk (100/10 = 10MHz)   
  •    #endif   
  •    
  •    I2caRegs.I2CCLKL = 10;           // NOTE: must be non zero   
  •    I2caRegs.I2CCLKH = 5;            // NOTE: must be non zero   
  •    I2caRegs.I2CIER.all = 0x24;      // Enable SCD & ARDY interrupts   
  •    
  •    I2caRegs.I2CMDR.all = 0x0020;    // Take I2C out of reset   
  •                                     // Stop I2C when suspended   
  •    
  •    I2caRegs.I2CFFTX.all = 0x6000;   // Enable FIFO mode and TXFIFO   
  •    I2caRegs.I2CFFRX.all = 0x2040;   // Enable RXFIFO, clear RXFFINT,   
  •    
  •    return;   
  • }   
  •    
  •    
  • Uint16 I2CA_WriteData(struct I2CMSG *msg)   
  • {   
  •    Uint16 i;   
  •    
  •    // Wait until the STP bit is cleared from any previous master communication.   
  •    // Clearing of this bit by the module is delayed until after the SCD bit is   
  •    // set. If this bit is not checked prior to initiating a new message, the   
  •    // I2C could get confused.   
  •    if (I2caRegs.I2CMDR.bit.STP == 1)   
  •    {   
  •       return I2C_STP_NOT_READY_ERROR;   
  •    }   
  •    
  •    // Setup slave address   
  •    I2caRegs.I2CSAR = msg->SlaveAddress;   
  •    
  •    // Check if bus busy   
  •    if (I2caRegs.I2CSTR.bit.BB == 1)   
  •    {   
  •       return I2C_BUS_BUSY_ERROR;   
  •    }   
  •    
  •    // Setup number of bytes to send   
  •    // MsgBuffer + Address   
  •    I2caRegs.I2CCNT = msg->NumOfBytes+2;   
  •    
  •    // Setup data to send   
  •    I2caRegs.I2CDXR = msg->MemoryHighAddr;   
  •    I2caRegs.I2CDXR = msg->MemoryLowAddr;   
  • // for (i=0; i<msg->NumOfBytes-2; i++)   
  •    for (i=0; i<msg->NumOfBytes; i++)   
  •    
  •    {   
  •       I2caRegs.I2CDXR = *(msg->MsgBuffer+i);   
  •    }   
  •    
  •    // Send start as master transmitter   
  •    I2caRegs.I2CMDR.all = 0x6E20;   
  •    
  •    return I2C_SUCCESS;   
  • }   
  •    
  •    
  • Uint16 I2CA_ReadData(struct I2CMSG *msg)   
  • {   
  •    // Wait until the STP bit is cleared from any previous master communication.   
  •    // Clearing of this bit by the module is delayed until after the SCD bit is   
  •    // set. If this bit is not checked prior to initiating a new message, the   
  •    // I2C could get confused.   
  •    if (I2caRegs.I2CMDR.bit.STP == 1)   
  •    {   
  •       return I2C_STP_NOT_READY_ERROR;   
  •    }   
  •    
  •    I2caRegs.I2CSAR = msg->SlaveAddress;   
  •    
  •    if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)   
  •    {   
  •       // Check if bus busy   
  •       if (I2caRegs.I2CSTR.bit.BB == 1)   
  •       {   
  •          return I2C_BUS_BUSY_ERROR;   
  •       }   
  •       I2caRegs.I2CCNT = 2;   
  •       I2caRegs.I2CDXR = msg->MemoryHighAddr;   
  •       I2caRegs.I2CDXR = msg->MemoryLowAddr;   
  •       I2caRegs.I2CMDR.all = 0x2620;         // Send data to setup EEPROM address   
  •    }   
  •    else if(msg->MsgStatus == I2C_MSGSTAT_RESTART)   
  •    {   
  •       I2caRegs.I2CCNT = msg->NumOfBytes; // Setup how many bytes to expect   
  •       I2caRegs.I2CMDR.all = 0x2C20;         // Send restart as master receiver   
  •    }   
  •    
  •    return I2C_SUCCESS;   
  • }   
  •    
  • interrupt void i2c_int1a_isr(void)     // I2C-A   
  • {   
  •    Uint16 IntSource, i;   
  •    
  •    // Read interrupt source   
  •    IntSource = I2caRegs.I2CISRC.all;   
  •    
  •    // Interrupt source = stop condition detected   
  •    if(IntSource == I2C_SCD_ISRC)   
  •    {   
  •       // If completed message was writing data, reset msg to inactive state   
  •       if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_WRITE_BUSY)   
  •       {   
  •          CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;   
  •       }   
  •       else   
  •       {   
  •          // If a message receives a NACK during the address setup portion of the   
  •          // EEPROM read, the code further below included in the register access ready   
  •          // interrupt source code will generate a stop condition. After the stop   
  •          // condition is received (here), set the message status to try again.   
  •          // User may want to limit the number of retries before generating an error.   
  •          if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)   
  •          {   
  •             CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;   
  •          }   
  •          // If completed message was reading EEPROM data, reset msg to inactive state   
  •          // and read data from FIFO.   
  •          else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY)   
  •          {   
  •             CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;   
  •             for(i=0; i < I2C_NUMBYTES; i++)   
  •             {   
  •               CurrentMsgPtr->MsgBuffer = I2caRegs.I2CDRR;   
  •             }   
  •          {   
  •          // Check recieved data   
  •          for(i=0; i < I2C_NUMBYTES; i++)   
  •          {   
  •             if(I2cMsgIn1.MsgBuffer == I2cMsgOut1.MsgBuffer)   
  •             {   
  •                 PassCount++;   
  •             }   
  •             else   
  •             {   
  •                 FailCount++;   
  •             }   
  •          }   
  •          if(PassCount == I2C_NUMBYTES)   
  •          {   
  •             pass();   
  •          }   
  •          else   
  •          {   
  •             fail();   
  •          }   
  •    
  •    
  •       }   
  •    
  •     }   
  •       }   
  •    }  // end of stop condition detected   
  •    
  •    // Interrupt source = Register Access Ready   
  •    // This interrupt is used to determine when the EEPROM address setup portion of the   
  •    // read data communication is complete. Since no stop bit is commanded, this flag   
  •    // tells us when the message has been sent instead of the SCD flag. If a NACK is   
  •    // received, clear the NACK bit and command a stop. Otherwise, move on to the read   
  •    // data portion of the communication.   
  •    else if(IntSource == I2C_ARDY_ISRC)   
  •    {   
  •       if(I2caRegs.I2CSTR.bit.NACK == 1)   
  •       {   
  •          I2caRegs.I2CMDR.bit.STP = 1;   
  •          I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;   
  •       }   
  •       else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)   
  •       {   
  •          CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;   
  •       }   
  •    }  // end of register access ready   
  •    
  •    else   
  •    {   
  •       // Generate some error due to invalid interrupt source   
  •       asm("   ESTOP0");   
  •    }   
  •    
  •    // Enable future I2C (PIE Group 8) interrupts   
  •    PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;   
  • }   
  •    
  • void pass()   
  • {   
  •     asm("   ESTOP0");   
  •     for(;;);   
  • }   
  •    
  • void fail()   
  • {   
  •     asm("   ESTOP0");   
  •     for(;;);   
  • }   
  •    
  •    
  • //===========================================================================   
  • // No more.   
  • //===========================================================================  

使用特权

评论回复

相关帖子

沙发
sensitivity| | 2019-12-29 10:23 | 只看该作者
感谢楼主分享!有点说明就更好了

使用特权

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

本版积分规则

个人签名:欢迎进入【TI DSP 论坛】 & 【DSP 技术】           TI忠诚粉丝!

935

主题

26376

帖子

589

粉丝