-- =========================================================== --
-- Usage of printf Function --
-- =========================================================== --
-- Designed and programmed by Duck-Yong Yoon in 2005. --
#include < avr/io.h >
#include < stdio.h >
#include "c:\AvrEdit\OK128c\OK128.h"
void USART0_initialize(void) -- initialize USART0 --
{
UBRR0H = 0; // 19200 baud
UBRR0L = 51;
UCSR0A = 0x00; // asynchronous normal mode
UCSR0B = 0x18; // Rx/Tx enable, 8 data
UCSR0C = 0x06; // no parity, 1 stop, 8 data
}
int USART0_putchar(char c) -- print a character --
{
if(c == '\n') // process carriage return
USART0_putchar('\r');
loop_until_bit_is_set(UCSR0A,UDRE0); // Tx ready ?
UDR0 = c;
return 0;
}
int main(void)
{ unsigned char i = 0;
double x = 0.0;
MCU_initialize(); // initialize MCU
Delay_ms(50); // wait for system stabilization
LCD_initialize(); // initialize text LCD module
LCD_string(0x80,"printf function "); // display title
LCD_string(0xC0," to USART0 ");
USART0_initialize(); // initialize USART0
fdevopen(USART0_putchar,0,0); // STDOUT and STDERR device open
while(1)
{ printf("This is printf test message !\n");
printf("Integer number : %3d\n",i);
printf("Float number : %7.3f\n\n",x);
i++;
x += 0.101;
Beep();
Delay_ms(1000);
}
}
-------------------------------------------------------------------------------------------------------------------------
fdevopen() 함수는 일반 C언어에서 fopen()에 해당하는 것으로, 파라미터가 3개 있는데 첫번째는 출력장치 함수(STDOUT, STDERR), 두번째는 입력장치 함수(STDIN)를 지정하며, 마지막 파라미터는 사용하지 않으므로 항상 0으로 줍니다.
(1) 우선 먼저 프로그램의 서두에서 헤더파일 stdio.h를 인클루드시킵니다.
(2) 이제 printf를 ATmega128의 USART0로 출력하는 것으로 가정하면 당연히 이 직렬포트를 초기화하여야 합니다. 아래 예제에서는 이를 USART0_initialize() 함수로 만들었습니다.
(3) 다음에는 USART0 에 1문자를 출력하는 함수를 만듭니다. printf 함수는 항상 내부적으로 vprintf 함수를 참조하고 이 vprintf 함수는 항상 STDOUT 장치를 참조하여 이 1문자 출력함수를 사용하게 됩니다. 아래 예제에서는 USART0_putchar() 함수로 만들었습니다. 이 함수의 return 형은 반드시 int로 하고 파라미터는 char 형으로 해야 합니다. 만약, 다른 형으로 하면 에러로 처리됩니다...
(4) 이제 fdevopen() 함수의 첫번째 파라미터로 1문자 출력함수를 STDOUT 디바이스로 할당합니다. 만약, scanf() 함수로 입력하는 기능이 필요하면 두번째 파라미터에도 1문자 입력함수를 만들어 할당하면 됩니다만 여기서는 생략합니다. 아래 예제에서는 fdevopen(USART0_putchar,0,0)으로 하였습니다.
(5) printf 함수를 사용합니다. 우리가 알고 있는 모든 %서식이 사용될 수 있습니다.
(6) 그런데 이 소스를 컴파일할 때는 반드시 printf 함수에 해당하는 라이브러리를 링크시켜주어야 합니다. WinAVR 패키지에 보면 이들 라이브러리 함수가 있습니다. 여기에는 정수까지만 출력할 수 있는 libprintf_min.a가 있고 부동소수점 형식까지 출력할 수 있는 libprintf_flt.a가 있습니다. 정수만 처리하는데 부동소수점 기능까지 포함되면 오브젝트 코드 전체가 쓸데없이 길어지기 때문에 이렇게 한 듯합니다.
만약 정수 출력만 한다면 이를 컴파일할 때 링커 옵션에 ,-Wl,-u,vfprintf -lprintf_min 을 추가하면 됩니다. 하지만, 아래의 예제에서처럼 부동소수점 포맷을 사용하면 반드시 링커 옵션에,-Wl,-u,vfprintf -lprintf_flt -lm 이라고 해주어야 합니다. 이 링커 옵션에서는 컴마 사용에 주의하시고, l은 숫자 1이 아니라 모두 L의 소문자라는 것에 유의하십시오...
'공부했던것' 카테고리의 다른 글
[ILINK32 Error] Error: Unable to perform link (0) | 2023.04.24 |
---|---|
CRC 계산기 (0) | 2023.03.27 |
아이폰 핫스팟 - 제한된 엑세스 (0) | 2023.03.27 |
[AVR] error: called object '??' is not a function (0) | 2023.03.27 |
[AVR]too few arguments to function '함수명' (0) | 2023.03.27 |