Memory Mapped I/O
๐ฆ ์ ์ฒด ๋ฉ๋ชจ๋ฆฌ ๋งต ๊ตฌ์กฐ (0x0000_0000 ~ 0xFFFF_FFFF)
STM32๋ ์ฃผ์ ๊ณต๊ฐ์ 512MB ๋จ์๋ก 8๊ฐ์ ๋ธ๋ก์ผ๋ก ๋๋๋๋ค:
์ฃผ์ ๋ฒ์ | ๋ธ๋ก | ์ค๋ช |
0x0000_0000 ~ 0x1FFF_FFFF | Block 0 | Code ์์ญ (Flash, Boot Memory) |
0x2000_0000 ~ 0x3FFF_FFFF | Block 1 | SRAM ์์ญ |
0x4000_0000 ~ 0x5FFF_FFFF | Block 2 | Peripherals (๋ ์ง์คํฐ) |
0x6000_0000 ~ 0x7FFF_FFFF | Block 3 | FSMC bank1 & bank2 (์ธ๋ถ ๋ฉ๋ชจ๋ฆฌ ์ธํฐํ์ด์ค) |
0x8000_0000 ~ 0x9FFF_FFFF | Block 4 | FSMC bank3 & bank4 |
0xA000_0000 ~ 0xBFFF_FFFF | Block 5 | FSMC ๋ ์ง์คํฐ |
0xC000_0000 ~ 0xDFFF_FFFF | Block 6 | ์ฌ์ฉ๋์ง ์์ |
0xE000_0000 ~ 0xFFFF_FFFF | Block 7 | Cortex-M3 ๋ด๋ถ ์์คํ ๋ฐ ๋๋ฒ๊ทธ์ฉ ๋ ์ง์คํฐ |
๐ธ Block 0 (Code ์์ญ) ์์ธ
์ฃผ์ | ์ค๋ช |
0x0000_0000 | Flash, System Memory, or SRAM์ผ๋ก alias ๋จ (BOOT ํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง) |
0x0800_0000 ~ 0x080F_FFFF | Flash ๋ฉ๋ชจ๋ฆฌ |
0x1FFF_0000 ~ 0x1FFF_7A0F | System Memory, OTP, Option Bytes ๋ฑ |
0x1FFF_C000 ~ 0x1FFF_FFFF | Option Bytes, Reserved ๋ฑ |
๐ธ Block 1 (SRAM ์์ญ) ์์ธ
์ฃผ์ | ์ค๋ช |
0x2000_0000 ~ 0x2001_BFFF | SRAM (112KB) |
0x2001_C000 ~ 0x2001_FFFF | SRAM (16KB) |
0x2002_0000 ~ 0x3FFF_FFFF | Reserved (bit-band alias ์์ญ ํฌํจ) |
๐ก Bit-Banding: ๋นํธ๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ๋ค๋ฃจ๊ธฐ ์ํด ํน๋ณํ ๋งคํ๋ ์ฃผ์ ์์ญ์ ๋๋ค.
๐ธ Block 2 (Peripherals ์์ญ) ์์ธ
์ฃผ์ | ์ฃผ๋ณ์ฅ์น |
0x4000_0000 ~ 0x4000_03FF | TIM2, TIM3, TIM4 ๋ฑ |
… | … |
0x4001_0000 ~ 0x4001_FFFF | USART1, SPI1, ADC1~3 ๋ฑ |
์ด 0x4000_0000 ~ 0x5006_03FF | ๋ชจ๋ AHB/APB ์ฅ์น๋ค์ด ์ฌ๊ธฐ์ ์์น |
๐ธ Block 3 & 4 (FSMC External Memory ์์ญ)
์ด ์์ญ์ **์ธ๋ถ ๋ฉ๋ชจ๋ฆฌ (PSRAM, NOR, NAND ๋ฑ)**๋ฅผ ์ฐ๊ฒฐํ๋ FSMC ์ปจํธ๋กค๋ฌ์ bank๋ณ ์ฃผ์์ ๋๋ค:
์ฃผ์ ๋ฒ์ | ์ฐ๊ฒฐ ์ฅ์น |
0x6000_0000 ~ 0x63FF_FFFF | FSMC bank1 NOR/PSRAM 1 |
0x6400_0000 ~ 0x67FF_FFFF | FSMC bank1 NOR/PSRAM 2 |
0x6800_0000 ~ 0x6BFF_FFFF | FSMC bank1 NOR/PSRAM 3 |
0x6C00_0000 ~ 0x6FFF_FFFF | FSMC bank1 NOR/PSRAM 4 |
0x7000_0000 ~ 0x7FFF_FFFF | FSMC bank2 NAND |
0x8000_0000 ~ 0x8FFF_FFFF | FSMC bank3 NAND |
๐ธ Block 7 (Cortex-M3 ๋ด๋ถ ์์ญ)
์ฃผ์ ๋ฒ์ | ์ค๋ช |
0xE000_0000 ~ 0xE00F_FFFF | NVIC, SCB, SysTick ๋ฑ |
0xE004_2000 ๋ฑ | ๋๋ฒ๊น , ITM, DWT ๋ฑ ๋๋ฒ๊ทธ ๋ชจ๋ |
์ด ๋ฉ๋ชจ๋ฆฌ ๋งต์ ๋ ์ง์คํฐ ์ ๊ทผ, DMA ์ค์ , Flash ์ ๊ทผ, SRAM ์ ์ด, ๋ถํธ ๋์ ๋ฑ STM32๋ฅผ ์ ํํ ๋ค๋ฃจ๊ธฐ ์ํ ํต์ฌ ์ ๋ณด์ ๋๋ค.
ํ์ํ๋ฉด ๊ฐ ๋ธ๋ก๋ณ๋ก ์ถ๊ฐ ์ค๋ช ์ด๋ ์์ ์ฝ๋๋ ์ ๊ณต ๊ฐ๋ฅํฉ๋๋ค.
ํน์ ์์ญ์์ ์์ธํ ์๊ณ ์ถ์ ๋ถ๋ถ์ด ์๋์?
๋์ ๋ง:
memory mapped i/o ์์
ChatGPT์ ๋ง:
๋ง์ต๋๋ค, ์ด STM32 ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ Memory-Mapped I/O (MMIO) ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฆ ๋๋ค. ์๋์์ ๊ฐ๋ ๋ถํฐ STM32์์์ ์ ์ฉ๊น์ง ํต์ฌ์ ์ ๋ฆฌํด ๋๋ฆฌ๊ฒ ์ต๋๋ค:
โ Memory-Mapped I/O๋?
Memory-Mapped I/O๋ ์ฃผ๋ณ ์ฅ์น (GPIO, USART, TIM ๋ฑ)์ ๋ ์ง์คํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ๊ณต๊ฐ์ ์ง์ ๋งคํํด์ ์ผ๋ฐ ๋ฉ๋ชจ๋ฆฌ์ฒ๋ผ ์ ๊ทผํ๋ ๋ฐฉ์์ ๋๋ค.
์ฆ,
c
๋ณต์ฌํธ์ง
#define GPIOA_MODER (*(volatile uint32_t*)0x40020000)
GPIOA_MODER = 0x00000001;
์ฒ๋ผ ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ ์ฐ๋ ๊ฒ์ฒ๋ผ ๋ ์ง์คํฐ๋ฅผ ์ ์ดํ๋ ๋ฐฉ์์ ๋๋ค.
โ STM32์์์ MMIO ์์
STM32์์๋ Block 2 (0x4000_0000 ~ 0x5FFF_FFFF)๊ฐ ๋ฐ๋ก ์ด MMIO๋ฅผ ์ํ ์ฃผ๋ณ์ฅ์น ๋ ์ง์คํฐ ์์ญ์ ๋๋ค.
์ฅ์น | ์์ ์ฃผ์ | ์์ ์ค๋ช |
GPIOA | 0x4002_0000 | ํฌํธ A ์ ์ด |
USART2 | 0x4000_4400 | ์๋ฆฌ์ผ ํต์ ์ ์ด |
TIM2 | 0x4000_0000 | ํ์ด๋จธ ์ ์ด |
RCC | 0x4002_3800 | ํด๋ญ ์ค์ |
โ ์ MMIO๋ฅผ ์ฌ์ฉํ ๊น?
๋ฐฉ์ | ํน์ง |
MMIO | CPU๊ฐ ๋ฉ๋ชจ๋ฆฌ์ฒ๋ผ ์ฅ์น ๋ ์ง์คํฐ์ ์ ๊ทผํจ. Load/Store ๋ช ๋ น ์ฌ์ฉ. |
Port-Mapped I/Oย (x86์์ ์ฌ์ฉ) | ํน๋ณํ I/O ๋ช
๋ น ์ฌ์ฉ (in ,ย out ) |
STM32๋ MMIO ๋ฐฉ์๋ง ์ง์ํฉ๋๋ค. ์ฅ์ ์:
- CPU ์ ์ฅ์์ I/O๋ ๋ฉ๋ชจ๋ฆฌ์ฒ๋ผ ์ฝ๊ณ ์
- ์ฃผ์ ๊ณต๊ฐ ํตํฉ ๊ด๋ฆฌ
- ๊ณ ์ ์ฒ๋ฆฌ (๋ฒ์ค์ ์ง์ ์ฐ๊ฒฐ๋จ)
โ STM32 MMIO ์๋ ๋ฐฉ์ ๊ทธ๋ฆผ
STM32 ๋ด๋ถ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ ํ๋ฆ์ ๋๋ค:
๋ณต์ฌํธ์ง
[ CPU ]
โ
[ BUS (AHB/APB) ]
โ
[ ์ฃผ์ ๋์ฝ๋ ] โ 0x4002_0000 = GPIOA
โ
[ ์ฅ์น ๋ ์ง์คํฐ ]
โ ์์ : GPIOA ํ ์ถ๋ ฅ ์ ์ด (MMIO ์ง์ ์ ๊ทผ)
c
๋ณต์ฌํธ์ง
#define RCC_AHB1ENR (*(volatile uint32_t*)0x40023830)
#define GPIOA_MODER (*(volatile uint32_t*)0x40020000)
#define GPIOA_ODR (*(volatile uint32_t*)0x40020014)
void gpio_init(void) {
RCC_AHB1ENR |= (1 << 0); // GPIOA ํด๋ญ ํ์ฑํ
GPIOA_MODER |= (1 << 10); // PA5๋ฅผ ์ถ๋ ฅ ๋ชจ๋๋ก
}
void gpio_write_high(void) {
GPIOA_ODR |= (1 << 5); // PA5 ์ถ๋ ฅ High
}
โ ์์ฝ
ํญ๋ชฉ | ์ค๋ช |
MMIO๋? | ์ฃผ๋ณ์ฅ์น ๋ ์ง์คํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ฒ๋ผ ์ง์ ์ ๊ทผ |
STM32 ์ ์ฉ ์ฃผ์ | 0x4000_0000 ~ 0x5FFF_FFFF (Block 2) |
์ ๊ทผ ๋ฐฉ๋ฒ | C ํฌ์ธํฐ๋ฅผ ์ด์ฉํด ์ง์ ๋ ์ง์คํฐ ์ฃผ์์ ์ ๊ทผ |
์ฅ์ | ๋น ๋ฅด๊ณ ์ผ๊ด๋ ์ ๊ทผ ๋ฐฉ์, ๊ฐ๊ฒฐํ ํ๋์จ์ด ์ ์ด |
ํ์ํ๋ฉด ์ฃผ๋ณ์ฅ์น๋ณ MMIO ์ฃผ์ ์ ๋ฆฌํ๋, ์ง์ ์ ๊ทผ ๋์ CMSIS๋ฅผ ์ฌ์ฉํ๋ ๊ตฌ์กฐ๋ ์ ๋ฆฌํด ๋๋ฆด ์ ์์ต๋๋ค. ํน์ ์ฅ์น๋ฅผ ์๋ก ๋ค์ด๋ณผ๊น์?
๋์ ๋ง:
block2 ๋ง memory mapped i/o์ผ?
ChatGPT์ ๋ง:
์์ฃผ ์ข์ ์ง๋ฌธ์ ๋๋ค. ๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด:
๐จ Block 2(0x4000_0000 ~ 0x5FFF_FFFF) ์์ญ์ด ๋ํ์ ์ธ Memory-Mapped I/O ์์ญ์ด์ง๋ง,
**๐ฅ Block 7(0xE000_0000 ~ 0xFFFF_FFFF)**๋ Memory-Mapped I/O ๋ฐฉ์์ผ๋ก ๋์ํฉ๋๋ค.
โ Memory-Mapped I/O๊ฐ ์ ์ฉ๋ ์์ญ
๋ธ๋ก | ์ฃผ์ ๋ฒ์ | ์ค๋ช | MMIO ์ฌ๋ถ |
Block 2 | 0x4000_0000 ~ 0x5FFF_FFFF | APB/AHB ๋ฒ์ค๋ฅผ ํตํย ์ธ๋ถ ์ฃผ๋ณ์ฅ์นย (GPIO, USART ๋ฑ) | โ O |
Block 7 | 0xE000_0000 ~ 0xE00F_FFFF | System Control Block (SCB),ย NVIC,ย SysTick,ย Debug ๋ฑ | โ O |
๊ธฐํ | ์ผ๋ถ Flash ์ปจํธ๋กค๋ฌ, Option Bytes | Flash interface (write/erase ์ ์ด์ฉ ๋ ์ง์คํฐ) | โ O (๊ฐ์ ์ ์ผ๋ก) |
โ MMIO๊ฐ ์๋ ์์ญ ์์
๋ธ๋ก | ์ฃผ์ ๋ฒ์ | ์ค๋ช | MMIO ์ฌ๋ถ |
Block 0 | 0x0000_0000 ~ 0x1FFF_FFFF | Flash, Boot ROM, alias ์์ญ | โ (์ผ๋ฐ ๋ฉ๋ชจ๋ฆฌ) |
Block 1 | 0x2000_0000 ~ 0x3FFF_FFFF | SRAM | โ (์ผ๋ฐ ๋ฉ๋ชจ๋ฆฌ) |
Block 3~5 | FSMC ์์ญ (0x6000_0000 ์ด์) | ์ธ๋ถ ๋ฉ๋ชจ๋ฆฌ ์ธํฐํ์ด์ค (SRAM, NAND ๋ฑ) | โ (์ธ๋ถ memory-mapped, ์ฅ์น์ ์ด๋ ์๋) |
โ ์ Block 7๋ MMIO์ธ๊ฐ?
0xE000_0000 ~
์ฃผ์๋ Cortex-M3 ์ฝ์ด ๋ด๋ถ ์์คํ
์ฅ์น๊ฐ ์์นํ๋ ์์ญ์
๋๋ค. ์๋ฅผ ๋ค์ด:
์ฅ์น | ์ฃผ์ | ์ค๋ช |
SCB (System Control Block) | 0xE000_ED00 | ์ธํฐ๋ฝํธ ์ฐ์ ์์, Sleep ์ ์ด |
NVIC (Interrupt Controller) | 0xE000_E100 | ์ธํฐ๋ฝํธ ํ์ฑํ/๋นํ์ฑํ |
SysTick Timer | 0xE000_E010 | ์์คํ ํ์ด๋จธ |
์ด๋ค์ ๋ ์ง์คํฐ ๋ฐฉ์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ์ฒ๋ผ ์ ๊ทผํ๋ฏ๋ก Memory-Mapped I/O์ ๋๋ค.
๐ ์ ๋ฆฌ
- โ Block 2, Block 7์ ๋ชจ๋ MMIO ์์ญ
- โ SRAM, Flash๋ ๋ฉ๋ชจ๋ฆฌ์ผ ๋ฟ I/O๊ฐ ์๋
- โ FSMC๋ ์ธ๋ถ ์ฅ์น์ ์ฐ๊ฒฐ๋์ง๋ง ๋ ์ง์คํฐ ์ ์ด์ฉ I/O๋ ์๋ (๋ฐ์ดํฐ ์์ญ)
ํ์ํ๋ค๋ฉด STM32 MMIO ์ ์ฒด ์ฃผ์ ์ ๋ฆฌํ๋ ์ ๊ณตํด ๋๋ฆด ์ ์์ด์. ํน์ ์์ญ์ด๋ ๋ ์ง์คํฐ๊ฐ ๊ถ๊ธํ์ ๊ฐ์?
๋์ ๋ง:
์
ChatGPT์ ๋ง:
์ข์ต๋๋ค! STM32์์ ์ฌ์ฉ๋๋ ์ฃผ์ Memory-Mapped I/O (MMIO) ์ฃผ์ ์ ๋ฆฌํ๋ฅผ ์๋์ ํต์ฌ๋ง ์์ฝํด๋๋ฆฝ๋๋ค. ์ด ํ๋ ์ค๋ฌด์์ ๋ ์ง์คํฐ ์ง์ ์ ๊ทผํ๊ฑฐ๋ ๋๋ฒ๊น ํ ๋ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
โ [1] Cortex-M3 ์์คํ MMIO (Block 7: 0xE000_0000 ~)
์ฅ์น | ์ฃผ์ ๋ฒ์ | ์ค๋ช |
NVIC | 0xE000_E100 ~ | ์ธํฐ๋ฝํธ ํ์ฑํ/๋นํ์ฑํ |
SCB | 0xE000_ED00 ~ | ์ฐ์ ์์, ๋ฒกํฐ ํ ์ด๋ธ, SYSRESET ๋ฑ |
SysTick | 0xE000_E010 ~ | ์์คํ ํ์ด๋จธ |
ITM/DWT/TPIU | 0xE000_0000 ~ | ๋๋ฒ๊ทธ ์ถ์ ๋ชจ๋ |
โ [2] ์ผ๋ฐ ์ฃผ๋ณ์ฅ์น MMIO (Block 2: 0x4000_0000 ~)
โฑ ํ์ด๋จธ
์ฅ์น | ์ฃผ์ |
TIM2 ~ TIM5 | 0x4000_0000 ~ 0x4000_3FFF |
TIM6 ~ TIM14 | 0x4000_1000 ~ 0x4000_4FFF |
๐ก USART / UART
์ฅ์น | ์ฃผ์ |
USART1 | 0x4001_3800 |
USART2 | 0x4000_4400 |
USART3 | 0x4000_4800 |
UART4 | 0x4000_4C00 |
UART5 | 0x4000_5000 |
๐ SPI / I2C
์ฅ์น | ์ฃผ์ |
SPI1 | 0x4001_3000 |
SPI2 | 0x4000_3800 |
I2C1 | 0x4000_5400 |
I2C2 | 0x4000_5800 |
๐ง RCC / PWR
์ฅ์น | ์ฃผ์ |
RCC | 0x4002_3800 |
PWR | 0x4000_7000 |
๐ก GPIO
์ฅ์น | ์ฃผ์ |
GPIOA | 0x4002_0000 |
GPIOB | 0x4002_0400 |
GPIOC | 0x4002_0800 |
GPIOD | 0x4002_0C00 |
โ [3] Flash, Option Bytes, System Memory (Block 0)
์ฅ์น | ์ฃผ์ |
Flash memory | 0x0800_0000 ~ |
System memory (bootloader) | 0x1FFF_0000 ~ 0x1FFF_7A0F |
Option Bytes | 0x1FFF_C000 ~ |
๐ ์์ ์ฝ๋: GPIOA์ PA5 ์ถ๋ ฅ
c
๋ณต์ฌํธ์ง
#define RCC_AHB1ENR (*(volatile uint32_t*)0x40023830)
#define GPIOA_MODER (*(volatile uint32_t*)0x40020000)
#define GPIOA_ODR (*(volatile uint32_t*)0x40020014)
void init_gpioa_pa5() {
RCC_AHB1ENR |= (1 << 0); // GPIOA ํด๋ญ ์ธ๊ฐ
GPIOA_MODER |= (1 << 10); // PA5 = Output
GPIOA_ODR |= (1 << 5); // PA5 High
}
์ํ์๋ฉด ์ ์ฒด MMIO ์ฃผ์ ๋งต์ PDF ํน์ ์์ ๋ก๋ ์ ๋ฆฌํด๋๋ฆด ์ ์์ด์.
์ด๋ค ์ฅ์น๋ฅผ ์์ฃผ๋ก ๋ ๋ณด๊ณ ์ถ์ผ์ ๊ฐ์? (์: DMA, ADC, SPI ๋ฑ)
๋์ ๋ง:
PDF ๋ก ์ค
ChatGPT์ ๋ง:
์๋ฃ๋์์ต๋๋ค. ์๋ ๋งํฌ์์ STM32์ MMIO ์ฃผ์ ๋งต PDF๋ฅผ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค:
๐ stm32_mmio_map.pdf ๋ค์ด๋ก๋
ํ์ํ์๋ฉด ADC, DMA, CAN ๋ฑ ์ถ๊ฐ ์ฃผ๋ณ์ฅ์น๋ ํฌํจํด์ ํ์ฅํ ์ ์์ต๋๋ค. ์ถ๊ฐ๋ก ํฌํจํ ๊น์?
๋์ ๋ง:

i2c๋ memory mapped io์์ ๊ทธ๋ฌ๋ฉด i2c๋ฅผ ํจ์๋ง๊ณ register ์ค์ ๋ง์ผ๋ก ํต์ ๊ฐ๋ฅํ๋๋ก
ChatGPT์ ๋ง:
๋ง์ต๋๋ค. STM32์ I2C1 (0x40005400), I2C2 (0x40005800) ๋ ๋ชจ๋ Memory-Mapped I/O ๋ฐฉ์์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅํ ๋ ์ง์คํฐ ๊ธฐ๋ฐ ์ฃผ๋ณ์ฅ์น์ ๋๋ค.
๋ฐ๋ผ์ HAL ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ๋ ์ง์คํฐ๋ง ์ง์ ์ ์ดํ์ฌ I2C ํต์ ์ ๊ตฌํํ ์ ์์ต๋๋ค.
โ ๋ชฉํ: HAL ์์ด I2C๋ฅผ ๋ ์ง์คํฐ๋ก ์ง์ ์ ์ด
์ฌ๊ธฐ์๋ ๋ง์คํฐ ์ก์ (Master Transmit) ๊ธฐ์ค์ผ๋ก I2C1์ ์ฌ์ฉํ ์์ ๋ฅผ ์ค๋ช ํฉ๋๋ค.
โ 1. ๊ด๋ จ ๋ ์ง์คํฐ (I2C1 ๊ธฐ์ค, 0x40005400)
์คํ์ | ์ด๋ฆ | ์ค๋ช |
0x00 | I2C_CR1 | Control register 1 |
0x04 | I2C_CR2 | Control register 2 |
0x08 | I2C_OAR1 | Own address register 1 |
0x10 | I2C_DR | Data register |
0x14 | I2C_SR1 | Status register 1 |
0x18 | I2C_SR2 | Status register 2 |
0x1C | I2C_CCR | Clock control register |
0x20 | I2C_TRISE | Maximum rise time |
โ 2. ์์ : I2C1๋ก 0x50 ์ฃผ์์ EEPROM์ 1๋ฐ์ดํธ ์ฐ๊ธฐ
๐ก ๊ธฐ๋ณธ ์ค์ (Clock & GPIO๋ RCC/GPIO ๋ ์ง์คํฐ๋ก ๋ณ๋ ์ค์ ํด์ผ ํจ)
c
๋ณต์ฌํธ์ง
#define I2C1_BASE 0x40005400
#define RCC_APB1ENR (*(volatile uint32_t*)0x40023840)
#define RCC_AHB1ENR (*(volatile uint32_t*)0x40023830)
#define I2C1_CR1 (*(volatile uint32_t*)(I2C1_BASE + 0x00))
#define I2C1_CR2 (*(volatile uint32_t*)(I2C1_BASE + 0x04))
#define I2C1_OAR1 (*(volatile uint32_t*)(I2C1_BASE + 0x08))
#define I2C1_DR (*(volatile uint32_t*)(I2C1_BASE + 0x10))
#define I2C1_SR1 (*(volatile uint32_t*)(I2C1_BASE + 0x14))
#define I2C1_SR2 (*(volatile uint32_t*)(I2C1_BASE + 0x18))
#define I2C1_CCR (*(volatile uint32_t*)(I2C1_BASE + 0x1C))
#define I2C1_TRISE (*(volatile uint32_t*)(I2C1_BASE + 0x20))
โ 3. ์ด๊ธฐํ ๋ฐ ์ก์ ํจ์ (์ง์ ๊ตฌํ)
c
๋ณต์ฌํธ์ง
void i2c1_init() {
RCC_APB1ENR |= (1 << 21); // I2C1 ํด๋ญ ํ์ฑํ
RCC_AHB1ENR |= (1 << 0); // GPIOA ํด๋ญ ํ์ฑํ ๋ฑ (SCL/SDA ํ ์ค์ ํ์)
I2C1_CR2 = 16; // APB1 ํด๋ญ 16MHz
I2C1_CCR = 80; // Standard mode 100kHz
I2C1_TRISE = 17; // ์ต๋ ์์น ์๊ฐ
I2C1_CR1 |= (1 << 0); // Peripheral Enable
}
void i2c1_start() {
I2C1_CR1 |= (1 << 8); // START bit
while (!(I2C1_SR1 & (1 << 0))); // SB ์ค์ ๋ ๋๊น์ง ๋๊ธฐ
}
void i2c1_send_addr(uint8_t addr) {
I2C1_DR = addr;
while (!(I2C1_SR1 & (1 << 1))); // ADDR ํ์ธ
(void)I2C1_SR2; // SR2 ์ฝ๊ธฐ๋ก ํด๋ฆฌ์ด
}
void i2c1_send_data(uint8_t data) {
while (!(I2C1_SR1 & (1 << 7))); // TXE
I2C1_DR = data;
while (!(I2C1_SR1 & (1 << 2))); // BTF
}
void i2c1_stop() {
I2C1_CR1 |= (1 << 9); // STOP
}
void i2c1_write_byte(uint8_t dev_addr, uint8_t reg, uint8_t data) {
i2c1_start();
i2c1_send_addr(dev_addr << 1); // Write mode
i2c1_send_data(reg); // Register address
i2c1_send_data(data); // Data
i2c1_stop();
}
โ 4. ์ฃผ์์ฌํญ
- GPIOB ํ(PB6: SCL, PB7: SDA ๋ฑ)๋
Alternate Function
์ค์ ํ์
AF4
๋ก ์ค์ (STM32F4 ๊ธฐ์ค)
- APB1 ํด๋ญ ์ฃผํ์์ ๋ฐ๋ผ
CCR
,TRISE
๊ฐ ๋ณ๊ฒฝ ํ์
โ ์์ฝ
ํญ๋ชฉ | ๋ด์ฉ |
๊ตฌ์กฐ | I2C๋ MMIO ๋ ์ง์คํฐ๋ฅผ ํตํด ์ง์ ์ ์ด ๊ฐ๋ฅ |
์ฃผ์ | I2C1 = 0x40005400, I2C2 = 0x40005800 |
์ฅ์ | HAL ๋ฏธ์ฌ์ฉ โ ์ฝ๋ ๊ฒฝ๋ํ, ๋น ๋ฅธ ์ ์ด |
์ํ | ์ค๋ฅ ์ฒ๋ฆฌ, ํ์ด๋ฐ, ACK ์ฒดํฌ ๋ฑ ์๋ ์ฒ๋ฆฌ ํ์ |
ํ์ํ๋ฉด “I2C ์์ ”์ด๋ “EEPROM ์ฝ๊ธฐ”, “ACK ๊ฒ์ฌ” ๋ฑ๋ ์ถ๊ฐ๋ก ์์ฑํด๋๋ฆด ์ ์์ต๋๋ค. ์ด๋ค ์์ ๋ ํด๋ณด์๊ฒ ์ด์?
๋์ ๋ง:
์ฝ๋์ ์ฃผ์์ ๋ฌ์์ผ์ง
ChatGPT์ ๋ง:
๋ฌผ๋ก ์ ๋๋ค. ์๋๋ HAL ์์ด ๋ ์ง์คํฐ๋ง์ผ๋ก I2C1 ๋ง์คํฐ ์ก์ ์ ๊ตฌํํ ์์ ์ฝ๋์ ์์ธํ ์ฃผ์์ ์ถ๊ฐํ ๋ฒ์ ์ ๋๋ค. ์ด ์ฝ๋๋ STM32์์ I2C๋ฅผ ์ง์ ์ ์ดํ์ฌ 0x50 ์ฃผ์์ ์ฌ๋ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ๋์์ ๋๋ค.
โ ๋ ์ง์คํฐ ์ ์ ๋ฐ ์ด๊ธฐํ ํจ์
c
๋ณต์ฌํธ์ง
// RCC ๊ด๋ จ ๋ ์ง์คํฐ: ํด๋ญ ์ค์ ์ฉ
#define RCC_APB1ENR (*(volatile uint32_t*)0x40023840) // APB1 ๋ฒ์ค (I2C ํด๋ญ)
#define RCC_AHB1ENR (*(volatile uint32_t*)0x40023830) // AHB1 ๋ฒ์ค (GPIO ํด๋ญ)
// I2C1 ๋ฒ ์ด์ค ์ฃผ์ ๋ฐ ๋ ์ง์คํฐ ์ ์
#define I2C1_BASE 0x40005400
#define I2C1_CR1 (*(volatile uint32_t*)(I2C1_BASE + 0x00)) // ์ ์ด 1
#define I2C1_CR2 (*(volatile uint32_t*)(I2C1_BASE + 0x04)) // ์ ์ด 2 (ํด๋ญ ์ค์ )
#define I2C1_OAR1 (*(volatile uint32_t*)(I2C1_BASE + 0x08)) // Own Address 1
#define I2C1_DR (*(volatile uint32_t*)(I2C1_BASE + 0x10)) // ๋ฐ์ดํฐ ๋ ์ง์คํฐ
#define I2C1_SR1 (*(volatile uint32_t*)(I2C1_BASE + 0x14)) // ์ํ 1
#define I2C1_SR2 (*(volatile uint32_t*)(I2C1_BASE + 0x18)) // ์ํ 2
#define I2C1_CCR (*(volatile uint32_t*)(I2C1_BASE + 0x1C)) // ํด๋ญ ์ ์ด
#define I2C1_TRISE (*(volatile uint32_t*)(I2C1_BASE + 0x20)) // ์ต๋ ์์น ์๊ฐ
โ I2C1 ์ด๊ธฐํ
c
๋ณต์ฌํธ์ง
void i2c1_init() {
RCC_APB1ENR |= (1 << 21); // I2C1 ํด๋ญ ํ์ฑํ
RCC_AHB1ENR |= (1 << 1); // GPIOB ํด๋ญ ํ์ฑํ (PB6=SCL, PB7=SDA)
I2C1_CR2 = 16; // APB1 ํด๋ญ ์ฃผํ์ ์ค์ (16MHz)
I2C1_CCR = 80; // 100kHz ์ค์ (Standard Mode = 16MHz / (2*CCR))
I2C1_TRISE = 17; // ์ต๋ ์์น ์๊ฐ = 1000ns ๊ธฐ์ค โ TRISE = Freq(MHz) + 1
I2C1_CR1 |= (1 << 0); // I2C1 Peripheral Enable
}
โ I2C1 ๋์ ํจ์๋ค (START โ ์ฃผ์ ์ ์ก โ ๋ฐ์ดํฐ ์ ์ก โ STOP)
c
๋ณต์ฌํธ์ง
void i2c1_start() {
I2C1_CR1 |= (1 << 8); // START ๋นํธ ์ค์
while (!(I2C1_SR1 & (1 << 0))); // SB (Start Bit ์ค์ ๋จ) ํ๋๊ทธ ๋๊ธฐ
}
void i2c1_send_addr(uint8_t addr) {
I2C1_DR = addr; // ์ฌ๋ ์ด๋ธ ์ฃผ์ (LSB = 0 for Write)
while (!(I2C1_SR1 & (1 << 1))); // ADDR ํ๋๊ทธ ๋๊ธฐ (์ฃผ์ ์ ์ก ์๋ฃ)
(void)I2C1_SR2; // SR2 ์ฝ๊ธฐ๋ก ADDR ํด๋ฆฌ์ด
}
void i2c1_send_data(uint8_t data) {
while (!(I2C1_SR1 & (1 << 7))); // TXE (์ ์ก ๋ฒํผ Empty) ๋๊ธฐ
I2C1_DR = data; // ๋ฐ์ดํฐ ์ ์ก
while (!(I2C1_SR1 & (1 << 2))); // BTF (Byte Transfer Finished) ๋๊ธฐ
}
void i2c1_stop() {
I2C1_CR1 |= (1 << 9); // STOP ๋นํธ ์ค์ โ ํต์ ์ข
๋ฃ
}
โ I2C1 ๋ง์คํฐ ์ก์ (1 ๋ฐ์ดํธ)
c
๋ณต์ฌํธ์ง
void i2c1_write_byte(uint8_t dev_addr, uint8_t reg, uint8_t data) {
i2c1_start(); // START ์ ํธ ๋ฐ์
i2c1_send_addr(dev_addr << 1); // ์ฌ๋ ์ด๋ธ ์ฃผ์ ์ ์ก (Write ๋ชจ๋)
i2c1_send_data(reg); // ๋ ์ง์คํฐ ์ฃผ์ ์ ์ก (๋ณดํต EEPROM์ ์ฃผ์ ์ง์ ํ์)
i2c1_send_data(data); // ์ค์ ์ ์กํ ๋ฐ์ดํฐ ๋ฐ์ดํธ
i2c1_stop(); // STOP์ผ๋ก ์ข
๋ฃ
}
โ ์ฌ์ฉ ์์
c
๋ณต์ฌํธ์ง
i2c1_init(); // I2C1 ์ด๊ธฐํ
i2c1_write_byte(0x50, 0x10, 0xAB); // EEPROM 0x50, ์ฃผ์ 0x10์ 0xAB ์ฐ๊ธฐ
โ ๏ธ ์ฃผ์์ฌํญ
- ๋ฐ๋์ GPIO (PB6, PB7 ๋ฑ)๋ฅผ Alternate Function์ผ๋ก ์ค์ ํด์ผ ๋์ํฉ๋๋ค.
- ์ค๋ฅ ํธ๋ค๋ง(ACK ์คํจ ๋ฑ)์ ์ ์ฝ๋์ ํฌํจ๋์ด ์์ง ์์ผ๋ฉฐ, ์ค์ ์์๋ ํ์์์ ์ฒ๋ฆฌ, ์๋ฌ ํ๋๊ทธ ํ์ธ์ด ์ถ๊ฐ๋์ด์ผ ํฉ๋๋ค.
- ๋น ๋ฅด๊ฒ ์ฐ๊ณ ๋ฐ๋ณต์ ์ผ๋ก ์ก์ ํ ๊ฒฝ์ฐ, BTF ํ์ธ ์์ด Stop์ ๋ด๋ฆฌ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ต๋๋ค.
ํ์ํ๋ค๋ฉด ์ฝ๊ธฐ(Receive) ์ฒ๋ฆฌ, EEPROM ์ฐ์ ์ฐ๊ธฐ, ACK ์ค๋ฅ ์ฒ๋ฆฌ, DMA ์ฐ๋ ๋ฒ์ ๋ ๋์๋๋ฆด ์ ์์ต๋๋ค. ์ด๋ค ์์ ์ ๋ ํด๋ณผ๊น์?
๋์ ๋ง:
i2c ํ๋กํ ์ฝ ์์ธํ ์ค๋ช
ChatGPT์ ๋ง:
์ข์ต๋๋ค. ์๋๋ I2C(Inter-Integrated Circuit) ํ๋กํ ์ฝ์ ๋ํ ํต์ฌ ๊ฐ๋ , ๋์ ์์, ์ ํธ ๊ตฌ์กฐ, ์ํ ํ๋๊ทธ ๋ฑ์ ํฌํจํ ์์ ํ ์ค๋ช ์ ๋๋ค.
๐ I2C๋?
I2C (Inter-Integrated Circuit) ๋ NXP(่ Philips) ๊ฐ ๋ง๋ ์๋ฐฉํฅ 2์ ์ ์ง๋ ฌ ํต์ ํ๋กํ ์ฝ์ ๋๋ค.
- ๐งท ์ 2๊ฐ๋ง ์ฌ์ฉ:
- SCL: Serial Clock Line
- SDA: Serial Data Line
- ๐งญ ๋ง์คํฐ/์ฌ๋ ์ด๋ธ ๊ตฌ์กฐ
ํ๋์ ๋ง์คํฐ๊ฐ ์๊ณ๋ฅผ ์ ์ดํ๊ณ , ์ฌ๋ ์ด๋ธ๊ฐ ์๋ตํฉ๋๋ค.
- ๐ฌ ์ฃผ์ ๊ธฐ๋ฐ ํต์ :
์ฌ๋ ์ด๋ธ๋ 7๋นํธ ๋๋ 10๋นํธ ์ฃผ์๋ฅผ ๊ฐ์ง (์ผ๋ฐ์ ์ผ๋ก 7๋นํธ)
๐งฉ I2C ๊ธฐ๋ณธ ํต์ ๊ตฌ์ฑ์์
sql
๋ณต์ฌํธ์ง
START โ ์ฃผ์(7bit) + R/W โ ACK โ ๋ฐ์ดํฐ ์ ์ก โ ACK โ STOP
- START (S): SDA๊ฐ High โ Low๋ก ๋จ์ด์ง ๋, SCL์ High
- STOP (P): SDA๊ฐ Low โ High๋ก ์ฌ๋ผ๊ฐ ๋, SCL์ High
- ACK/NACK: ์์ ์๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ์ ์์ ํ์์ ์๋ฆฌ๋ ์ ํธ (ACK: 0, NACK: 1)
๐งพ ๋ฐ์ดํฐ ์ ์ก ํ๋ ์ ๊ตฌ์กฐ
๊ตฌ๋ถ | ๋นํธ์ | ์ค๋ช |
Start | 1 | ์์ ์กฐ๊ฑด |
Address | 7 | ์ฌ๋ ์ด๋ธ ์ฃผ์ |
R/W | 1 | 0: Write, 1: Read |
ACK | 1 | ์์ ์์ ์๋ต |
Data | 8 | ๋ณด๋ผ ๋ฐ์ดํฐ |
ACK | 1 | ์์ ์์ ์๋ต |
… | … | ๋ฐ๋ณต ๊ฐ๋ฅ |
Stop | 1 | ์ข ๋ฃ ์กฐ๊ฑด |
๐ I2C ์ฐ๊ธฐ(Write) ์ํ์ค (๋ง์คํฐ ๊ธฐ์ค)
css
๋ณต์ฌํธ์ง
[S] โ [ADDR + 0] โ [ACK] โ [DATA1] โ [ACK] โ [DATA2] โ [ACK] โ [P]
์: EEPROM์ 0x50 ์ฃผ์๋ก 0xAB ์ ์ก
- START ์กฐ๊ฑด ๋ฐ์
- ์ฌ๋ ์ด๋ธ ์ฃผ์ ์ ์ก (0x50 << 1 | 0 = 0xA0)
- ์ฌ๋ ์ด๋ธ๊ฐ ACK ๋ณด๋
- ๋ฐ์ดํฐ ๋ฐ์ดํธ ์ ์ก (0xAB)
- ์ฌ๋ ์ด๋ธ๊ฐ ACK ๋ณด๋
- STOP ๋ฐ์
๐ I2C ์ฝ๊ธฐ(Read) ์ํ์ค
css
๋ณต์ฌํธ์ง
[S] โ [ADDR + 0] โ [ACK] โ [MEM_ADDR] โ [ACK] โ [S repeated] โ [ADDR + 1] โ [ACK] โ [DATA] โ [NACK] โ [P]
- 2๊ฐ์ START ์กฐ๊ฑด ์ฌ์ฉ (Repeated START)
- ๋ง์ง๋ง ๋ฐ์ดํธ๋ NACK์ผ๋ก ๋ง๋ฌด๋ฆฌ
โ I2C ์ํ ํ๋๊ทธ ์์ (STM32 ๊ธฐ์ค)
ํ๋๊ทธ | ์ค๋ช | ์์น |
SB (Start Bit) | START ์ ํธ ๋ฐ์๋จ | SR1[0] |
ADDR | ์ฃผ์ ์ ์ก ์๋ฃ | SR1[1] |
BTF | ๋ฐ์ดํธ ์ ์ก ์๋ฃ | SR1[2] |
TXE | ๋ฐ์ดํฐ ๋ ์ง์คํฐ ๋น์ด ์์ | SR1[7] |
RXNE | ์์ ๋ฐ์ดํฐ ์ค๋น ์๋ฃ | SR1[6] |
STOPF | ์ฌ๋ ์ด๋ธ๊ฐ STOP ๊ฐ์ง | SR1[4] |
๐ง ํน์ง ์์ฝ
ํญ๋ชฉ | ์ค๋ช |
๐งท ์ ์ | 2๊ฐ (SDA, SCL) |
๐ ๊ตฌ์กฐ | ๋ง์คํฐ-์ฌ๋ ์ด๋ธ |
โฑ ์๋ | ํ์ค(100kHz), ํจ์คํธ(400kHz), ํจ์คํธํ๋ฌ์ค(1MHz), ํ์ด์คํผ๋(3.4MHz) |
๐งช ์๋ฌ ์ฒ๋ฆฌ | ์ฌ๋ ์ด๋ธ๊ฐ ์๋ตํ์ง ์์ผ๋ฉด ACK ์์, ํ์์์ ํ์ |
๐ง ์ฅ์ | ํ๋ก ๋จ์, ์ฃผ์ ๊ธฐ๋ฐ, ๋ฉํฐ์ฌ๋ ์ด๋ธ ์ง์ |
๐ฉ ๋จ์ | SPI๋ณด๋ค ๋๋ฆผ, ํ๋กํ ์ฝ ๋ณต์ก๋ โ |
๐ ์ค์ ํต์ ํํ ์์
text
๋ณต์ฌํธ์ง
SCL: __|โพ|__|โพ|__|โพ|__|โพ|__|โพ|__|โพ|__|โพ|__|โพ|__
SDA: --\___0_1_0_1_0_0_0/---ACK---data_byte---/
START 7bit ADDR + W
