Bare metal C Ch11 ADC - Hongjayeong-02/Basic_SoC_implementation GitHub Wiki

Ch11. ADC (Analog-to-Digital Converter)

ํ•œ ์ค„ ์š”์•ฝ: PA1์˜ ์•„๋‚ ๋กœ๊ทธ ์ž…๋ ฅ์„ ADC1 Channel 1๋กœ ์—ฐ์† ๋ณ€ํ™˜ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ UART/printf๋กœ ์ถœ๋ ฅํ•œ๋‹ค.

1. ํ•ต์‹ฌ ์ด๋ก 

ADC๋Š” ์—ฐ์†์ ์ธ ์•„๋‚ ๋กœ๊ทธ ์ „์••์„ ๋””์ง€ํ„ธ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. ์ด ์‹ค์Šต์˜ ADC ๊ฒฐ๊ณผ๋Š” 12-bit์ด๋ฏ€๋กœ ์ถœ๋ ฅ ๋ฒ”์œ„๋Š” 0 ~ 4095์ด๋‹ค.

0 V     โ†’ 0 ๋ถ€๊ทผ
VREF    โ†’ 4095 ๋ถ€๊ทผ

๋ณด๋“œ ์ฐจ์ด

Notion ์ •๋ฆฌ์—์„œ๋Š” PA1 โ†’ ADC1_IN1 ๋งคํ•‘๊ณผ ADC1 register ๊ตฌ์„ฑ์ด ์›์„œ F411๊ณผ F439ZI์—์„œ ๋™์ผํ•˜๋‹ค๊ณ  ์ •๋ฆฌํ–ˆ๋‹ค.

ํ•ต์‹ฌ ๋ ˆ์ง€์Šคํ„ฐ

Register | ์—ญํ•  -- | -- ADC1->SQR3 | ๋ณ€ํ™˜ sequence์˜ ์ฒซ channel ์„ ํƒ ADC1->SQR1 | sequence ๊ธธ์ด ADC1->CR2 | ADON, CONT, SWSTART ADC1->SR | EOC ๋ณ€ํ™˜ ์™„๋ฃŒ ADC1->DR | ๋ณ€ํ™˜ ๊ฒฐ๊ณผ

Continuous conversion

ADC1->CR2 |= CR2_CONT;
ADC1->CR2 |= CR2_SWSTART;

CONT=1์ด๋ฏ€๋กœ SWSTART๋ฅผ ํ•œ ๋ฒˆ ์„ค์ •ํ•œ ๋’ค ADC๊ฐ€ ์—ฐ์† ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

EOC polling

while (!(ADC1->SR & SR_EOC)) { }
return ADC1->DR;

๋ณ€ํ™˜์ด ๋๋‚ฌ์Œ์„ ํ™•์ธํ•œ ๋’ค ๊ฒฐ๊ณผ register๋ฅผ ์ฝ๋Š”๋‹ค.

2. ๋™์ž‘ ํ๋ฆ„

PA1
 โ”‚ Analog input
 โ–ผ
GPIOA MODER = Analog
 โ”‚
 โ–ผ
ADC1 Channel 1
 โ”‚
 โ–ผ
Continuous Conversion
 โ”‚
 โ–ผ
EOC = 1
 โ”‚
 โ–ผ
ADC1->DR
 โ”‚
 โ–ผ
printf โ†’ USART3 โ†’ PC

3. ์‹ค์ œ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ


Ch11_adc/

โ”œโ”€โ”€ Inc/adc.h

โ”œโ”€โ”€ Src/adc.c

โ”œโ”€โ”€ Inc/uart.h

โ”œโ”€โ”€ Src/uart.c

โ”œโ”€โ”€ Src/main.c

syscalls.c, sysmem.c, startup file, linker script, CubeIDE metadata/build output์€ Ch04์—์„œ ๋‹ค๋ฃฌ ๊ณตํ†ต ๊ธฐ๋ฐ˜์ด๋ฏ€๋กœ ์ด ํŽ˜์ด์ง€์—์„œ๋Š” ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๋Š”๋‹ค. ์•„๋ž˜์—๋Š” ์ด chapter ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ์ง์ ‘ ์‚ฌ์šฉํ•œ source/header๋ฅผ ์ „๋ถ€ ๊ธฐ๋กํ•œ๋‹ค.

4. ์ „์ฒด ์ฝ”๋“œ

Inc/adc.h

#ifndef ADC_H__
#define ADC_H__

#include <stdint.h> #include "stm32f4xx.h"

void pa1_adc_init(void); void start_conversion(void); uint32_t adc_read(void);

#endif

Src/adc.c

#include "adc.h"

#define GPIOAEN (1U << 0) #define ADC1EN (1U << 8) #define ADC_CH1 (1U << 0) #define ADC_SEQ_LEN_1 0x00U

#define CR2_ADON (1U << 0) #define CR2_CONT (1U << 1) #define CR2_SWSTART (1U << 30) #define SR_EOC (1U << 1)

void pa1_adc_init(void) { RCC->AHB1ENR |= GPIOAEN;

GPIOA-&gt;MODER |= (1U &lt;&lt; 2);
GPIOA-&gt;MODER |= (1U &lt;&lt; 3);   /* PA1 -&gt; Analog ๋ชจ๋“œ */

RCC-&gt;APB2ENR |= ADC1EN;

ADC1-&gt;SQR3 = ADC_CH1;
ADC1-&gt;SQR1 = ADC_SEQ_LEN_1;

ADC1-&gt;CR2 |= CR2_ADON;

}

void start_conversion(void) { ADC1->CR2 |= CR2_CONT; ADC1->CR2 |= CR2_SWSTART; }

uint32_t adc_read(void) { while (!(ADC1->SR & SR_EOC)) { } return ADC1->DR; }

Inc/uart.h

#ifndef UART_H
#define UART_H

#include "stm32f4xx.h"

void uart_init(void); void uart_write_string(const char *s); int __io_putchar(int ch);

#endif

Src/uart.c

#include <stdint.h>
#include "uart.h"

#define GPIODEN (1U << 3) #define USART3EN (1U << 18)

#define DBG_UART_BAUDRATE 115200U #define SYS_FREQ 16000000U #define APB1_CLK SYS_FREQ

#define CR1_TE (1U << 3) #define CR1_UE (1U << 13) #define SR_TXE (1U << 7)

static void uart_write(int ch); static uint16_t compute_uart_bd(uint32_t periph_clk, uint32_t baudrate); static void uart_set_baudrate(uint32_t periph_clk, uint32_t baudrate);

int __io_putchar(int ch) { uart_write(ch); return ch; }

void uart_init(void) { RCC->AHB1ENR |= GPIODEN;

GPIOD-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (8 * 2));
GPIOD-&gt;MODER |=  (0x2UL &lt;&lt; (8 * 2));
GPIOD-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (9 * 2));
GPIOD-&gt;MODER |=  (0x2UL &lt;&lt; (9 * 2));

GPIOD-&gt;AFR[1] &amp;= ~(0xFUL &lt;&lt; 0);
GPIOD-&gt;AFR[1] |=  (0x7UL &lt;&lt; 0);   /* PD8 -&gt; AF7 (USART3_TX) */
GPIOD-&gt;AFR[1] &amp;= ~(0xFUL &lt;&lt; 4);
GPIOD-&gt;AFR[1] |=  (0x7UL &lt;&lt; 4);   /* PD9 -&gt; AF7 (USART3_RX) */

RCC-&gt;APB1ENR |= USART3EN;

uart_set_baudrate(APB1_CLK, DBG_UART_BAUDRATE);

USART3-&gt;CR1 = CR1_TE;
USART3-&gt;CR1 |= CR1_UE;

}

static void uart_write(int ch) { while (!(USART3->SR & SR_TXE)) { } USART3->DR = (ch & 0xFF); }

void uart_write_string(const char *s) { while (*s) uart_write((int)*s++); }

static uint16_t compute_uart_bd(uint32_t periph_clk, uint32_t baudrate) { return (uint16_t)((periph_clk + (baudrate / 2U)) / baudrate); }

static void uart_set_baudrate(uint32_t periph_clk, uint32_t baudrate) { USART3->BRR = compute_uart_bd(periph_clk, baudrate); }

Src/main.c

#include <stdio.h>
#include "adc.h"
#include "uart.h"

int sensor_value;

int main(void) { uart_init(); pa1_adc_init(); start_conversion();

while (1)
{
    sensor_value = adc_read();
    printf("Sensor Value: %d\r\n", sensor_value);
}

}

5. ์‹ค์Šต ๊ฒฐ๊ณผ

Notion ๊ธฐ๋ก ๊ธฐ์ค€ ์‹ค์ œ ๋ณด๋“œ์—์„œ potentiometer ์ž…๋ ฅ์„ ์‚ฌ์šฉํ•ด 0 ~ 4095 ๋ฒ”์œ„๋กœ ADC ๊ฐ’์ด ๋ณ€ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค.

text = 1420 bytes
data = 0 bytes
bss  = 2560 bytes
warning ์—†์Œ

ํ˜„์žฌ ZIP๊ณผ Notion ๊ธฐ๋ก์˜ ์ฐจ์ด

Notion ์„ค๋ช…์˜ ์˜ˆ์‹œ main()์—๋Š” ์ถœ๋ ฅ ์‚ฌ์ด์— systick_msec_delay(200)๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€๋งŒ, ํ˜„์žฌ ์ฒจ๋ถ€ ZIP์˜ ์‹ค์ œ Ch11_adc/Src/main.c์—๋Š” delay๊ฐ€ ์—†๋‹ค.
์ด Wiki์˜ ์ „์ฒด ์ฝ”๋“œ๋Š” ์ฒจ๋ถ€ ZIP์˜ ์‹ค์ œ ํŒŒ์ผ์„ ๊ทธ๋Œ€๋กœ ์‹ฃ๋Š”๋‹ค.

6. ํ•ต์‹ฌ ์ •๋ฆฌ

  • 12-bit ADC ๊ฒฐ๊ณผ ๋ฒ”์œ„๋Š” 0~4095๋‹ค.

  • Continuous mode์—์„œ๋Š” SWSTART ํ›„ ๋ฐ˜๋ณต ๋ณ€ํ™˜๋œ๋‹ค.

  • EOC๋ฅผ ํ™•์ธํ•œ ๋’ค DR์„ ์ฝ๋Š”๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ