以下附上的是模拟IIC通信模块程序,是我在TI官网提供的投影仪评估板例程中拿出来的,本人还没有验证,暂且认为他可以工作,估计下个星期就会去验证他,到时候再修改。
其实贴出这个程序的主要目的是,我刚开始不理解他对于SCL、SDA的高低电平的操作方法,下一篇文章我将解释。
i2c_master.h
[cpp] view plain copy
- #ifndef __i2c_master
- #define __i2c_master
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- // defines
- #define I2C_NO_ACK 0
-
- // functions
- void I2C_Master_Start(void);
- void I2C_Master_Stop(void);
- uint08 I2C_MasterTransmitByte(uint08 data);
- uint08 I2C_MasterReceiveByte(void);
- uint08 I2C_PolledMasterWrite(uint08 device_addr, uint08* write_data, uint08 num_bytes);
- uint08 I2C_PolledMasterRead(uint08 device_addr, uint08* read_data, uint08 num_bytes);
- //uint08 I2C_Write_DPP(uint08 subaddr, uint32 data);
- //uint08 I2C_Read_DPP(uint08 subaddr, uint32* data);
-
- void I2C_Master_Init (void);
- void I2C_SetSDA_High (void);
- void I2C_SetSDA_Low (void);
- BOOL I2C_GetSDA_Input (void);
- void I2C_SetSCL_High (void);
- void I2C_SetSCL_Low (void);
- BOOL I2C_GetSCL_Input (void);
-
- #ifdef __cplusplus /* matches __cplusplus construct above */
- }
- #endif
-
- #endif // #ifndef __i2c_master
i2c_master.c
[cpp] view plain copy
- #include "common.h"
- #include "i2c_master.h"
- #include "msp430x22x4.h" //org ==> //#include "msp430f2132.h"
- #include "ddp343xEVM_pins.h"
-
- #define SDA_HI I2C_SetSDA_High()
- #define SDA_LO I2C_SetSDA_Low()
- #define SDA_IN I2C_GetSDA_Input()
- #define SCL_HI I2C_SetSCL_High()
- #define SCL_LO I2C_SetSCL_Low()
- #define SCL_IN I2C_GetSCL_Input()
-
- // local functions
- //uint08 i2c_master_check_nak_timeout(uint08 timeout, uint08 check_nak);
- //void i2c_master_cleanup(void);
-
- ////////////////////////////////////////////////////////////////////////
- void I2C_Master_Start(void) // Set up start condition for I2C
- /**
- * Generates the start condition for I2C read/write
- *
- */
- {
- volatile uint08 i;
- SDA_HI;
- __no_operation();
- SCL_HI;
-
- for (i=0; i<5; i++)
- {
- __no_operation();
-
- SDA_LO;
- __no_operation();
- __no_operation();
- SCL_LO;
-
- //after end of start condition both SDA and SCL will be low
- }
-
- }
-
- ////////////////////////////////////////////////////////////////////////
- void I2C_Master_Stop(void) // Set up stop condition for I2C
- /**
- * Generates the stop condition for I2C read/write
- *
- */
- {
- volatile uint08 i;
- SDA_LO;
- __no_operation();
- SCL_HI;
- for (i=0; i<8; i++) {
- __no_operation();
- }
- SDA_HI;
-
- i=0;
- //ensure bus is in default condition ( freed by slave)
- while(!SDA_IN) // i is just a variable to control the while loop run time.
- {
- SCL_HI;
- __no_operation();
- __no_operation();
- SCL_LO;
- __no_operation();
- __no_operation();
- i++;
- if( i > 25)
- {
- break;
- }
- }
- SCL_HI;
- //After generating stop condition SCL and SDA are both high. Default condition for I2C bus.
- }
-
- ////////////////////////////////////////////////////////////////////////
- uint08 I2C_PolledMasterWrite(uint08 device_addr, uint08* write_data, uint08 num_bytes)
- /**
- * Writes data to the specified device address
- *
- * @param device_addr - I - 7 Bit device Address
- * @param write_data - I - Pointer to data buffer to be written to slave
- * @param num_bytes - I - Number of bytes to be written
- * @return PASS - Completed successfully
- * I2C_NO_ACK - Slave NAck'ed
- *
- */
- {
- uint08 ByteCount;
- uint08 *data_ptr;
- uint08 status=PASS;
- // initialize pointer to the data and start the transfer
- data_ptr = write_data;
-
-
- // Generate START condition //
- // Data line loow when clock is high //
-
- I2C_Master_Start();
-
- // Before writing address ensure the bit 0 is set to zero
- // Bit 0 =0 means master is writing , Bit 0 =1 means master wants to read
- // BIT0 = 0x1
- if (I2C_MasterTransmitByte(device_addr & ~0x1) == I2C_NO_ACK)
- {
- // If not Acknowledged by slave//
- status = I2C_NO_ACK;
- }
- else
- // Tranmit all the data bytes as slave has acknowledged//
- {
- for (ByteCount=0; ByteCount
- {
- if (I2C_MasterTransmitByte(*data_ptr)== I2C_NO_ACK)
- {
- // If not Acknowledged by slave//
- status = I2C_NO_ACK;
- break;
- }
- else
- data_ptr++;
- }
- }
-
- // Generate STOP Condition
- // Data line high, when clock is high
- I2C_Master_Stop();
-
- return status;
- }
-
- ////////////////////////////////////////////////////////////////////////
- uint08 I2C_PolledMasterRead(uint08 device_addr, uint08* read_data, uint08 num_bytes)
- /**
- * Reads data from the specified device address
- *
- * @param device_addr - I - 7 Bit device Address
- * @param read_data - I - Pointer to buffer to hold received data from slave
- * @param num_bytes - I - Number of bytes to be read
- * @return PASS - Completed successfully
- * I2C_NO_ACK - Slave NAck'ed
- *
- */
- {
- uint08* data_ptr;
- uint08 status=PASS;
- uint08 ByteCount;
- data_ptr = read_data;
-
-
- // Generate START condition //
- // Data line low when clock is high //
-
- I2C_Master_Start();
-
- // Transmit the slave address //
- // Before writing address ensure the bit 0 is set to 1
- // Bit 0 =0 means master is writing , Bit 0 =1 means master is reading
- // BIT0 = 0x1
-
- if(I2C_MasterTransmitByte(device_addr | 0x1) == I2C_NO_ACK)
- {
- // If not Acknowledged //
- status = I2C_NO_ACK;
- }
- else
- {
- // Receive all the data bytes //
- for(ByteCount = 0; ByteCount < num_bytes; ByteCount++)
- {
- *data_ptr = I2C_MasterReceiveByte();
- data_ptr++;
- }
- }
-
- // Generate STOP Condition
- // Data line high, when clock is high
- I2C_Master_Stop();
- return status;
- }
-
- ////////////////////////////////////////////////////////////////////////
- uint08 I2C_MasterTransmitByte(uint08 data)
- /**
- * This routine transmits one byte of data over the given clock and data lines and
- * receives the ack from slave.
- *
- * @param data - I - The 8 bit data to be transmitted
- * @return I2C_NO_ACK - Not Acknowledgeed
- * PASS - Acknowledged
- *
- */
- {
- uint08 Ack=1;
- uint08 i;
- uint08 Byte = data;
-
- // Send Byte It is assumed that the start condition would have made SCL and SDA low.
- // SDA should change only when SCA is low.
-
- SCL_LO;
- for(i = 0; i < 8 ; i++)
- {
- if( Byte & 0x80)
- SDA_HI;
- else
- SDA_LO;
- __no_operation();
- __no_operation();
-
- SCL_HI;
- Byte <<= 1;
-
- __no_operation(); //need to optimize the delay.
- __no_operation();
- __no_operation();
- __no_operation();
-
- SCL_LO;
-
- //leave SDA at the end
- if(i == 7)
- {
- SDA_HI;
- }
- __no_operation();
- __no_operation();
-
- }
-
- //Receive Ack
- __no_operation();
- __no_operation();
-
- SCL_HI;
- __no_operation();
- __no_operation(); // delay added bcoz without this delay ack was received wrong.
- __no_operation(); // need to optimize the delay.
-
- // If data line is pulled low by slave- it is acknowledged
- if (SDA_IN)
- Ack = 0; //ack not received
- else
- Ack = 1; //ack received
-
- SCL_LO;
- __no_operation();
- __no_operation();
- SDA_LO;
-
- //After transmitting one byte of data SCL and SDA are both low.
- return Ack;
- }
-
- ////////////////////////////////////////////////////////////////////////
- uint08 I2C_MasterReceiveByte()
- /**
- * This routine receives one byte of data over the given clock and data lines and
- * sends the ack to slave.
- *
- * @return one byte of data received from slave.
- *
- */
- {
- uint08 Data=0;
- uint08 i;
-
- //Make SDA as input
- SDA_HI;
- __no_operation();
- __no_operation();
-
- for(i = 0; i < 8 ; i ++)
- {
- SCL_HI;
- __no_operation();
- __no_operation();
- Data <<= 1;
- if (SDA_IN)
- Data |=1;
- else
- Data |=0;
-
- SCL_LO;
- __no_operation();
- __no_operation();
- }
-
- //After the eight bits are transferred by slave, slave will pull SDA high ( default condition for I2C bus)
- // Generate ack for slave.
- SDA_LO;
- __no_operation();
- __no_operation();
- SCL_HI;
- __no_operation();
- __no_operation();
- SCL_LO;
-
- //After receiving one byte of data SCL and SDA are both low.
-
- return Data;
- }
-
- //////////////////////////////////////////////////
-
- void I2C_Master_Init(void)
- /**
- * Initializes I2C. Makes SCL and SDA high.
- */
- {
- //bit banging
- P3SEL &= ~(SCL | SDA); // Set GPIO function
- P3OUT &= ~(SDA | SCL);
-
- I2C_SetSCL_Low(); //although not required but want to make sure SCL is low when SDA goes high
- I2C_SetSDA_High();
- __no_operation();
- I2C_SetSCL_High();
- __no_operation();
- }
-
- //////////////////////////////////////////////////
- /* I2C SDA and SCL Lines */
- void I2C_SetSDA_High (void)
- {
- P3DIR &= ~SDA;
- }
-
- //////////////////////////////////////////////////
- void I2C_SetSDA_Low (void)
- {
- P3DIR |= SDA;
- }
-
- //////////////////////////////////////////////////
- BOOL I2C_GetSDA_Input (void)
- {
- return (P3IN & SDA ? 1 : 0);
- }
-
- //////////////////////////////////////////////////
- void I2C_SetSCL_High (void)
- {
- P3DIR &= ~SCL;
- }
-
- //////////////////////////////////////////////////
- void I2C_SetSCL_Low (void)
- {
- P3DIR |= SCL;
- }
-
- //////////////////////////////////////////////////
- BOOL I2C_GetSCL_Input (void)
- {
- return (P3IN & SCL ? 1 : 0);
- }