تابع printf در stm32 موضوع این مقاله می باشد . یکی از مواردی که برای اشکال زدایی کدها بسیار مفید می باشد استفاده از تابع printf برای چاپ یک رشته یا متغیر جهت نمایش خروجی توابع و بخش های مختلف برنامه می باشد .
موضوعاتی که در این مقاله به آنها پرداخته خواهد شد :
آشنایی با تابع printf در کتابخانه stdio.h
همانطور که می دانید printf یک تابع از کتابخانه stdio.h می باشد . بهتر است قبل از هر چیز ابتدا کمی با کتابخانه stdio.h آشنا شویم .
کتابخانه stdio.h یک هدر فایل (header file) در زبان برنامهنویسی C است که شامل تعاریف و توابعی برای ورودی و خروجی استاندارد میباشد. این کتابخانه توابعی مانند printf برای چاپ خروجی و scanf برای خواندن از ورودی را فراهم میکند. به عبارت دیگر، stdio.h مخفف “Standard Input/Output” است و به عنوان یک رابط بین برنامه و محیط Input/Output عمل میکند.
توابع مهم در کتابخانه stdio.h
printf : این تابع برای چاپ مقادیر مختلف (مانند اعداد، متن، متغیرها) به خروجی استاندارد (معمولاً صفحه نمایش) استفاده میشود.
scanf : این تابع برای خواندن ورودی از ورودی استاندارد (معمولاً صفحه کلید) استفاده میشود.
getchar : این تابع برای خواندن یک کاراکتر از ورودی استاندارد استفاده میشود.
putchar : این تابع برای نوشتن یک کاراکتر به خروجی استاندارد استفاده میشود.
به طور خلاصه، کتابخانه stdio.h یک ابزار ضروری برای هر برنامه C است که نیاز به تعامل با کاربر دارد.
در مثال زیر نحوه استفاده از تابع printf برای نمایش انواع متغییرها را مشاهده می کنید . (منبع)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* printf example */ #include <stdio.h> int main() { printf ("Characters: %c %c \n", 'a', 65); printf ("Decimals: %d %ld\n", 1977, 650000L); printf ("Preceding with blanks: %10d \n", 1977); printf ("Preceding with zeros: %010d \n", 1977); printf ("Some different radices: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100); printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416); printf ("Width trick: %*d \n", 5, 10); printf ("%s \n", "A string"); while(1) { }; } |
نتیجه و خروجی توابع printf بالا به شکل زیر خواهد بود .
در برخی از میکروکنترلرها مثل AVR ، کامپایلر کتابخانه stdio.h را به صورت پیش فرض بر روی پورت سریال UART پیکربندی می کند و زمانی که داخل برنامه از تابع printf استفاده می کنیم داده های ما به پایه TX از پورت UART هدایت می شوند .
اما در برخی از میکروکنترلرهای پیشرفته تر مانند STM32 که انواع پورتهای Input/Output و واحدهای مختلف اشکال زدایی و دیباگینگ دارند ، کامپایلر روشهای مختلفی برای پیادهسازی printf ارایه می دهد . از جمله ارسال رشته ها و کاراکترها توسط printf به واحد UART یا ITM .
احتمالا برای شما هم این اتفاق افتاده است که در محیطی مثل STM32CubeIDE از تابع printf درون برنامه خود استفاده کرده اید و برنامه شما با موفقیت کامپایل میشود ، اما هیچ رشتهای به UART ارسال نمیشود .
البته ما می توانیم رشته های خود را توسط توابع HAL (مثلا HAL_UART_Transmit) یا رجیستری به پورت سریال UART هدایت کنیم . اما گاهی اوقات استفاده از توابع استاندارد کتابخانه C مانند printf و scanf و غیره استاندارد و آسانتر است.
برای انجام این کار، باید برخی توابع اساسی که توسط کامپایلر تولید شده را دوباره بازنویسی کنیم و برای کامپایلر مشخص کنیم رشته های ما را به بلوک UART یا ITM هدایت کند که در اصطلاح به این عمل ریدایرکت (Redirect) کردن می گوییم .
وقتی پروژه ای توسط کامپایلر ایجاد می کنیم توابع خواندن/نوشتن از قبل در فایل syscalls.c (معمولاً در مسیر Core/Src) ارائه شده است .
در فایل syscalls.c ، کامپایلر توابع زیر را برای انجام ورودی/خروجی سطح پایین فراخوانی میکند.
توابع read_ و write_ در فایل syscalls.c با پیوند ((weak)) یا ضعیف تعریف شدهاند . خاصیت __weak به شما امکان میدهد اگر هر یک از توابع فوق را در کد اصلی در فایل main.c قرار دهید ، تابع تعریف شده در فایل syscalls.c لغو شده و اولویت اجرا با توابعی باشد که در فایل main.c بازتعریف یا rewrite می شوند .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
__attribute__((weak)) int _read(int file, char *ptr, int len) { (void)file; int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++) { *ptr++ = __io_getchar(); } return len; } __attribute__((weak)) int _write(int file, char *ptr, int len) { (void)file; int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++) { __io_putchar(*ptr++); } return len; } |
داخل توابع read_ و write_ از دو تابع __io_getchar و __io_putchar استفاده شده است . این دو تابع از توابع مهم کتابخانه stdio.h هستند و وظیفه ارسال و دریافت فقط یک کاراکتر را دارند . این توابع در ابتدای فایل syscalls.c به صورت extern با پیوند ((weak)) تعریف شده اند . خاصیت extern به ما این امکان را می دهد توابع یا متغییرهایی که در فایل یا کتابخانه ای دیگر تعریف شده اند را در کتابخانه ای دیگر فراخوانی و از آنها استفاده کنیم .
1 2 |
extern int __io_putchar(int ch) __attribute__((weak)); extern int __io_getchar(void) __attribute__((weak)); |
حالا برای هدایت یا ریدایرکت کردن رشته ها به پورت UART توسط printf باید دو تابع _write و __io_putchar را داخل فایل main.c بازنویسی یا rewrite کنیم . سپس داخل تابع __io_putchar دستورات مربوط به ارسال یک کاراکتر به پورت uart را قرار دهیم .
1 2 3 4 |
int __io_putchar(int ch) { // Code to write character 'ch' on the UART } |
به عنوان مثال زمانی که از دستور printf(“Hello World!!”) استفاده می کنیم . ابتدا تابع write_ فراخوانی می شود و آدرس رشته Hello World!! درون آرگومان تابع (*ptr) که از نوع اشاره گر است قرار می گیرد . سپس توسط حلقه for کاراکترها یکی یکی توسط تابع putchar ارسال می شوند .
ریدایرکت کردن printf به uart در STM32CubeIDE
برای استفاده از printf با UART در STM32CubeIDE برای اشکالزدایی یا خروجی داده ، تابع استاندارد printf باید به دستگاه جانبی UART هدایت شود. این شامل redirected تابع _write (یا __io_putchar) در فایل syscalls.c برای ارسال کاراکترها از طریق UART می باشد .
ابتدا با استفاده از ابزار پیکربندی CubeMX یک پروژه ایجاد کنید. در اینجا، فقط تنظیمات UART را توضیح خواهیم داد.
زبانه Pinout & Configuration → Connectivity → USART2 → Mode را انتخاب کنید و حالت را از Disable به Asynchronous تغییر دهید. سایر تنظیمات را مطابق تصویر زیر تنظیم کنید.
نرخ Baud Rate سرعت ارتباط است، بنابراین اگر سرعت بیشتری میخواهید، آن را روی مقدار بزرگتری تنظیم کنید.
پس از اتمام تنظیمات، دکمه Generate را برنید تا کدها داخل فایل main.c ایجاد شود .
فایل main,c را باز کنید و کتابخانه stdio.h را به فایل اصلی C خود اضافه کنید.
1 2 3 4 5 6 7 |
/* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */ |
اکنون تابع _write و __io_putchar باید بازنویسی شوند .کافیست کد زیر را در فایل main.c اضافه کنید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ int __io_putchar(int ch) { while ((USART2->SR & 0X40 ) == 0); // Wait for transmission to complete USART2->DR = (uint8_t) ch; return ch; } int _write(int file, char *ptr, int len) { int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++) { __io_putchar(*ptr++); } return len; } /* USER CODE END 0 */ |
می توانیم هر دو تا تابع را در یک تابع ادغام کنیم .
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ int _write(int file, char *ptr, int len) { int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++) { while ((USART2->SR & 0X40 ) == 0); // Wait for transmission to complete USART2->DR = (uint8_t) (*ptr++); } return len; } /* USER CODE END 0 */ |
اگر از توابع hal استفاده می کنید ساده ترین راه هم استفاده به شکل زیر است
1 2 3 4 5 6 7 8 9 10 |
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ int _write(int file, char *ptr, int len) { if (HAL_UART_Transmit(&huart2,ptr,len, HAL_MAX_DELAY) != HAL_OK) { Error_Handler(); } } /* USER CODE END 0 */ |
printf به خودی خود کار نمیکند، باید مقداردهی اولیه شود. قبل از فراخوانی printf، یک بار تابع setbuf ( stdout , NULL ) را در ابتدای تابع main فراخوانی کنید . این تابع باعث غیر فعال شدن بافرینگ printf می شوند .
بعد از فراخوانی این تابع ، هرگونه استفاده از printf مستقیماً بدون بافرینگ و انتظار برای دریافت کاراکتر newline در خروجی نوشته میشود. این تضمین میکند که خروجی بلافاصله ظاهر شود، که میتواند برای اشکالزدایی یا نظارت بر زمان واقعی مفید باشد.
1 2 3 4 5 |
int main ( void ) { /* USER CODE BEGIN 1 */ setbuf ( stdout , NULL ) ; /* USER CODE END 1 */ |
1 2 3 4 5 6 7 8 9 |
/* USER CODE BEGIN WHILE */ while ( 1 ) { /* USER CODE END WHILE */ printf ( "Hello World!!\r\n" ) ; HAL_Delay ( 1000 ) ; /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ |
اکنون برای نمایش عبارت Hello World!! بر روی مانیتور ، ما نیاز به یک مبدل usb to serial داریم تا رشته ها را از روی UART2 بگیرد و به COM کامپیوتر ارسال کند .
بر روی کامپیوتر هم نیاز به یک کنسول یا ترمینال سریال داریم تا رشته های دریافت شده بر روی COM را نمایش دهد . می توانید از کنسول سریال خود STM32CubeIDE برای نمایش استفاده کنید . تنظیمات را مطابق تصویر زیر انجام دهید .
1. دکمه New Consol View را بفشارید.
2. عبارت Command Sell Console را انتخاب کنید .
3. در پنجره باز شده منوی Connection Type را بر روی Serial Port قرار دهید .
4. دکمه New را بفشارید و در پنجره باز شده تنظیمات پورت سریال را انجام دهید .
در پایان نتیجه کار را باید بر روی کنسول مشاهده کنید .
ریدایرکت کردن printf به uart در Keil
در نرم افزار keil نیازی به بازنویسی تابع write_ و putchar نمی باشد . به منوی Manage Run-Time Environment بروید و گزینه Compiler->I/O را انتخاب کنید و تیک گزینه های STDIN , SDTOUT را به حالت انتخاب درآورید و از زبانه کشویی گزینه USER را انتخاب کنید . این کار باعث می شود خروجی تابع printf به واحد USART هدایت یا Redirect شود .
ارسال printf بر روی SWO
در روش قبل ، ریدایرکت printf به uart یکی از پورتهای UART میکروکنترلر اشغال می شد و همچنین نیاز به سخت افزار مجزا مثل مبدل usb to serial و استفاده از یک کابل USB و سیم کشی دیگر فقط برای استفاده از UART داشتیم .
یک راه سادهتر برای debuging یا اشکالزدایی میکروکنترلر STM32 با تابع printf با استفاده از خود پروگرامر ST-Link وجود دارد و نیازی به اضافه کردن پورت UART و سخت افزار اضافی دیگری نیست.
اگر یک پروگرامر ST-Link (اصلی یا کپی) دارید، اشکالزدایی میکروکنترلرهای STM32 خود با تابع printf آسانتر خواهد بود. دلیل این امر این است که ST یک ساختار اشکالزدایی و ردیابی انعطافپذیر را در نرمافزار و بیشتر MCUهای STM32 خود با نام ITM گنجانده است. تنها چیزی که نیاز دارید پینهای اصلی Serial Wire Debug (SWD) و یک پین خروجی سیم سریال اضافی (SWO) Serial Wire Output است.
ARM امکان استفاده از تابع printf مانند خروجی سریال را با استفاده از رابط ITM را فراهم میکند. این مقاله نحوهی استفاده از تابع printf را با استفاده از پروگرامر ST LINK و ITM Stimulus Ports شرح میدهد.
ITM چیست؟
(Instrumentation Trace Macrocell) ITM یک بلوک اختیاری و یک منبع ردیابی(Trace) اختیاری مبتنی بر برنامه است که در پیادهسازیهای خاص Cortex-M یافت میشود. معمولاً میکروکنترلرهای با هسته Cortex-M3، M4 و M7 شامل ITM هستند، در حالی که Cortex-M0 و M0+ این ویژگی را ندارند. ITM به عنوان یک منبع ردیابی(TRACE) مبتنی بر برنامه عمل میکند و از اشکالزدایی به سبک printf برای ردیابی رویدادهای سیستم عامل و برنامه پشتیبانی میکند.
SWV چیست؟
وقتی از هر دو پین SWD و SWO استفاده میکنید، آماده ورود به حالت اشکالزدایی Serial Wire Viewer (SWV) هستید. SWV ردیابی و تحلیل پیشرفته سیستم را به صورت real-time ارائه میدهد که همتای حالت اشکالزدایی SWD آن قادر به انجام آن نیست. علاوه بر این، برخلاف SWD، با SWV بدون نیاز به توقف در طول وضعیت اشکالزدایی، دادههای real-time را دریافت میکنید.
ITM (Instrumentation Trace Macrocell) به برنامهها اجازه میدهد تا از طریق پورتها، دادهها را روی خط پین SWO بنویسند. با این کار، میتوانید تابع printf را برای نوشتن در یک کنسول در حالت SWV با استفاده از ویژگی ITM هدایت کنید.
چه نوع سختافزار ST-Link برای Trace مورد نیاز است؟
- Nucleo
سختافزار بورد توسعه Nucleo آماده راهاندازی SWV است زیرا معمولاً ST-Link بصورت یکپارچه روی بورد آن وجود دارد . برای فعال کردن این ویژگی، ممکن است لازم باشد برخی از پدهای روی برد را پل بزنید. - ST-Link clone
متاسفانه، کلونهای ST-Link V2 (برخلاف بردهای اصلی NUCLEO)، برای رفتن به حالت ردیابی اشکالزدایی SWV آماده نیستند. این کلونها فقط پینهای SWD را خروجی میدهند و پین SWO ندارند.
افزودن پشتیبانی Trace به پروگرامر ST-Link v2
وقتی صحبت از برنامهنویسی میکروکنترلرهای ST میشود، من ترجیح میدهم بجای بورد توسعه Nucleo ، یک پروگرامر کلون st-link که یک دانگل خوب در جعبه آلومینیومی با ابعادی کوچک بهمراه مقداری سیم است را با قیمتی ارزان تهیه کنم.
Trace یک ویژگی بسیار جالب است. یکی از کاربردهای رایج، هدایت جریان stdout توسط تابع printf در stm32 به پورت صفر محرک(stimulus port 0) برای چاپ اطلاعات اشکالزدایی است.
همه نسخههای اخیر ST-Link v2 از ویژگی Trace پشتیبانی میکنند ، SWO Trace یک ویژگی بسیار مفید است که با افزودن این ویژگی به پروگرامر کلون ST-Link v2 خود از این به بعد یک دانگل بسیار مفیدتر در اختیار دارید .
اما برای حل مشکل نبود پایه swo در پروگرامر کلون ST-Link v2 ، باید داخل پروگرامر ST-Link پایه ای که به عنوان SWO عمل میکند را پیدا کنید و آن را بیرون بیاورید. معمولاً این کلونهای ST-Link فقط STM32F103 هستند. عملکرد SWO همانطور که در زیر مشاهده میکنید در PA10 قرار دارد.
من نتوانستم شماتیک یک پروگرامر مستقل کلون ST-Link v2 پیدا کنم، بنابراین فرض کردم که دقیقاً مشابه پروگرامر موجود روی برد دیسکاوری خواهد بود. PA10 برای SWO استفاده میشود، بنابراین مرحله بعدی بسیار سرراست خواهد بود.
من مسیر پین ۵ ولتی را درست بعد از via بریدم و مقداری سیم رابط به PA10 لحیم کردم. همچنین یک مقاومت بین ۲۲ تا 100 اهمی را برای محافظت از جریان اتصال کوتاه اضافه کردم تا در صورت بروز مشکل جدی پروگرامر یا میکروکنترلر stm32 آسیب نبیند.
در ابتدا میخواستم از پین SWIM استفاده کنم، چون به STM8 علاقهای ندارم و استفاده از این پایه فقط نیاز به لحیمزدایی یک مقاومت بدون بریدن هیچ مسیری داشت ، اما دسترسی به پین ۵ ولتی آسانتر بود.
توجه : اگر از نرم افزار STM32CUBEIDE استفاده می کنید ، ممکن است پروگرامر ST-Link v2 clone و هدر بورد شما مانند Bluepill در محیط نرم افزار شناسایی نشود ، طبق تجربیات خودم به دلیل فیک یا کوپی بودن چیپ روی پروگرامر یا هدربورد شما می باشد .
در این صورت نرم افزار STM32CUBEIDE اجازه هر گونه عملیات پروگرم کردن و اشکال زدایی و Trace را به شما نمی دهد . اما از پروگرامر و هدربورد خود می توانید در نرم افزار هایی دیگری مانند ST-Link Utility و Keil و STM32CubeProgramer استفاده کنید .
تصویر زیر یک نمونه پروگرامر ST-Link v2 clone با چیپ فیک می باشد که در محیط نرم افزار STM32CUBEIDE شناسایی نمی شود .
آموزش تبدیل پروگرامر فیک به اورجینال قابل شناسایی و بروزرسانی در stm32cubeide را مطالعه نمایید .
ریدایرکت printf به ITM در STM32CubeIDE
یک پروژه و نمونه کد آماده کنید ، کد زیر را کپی کرده و در فایل main.c خود قرار دهید. در صورت ابهام، این کد از فایل syscalls.c آمده است.
تابع write_ که توسط تابع printf در stm32 فراخوانی خواهد شد را باید تغییر دهیم. تابع io_putchar__ را با تابع ()ITM_SendChar جایگزین کنید. تابع ()ITM_SendChar کاراکترهای ()printf را به ITM Port 0 ارسال میکند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* USER CODE BEGIN 0 */ int _write(int file, char *ptr, int len) { (void)file; int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++) { //__io_putchar(*ptr++); ITM_SendChar(*ptr++); } return len; } /* USER CODE END 0 */ |
همچنین فایل stdio.h را نیز اضافه کنید، زیرا این فایل برای عملکرد تابع pintf در stm32 و عدم تولید هشدارهای اشکالزدایی غیرضروری مورد نیاز است.
1 2 3 4 |
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <stdio.h> /* USER CODE END Includes */ |
اکنون میتوانید تابع printf را در فایل اصلی خود وارد کنید.
1 2 3 4 5 6 7 8 9 10 11 |
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { printf("Hello www.micronik.ir \n"); HAL_Delay(1000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ |
قبل از اینکه بتوانید با استفاده از SWV اشکالزدایی کنید، باید Trace Asynch Sw را در Debug on SYS در System Core فعال کنید. این کار تمام پینهای مورد نیاز برای SWV را تنظیم میکند.
سپس، در مسیر Run -> Debug Configurations، به تب Debugger بروید. Serial Wire Viewer (SWV) را فعال کنید و سپس فرکانس کلاک سیستم خود را با Core Clock مورد استفاده توسط SWV مطابقت دهید.
شما باید نمایشگر سیم سریال (SWV) را فعال کنید. مرتبطترین تنظیم ، Core Clock است. شما باید فرکانس ساعت صحیح را که در برنامه خود مقداردهی اولیه میکنید، پیکربندی کنید.
برای اینکه بتوانید تابع printf خود را در کنسول نمایش دهید، باید به پنجره کنسول داده SWV ITM دسترسی داشته باشید. در حالی که هنوز در حالت اشکالزدایی (Debug) هستید (در حالت مکث)، به مسیر Window -> Show View -> SWV ITM Data Console بروید.
پنجره کنسول SWV ITM را از طریق دکمه پیکربندی زیر پیکربندی کنید.
سپس، پورت 0 از پورتهای ITM Stimulus را تیک بزنید. معمولاً از این پورت برای تغییر مسیر کاراکترهای تولید شده توسط تابع printf در stm32 استفاده میشود. برای ادامه، OK را فشار دهید.
برای اجرای SWV، باید به یاد داشته باشید که روی دکمه Start Trace کلیک کنید.
پس از آن، میتوانید با فشردن دکمهی Resume به جلسهی اشکالزدایی خود ادامه دهید. اکنون باید دادههای اشکالزدایی تابع printf در stm32 خود را مشاهده کنید.
ریدایرکت printf به ITM در keil
تابع printf یکی از توابع موجود در کتابخانه stdio می باشد . بنابراین ابتدا باید stdio.h را به ابتدای برنامه اضافه کنید . در نرم افزار keil نیازی به اضافه کردن تابع write_ به برنامه نمی باشد .
سپس به منوی Manage Run-Time Environment بروید و گزینه Compiler->I/O را انتخاب کنید و تیک گزینه های STDERR , STDIN , SDTOUT را به حالت انتخاب درآورید و از زبانه کشویی گزینه ITM را انتخاب کنید . این کار باعث می شود خروجی تابع printf به واحد ITM هدایت یا Redirect شود .
بعد از redirect کردن تابع printf ، حالا باید ردیابی یا Trace را فعال کنید . منوی Options for Target را انتخاب کنید و به مسیر Debug->Settings بروید ، در مرحله بعد منوی Trace را انتخاب کنید .
تیک گزینه Trace Enable را انتخاب کنید و فرکانسی که برای میکرو تنظیم کرده اید در قسمت Core Clock وارد کنید . از قسمت ITM Stimulus Ports تیک قسمت Port 0 را به حالت انتخاب در آورید و در پایان گزینه OK را بزنید .
با زدن گزینه Start/Stop Debug session وارد حالت اشکال زدایی یا دیباگ شوید ، اکنون باید رشته ای را که توسط تابع printf درون برنامه نوشتید در بخش Debug (printf) Viewer مشاهده نمایید .
استفاده از printf در STM32 ST-Link Utility
از منوی ST-LINK گزینه Printf via SWO viewer را انتخاب کنید ، پنجره Serial Wire Viewer(swv) باز می شود . گزینه System clock را برابر فرکانس کاری میکروکنترلر قرار دهید و Stimulus port را 0 انتخاب کنید و در پایان گزینه START را بزنید .
آموزش استفاده از اعداد float در printf در STM32CubeIDE
به صورت پیش فرض مقادیر float در printf در پروژههای جدید ایجاد شده در stm32cubeide کار نمی کند.
اگر اعداد اعشاری در برنامه شما استفاده نشوند، این ممکن است مشکلی ایجاد نکند. با این حال، اگر استفاده میشوند و میخواهید آنها را فعال کنید، کافیست روی نام پروژه در Project Explorer کلیک راست کرده و Properties را انتخاب کنید. در دسته “C/C++ Build” گزینه Settings را انتخاب کنید و در تب Tool Settings، گزینه MCU Settings را انتخاب کنید. همانطور که در شکل زیر نشان داده شده است، کادر کنار “Use float with printf from newlib-nano” را علامت بزنید. روی Apply و Close کلیک کنید.
اگر با علامت زدن تیک گزینه use float with printf همچنان اعداد اعشاری در خروجی printf نمایش داده نمی شود . باید پرچم یا flag زیر را بصورت دستی طبق تصویر زیر به linker اضافه کنید .
1 |
-u _printf_float |
توجه داشته باشید که فعال کردن پشتیبانی از قالببندی اعشاری برای printf مقدار قابل توجهی حافظه اضافی مصرف میکند. این ممکن است برای میکروکنترلرهای رده پایین مشکلساز باشد.