㈠ IIC(I2C)匯流排上的設備其地址如何定義
IIC匯流排
一般串列數據通訊都有時鍾和數據之分,有非同步和同步之別.
有單線,雙線和三線等.
I2C肯定是2線的(不算地線).
I2C協議確實很科學,比3/4線的SPI要好,當然線多通訊速率相對就快了.
I2C的原則是:
在SCL=1(高電平)時,SDA千萬別忽悠!!!
否則,SDA下跳則"判罰"為"起始信號S",SDA上跳則"判罰"為"停止信號P".
在SCL=0(低電平)時,SDA隨便忽悠!!!(可別忽悠過火到SCL跳高)
每個位元組後應該由對方回送一個應答信號ACK做為對方在線的標志.
非應答信號一般在所有位元組的最後一個位元組後.一般要由雙方協議簽定.
SCL必須由主機發送,否則天下大亂.
首位元組是"片選信號",即7位從機地址加1位方向(讀寫)控制.
從機收到(聽到)自己的地址才能發送應答信號(必須應答!!!)表示自己在線.
其他地址的從機不允許忽悠!!!(當然群呼可以忽悠但只能聽不許說話)
讀寫是站在主機的立場上定義的.
"讀"是主機接收從機數據,"寫"是主機發送數據給從機.
重復位主要用於主機從發送模式到接收模式的轉換"信號",由於只有2線,
所以收發轉換肯定要比SPI復雜,因為SPI可用不同的邊沿來收發數據,而I2C不行.
在硬體I2C模塊,特別是MCU/ARM/DSP等每個階段都會得到一個准確的狀態碼,
根據這個狀態碼可以很容易知道現在在什麼狀態和什麼出錯信息.
7位I2C匯流排可以掛接127個不同地址的I2C設備,0號"設備"作為群呼地址.
10位I2C匯流排可以掛接更多的10位I2C設備.
總之,只要掌握I2C的忽悠記,一般很容易掌控... 第一個位元組(為slave address)由7位地址和一位R/W讀寫位組成的,這位元組是個器件地址。
首先,你要知道:常用IIC介面通用器件的器件地址是由種類型號,及定址碼組成的,共7位。
如格式如下:
D7 D6 D5 D4 D3 D2 D1 D0
1-器件類型由:D7-D4 共4位決定的。這是由半導公司生產時就已固定此類型的了,也就是說這4位已是固定的。
2-用戶自定義地址碼:D3-D1共3位。這是由用戶自己設置的,通常的作法如EEPROM這些器件是由外部IC的3個引腳所組合電平決定的(用常用的名字如A0,A1,A2)。這也就是定址碼。
所以為什麼同一IIC匯流排上同一型號的IC只能最多共掛8片同種類晶元的原因了。
3-最低一位就是R/W位。這位不用我多說了。
在現代電子系統中,有為數眾多的IC需要進行相互之間以及與外界的通信。為了提供硬體的效率和簡化電路的設計,PHILIPS開發了一種用於內部IC控制的簡單的雙向兩線串列匯流排I2C。I2C匯流排支持任何一種IC製造工藝,並且PHILIPS和其他廠商提供了種類非常豐富的I2C兼容晶元。作為一個專利的控制匯流排,I2C已經成為世界性的工業標准。
每個器件都有一個唯一的地址,而且可以是單接收的器件(例如:LCD驅動器)或者可以接收也可以發送的器件(例如:存儲器)。發送器或接收器可以在主模式或從模式下操作,這取決於晶元是否必須啟動數據的傳輸還是僅僅被定址。I2C是一個多主匯流排,即它可以由多個連接的器件控制。
基本的I2C匯流排規范於20年前發布,其數據傳輸速率最高為100Kbits/s,採用7位定址。但是由於數據傳輸速率和應用功能的迅速增加,I2C匯流排也增強為快速模式(400Kbits/s)和10位定址以滿足更高速度和更大定址空間的需求。
I2C匯流排始終和先進技術保持同步,但仍然保持其向下兼容性。並且最近還增加了高速模式,其速度可達3.4Mbits/s。它使得I2C匯流排能夠支持現有以及將來的高速串列傳輸應用,例如EEPROM和Flash存儲器。 在現代電子系統中,有為數眾多的IC需要進行相互之間以及與外界的通信。為了提供硬體的效率和簡化電路的設計,PHILIPS開發了一種用於內部IC控制的簡單的雙向兩線串列匯流排I2C。I2C匯流排支持任何一種IC製造工藝,並且PHILIPS和其他廠商提供了種類非常豐富的I2C兼容晶元。作為一個專利的控制匯流排,I2C已經成為世界性的工業標准。
每個器件都有一個唯一的地址,而且可以是單接收的器件(例如:LCD驅動器)或者可以接收也可以發送的器件(例如:存儲器)。發送器或接收器可以在主模式或從模式下操作,這取決於晶元是否必須啟動數據的傳輸還是僅僅被定址。I2C是一個多主匯流排,即它可以由多個連接的器件控制。
基本的I2C匯流排規范於20年前發布,其數據傳輸速率最高為100Kbits/s,採用7位定址。但是由於數據傳輸速率和應用功能的迅速增加,I2C匯流排也增強為快速模式(400Kbits/s)和10位定址以滿足更高速度和更大定址空間的需求。
I2C匯流排始終和先進技術保持同步,但仍然保持其向下兼容性。並且最近還增加了高速模式,其速度可達3.4Mbits/s。它使得I2C匯流排能夠支持現有以及將來的高速串列傳輸應用,例如EEPROM和Flash存儲器。
㈡ i2c匯流排可以連接幾個設備
IIC協議規定,在啟動匯流排後第1位元組的高7位是從節點的定址地址,第8位為方向位。所以在單位元組定址中最多128個從設備。但又不能是同一類設備,因為在地址還要區分設備類型。
㈢ i2c匯流排上最多可以掛多少個從器件
有IIC地址決定,8位地址,減去1位廣播地址,是7位地址,2^7=128,但是地址0x00不用,那就是127個地址, 所以理論上可以掛127個從器件。
I2C(Inter-Integrated Circuit)匯流排是由PHILIPS公司開發的兩線式串列匯流排,用於連接微控制器及其外圍設備。是微電子通信控制領域廣泛採用的一種匯流排標准。它是同步通信的一種特殊形式,具有介面線少,控制方式簡單,器件封裝形式小,通信速率較高等優點。I2C 匯流排支持任何IC 生產過程(CMOS、雙極性)。通過串列數據(SDA)線和串列時鍾 (SCL)線在連接到匯流排的器件間傳遞信息。每個器件都有一個唯一的地址識別(無論是微控制器——MCU、LCD 驅動器、存儲器或鍵盤介面),而且都可以作為一個發送器或接收器(由器件的功能決定)。LCD 驅動器只能作為接收器,而存儲器則既可以接收又可以發送數據。除了發送器和接收器外,器件在執行數據傳輸時也可以被看作是主機或從機(見表1)。主機是初始化匯流排的數據傳輸並產生允許傳輸的時鍾信號的器件。此時,任何被定址的器件都被認為是從機。
㈣ STM32CubeMX學習筆記(9)——I2C介面使用(讀寫EEPROM AT24C02)
一、I2C簡介I2C(Inter-Integrated Circuit ,內部集成電路) 匯流排是一種由飛利浦 Philip 公司開發的串列匯流排。是兩條串列的匯流排,它由一根數據線(SDA)和一根 時鍾線(SDL)組成。I2C 匯流排上可以接多個 I2C 設備,每個器件都有一個唯一的地址識別。同一時間只能有一個主設備,其他為從設備。通常 MCU 作為主設備控制,外設作為從設備。
STM32 的 I2C 外設可用作通訊的主機及從機,支持 100Kbit/s 和 400Kbit/s 的速率,支持 7 位、10 位設備地址,支持 DMA 數據傳輸,並具有數據校驗功能。它的 I2C 外設還支持 SMBus2.0 協議,SMBus 協議與 I2C 類似,主要應用於筆記本電腦的電池管理中。
二、引腳分布STM32 晶元有多個 I2C 外設,它們的 I2C 通訊信號引出到不同的 GPIO 引腳上,使用時必須配置到這些指定的引腳。PB8 PB9 為重映射。
三、EEPROM晶元開發板中的 EEPROM 晶元型號:AT24C02。AT24C 系列為美國 ATMEL 公司推出的串列 COMS 型 EEPROM。晶元型號後兩位表示晶元容量,例如 ATC24C02 為 2K。引腳圖中 A0、A1、A2 為器件地址引腳,GND為地,VCC為正電源,WP為防寫,SCL為串列時鍾線,SDA為串列數據線。
EEPROM 晶元中 WP 引腳具有防寫功能,當該引腳電平為高時,禁止寫入數據,當引腳為低電平時,可寫入數據,我們直接接地,不使用防寫功能。AT24Cxx 設備地址為如下,前四位固定為 1010,A2~A0為由管腳電平決定。AT24Cxx EEPROM Board模塊中默認為接地。A2~A0 為 000,最後一位 R/W 表示讀寫操作。所以由於 I2C 通訊時常常是地址跟讀寫方向連在一起構成一個 8 位數,且當 R/W 位為 0 時,表示寫方向,所以加上 7 位地址,其值為 0xA0,常稱該值為 I2C 設備的「寫地址」;當 R/W 位為 1 時,表示讀方向,加上 7 位地址,其值為 0xA1,常稱該值為「讀地址」。
四、新建工程1. 打開 STM32CubeMX 軟體,點擊「新建工程」
2. 選擇 MCU 和封裝
3. 配置時鍾 RCC 設置,選擇 HSE(外部高速時鍾) 為 Crystal/Ceramic Resonator(晶振/陶瓷諧振器)選擇 Clock Configuration,配置系統時鍾 SYSCLK 為 72MHz 修改 HCLK 的值為 72 後,輸入回車,軟體會自動修改所有配置
4. 配置調試模式 非常重要的一步,否則會造成第一次燒錄程序後續無法識別調試器 SYS 設置,選擇 Debug 為 Serial Wire
五、I2C15.1 參數配置在 Connectivity 中選擇 I2C1 設置,並選擇 I2C 內部集成電路I2C 為默認設置不作修改。只需注意一下,I2C 為標准模式,I2C 傳輸速率 (I2C Clock Speed) 為 100KHz。
5.2 生成代碼輸入項目名和項目路徑選擇應用的 IDE 開發環境 MDK-ARM V5每個外設生成獨立的 』.c/.h』 文件 不勾:所有初始化代碼都生成在 main.c 勾選:初始化代碼生成在對應的外設文件。 如 GPIO 初始化代碼生成在 gpio.c 中。點擊 GENERATE CODE 生成代碼
5.3 添加全局變數在 main.c 頭部添加寫地址 0xA0,讀地址 0xA1,寫緩存區 WriteBuffer,讀緩存區 ReadBuffer。
/* Private variables ---------------------------------------------------------*/I2C_HandleTypeDef hi2c1;UART_HandleTypeDef huart1;/* USER CODE BEGIN PV */#define ADDR_24LCxx_Write 0xA0#define ADDR_24LCxx_Read 0xA1#define BufferSize 256uint8_t WriteBuffer[BufferSize] = {0};uint8_t ReadBuffer[BufferSize] = {0};/* USER CODE END PV */5.4 添加寫入和讀取函數/*** @briefThe application entry point.* @retval int*/int main(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_USART1_UART_Init();MX_I2C1_Init();/* USER CODE BEGIN 2 */printf(" ***************I2C Example******************************* ");uint32_t i;uint8_t j;for(i = 0; i < 256; i++){WriteBuffer[i] = i;/* WriteBuffer init */printf("0x%02X ", WriteBuffer[i]);if(i % 16 == 15){printf(" ");}}/* wrinte date to EEPROM */for (j = 0; j < 32; j++){if(HAL_I2C_Mem_Write(&hi2c1, ADDR_24LCxx_Write, 8*j, I2C_MEMADD_SIZE_8BIT, WriteBuffer+8*j, 8, 100) == HAL_OK){printf(" EEPROM 24C02 Write Test OK ");}else{printf(" EEPROM 24C02 Write Test False ");}} /* read date from EEPROM */HAL_I2C_Mem_Read(&hi2c1, ADDR_24LCxx_Read, 0, I2C_MEMADD_SIZE_8BIT, ReadBuffer, BufferSize, 1000);for(i = 0; i < 256; i++){printf("0x%02X",ReadBuffer[i]);if(i%16 == 15){printf(" ");}}if(memcmp(WriteBuffer,ReadBuffer,BufferSize) == 0 ) /* check date */{printf(" EEPROM 24C02 Read Test OK ");}else{printf(" EEPROM 24C02 Read Test False ");}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}程序中先初始化寫數據緩存。然後調用 HAL_I2C_Mem_Write() 函數將數據寫入 EEPROM 中。根據函數返回值判斷寫操作是否正確。在 I2C 中可以找到內存寫函數說明。
第一個參數為 I2C 操作句柄。
第二個參數為 EEPROM 的寫操作設備地址。
第三個參數為內存地址。
第四個參數為內存地址長度,EEPROM 內存長度為 8bit。
第五個參數為數據緩存的起始地址。
第六個參數為傳輸數據的大小。AT24C02 型號的晶元頁寫入時序最多可以一次 發送 8 個數據(即 n = 8 ),該值也稱為頁大小,某些型號的晶元每個頁寫入時序最多可傳輸 16 個數據。
第七個參數為操作超時時間。
/*** @briefWrite an amount of data in blocking mode to a specific memory address* @paramhi2c Pointer to a I2C_HandleTypeDef structure that contains*the configuration information for the specified I2C.* @paramDevAddress Target device address: The device 7 bits address value* in datasheet must be shifted to the left before calling the interface* @paramMemAddress Internal memory address* @paramMemAddSize Size of internal memory address* @parampData Pointer to data buffer* @paramSize Amount of data to be sent* @paramTimeout Timeout ration* @retval HAL status*/HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,uint16_t MemAddress, uint16_t MemAddSize,uint8_t *pData, uint16_t Size, uint32_t Timeout)調用 HAL_I2C_Mem_Read() 函數讀取 EEPROM 中剛才寫入的數據。HAL_I2C_Mem_Read() 函數描述如下。
第一個參數為 I2C 操作句柄。
第二個參數為 EEPROM 的讀操作設備地址。
第三個參數為內存地址。
第四個參數為內存地址長度。
第五個參數為讀取數據存儲的起始地址。
第六個參數為傳輸數據的大小。
第七個參數為操作超時時間。
/*** @briefRead an amount of data in blocking mode from a specific memory address* @paramhi2c Pointer to a I2C_HandleTypeDef structure that contains*the configuration information for the specified I2C.* @paramDevAddress Target device address: The device 7 bits address value* in datasheet must be shifted to the left before calling the interface* @paramMemAddress Internal memory address* @paramMemAddSize Size of internal memory address* @parampData Pointer to data buffer* @paramSize Amount of data to be sent* @paramTimeout Timeout ration* @retval HAL status*/HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)程序最後調用 memcmp() 函數判斷讀寫的兩個緩存的數據是否一致。memcmp() 是比較內存區域是否相等,標准庫裡面的函數,在 main.c 前面添加 string.h 頭文件。
5.5 查看列印串口列印功能查看 STM32CubeMX學習筆記(6)——USART串口使用
5.6 HAL庫與標准庫代碼比較STM32CubeMX 使用 HAL 庫生成的代碼:
/*** @brief I2C1 Initialization Function* @param None* @retval None*/static void MX_I2C1_Init(void){/* USER CODE BEGIN I2C1_Init 0 *//* USER CODE END I2C1_Init 0 *//* USER CODE BEGIN I2C1_Init 1 *//* USER CODE END I2C1_Init 1 */hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 100000;hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1 = 0;hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2 = 0;hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN I2C1_Init 2 *//* USER CODE END I2C1_Init 2 */}HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);使用 STM32 標准庫的代碼:
/*** @briefI2C I/O配置* @param無* @retval 無*/static void I2C_GPIO_Config(void){GPIO_InitTypeDefGPIO_InitStructure; /* 使能與 I2C 有關的時鍾 */EEPROM_I2C_APBxClock_FUN ( EEPROM_I2C_CLK, ENABLE );EEPROM_I2C_GPIO_APBxClock_FUN ( EEPROM_I2C_GPIO_CLK, ENABLE );/* I2C_SCL、I2C_SDA*/GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;// 開漏輸出GPIO_Init(EEPROM_I2C_SCL_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;// 開漏輸出GPIO_Init(EEPROM_I2C_SDA_PORT, &GPIO_InitStructure);}/*** @briefI2C 工作模式配置* @param無* @retval 無*/static void I2C_Mode_Config(void){I2C_InitTypeDefI2C_InitStructure; /* I2C 配置 */I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;/* 高電平數據穩定,低電平數據變化 SCL 時鍾線的占空比 */I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;I2C_InitStructure.I2C_OwnAddress1 =I2Cx_OWN_ADDRESS7; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;/* I2C的定址模式 */I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;/* 通信速率 */I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;/* I2C 初始化 */I2C_Init(EEPROM_I2Cx, &I2C_InitStructure);/* 使能 I2C */I2C_Cmd(EEPROM_I2Cx, ENABLE); }void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);六、注意事項用戶代碼要加在 USER CODE BEGIN N 和 USER CODE END N 之間,否則下次使用 STM32CubeMX 重新生成代碼後,會被刪除。
? 由 Leung 寫於 2021 年 1 月 26 日
? 參考:STM32CubeMX系列教程9:內部集成電路(I2C)
【STM32Cube_13】使用硬體I2C讀寫EEPROM(AT24C02)
原文:https://juejin.cn/post/7100502480986832926