আমি কীভাবে এসটিএম 32 এ মুদ্রণ কাজটি ব্যবহার করব?


19

সিরিয়াল বন্দরটিতে মুদ্রণের জন্য কীভাবে প্রিন্টফ ফাংশনটি ব্যবহার করতে হয় তা নির্ধারণ করার চেষ্টা করছি।

আমার বর্তমান সেটআপটি STM32CubeMX উত্পন্ন কোড এবং এসটিএম 32 এফ 407 আবিষ্কার বোর্ডের সাথে সিস্টেম ورکব্যাঞ্চ 32 ।

আমি stdio.h এ দেখছি যে প্রিন্টফ প্রোটোটাইপ হিসাবে সংজ্ঞায়িত করা হয়েছে:

int _EXFUN(printf, (const char *__restrict, ...)
               _ATTRIBUTE ((__format__ (__printf__, 1, 2))));

এর মানে কী? এই ফাংশন সংজ্ঞা সঠিক অবস্থান কোথায়? আউটপুট থেকে এই জাতীয় ফাংশনটি কীভাবে ব্যবহার করবেন তা জানার সাধারণ বিষয় কী হবে?


5
আমি মনে করি আপনার সিরিয়াল পোর্টে যেমন এখানে স্ট্যান্ডার্ড আউটপুট প্রেরণ করতে আপনার নিজের "int _writ (int ফাইল, চর * পিটিআর, ইন লেন)" লিখতে হবে । আমি বিশ্বাস করি এটি সাধারণত সিসক্যালস.কম নামে একটি ফাইলে সম্পন্ন হয় যা "সিস্টেম কলস রিম্যাপিং" পরিচালনা করে। গুগলিং "সিসক্ল্যাশনস" চেষ্টা করুন।
টুট

1
এটি কোনও ইলেকট্রনিক্স সমস্যা নয়। আপনার সংকলক লাইব্রেরির জন্য ম্যানুয়ালটি দেখুন।
অলিন ল্যাথ্রপ

আপনি কি সেমিহোস্টিং (ডিবাগারের উপরে) বা সাধারণভাবে কেবল প্রিন্টফের মাধ্যমে প্রিন্টফ ডিবাগিং করতে চান?
ড্যানিয়েল

@ টুট যেমন বলেছে, _write()ফাংশনটি আমি যা করেছি। নীচে আমার উত্তর বিস্তারিত।
cp.engr

এটি একটি দুর্দান্ত টিউটোরিয়াল ছিল: youtu.be/Oc58Ikj-lNI
জোসেফ পিঘেটি

উত্তর:


19

আমি আমার STM32F072 এ কাজ করে এই পৃষ্ঠাটি থেকে প্রথম পদ্ধতিটি পেয়েছি।

http://www.openstm32.org/forumthread1055

সেখানে বলা হয়েছে,

আমি যেভাবে প্রিন্টফ (এবং অন্যান্য সমস্ত কনসোল-ভিত্তিক স্টিডিও ফাংশন) পেয়েছি তা হ'ল নিম্ন স্তরের আই / ও ফাংশনের কাস্টম বাস্তবায়ন _read()এবং এর মাধ্যমে_write()

জিসিসি সি লাইব্রেরি নিম্ন স্তরের আই / ও সম্পাদন করার জন্য নিম্নলিখিত ফাংশনগুলিতে কল করে:

int _read(int file, char *data, int len)
int _write(int file, char *data, int len)
int _close(int file)
int _lseek(int file, int ptr, int dir)
int _fstat(int file, struct stat *st)
int _isatty(int file)

এই দু'টি ফাংশন GCC সি লাইব্রেরিতে "দুর্বল" সংযোগের সাথে স্টাব রুটিন হিসাবে প্রয়োগ করা হয়। যদি উপরের কোনও ফাংশনটির কোনও ঘোষণা আপনার নিজস্ব কোডে উপস্থিত হয়, আপনার বিকল্প রুটিনটি লাইব্রেরিতে ঘোষণাকে ওভাররাইড করবে এবং ডিফল্ট (অ-কার্যকরী) রুটিনের পরিবর্তে ব্যবহৃত হবে।

আমি huart1সিরিয়াল পোর্ট হিসাবে USART1 ( ) সেটআপ করতে STM32CubeMX ব্যবহার করেছি । যেহেতু আমি কেবল চেয়েছিলাম printf(), আমার কেবলমাত্র _write()ফাংশনটি পপুলি করা দরকার যা আমি নীচের মতো করেছিলাম। এটি প্রচলিতভাবে অন্তর্ভুক্ত রয়েছে syscalls.c

#include  <errno.h>
#include  <sys/unistd.h> // STDOUT_FILENO, STDERR_FILENO

int _write(int file, char *data, int len)
{
   if ((file != STDOUT_FILENO) && (file != STDERR_FILENO))
   {
      errno = EBADF;
      return -1;
   }

   // arbitrary timeout 1000
   HAL_StatusTypeDef status =
      HAL_UART_Transmit(&huart1, (uint8_t*)data, len, 1000);

   // return # of bytes written - as best we can tell
   return (status == HAL_OK ? len : 0);
}

আমি যদি কোনও মেকফাইল ব্যবহার করি এবং আইডিই না করি? আমার মেকফিল প্রকল্পে কাজ করার জন্য এটি থেকে কিছু অনুপস্থিত ... কেউ সাহায্য করতে পারে?
টেডি

@ টেডি, আপনি কি জিসিসি ব্যবহার করছেন? এটি একটি সংকলক-নির্দিষ্ট উত্তর। আপনি কি চেষ্টা করেছেন এবং ফলাফলগুলি কী ছিল?
cp.engr

হ্যাঁ আমি জিসিসি ব্যবহার করি। আমি সমস্যাটি খুঁজে পেয়েছি। _ রাইটার () ফাংশনটি ডাকা হয়েছিল। সমস্যাটি স্ট্রিং প্রেরণের জন্য আমার কোডে ছিল। আমি সেগারের আরটিটি গ্রন্থাগারটি অপব্যবহার করেছি তবে এখন ঠিকঠাক কাজ করে। ধন্যবাদ। সব এখন কাজ।
টেডি

4

_EXFUN হ'ল একটি ম্যাক্রো, সম্ভবত কিছু আকর্ষণীয় নির্দেশ রয়েছে যা সংকলককে বলে যে এটি প্রিন্টফ-সামঞ্জস্যপূর্ণ হওয়ার জন্য বিন্যাসের স্ট্রিংটি পরীক্ষা করা উচিত এবং প্রিন্টফের জন্য আর্গুমেন্টগুলি বিন্যাসের স্ট্রিংয়ের সাথে মেলে কিনা তা নিশ্চিত করা উচিত।

কীভাবে প্রিন্টফ ব্যবহার করবেন তা শিখতে আমি ম্যান পেজ এবং আরও কিছুটা গুগল করার পরামর্শ দিই । কিছু সাধারণ সি প্রোগ্রাম লিখুন যা প্রিন্টফ ব্যবহার করে এবং আপনার কম্পিউটারে মাইক্রো ব্যবহার করে রূপান্তর করার চেষ্টা করার আগে এগুলি আপনার কম্পিউটারে চালিত করে।

আকর্ষণীয় প্রশ্নটি হবে "মুদ্রিত পাঠ্যটি কোথায় যায়?"। ইউনিক্সের মতো সিস্টেমে এটি "স্ট্যান্ডার্ড আউট" এ চলে যায় তবে একটি মাইক্রোকন্ট্রোলারের কাছে এ জাতীয় জিনিস থাকে না। সিএমএসআইএস ডিবাগ লাইব্রেরিগুলি আর্ম সেমিহোস্টিং ডিবাগ পোর্টে প্রিন্টফ পাঠ্য প্রেরণ করতে পারে, অর্থাত্ আপনার জিডিবি বা ওপেনকডি সেশনে but তবে সিস্টেমওয়ার্কবেঞ্চ 32 কী করবে তা আমার কোনও ধারণা নেই।

আপনি যদি কোনও ডিবাগারে কাজ না করে থাকেন তবে আপনি যে স্ট্রিংটি মুদ্রণ করতে চান সেটিকে ফর্ম্যাট করতে স্প্রিন্টফ ব্যবহার করতে আরও সান্নিধ্য তৈরি হতে পারে এবং তারপরে সেই স্ট্রিংগুলি সিরিয়াল পোর্টের উপরে বা আপনার সংযুক্তিযুক্ত প্রদর্শনগুলিতে প্রেরণ করতে পারেন।

সাবধান: প্রিন্টফ এবং এর সাথে সম্পর্কিত কোড খুব বড় are এটি সম্ভবত 32F407 এ খুব বেশি গুরুত্ব দেয় না, তবে এটি সামান্য ফ্ল্যাশযুক্ত ডিভাইসগুলিতে একটি আসল সমস্যা।


আইআইআরসি _এক্সএফইএন রফতানির জন্য একটি ফাংশন চিহ্নিত করে, অর্থাত্ ব্যবহারকারীর কোডে ব্যবহৃত হবে এবং কলিং কনভেনশনটি সংজ্ঞায়িত করে। বেশিরভাগ (এম্বেডেড) প্ল্যাটফর্মগুলিতে ডিফল্ট কলিং কনভেনশন ব্যবহার করা যেতে পারে। তবে ডায়ামিক লাইব্রেরি সহ x86-এ আপনাকে __cdeclত্রুটিগুলি এড়ানোর জন্য ফাংশনটি সংজ্ঞায়িত করতে হতে পারে। কমপক্ষে newlib / cygwin এ, _EXFUN কেবল সেট করতে ব্যবহৃত হয় __cdecl
এরেবোস

4

@ অ্যাডামহান এর উত্তরটি আপনার যা দরকার sprintf()তা হ'ল স্ট্রিং তৈরি করা এবং তারপরে পাঠানো সহজ। তবে যদি আপনি সত্যিই printf()নিজের কোনও ফাংশন চান তবে ভেরিয়েবল আর্গুমেন্ট ফাংশন (va_list) এর উপায়।

va_listএকটি কাস্টম মুদ্রণ ফাংশন সহ নীচের মত দেখাচ্ছে:

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

void vprint(const char *fmt, va_list argp)
{
    char string[200];
    if(0 < vsprintf(string,fmt,argp)) // build string
    {
        HAL_UART_Transmit(&huart1, (uint8_t*)string, strlen(string), 0xffffff); // send message via UART
    }
}

void my_printf(const char *fmt, ...) // custom printf() function
{
    va_list argp;
    va_start(argp, fmt);
    vprint(fmt, argp);
    va_end(argp);
}

ব্যবহারের উদাহরণ:

uint16_t year = 2015;
uint8_t month = 12;
uint8_t day   = 18;
char* date = "date";

// "Today's date: 2015-12-18"
my_printf("Today's %s: %d-%d-%d\r\n", date, year, month, day);

মনে রাখবেন যে এই সমাধানটি আপনাকে ব্যবহার করতে সুবিধাজনক ফাংশন দেয় তবে এটি কাঁচা ডেটা প্রেরণ বা এমনকি ব্যবহার করার চেয়ে ধীর sprintf()। উচ্চ ডেটরেট সহ আমি মনে করি এটি যথেষ্ট হবে না।


আর একটি বিকল্প, এবং সম্ভবত আরও ভাল বিকল্পটি এসটি-লিংক ইউটিলিটি সহ এসটি-লিংক, এসডাব্লুডি ডিবাগার ব্যবহার করা। এবং এসডাব্লুও দর্শকের মাধ্যমে প্রিন্টফ ব্যবহার করুন , এখানে এসটি-লিংক ইউটিলিটির ম্যানুয়াল রয়েছে , প্রাসঙ্গিক অংশটি পৃষ্ঠা 31 এ শুরু হয়।

এসডাব্লুও ভিউয়ারের মাধ্যমে মুদ্রণযন্ত্রটি এসডাব্লুওয়ের মাধ্যমে লক্ষ্য থেকে প্রেরিত প্রিন্টফ ডেটা প্রদর্শন করে। এটি চলমান ফার্মওয়্যারটিতে কিছু দরকারী তথ্য প্রদর্শন করতে দেয়।


আপনি va_arg ব্যবহার করবেন না, আপনি পরিবর্তনশীল যুক্তি দিয়ে কীভাবে পদক্ষেপ নিবেন?
iouzzr

1

প্রিন্টফ () সাধারণত (স্ট্যান্ডার্ড) সি স্ট্যান্ডার্ড লাইব্রেরির অংশ। আপনার লাইব্রেরির সংস্করণ যদি সোর্স কোড নিয়ে আসে তবে আপনি সেখানে একটি প্রয়োগ খুঁজে পেতে পারেন।

স্ট্রিং তৈরি করতে স্প্রিন্টফ () ব্যবহার করা আরও সহজ হবে, তারপরে সিরিয়াল বন্দর দিয়ে স্ট্রিংটি প্রেরণ করতে অন্য ফাংশনটি ব্যবহার করুন। এইভাবে সমস্ত কঠিন ফর্ম্যাটিং আপনার জন্য করা হয় এবং আপনাকে স্ট্যান্ডার্ড লাইব্রেরি হ্যাক করতে হবে না।


2
প্রিন্টফ () সাধারণত লাইব্রেরির অংশ, হ্যাঁ, তবে কেউ পছন্দসই হার্ডওয়্যার থেকে আউটপুটে অন্তর্নিহিত ক্ষমতা সেট আপ না করা পর্যন্ত এটি কিছুই করতে পারে না। এটি গ্রন্থাগারটি "হ্যাকিং" নয়, বরং এটি ইচ্ছাকৃতভাবে ব্যবহার করা।
ক্রিস স্ট্রাটন

বেনস এবং উইলিয়াম তাদের উত্তরের পরামর্শ অনুসারে ডিবাগার সংযোগের মাধ্যমে পাঠ্য প্রেরণে পূর্বনির্ধারিত হতে পারে। (প্রশ্নকারী অবশ্যই এটি চেয়েছিল না))
অ্যাডাম হাওন

এটি কেবলমাত্র আপনার বোর্ডকে সমর্থন করার জন্য লিংকে বেছে নেওয়া কোডের ফলাফল হিসাবে ঘটতে পারে তবে আপনি নিজের আউটপুট ক্রিয়াকলাপটি নির্ধারণ করেই তা পরিবর্তন করেন। তোমার প্রস্তাব সঙ্গে সমস্যা এটি বুঝতে কিভাবে গ্রন্থাগার তার উপর ভিত্তি করে না হয় বোঝানো বদলে কি আপনি প্রতিটি ouput, অন্যান্য বিষয়ের মধ্যে, যা যেকোনো বিদ্যমান পোর্টেবল ধেড়ান জন্য একটি একাধিক ধাপ অনুসরণ প্রস্তাব করছি যে - ব্যবহার করা কোডগুলি যা কাজগুলি স্বাভাবিকভাবে করে।
ক্রিস

এসটিএম 32 একটি নিখরচায় পরিবেশ। সংকলকটির stdio.h সরবরাহ করার প্রয়োজন নেই - এটি সম্পূর্ণ .চ্ছিক। তবে এটি যদি stdio.h সরবরাহ করে তবে এটি অবশ্যই সমস্ত লাইব্রেরি সরবরাহ করবে। প্রিন্টফ প্রয়োগ করে এমন ফ্রিস্ট্যান্ডিং সিস্টেম সংকলকগুলি এটি ইউআরটি যোগাযোগ হিসাবে প্রবণতা দেখায়।
লন্ডিন

1

যারা লড়াই করছেন তাদের জন্য নিম্নলিখিতটি সাইকেলস.কে যোগ করুন:

extern UART_HandleTypeDef huart1; // access huart1 instance
//extern int __io_putchar(int ch) __attribute__((weak)); // comment this out

__attribute__((weak)) int __io_putchar(int ch)
{
    HAL_StatusTypeDef status = HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
    return (status == HAL_OK ? ch : 0);
}

পুট্টির মাধ্যমে আপনার সিওএম বন্দরে সংযোগ করুন এবং আপনার ভাল হওয়া উচিত।


1

আপনি যদি অন্য কোনও পদ্ধতির চান এবং যদি ফাংশনগুলি ওভাররাইট করতে বা আপনার নিজের ঘোষণা করতে না চান তবে আপনি কেবল snprintfএকই লক্ষ্য সংরক্ষণাগার ব্যবহার করতে পারেন । তবে এটি তেমন মার্জিত নয়।

char buf[100];
snprintf(buf, 100, "%X %X", val1, val2);
HAL_UART_Transmit(&huart1, (uint8_t*)buf, strlen(buf), 1000);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.