STM32微控制器硬體I2C驅動程式(查詢方式)
阿新 • • 發佈:2018-11-19
本文章原始地址:http://feotech.com/?p=69
本程式主要用於驅動STM32微控制器晶片的硬體I2C暫存器,實現通過使用晶片自帶的I2C暫存器進行資料的傳送與接收.
本例程中採用I2C暫存器查詢的方式來實現資料傳輸,當I2C對應暫存器指定狀態時方可執行下一步操作.
/** ****************************************************************************** * @file Hardware_I2C.c * @author Ryan Zhao * @version V1.0.0 * @date 2017-04-27 * @brief STM32硬體I2C底層驅動. ****************************************************************************** * @attention Null * ****************************************************************************** */ /** * @brief I2C引腳與暫存器功能配置. * @param None. * @retval None. */ void I2C_Configuration(void) { /*GPIO與IIC初始化結構體*/ GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; /*GPIO與IIC時鐘使能*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //GPIOB時鐘使能 RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE ); //I2C時鐘使能 /*初始化GPIO*/ GPIO_InitStructure.GPIO_Pin = HW_I2C_SDA_PIN | HW_I2C_SCL_PIN; //初始化 IIC GPIO GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最高輸出速度50Hz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //輸入輸出模式為複用功能開漏輸出 GPIO_Init( GPIOB, &GPIO_InitStructure ); //根據GPIO初始化結構體初始化GPIOB /*初始化I2C*/ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //設定為I2C模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //設定I2C的佔空比,低電平除以高電平值為2 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能ACK訊號 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //指定7位地址 I2C_InitStructure.I2C_ClockSpeed = 400000; //時鐘頻率,必須小於等於400KHz I2C_Cmd( HW_I2C, ENABLE ); //使能I2C I2C_Init( HW_I2C, &I2C_InitStructure ); //根據I2C初始化結構體初始化I2C /*允許一位元組一應答模式*/ I2C_AcknowledgeConfig( HW_I2C, ENABLE ); //使能I2C應答狀態 } /** * @brief 從I2C指定地址中讀取資料; * @param 讀取的地址,讀取後返回的資料; * @retval 1:讀取資料成功,0:讀取資料無效; */ unsigned char I2C_ReadByte(unsigned char Read_Address,unsigned char * Read_Data) { unsigned char wait_time_out = wait_time_value;//等待I2C器件響應的延時 * Read_Data = 0; while (I2C_GetFlagStatus(HW_I2C, I2C_FLAG_BUSY)) //判斷IIC介面狀態.當IIC狀態為BUSY時,一直停在這裡迴圈 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } /*傳送START之後要等待,意味著START條件被正確釋放,此時IIC總線上沒有其它外設*/ I2C_GenerateSTART( HW_I2C, ENABLE ); //產生START條件 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT)) //判斷開始訊號是否已經發送完成 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_Send7bitAddress(HW_I2C, ADXL_WRITE, I2C_Direction_Transmitter ); //傳送從機地址ADXL_WRITE以選擇從機,主機為傳送模式 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //如果主機發射模式被選中(死迴圈等待從機發送ACK訊號) { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_SendData(HW_I2C, Read_Address ); //將write_address,即要讀的地址通過IIC2傳送出去 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //如果地址已經從IIC成功發射出去(死迴圈等待ACK訊號 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_GenerateSTART(HW_I2C, ENABLE ); //產生START條件 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT)) //如果主機被選中(死迴圈等待ACK訊號) { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } /***主機接收資料***/ I2C_Send7bitAddress(HW_I2C, ADXL_READ, I2C_Direction_Receiver ); //主機設定為接收模式 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) //如果主機接收模式被選中(死迴圈等待ACK訊號) { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_AcknowledgeConfig(HW_I2C, DISABLE ); //失能IIC的應答狀態 NACK I2C_GenerateSTOP( HW_I2C, ENABLE ); //產生STOP條件 while (!(I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED))) //判斷資料是否接收完成 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_AcknowledgeConfig(HW_I2C, ENABLE ); //再一次使能IIC的應答狀態 * Read_Data = I2C_ReceiveData(HW_I2C); //返回IIC接收的資料 return 1; } /** * @brief 通過I2C介面將資料寫入從機指定地址中. * @param 要寫入的資料,接收資料的地址; * @retval 1:資料寫入成功 0:資料寫入失敗 */ unsigned char I2C_Write_Byte(uint8_t Point_Buffer,uint8_t Write_Address) { unsigned char wait_time_out = wait_time_value;//等待I2C器件響應的延時 while (I2C_GetFlagStatus(HW_I2C, I2C_FLAG_BUSY)) //判斷當前I2C介面狀態是否為Busy { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_GenerateSTARTHW_I2C, ENABLE ); //產生Start訊號 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT)) //判斷Start訊號是否已經發送 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_Send7bitAddress(HW_I2C, ADXL_WRITE, I2C_Direction_Transmitter ); //傳送從機地址以選擇從機,主機為傳送模式 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //判斷髮送的地址是否與從機匹配,等待從機發送ACK訊號 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_SendData(HW_I2C, Write_Address ); //將write_address,即要寫的暫存器地址通過IIC傳送出去 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //判斷資料是否傳送完成 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } /*往暫存器傳送資料data*/ I2C_SendData(HW_I2C, Point_Buffer ); while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //判斷資料是否傳送完成 { if((wait_time_out --) == 0) //延時等待 { return 0; //響應超時,返回無效標誌 } } I2C_GenerateSTOP( HW_I2C, ENABLE ); //IIC2產生STOP條件 return 1;//資料寫入完成 1 }
/** ****************************************************************************** * @file Hardware_I2C.h * @author Ryan Zhao * @version V1.0.0 * @date 2017-04-27 * @brief STM32硬體I2C底層驅動. ****************************************************************************** * @attention Null * ****************************************************************************** */ /*********************I2C 物理層GPIO定義*******************/ #define HW_I2C I2C1 //第一組I2C介面 #define HW_I2C_SDA_PIN GPIO_Pin_7 #define HW_I2C_SDA_GPIO_PORT GPIOB #define HW_I2C_SCL_PIN GPIO_Pin_6 #define HW_I2C_SCL_GPIO_PORT GPIOB #define wait_time_value 200 //等待I2C器件響應的延時