[资料分享] 单片机 MSP430 模拟IIC编程(1)

Aguilera   2017-10-17 21:32 楼主

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


回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复