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

原创 2015年11月21日 10:17:28

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














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

示例 ////////////////////////////////////////////////// void I2C_Master_Init(void) /** * Initializes...

光电隔离RS485典型电路

一、RS485总线介绍 RS485总线是一种常见的串行总线标准,采用平衡发送与差分接收的方式,因此具有抑制共模干扰的能力。在一些要求通信距离为几十米到上千米的时候,RS485总线是一种应用最为广泛的...

单片机 MSP430 IIC控制器编程(1)

近日在开发开发微型投影仪的单片机程序,主要是用单片机控制DLP芯片组进行相应的初始化和参数设置,所有芯片的通信接口都是用IIC。 在此记录下,IIC的开发过程。 1.初始化 17.3.1 USCI...

msp430f149单片机模拟IIC驱动OLED

  • 2014年07月24日 14:55
  • 32KB
  • 下载

GSM/GPRS模块 AT指令集C语言编程——基于有方M660+和MSP430单片机

GSM/GPRS芯片是手机中负责收发短信、拨打电话以及访问GPRS网络的核心器件。有方M660+为深圳有方公司生产的一款超小封装的GSM/GPRS工业无线模块,可以提供高品质的语音、短信、数据业务等功...
  • jzj1993
  • jzj1993
  • 2013年09月23日 14:51
  • 7991

利用MSP430F5438A单片机进行SD卡初始化——实战应用(四)与FatFs的整合1

整合进入FatFs 在前文中提到过,如果需要所存储的数据能够在电脑上读取出来,需要建立文件系统,FatFs作为一个开源的文件系统具有很好的可移植性,在成功完成SD卡初始化,并借助实现过程对SPI通信...
  • liujj05
  • liujj05
  • 2015年04月05日 21:46
  • 647

Proteus中MSP430与SHT11的IIC通信问题

调了两天,MSP430始终接收不到数据,一直以为是代码的问题,今天无意中看到别人的一片文章,才发现问题出在上拉电阻上。DATA线的上拉电阻不能太大,10k不行,换成了1k就没问题了。mark一下,顺便...

MSP430 IIC通信

#include #define OP_READ 0xa1 //器件地址读 #define OP_WRITE 0xa0 //...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:单片机 MSP430 模拟IIC编程(1)
举报原因:
原因补充:

(最多只允许输入30个字)