티스토리 뷰
이번글에서는 STM32F103에서의 UART 설정 방법에 대해서 설명하도록 하겠다.
UART의 동작 원리에 대해서는 AVR 입문과정 UART - 원리와 연결에서 이미 설명하였기 때문에 여기에서는 UART 설정 부분에 대해서만 설명하도록 하겠다.
위의 그림에서 보는바와 같이 STM32F103에는 모두 3개의 UART 블럭이 있다. UART1은 APB2버스에 연결되어 있고, UART2,3은 APB1 버스에 연결되어 있다.
이 글에서는 UART1만 고려해서 설명하게 된다. UART2,3에 대해서는 UART1 설정 방법과 동일하고 단지, 버스가 달라짐과 사용하는 핀번호가 다른것만 주의해서 설정하면 큰 어려움 없이 사용가능할 것이다.
UART1을 사용하기 위한 핀번호는 PA9와 PA10이다. 특히 TX핀이 PA9에 할당되어 있음을 알고 있어야 한다.
UART 설정에 있어서 가장 중요한 부분이 버스 클럭과 사용하고자 하는 baudrate에 따른 레지스터 값을 구하는 것이다. AVR 입문 과정 중 마지막 글인 시스템 클럭에서도 설명하였듯이 AVR이 16MHz로 동작될 때 baudrate가 115200이 되게 하기 위한 UBRR 레지스터 값이 계산상으로는 7이 나오지만, 오차율이 8이 더 적기 때문에 7이 아닌 8을 사용하였다. STM32F103에서는 이러한 계산 오차를 최소화 하기 위하여 계산식 결과가 소수점이 나오게 되면 그 부분까지도 설정할 수 있게 한 것이다.
설정하는 예는 datasheet에 잘 나와 있으므로 참고하기 바란다.
UART1은 APB2버스에 연결되어 있으므로 APB2 클럭에 따라 BRR 값이 달라지게 된다. 이 글에서는 비록 APB2 버스 클럭이 변경되더라도 UART 설정 부분은 수정하지 않아도 문제 없도록 코드를 만들것이다. 그렇게 하기 위해서는 RCC 레지스터 값을 참조하여 실제 버스 클럭을 계산하여 그 결과를 이용하면 되기때문이다.
따라서 UART 레지스터 설정에 앞서 먼저 설명할 부분은 시스템 클럭, AHB 버스 클럭, APB2버스 클럭 값을 계산하는 코드이다.
rcc_get_sysclk() 함수는 시스템 클럭 주파수값을 구하는 함수이다. REFCLK_FREQ으로 define된 값은 HSI값인 8MHz이거나 HSE를 사용할 경우 크리스털 주파수 값이다. 이값은 보드가 제작되면 거의 고정된 값이므로 상수값으로 간주한다.
RCC블럭의 CFGR 레지스터 값에서 SWS 비트 값이 PLL이 아닐경우 REFCLK_FREQ가 시스템 클럭 값이 된다. 만약 PLL을 이용하게 되면 REFCLK_FREQ 값에 PLLMUL 값을 곱한 값이 시스템 클럭이 된다. 이때 주의할 점이 PLL의 소스 클럭이 HSI일 경우 2로 나눈값을 사용하여야 하고, PLLMUL 값에 2를 더한 값이 실제 클럭 배수값이 되는것이다.
rcc_get_ahbclk() 함수는 시스템 클럭 값을 기반으로 AHB prescaler 값으로 나누어 AHB 버스의 동작 주파수값을 구하는 함수이다.
rcc_get_apb2clk() 함수는 AHB 버스 클럭을 기준으로 APB2 prescaler값으로 나누어 APB2 버스의 동작 주파수값을 구하는 함수이다.
rcc_get_ahbclk()와 rcc_get_apb2clk() 함수에서 prescaler레지스터 값에 따른 실제 나누기 값을 구하는 방법은 datasheet를 분석하면 이해할수 있을것이다.
그럼 이제, 실제적으로 UART를 설정하는 코드에 대해서 설명하도록 하겠다.
6번째 줄은 UART1과 외부와 연결되는 GPIO핀을 동작시키기 위하여 클럭을 공급할 수 있게 해주는 부분이다.
7번째 줄은 GPIO핀중 UART TX 용도로 사용하기 위한 PA9에 대해서 Alternate function으로 설정해 주는 부분이다. AVR에서는 별도의 설정없이 사용 가능했지만 STM에서는 따로 설정해 주어야 한다.
9~12번째 줄이 APB2 버스 클럭과 baudrate에 따른 BRR 계산 식이다. 계산 결과에 따른 소수점 앞 정수 부분과 소수점 아래 부분을 구하는 예는 datasheet에 다음과 같이 나와 있다.
위의 경우 계산 결과과 10진수로 25.62가 되었을 때, mantissa는 0x19가 되고 fraction은 0xA가 되어 BRR 값으로는 0x19A가 되는 것을 보여주고 있다.
그럼 이 글에서 사용되는 보드의 경우 APB2 클럭이 56MHz이고 baudrate를 115200bps로 설정하고자 할 때의 BRR 값을 손으로 계산하면 다음과 같이 된다.
56000000 / (115200 * 16) = 30.38194
mantissa = 30(0x1E)
fraction = 0.38194 * 16 = 6.111
BRR = 0x1E6
보드에서 실제로 수행한 결과를 보면 다음과 같다.
UART1 BRR 레지스터의 값이 0X1E6이 들어있는것을 볼 수 있고, 계산값과 정확히 일치하는 것을 확인할 수 있다.
코드의 마지막 18번째 줄은 UART, TX, RX enable bit를 설정하여 UART를 동작 시키게 해주는 코드이다.
한 글자를 UART로 내보내기 위한 코드는 다음과 같다.
UART가 제대로 동작되는지 확인하기 위하여 main() 함수를 다음과 같이 만들고 실제 보드를 동작시켜 보도록 하겠다.
LED 점멸과 동시에 UART 콘솔창에 '>' 문자가 한개씩 표시되는 것을 볼 수 있을 것이다.
정상적인 출력이 이루어지는 것을 확인하였으면 다음 단계로 콘솔 창의 입력을 받아 들이는 코드를 만들어 보고 실제 동작을 시험해 보도록 하겠다.
콘솔창에서 키보드 입력을 받아서 에코해준 것을 확인하였으므로, UART 블럭의 송수신 동작이 모두 잘 되고 있음을 확인할 수 있다.
참고로, APB2 클럭에 따른 BRR 값을 구할 때 실수형 나누기 계산을 수행하는데, 이때 다음과 같은 컴파일 에러가 발생할 것이다.
나누기 계산하는 코드는 GCC 컴파일러에서 제공하는데 링크 시점에 GCC 라이브러리가 포함되어 있지 않기 때문에 발생하게 되는 에러이다.
GCC 라이브러리를 포함 시켜 주기 위해서는 Makefile에 다음과 같은 부분을 추가해 주어야 한다.
'ARM Cortex-M' 카테고리의 다른 글
System Timer (0) | 2017.02.24 |
---|---|
UART - STDIO (5) | 2017.02.18 |
Clock 설정 (0) | 2017.02.17 |
GPIO를 통한 LED 제어 (0) | 2017.02.12 |
Start up 2 (6) | 2017.02.12 |