ARM, STM32, آموزش, توصیه شده, دوره آموزشی STM32, مقاله های سیسوگ

آموزش میکروکنترلر STM32 قسمت نهم: وقفه رابط سریال

آموزش میکروکنترلر STM32 وقفه رابط سریال

آموزش میکروکنترلر STM32; سیسوگ در قسمت هشتم از آموزش میکروکنترلر STM32  رابط سریال UART را به صورت یک مثال عملی آموزش داد. در این قسمت از آموزش میکروکنترلر STM32 قصد دارد طریقه کار با وقفه رابط سریال را با استفاده و بدون استفاده از توابع کتابخانه hal  آموزش دهد. در مجموعه آموزشی ” آموزش میکروکنترلر STM32 ” با سیسوگ همراه باشید.

وقفه رابط سریال با استفاده از توابع کتابخانه hal

برای شروع کار دوباره به محیط CubeMX می‌رویم و این‌بار در قسمت Configuration بعد از زدن دکمه UART1 و رفتن به قسمت تنظیمات این رابط سریال برگه NVIC Setting را انتخاب می‌کنیم و تیک مورد نظر را مطابق عکس زیر فعال می‌نمائیم.

 

فعال کردن وقفه عمومی رابط سریال

 

بعد از انجام این تنظیمات دوباره از CubeMX خروجی می‌گیریم و به محیط برنامه‌نویسی نرم‌افزار keil وارد می‌شویم. حال اگر توجه کنید در برگه stm32f1xx_it.c یک روتین وقفه برای رابط USART1 اضافه شده است.

 

 

وقفه رابط سریال UART1

 

خوب همان‌طور که پیش از این گفته شد این‌بار سعی داریم توسط توابع کتابخانه hal وقفه رابط سریال را تست کنیم، برای همین به سراغ توابع عمومی رابط سریال UART که مربوط به وقفه این رابط می‌گردد می‌رویم. اولین تابعی که باید مورد بررسی قرار دهیم، تابع مربوط به پیکره بندی وقفه دریافت رابط سریال است .

 

 

در آرگومان *huart تابع نام uart مورد استفاده ما قرار می‌گیرد و در آرگومان *pData رشته‌ای که قرار است اطلاعات دریافتی از رابط سریال در داخل آن قرار بگیرد. در آرگومان Size سایز یا تعداد بایتی که قرار است دریافت شود را تعیین می‌کند. برای فهم بهتر مسئله و قابلیت‌های این تابع بهتر است به متن تابع در برگه stm32f1xx_hal_uart.c نگاه کنیم.

 

 

متن تابع در برگه stm32f1xx_hal_uart.c برای رابط سریال

همان‌طور که می‌بینید در این تابع آرایه‌ای که قرار است اطلاعات دریافتی داخل آن ریخته شود مشخص می‌شود و در ادامه سایز و تعداد بایتی که قرار است دریافت شود نیز مشخص می‌گردد. هم‌چنین در سه فرمان وقفه‌های خطای پریتی و خطای عمومی دریافت و همچنین وقفه دریافت فعال می‌گردد. خوب تا اینجا متوجه شدیم که ما باید در ابتدای برنامه از این فرمان برای پیکره‌بندی و فعال کردن وقفه دریافت رابط سریال UART استفاده کنیم. سیستم کار هم بدین صورت است که ما بعد از دریافت تعداد کاراکتر که مشخص کردیم به صورت خودکار به تابع HAL_UART_RxCpltCallback که باید آن را در main برنامه جاسازی کنیم برود و این عمل به صورت نرم‌افزاری صورت می‌پذیرد و نه سخت‌افزاری. برای درک بیشتر مسئله بهتر است کد نویسی‌های داخل توابع را بررسی کنیم تا با نحوه دریافت بیشتر آشنا شویم. اصولا با دریافت هر کاراکتر ما به روتین وقفه USART1_IRQHandler در برگه stm32f1xx_it.c خواهیم رفت حال اگر توجه کنید در آن تابع ، تابع دیگری با نام HAL_UART_IRQHandler فراخوانی شده است، اکنون به محل تعریف شدن آن تابع می‌رویم تا متن آن را مورد بررسی قرار دهیم.

 

 

وقفه رابط سریال

همان‌طور که در عکس بالا می‌بینید، در صورتی که پرچم‌های خطا فعال نشده باشند و در عین حال پرچم وقفه دریافت فعال شده باشد به تابع UART_Receive_IT خواهیم رفت. برای بررسی این تابع به محل تعریف این تابع می‌رویم تا متن این تابع را هم بررسی کنیم.  برای فهم بیشتر به عکس زیر که متن تابع را به همراه توضیحات لازم نمایش می‌دهد توجه کنید.

 

 

وقفه رابط سریال

در نیمه بالایی تابع ما با دریافت هر بایت، بافر دریافت اطلاعات را با هر بار فراخوانی این تابع یک بایت پر می‌کنیم و در نیمه پایینی تابع هر دفعه یکی از متغیر huart->RxXferCount کم می‌کنیم تا زمانی که به صفر برسد و در این حالت است که ما همه تعداد  بایت‌هایی را که می‌خواستیم دریافت کرده‌ایم. بعد از این مرحله سه وقفه‌ای که قبلا فعال کرده‌ایم غیر فعال می‌شود و در مرحله بعد به تابع HAL_UART_RxCpltCallback هدایت می‌گردیم. این تابع را می‌توانیم در main.c برنامه خود جایگذاری کنیم. به عکس زیر که نمایی از کدهای تابع مورد نظر در main.c برنامه است توجه کنید، همانطور که در عکس زیر می‌بینید ما باید در ابتدای برنامه یکبار تابع HAL_UART_Receive_IT را بنویسیم تا وقفه دریافت فعال گردد و بافر دریافت و تعداد کاراکتری که می‌خواهیم دریافت کنیم مشخص شود.

 

 

وقفه رابط سریال

حالا ما به دو روش می‌توانیم اتمام دریافت اطلاعات از وقفه رابط سریال را متوجه شویم. یکی اینکه در حلقه اصلی main یکسره متغیر huart1.RxXferCount را چک کنیم که اگر صفر شد یعنی هر 10 بایتی که ما می‌خواستیم دریافت شده، بعد از این مرحله بایت‌هایی که دریافت شده را توسط همان رابط سریال نمایش می‌دهیم و دوباره همان فرمان پیکره‌بندی وقفه دریافت را می‌نویسیم تا برای بار دیگر 10 بایت از درگاه سریال دریافت کنیم.

 

 

وقفه رابط سریال

توجه داشته باشید در اینجا کاراکتر یازدهم که در بحث نمایش اطلاعات دریافتی نمایش می‌دهیم، منظور همان کاراکتر 13 است که برای همان نمایش اینتر از آن استفاده می‌کنیم. روش دیگر هم نمایش و پیکره بندی دوباره در همان تابع HAL_UART_RxCpltCallback است که در عکس زیر مشاهده می‌کنید.

 

وقفه رابط سریال

 

برای وقفه ارسال هم در کتابخانه hal از تابع HAL_UART_Transmit_IT استفاده می‌شود، که بدلیل مشابه بودن مراحل و جلوگیری از ازدیاد مطلب بر عهده خود دانش پژوهان گذاشته می‌شود.

وقفه رابط سریال بدون استفاده از توابع کتابخانه hal

حال سعی داریم طریقه کار با وقفه رابط سریال را بدون استفاده از توابع کتابخانه hal و کار مستقیم با رجیسترها آموزش دهیم. برای شروع کدهای قبلی را که به برنامه قبل اضافه کرده بودیم پاک می‌کنیم تا برنامه را به صورت دیگری بنویسیم. شکل برنامه هم به صورتی است که ما داخل وقفه دریافت در یک بافر تا زمانی که کاراکتر 13 یا همان کاراکتر اینتر بیاید اطلاعات را ذخیره می‌کنیم و بعد از رسیدن به این کاراکتر کل رشته دریافتی را با فرمان printf در main برنامه نمایش می‌دهیم. بدین منظور به تابع وقفه رابط سریال UART1 با نام USART1_IRQHandler در برگه stm32f1xx_it.C می‌رویم و کدها را به این صورت اصلاح می‌کنیم.

 

وقفه رابط سریال

بر طبق عکس بالا ما در وقفه دریافت رابط سریال تابع HAL_UART_IRQHandler را حذف می‌کنیم و تنها با چک کردن پرچم دریافت رابط سریال و خواندن از رجیستر USART1->DR بافر خود را پر می‌کنیم. در عکس زیر می‌توانید متن برنامه را حلقه اصلی برنامه در برگه main.c ببینید.

 

وقفه رابط سریال

سیسوگ در قسمت دهم آموزش میکروکنترلر STM32 کار با DMA رابط سریال UART را آموزش خواهد داد. با سیسوگ همراه باشید.

 

 

انتشار مطالب با ذکر نام و آدرس وب سایت سیسوگ، بلامانع است.

شما نیز میتوانید یکی از نویسندگان سیسوگ باشید.   همکاری با سیسوگ

18 دیدگاه در “آموزش میکروکنترلر STM32 قسمت نهم: وقفه رابط سریال

  1. Avatar for محمد گل زاده محمد گل زاده گفت:

    سلام. متغیرهای تعریفی به چه صورت باید باشد

  2. Avatar for سعید سعید گفت:

    درود بسیار عالی بود
    بعد از فرمان فعال سازی وقفه
    HAL_UART_ENABLE_IT( &huart2 , UART_IT_RXNE )

    الویت وقفه را با چگونه فرمان دهیم ( بدون استفاده از حیط MxCube )

    سپاس

    1. Avatar for Zeus ‌ Zeus ‌ گفت:

      سلام کار مدیریت وقفه ها و اولویت بندی آنها به عهده NVIC است
      اگر در مورد وقفه ها اطلاعات بیشتری نیاز دارید مطلب زیر را مطالعه کنید.
      آموزش STM32 با توابع LL قسمت هفتم: Interrupt

  3. Avatar for سعید سعید گفت:

    درود. خیلی عالی بود
    الویت وقفه را چگونه تنظیم کنیم؟

    سپاس

    1. Avatar for Zeus ‌ Zeus ‌ گفت:

      سلام دوست عزیز
      اولویت ها رو با توابع NVICمیشه تنظیم کرد.

  4. Avatar for tariq tariq گفت:

    دمت گرم خیلی خوب بود

  5. Avatar for داود داود گفت:

    در ضمن من از آموزشهایی که توی این سایت قرار دادین بهره زیادی بردم و خیلی از جوابهایی که دنبالش بودم رو اینجا پیدا کردم
    خواستم از این طریق تشکر ویژه ای از شما داشته باشم

    1. Avatar for Sisoog Os Sisoog Os گفت:

      خبر خوشحال کننده ایه برای ما
      ممنون از شما

  6. Avatar for داود داود گفت:

    سلام
    در کدویژن با استفاده از دو دستور asm cli و asm sei میشه وقفه عمومی رو فعال یا غیر فعال کرد
    میخواستم بپرسم در IAR یا KEIL چطوری میشه این وقفه ها رو فعال یا غیر فعال کرد چون تا اونجا که من میدونم فقط asm nop تو این محیط کار میکنه
    ممنون میشم از پاسخگویی شما

    1. Avatar for زئوس Zeus زئوس Zeus گفت:

      سلام دوست عزیز برای این کار میتونید از ماکروهای

      __disable_irq()
      __enable_irq()

      استفاده کنید که در نهایت با کد اسمبلی معادلش جایگزین میشه

      1. Avatar for داود داود گفت:

        ممنونم از پاسخگویی شما

  7. Avatar for رسول رسول گفت:

    سلام . خیلی ممنون بابت آموزشها .
    من یک مشکلی دارم با وقفه دریافت یوزارت .مشکل اینه که وقتی 2 یا 3 ارتباط یوزارت استفاده میکنم پس از یه مدتی وقفه دریافت غیر فعال میشه و دیگه اطلاعت دریافقت نمیشه .
    ممنون میشم راهنمایی کنید

    1. Avatar for کامین جلیلی کامین جلیلی گفت:

      سلام رسول. در تابع روتین وقفه ابتدا با شرط چک کنید که وقفه از کدوم UART رسیده، سپس عملیات رو انجام بدید.

  8. Avatar for امیر امیر گفت:

    با سلام
    علت رویکرد کتابخانه‌های به نوشتن وقفه به صورت سه تابع چیست؟ چرا تو همون سرویس روتین خواسته های وقفه اجرای نمیشه و ما باید بریم تو تابع وقفه هال و بعد هم کالبک؟

  9. Avatar for صادق صادق گفت:

    سلام ، ممنون بابت مطالب خوبتون .
    این قسمت آخر که بدون توابع Hal نوشتین رو میشه به همین شکل برای دریافت در spi با وقفه پیاده سازی کرد ؟

  10. Avatar for زهرا زهرا گفت:

    عالییییییییی بود. ممنونم

    1. Avatar photo electronic girl گفت:

      خواهش میکنم ممنون از شما

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *