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

来源:互联网 发布:淘宝保证金计划5000元 编辑:程序博客网 时间:2024/05/18 23:54

20151121

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

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


i2c_master.h

#ifndef __i2c_master#define __i2c_master#ifdef __cplusplusextern "C" {#endif// defines#define I2C_NO_ACK                 0// functionsvoid    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