关闭

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

标签: 微型投影仪单片机
1061人阅读 评论(0) 收藏 举报
分类:

20151121

以下附上的是模拟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<num_bytes; 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);
}














0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:218545次
    • 积分:3699
    • 等级:
    • 排名:第9281名
    • 原创:136篇
    • 转载:96篇
    • 译文:0篇
    • 评论:84条
    最新评论