×
嵌入式 > 技术百科 > 详情

单片机 MSP430 模拟IIC编程(1)

发布时间:2020-06-17 发布时间:
|

以下附上的是模拟IIC通信模块程序,是我在TI官网提供的投影仪评估板例程中拿出来的,本人还没有验证,暂且认为他可以工作,估计下个星期就会去验证他,到时候再修改。

其实贴出这个程序的主要目的是,我刚开始不理解他对于SCL、SDA的高低电平的操作方法,下一篇文章我将解释。


i2c_master.h

#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

#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);  

}  



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
联发科高端芯片系列出新品Helio P10 中文名[曦力"