- #include "mpu_i2c.h"
- #include "usart.h"
- //配置i2c端口
- void I2C_GPIO_Config(void)
- {
- //定義結構體
- GPIO_InitTypeDef GPIO_InitStruct;
-
- //打開SDA與SCL端口時鐘
- RCC_APB2PeriphClockCmd(I2C_SDA_CLK,ENABLE);
- RCC_APB2PeriphClockCmd(I2C_SCL_CLK,ENABLE);
-
- //配置SDA端口
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//開漏復用輸出
- GPIO_InitStruct.GPIO_Pin = I2C_SDA_Pin;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(I2C_SDA_PORT,&GPIO_InitStruct);
- //配置SCL端口
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//開漏復用輸出
- GPIO_InitStruct.GPIO_Pin = I2C_SCL_Pin;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(I2C_SCL_PORT,&GPIO_InitStruct);
- }
- void I2C_InitConfig(void)
- {
- I2C_GPIO_Config();
- }
- void delay(void)
- {
- uint8_t time = 10;
- while(time--)
- {
- }
- }
- void I2C_START(void)
- {
- SDA_OUT();
- I2C_SDA_1();
- I2C_SCL_1();
- delay();
- I2C_SDA_0();
- delay();
- I2C_SCL_0();
- delay();
- }
- void I2C_STOP(void)
- {
- SDA_OUT();
- I2C_SDA_0();
- I2C_SCL_1();
- delay();
- I2C_SDA_0();
- delay();
- }
- void I2C_Ack(void)
- {
- I2C_SCL_0();
- I2C_SDA_1();
- delay();
- I2C_SDA_1();
- delay();
- I2C_SDA_0();
- delay();
- I2C_SCL_1();
- delay();
- I2C_SCL_0();
- delay();
- I2C_SDA_1();
- }
- void I2C_NACK(void)
- {
- I2C_SCL_0();
- I2C_SDA_0() ;
- delay();
- I2C_SDA_1();
- delay();
- I2C_SCL_1();
- delay();
- I2C_SCL_0();
- delay();
- I2C_SDA_0();
- delay();
- }
- void I2C_Sent_Byte(uint8_t msg)
- {
- uint8_t i;
- SDA_OUT();
- I2C_SCL_0();
- delay();
- /* 先發送字節的高位bit7 */
- for (i = 0; i < 8; i++)
- {
- if (msg & 0x80 ==1)
- {
- I2C_SDA_1();
- }
- else
- {
- I2C_SDA_0();
- }
- delay();
- I2C_SCL_1();
- delay();
- I2C_SCL_0();
- if (i == 7)
- {
- I2C_SDA_1(); // 釋放總線
- }
- msg <<= 1; /* 左移一個bit */
- delay();
- }
- I2C_SCL_0();
- }
- uint8_t I2C_Read_Byte(void)
- {
- uint8_t i;
- uint8_t receive = 0;
-
- /* 讀到的第一位為數據的7bit位!!!
- 所以每次讀取數據時都要將數據左移一位*/
-
- I2C_SCL_1();//鎖定SCL線,確保其穩定
- for(i=0;i<8;i++)
- {
- receive <<= 1;
- I2C_SCL_0();//讀取數據時拉低SCL
- delay();
- if(I2C_SDA_State() == 1)
- {
- receive++;
- }
- I2C_SCL_0();
- delay();
-
- }
-
- return receive;
- }
- void delay_us(uint8_t i)
- {
- while(i--)
- {
- }
- }
- uint8_t I2C_WaitAck(void)
- {
- uint8_t re;
- I2C_SDA_1(); /* CPU釋放SDA總線 */
- delay();
- I2C_SCL_1(); /* CPU驅動SCL = 1, 此時器件會返回ACK應答 */
- delay();
- if (I2C_SDA_State()) /* CPU讀取SDA口線狀態 */
- {
- re = 1;
- }
- else
- {
- re = 0;
- }
- I2C_SCL_0();
- delay();
- return re;
- }
- uint8_t EEPROM_Byte_Write(uint16_t _usAddress, uint16_t data)
- {
- uint8_t i;
- //開始信號
- I2C_START();
- //發送地址
- I2C_Sent_Byte(Slave_Addr | I2C_Write);
- //檢測應答
- //delay();
- //return printf("SDA的狀態為:%d\n",I2C_SDA_State());
- if(I2C_WaitAck() != 0)
- {
- return printf("寫入失敗,未檢測到響應1\n");
- }
- //發送從機中的數據地址(起始地址)
- I2C_Sent_Byte(_usAddress);
- //檢測應答
- if(I2C_WaitAck() != 0)
- {
- return printf("寫入失敗,未檢測到響應2\n");
- }
-
- for(i=0;i<8;i++)
- {
- I2C_Sent_Byte(data & 0x80);
- I2C_Ack();
- data <<= 1;
- }
- return printf("寫入完成!!!\n");
- }
- uint8_t EEPROM_Byte_Read(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
- {
- uint8_t i;
- //開始信號
-
- //test SDA
- //return printf("開始信號前SDA狀態為:%d\n",READ_I2C_SDA());
-
- I2C_START();
- //發送地址
-
- //test SDA
- //return printf("開始信號后SDA狀態為:%d\n",READ_I2C_SDA());
-
- I2C_Sent_Byte(Slave_Addr | I2C_Write);
- //test SDA
- //return printf("發送地址后SDA狀態為:%d\n",READ_I2C_SDA());
-
- //檢測應答
- if(I2C_WaitAck() != 0)
- {
- return printf("讀取失敗,未檢測到響應1\n");
- }
- //發送從機中的數據地址(起始地址)
- I2C_Sent_Byte(_usAddress);
- //檢測應答
- if(I2C_WaitAck() != 0)
- {
- return printf("讀取失敗,未檢測到響應2\n");
- }
- //開始信號
- I2C_START();
- //發送地址
- I2C_Sent_Byte(Slave_Addr | I2C_Read);
- //檢測應答
- if(I2C_WaitAck() != 0)
- {
- return printf("讀取失敗,未檢測到響應3\n");
- }
-
- //讀取數據
- for(i=0;i< _usSize;i++)
- {
- // if(I2C_GetFlagStatus(I2C_Driver,I2C_FLAG_BUSY) == SET)
- // {
- // return printf("他媽的鎖死了,讀取失敗\n");
- // }
-
- _pReadBuf[i] = I2C_Read_Byte();//每次讀取一個字節
- if(i != (_usSize-1))
- {
- I2C_Ack();
- }
- else
- {
- I2C_NACK();
- }
- }
-
- //發送停止信號
- I2C_STOP();
-
- return printf("讀取完成!\n");
-
- }
復制代碼 |