آموزش میکروکنترلر 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 را آموزش خواهد داد. با سیسوگ همراه باشید.

 

 

حمایت از مهدی عبدالهی

خوشحال میشیم برای تداوم و کیفیت ما رو حمایت کنید.

0 نفر

پــــســنــدیـده انـد

توجه

مهدی عبدالهی
مهدی عبدالهی

کانال میکروالکترونیک @microstm32

دیدگاه ها

17 دیدگاه

  • سعید
    ۲۶ تیر ۱۴۰۱

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

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

    سپاس

  • سعید
    ۲۶ تیر ۱۴۰۱

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

    سپاس

    • Zeus ‌
      Zeus ‌
      ۲۹ تیر ۱۴۰۱

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

  • tariq
    ۲۰ بهمن ۱۳۹۹

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

  • داود
    ۲۰ دی ۱۳۹۹

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

    • Sisoog Os
      Sisoog Os
      ۲۰ دی ۱۳۹۹

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

  • داود
    ۲۰ دی ۱۳۹۹

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

    • Zeus ‌
      زئوس Zeus
      ۲۱ دی ۱۳۹۹

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

      __disable_irq()
      __enable_irq()

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

  • رسول
    ۱۳ آبان ۱۳۹۹

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

    • کامین جلیلی
      ۲۲ فروردین ۱۴۰۰

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

  • امیر
    ۳۱ شهریور ۱۳۹۸

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

  • صادق
    ۲۲ شهریور ۱۳۹۸

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

  • زهرا
    ۱ اسفند ۱۳۹۷

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

    • Nasim Hematian
      electronic girl
      ۱ اسفند ۱۳۹۷

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

پر بحث ترین ها

مسابقه دوم : چالش برنامه نویسی به زبان C

مسابقه اول سیسوگ (مسابقه اول: درک سخت افزار) انتقادهای زیادی رو در پی داشت تا جایی که حتی خودمم به نتیجه مسابقه...

Zeus ‌ Zeus ‌
  • 2 سال پیش

راه اندازی LCD گرافیکی Nokia 1661 و دانلود کتابخانه آن

LCD گرافیکی یکی از مهم ترین پارامترهای موجود در طراحی انواع مدارات الکترونیکی پیچیده و حتی ساده است ، نمایش وضعیت و...

Zeus ‌ Zeus ‌
  • 4 سال پیش

ریموت کدلرن و چکونگی دکد کردن آن به همراه سورس برنامه

ریموت کنترل امروزه کاربرد زیادی پیدا کرده است؛ از ریموت‌های درب بازکن تا ریموت‌های دزدگیر و کنترل روشنایی همه از یک اصول اولیه پیروی می‌کنند و آن‌هم ارسال اطلاعات به‌صورت بی‌سیم است....

Zeus ‌ Zeus ‌
  • 5 سال پیش

همه چیز درباره ریموت کنترل‌های هاپینگ

امنیت همیشه و در همه‌ی اعصار، مقوله‌ی مهم و قابل‌توجه‌ ای بوده و همیشه نوع بشر به دنبال امنیت بیشتر، دست به ابداعات و اختراعات گوناگونی زده است. ریموت کنترل یکی از این اختراعات است. در این مقاله، به بررسی امنیت انواع ریموت‌های کنترل خواهیم پرداخت....

Zeus ‌ Zeus ‌
  • 5 سال پیش

مسابقه سوم: استخراج داده از رشته ها در زبان C

نزدیک به 5 ماه از مسابقه دوم سیسوگ می‌گذره و فکر کردم که بد نیست یک چالش جدید داشته باشیم! البته چالش‌ها...

Zeus ‌ Zeus ‌
  • 2 سال پیش

مسابقه ششم: بزن میکروکنترلر را بسوزون!

بزنم میکروکنترلر را بسوزونم اونم تو  این شرایط!، طراحی مسابقه از اون چیزی که به نظر می‌رسه سخت‌تر است، باید حواست باشه...

Zeus ‌ Zeus ‌
  • 11 ماه پیش

آموزش قدم به قدم راه اندازی +NRF24L01

آموزش قدم به قدم راه اندازی +NRF24L01  با کتابخانه سازگار با انواع میکروکنترلرها و کامپایلرها قبل از اینکه قسمت بشه با ماژول...

رسول خواجوی بجستانی رسول خواجوی بجستانی
  • 3 سال پیش

ساخت ماینر با FPGA و ARM

چند ماهی هست که تب بیت کوین و ارزهای دیجیتال خیلی بالا رفته! چه شد که این پست را نوشتم همانطور که...

Zeus ‌ Zeus ‌
  • 3 سال پیش

کار با ماژول تمام عیار mc60 – قسمت دوم – راه اندازی OpenCPU

در قسمت اول به یکسری اطلاعات کلی ماژول mc60 پرداختیم، با نرم افزار QNavigator کار کردیم و یک هدربرد هم برای کار...

Mahdi.h   Mahdi.h  
  • 3 سال پیش

مسابقه چهارم: کدام حلقه سریع‌تر است؟

حدود ۷ ماه پیش، مسابقه سوم سیسوگ رو برگزار کردیم و کلی نکته در مورد خواندن رشته‌های ورودی را بررسی کردیم. فکر...

Zeus ‌ Zeus ‌
  • 1 سال پیش
سیـــســـوگ

مرجع متن باز آموزش الکترونیک