版本 64da468f8aa6ff1712792bef2457e198f8886950
Changes from 64da468f8aa6ff1712792bef2457e198f8886950 to 82ce98b591ceca13c295ecb1dfa1378758faeb96
---
title: I2C
categories: I2C, Peripherals, STM32F4, STM32F429
...
I²C 簡介
=====================================
I²C(Inter-Integrated Circuit)是內部整合電路的稱呼,是一種串列通訊匯流排,由Philips公司在1980年代為了讓主機板、手機及嵌入式系統用以連接低速週邊裝置而發展,主要應用在board-to-board,它的設計並不能應用到長距離裝置的通訊,由於協定中從樸裝置位址只有7個位元,因此一組I²C的最多裝置位址定義至127個。
I²C只使用兩條雙向開放汲極(Open Drain)(master and slave只能把電位拉到LOW或是讓他OPEN)(串列資料(SDA)及串列時脈(SCL))並利用電阻將電位上拉。I²C允許相當大的工作電壓範圍,但典型的電壓準位為+3.3V或+5v。
I²C bus
...................
.. image:: /embedded/i2c_bus.png
藉由Master發送訊號來控制與Slave之間的通訊
I²C 特性
...................
- I²C 串列傳輸包括四個部分:起始信號、設備位址發送、數據傳送和停止信號。
- 只能Master<->Slave,無法Slave<->Slave,每個slave都要有一個特定且唯一的位址。
- START condition: SCL=High 且 SDA為負緣
- STOP condition: SCL=High 且 SDA=為正緣
.. image:: /embedded/i2c_condition.png
- 由Master發送起始信號來開起通訊,所有的slave device接收到起始信號後會進入接收數據模式。接著Master需要發送通訊目標設備的address及R/W資訊。
- STM32F429提供兩種 address mode - 7bit and 10bit
- 7bit mode: 發送 7bit 的address (MSB) 及一位元的 R(1)/W(0)後,該 address 的slave端會發送一個bit的 Ack(acknowledge) bit,ACK=0表設定成功(Slave把SDA拉到LOW),開始數據傳送。
.. image:: /embedded/i2c_com.png
(7bit mode)
- 10bit mode: 總共用兩個byte來傳送 address資訊。第一個byte的前五個位元需為 "11110" 來表示要使用 10-bit addressing。
.. image:: /embedded/i2c_10bit.gif
(10bit mode)
- 資料傳輸
- 在 SCL 為 HIGH 時,SDA 必須是 stable 的。
- SDA 只能在 SCL 為 LOW 時改變。
- 一次傳一個 byte,每個byte都跟著一個 ACK bit ,在 ACK bit 時 Master 會釋放bus,此時 Slave 端需把 SDA 拉 LOW,否則 Master 需要發出 STOP訊號 或是重新發送 START 訊號。
- 在每個 byte 之間 Slave 端可以把 SCL 拉 LOW 來強制讓傳輸暫停。
-
I²C on STM32F429-Discovery
=====================================
實驗一: touch panel
...................
觀察及使用stm32f429i_discovery_ioe.c,並量測對應的訊號
- `Data sheet <http://www.st.com/web/en/resource/technical/document/datasheet/CD00186725.pdf>`_
demo code:
[stm32f429i_discovery_ioe.h]
.. code-block:: c
#define IOE_I2C I2C3
#define IOE_I2C_CLK RCC_APB1Periph_I2C3
#define IOE_I2C_SCL_PIN GPIO_Pin_8
#define IOE_I2C_SCL_GPIO_PORT GPIOA
#define IOE_I2C_SCL_GPIO_CLK RCC_AHB1Periph_GPIOA
#define IOE_I2C_SCL_SOURCE GPIO_PinSource8
#define IOE_I2C_SCL_AF GPIO_AF_I2C3
#define IOE_I2C_SDA_PIN GPIO_Pin_9
#define IOE_I2C_SDA_GPIO_PORT GPIOC
#define IOE_I2C_SDA_GPIO_CLK RCC_AHB1Periph_GPIOC
#define IOE_I2C_SDA_SOURCE GPIO_PinSource9
#define IOE_I2C_SDA_AF GPIO_AF_I2C3
#define IOE_I2C_DR ((uint32_t)0x40005C10)
GPIO 設定
.. code-block:: c
GPIO_InitTypeDef GPIO_InitStructure;
/* 設定RCC clock*/
/* Enable IOE_I2C and IOE_I2C_GPIO_PORT & Alternate Function clocks */
RCC_APB1PeriphClockCmd(IOE_I2C_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(IOE_I2C_SCL_GPIO_CLK | IOE_I2C_SDA_GPIO_CLK |
IOE_IT_GPIO_CLK, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Reset IOE_I2C IP */
RCC_APB1PeriphResetCmd(IOE_I2C_CLK, ENABLE);
/* Release reset signal of IOE_I2C IP */
RCC_APB1PeriphResetCmd(IOE_I2C_CLK, DISABLE);
/*設定PA8、PC9 的Alternate function設為 GPIO_AF_I2C3*/
/* Connect PXx to I2C_SCL*/
GPIO_PinAFConfig(IOE_I2C_SCL_GPIO_PORT, IOE_I2C_SCL_SOURCE, IOE_I2C_SCL_AF);
/* Connect PXx to I2C_SDA*/
GPIO_PinAFConfig(IOE_I2C_SDA_GPIO_PORT, IOE_I2C_SDA_SOURCE, IOE_I2C_SDA_AF);
/* 設定 SCL、SDA pin*/
/* IOE_I2C SCL and SDA pins configuration */
GPIO_InitStructure.GPIO_Pin = IOE_I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IOE_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = IOE_I2C_SDA_PIN;
GPIO_Init(IOE_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
I2C參數設定
.. code-block:: c
I2C_InitTypeDef I2C_InitStructure;
/* If the I2C peripheral is already enabled, don't reconfigure it */
if ((IOE_I2C->CR1 & I2C_CR1_PE) == 0)
{
/* 設定 I2C參數*/
/* IOE_I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
/* Initialize the I2C peripheral */
I2C_Init(IOE_I2C, &I2C_InitStructure);
/* Enable the I2C peripheral */
I2C_Cmd(IOE_I2C, ENABLE);
}
(待補)
SCL: PA8
SDA: PC9
slave address: 0x82 (0x01000010)
.. image:: /embedded/I2C_touchpanel_test.jpg
.. image:: /embedded/i2c_scope_0.bmp
實驗二: 兩塊(以上)板子的數據傳輸
...................
一塊板子當作Master,其他的作為Slave,實驗I2C的資料傳輸
(待補)
(NVIC & I2C interrupt)