استفاده از رابط SPI در دستگاه های STM32

این آموزش نشان می دهد که چگونه از رابط کاربری SPI دستگاه های STM32 با استفاده از API STM32CubeMX HAL استفاده کنید. ما SPI را در چندین حالت مختلف پیکربندی می کنیم، نشان می دهد که چگونه روی سیگنال تولید شده تأثیر می گذارد و حالت دو بافر را برای نشان دادن حالت بی وقفه پیوسته تنظیم می کند.

ما از یک صفحه STM32F4Discovery برای نشان دادن SPI و یک صفحه Nucleo-F411RE با Analyzer2Go برای نشان دادن و تجزیه و تحلیل سیگنال های SPI تولید استفاده می کنیم.

قبل از شروع، Visual Studio و VisualGDB را نصب کنید:

  1. شروع به ویژوال استودیو و VisualGDB جاسازی شده جادوگر پروژه را باز کنید:01-newprj
  2. با تنظیمات پیش فرض در صفحه اول انجام دهید:02 باینری
  3. در صفحه بعد STM32 دستگاه خود را انتخاب کنید. در این آموزش ما از صفحه STM32F4Discovery که از تراشه STM32F407VG استفاده می کند استفاده می کنیم، اما تکنیک های شرح داده شده در اینجا برای تراشه های دیگر نیز کار خواهند کرد:03 دستگاه
  4. مثال پیش فرض “LEDBlink” را انتخاب کرده و روی “بعدی” کلیک کنید:04 چشمک زدن
  5. در نهایت تنظیمات اشکال زدایی خود را مشخص کنید. برای اکثر دستگاه های STM32 قابل برنامه ریزی از طریق ST-Link ما توصیه می کنیم با استفاده از OpenOCD. هیئت مدیره خود را به کامپیوتر وصل کنید و روی «شناسایی» کلیک کنید تا به طور خودکار رابط ST-Link خود را تشخیص دهید:05-اشکال زدایی
  6. روی “پایان” کلیک کنید تا پروژه اساسی ایجاد شود و مطمئن شوید که آن را می سازد. حالا ما این پروژه را برای ارسال یک پیام اساسی از رابط STI32 SPI تغییر خواهد داد. اول از همه، Datasheet را برای دستگاه STM32 خود قرار دهید و پین هایی را که می توانید برای SPI استفاده کنید پیدا کنید. برای STM32F407VG ما از پین های PA4-PA7 با SPI1 استفاده می کنیم (توجه کنید که شماره تابع متناوب AF5 در این مورد است):قابل دسترس است
  7. محتویات اصلی فایل .cpp با کد زیر را جایگزین کنید:
  8. کد را وارد کنید که SPI محیطی را به تابع GenerateTestSPISignal () راه اندازی خواهد کرد:
  9. اگر ما بعد از فراخوانی HAL_SPI_Init () از SPI محیطی استفاده کنیم، محیطی از دیدگاه برنامه کار می کند، اما سیگنال های SPI در واقع روی پین های تراشه قابل مشاهده نخواهد بود. برای حل این مشکل، ما باید صریح پین PA5-PA7 را به حالت SPI سوئیچ کنیم. ما یک پین PA4 را به یک پین Generic GPIO برای نشان دادن نحوه کنترل سیگنال NSS به صورت دستی خواهیم پرداخت.

    توجه داشته باشید که GPIO_AF5_SPI1 مربوط به شماره تابع متناوب (AF5) برای SPI1 از جدول تابع جایگزین در صفحه داده است.

  10. سرانجام کد زیر را اضافه کنید که به طور مرتب رشته “Hello، World” را بر روی SPI ارسال می کند:

    توجه داشته باشید که ما دستی کنترل سیگنال NSS را با تنظیم مقدار PIN PA4 به 0 قبل از انتقال و تنظیم آن را به عقب 1 پس از انتقال.

  11. ساختن پروژه و حصول اطمینان از موفقیت بدون هیچ گونه خطا:06-ساخت
  12. یک نقطه توقف در اولین تماس به HAL_GPIO_WritePin () و شروع به اشکالزدایی کنید. اطمینان حاصل کنید که نقطه توقف:07 مرحله ای
  13. اکنون از یک تحلیلگر منطقی برای مشاهده سیگنال های SPI تولید شده توسط هیئت مدیره استفاده می کنیم. در این آموزش از Analyzer2Goو هیئت مدیره ST NUCLEO-F411RE برای گرفتن و تحلیل سیگنال استفاده می شود. اگر شما Nucleo-F411RE هیئت مدیره ندارید، می توانید از هر یک از تخته های دیگر پشتیبانی شده توسط Analyzer2Go یا یک آنالیز منطقی خارجی استفاده کنید. ابتدا Analyzer2Go را شروع کنید، هیئت مدیره را که می خواهید به عنوان یک تحلیلگر منطقی استفاده کنید، وصل کنید و آن را در لیست انتخاب کنید:08-selboard
  14. سپس سیگنال های SPI مرتبط (MOSI، SCLK و NSS) را به ورودی های هیئت تحلیل کننده منطقی که در پنجره Analyzer2Go نشان داده شده است، وصل کنید. فراموش نکنید که زمین را بین 2 تخته وصل کنید:2boards
  15. در نهایت بر روی سیگنال متصل شده در پنجره Analyzer2Go کلیک کنید تا بلافاصله سیگنال Live SPI را ببینید:09 سیگنالالگوی مکرر را مشاهده کنید: سیگنال NSS از 1 به 0 می رود (نشان دهنده شروع انتقال است)، سپس سیگنال SCK و MOSI به سرعت مقادیر را تغییر می دهد و NSS به 1 می رسد.
  16. ستون “Trigger” از سیگنال NSS را کلیک کنید تا کادر داده به لبه سقوط (شروع انتقال) برسد. سپس روی هر کدام از بلوک های جامد سیگنال SCK یا MOSI دوبار کلیک کنید تا زوم کنید تا سیگنال واقعی ببینید:10 اسپایشکل موج سیگنال SPI معمولی را مشاهده کنید: ساعت SCK موجب تولید پالس های ساعت یکنواخت در طول انتقال می شود و سیگنال MOSI (ورودی فرعی خروجی اصلی) یک بار یک بار داده را انتقال می دهد.
  17. افزودن برچسب به سیگنال های SCK و MOSI با کلیک بر روی “کلیک کنید برای اضافه کردن توضیحات”، سپس باز کردن تب پروتئین Analyzers، اضافه کردن و اتصال تجزیه و تحلیل پروتکل SPI:11-رمزگشاییمشاهده کنید که پیام “Hello، World” رمزگشایی شد.
  18. در حال حاضر ما خواهیم دید که چگونه پیام های کد شده در هنگام استفاده از حالت های مختلف SPI کد گذاری می شوند. شخصیت ‘H’ را انتخاب کنید و بر روی نوار یادداشت کلیک کنید تا یک یادداشت اضافه کنید:12-hnote
  19. سپس نمایش سیگنال MOSI را از SPI به Raw تغییر دهید تا بیت دقیق را که با بایت ‘H’ مطابقت دارد مشاهده کنید:13 خام
  20. هر یک از 8 عدد ساعت، دقیقا 1 بیت از کاراکتر 8 بایت را انتقال می دهد (MOSI پایین خواهد بود اگر مقدار بیت ‘0’ باشد و اگر مقدار بیت ‘1’ باشد). برای تجسم این، چرخه ساعت SCK مربوط به شخصیت “H” را انتخاب کنید و روی ‘تنظیم این سیگنال به عنوان ساعت اولیه’ کلیک کنید:14 سیگنال
  21. Analyzer2Go به صورت خودکار مقدار MOSI را در هر چرخه ساعت چاپ می کند. همانگونه که ابتدا بیت کمترین مقدار را انتقال می دهیم 00010010 مربوط به 0b01001000 است که برابر با 0x48 یا کد ASCII برای شخصیت capital ‘H’ است:15 ارزش
  22. توجه داشته باشید که هنگامی که سیگنال MOSI نیاز به تغییر دارد، آن دقیقا در لبه ساعت سقوط SCK تغییر می کند. این تضمین می کند که سیگنال به اندازه کافی زمان (1/2 چرخه) برای تثبیت شدن به زمانی که دستگاه دریافت کننده SPI در واقع نمونه آن را داشته باشد:16 لبه
  23. برای تغییر این رفتار، میدان CLKPolarity ساختار اولیه برای SPI را به SPI_POLARITY_LOW تنظیم کنید:
  24. مشاهده کنید که چگونه ارزش MOSI در حال حاضر بر لبه رو به افزایش SCLK تغییر می کند:17 معکوسمقدار درست برای استفاده بستگی به مشخصات دستگاهی است که میخواهید از طریق SPI به آن متصل شوید. اگر خروجی MOSI را در لبه های در حال افزایش قرار می دهد، SPI محیطی را پیکربندی کنید تا مقدار آن را در لبه های سقوط تغییر دهید. در غير اينصورت، آن را در لبه هاي ساعت در حال تغيير تنظيم کنيد.
  25. یکی دیگر از پارامترهای مهم، فاز ساعت است. این وضعیت سیگنال SCK را هنگامی که هیچ گیرنده فعال نیست فعال می کند. توجه داشته باشید که فعال کردن فاز clock نیز لبه فعال را تغییر می دهد:
    CLKPolarity CLKPhase MOSI تغییر در مقدار SCK زمانی که غیر فعال است
    SPI_POLARITY_HIGH SPI_PHASE_2EDGE سقوط لبه بالا
    SPI_POLARITY_LOW SPI_PHASE_2EDGE افزایش لبه کم
    SPI_POLARITY_LOW SPI_PHASE_1EDGE سقوط لبه کم
    SPI_POLARITY_HIGH SPI_PHASE_1EDGE افزایش لبه بالا

    تنظیم CLKPhase به SPI_PHASE_1EDGE و مشاهده نحوه تغییر سیگنال:

    18-1 دقيقه

  26. حالا ما نشان خواهیم داد که چگونه SPI محیطی را پیکربندی کنیم تا سیگنال NSS را به طور خودکار کنترل کنیم. به طور معمول، دستگاه های SPI برده هر گونه ارتباط SPI را که هنگام ورود ناسازگار NSS خود غیر فعال است (به 1 تنظیم می شود) نادیده می گیرد. این اجازه می دهد تا سیگنال های MOSI، MISO و SCK را بین چندین دستگاه برده و با استفاده از سیگنال های NSS (1 برای هر دستگاه) به منظور انتخاب هر دستگاه باید به هر ارتباط پاسخ دهد. تا کنون ما NSS را به صورت دستی با استفاده از تابع HAL_GPIO_WritePin () کنترل کرده ایم، با این حال STM32 SPI محیطی اجازه می دهد تا بطور خودکار سیگنال NSS را تولید کند. به این ترتیب کد اولیه را تغییر دهید:

    در نهایت تماس ها را به HAL_GPIO_WritePin () حذف کنید.

  27. کد را اجرا کنید و سیگنال های جدید را مشاهده کنید. توجه کنید که چگونه NSS در طول و بین انتقالها کم می شود:19-hardnss
  28. تنها راه غلبه بر این رفتار در حالی که هنوز با استفاده از حالت NSS سخت افزار است، پس از هر انتقال، غیر فعال کردن SPI محیطی است:
  29. کد به روزرسانی را اجرا کنید و تأیید کنید که سیگنال NSS دوباره ظاهر می شود:20-hardc2
  30. اکنون ما از طریق تابع HAL_SPI_DeInit () گام می بینیم که در کدام نقطه NSS از 0 به 1 برسد. کد خود را در یک نقطه پایانی متوقف کنید و دکمه “Record” را در Analyzer2Go کلیک کنید تا به طور مداوم ضبط مقادیر سیگنال، سپس به و از طریق HAL_SPI_DeInit ():21 مداوم
  31. سیگنال NSS از 0 تا 1 به بعد یک خط __HAL_SPI_DISABLE (hspi) اجرا می شود:22 دینت
  32. از دستور “دستورالعمل پیش پردازش” استفاده کنید تا ببینید که در واقع بیت # 6 (SPE) در ثبت نام SPI_CR پاک میشود:23-prepro
  33. STM32 SPI محیطی همچنین از یک حالت خاص TI پشتیبانی می کند. با تغییر دادن کد راه اندازی به صورت زیر، آن را تغییر دهید:

    توجه کنید که چگونه سیگنال NCS در یک دوره قبل از انتقال در 1 باقی می ماند و سپس به 0 می رسد (دستور بیت به MSB نیز تغییر می کند):24-timode

  34. حالا ما نشان خواهیم داد که چگونه از STM32 SPI برای انتقال داده های بزرگی از داده ها (به عنوان مثال جریان از مقادیر به یک مبدل دیجیتال به آنالوگ) استفاده کنیم. ابتدا ساده ترین رویکرد را امتحان کنید: یک بلوک از مقادیر ایجاد کنید، سپس فقط از طریق HAL_SPI_Transmit () ارسال کنید:

    FillNextFrame () بافر های انتقال را با مقادیر 32 بیتی از (FrameNumber * 0x100) به (FrameNumber * 0x100 + 0xFF) پر می کند. این اجازه می دهد تا کادر و موقعیت در داخل قاب را از مقدار مشخص کند. مثلا 0x002501 به معنای مقدار 01 است (از # 00) در کادر 0x25.

  35. کد به روزرسانی را اجرا کنید. همانطور که FillNextFrame () و HAL_SPI_Transmit () در یک زمان اجرا نمی شوند، شما می توانید شکاف بین مقادیر مربوط به فریم های مختلف را مشاهده کنید:25 شکاف
  36. برای از بین بردن شکافها، SPI را برای استفاده از DMA (دسترسی مستقیم به حافظه) با دو بافر، پیکربندی خواهیم کرد. نیمه اول بافر را به طور خودکار انتقال می دهد در حالی که کد شما نیمه دوم را پر می کند و برعکس، در نتیجه 100٪ بدون وقفه انتقال می یابد. اول کانال DMA و جریان که به کانال TX SPI1 متصل است:دمرک
  37. سپس کد را پس از آخرین تماس به HAL_GPIO_Init () با کد اولیه و شروع DMA جایگزین کنید:
  38. سپس کد زیر را قبل از تابع GenerateTestSPISignal () اضافه کنید:
  39. با استفاده از HAL_SPI_Transmit_DMA () به جای HAL_SPI_Transmit () ما SPI محیطی را برای شروع انتقال s_TransferBuffer با استفاده از مکانیزم دسترسی مستقیم حافظه پسزمینه و بلافاصله کنترل بازگشت می دهیم. وقتی نیمه اول بافر انتقال می شود، DMA یک وقفه ایجاد می کند که به HAL_SPI_TxHalfCpltCallback () هدایت می شود که نیمه اول فریم بعدی را تولید می کند در حالی که فریم فعلی هنوز منتقل می شود. هنگامی که کل بافر انتقال می شود، HAL_SPI_TxCpltCallback () فراخوانی می شود و نیمه دوم فریم را تولید می کند (در حالی که DMA در حال حاضر نیمه اول آن را ارسال می کند). این باعث انتقال 100٪ بدون وقفه بدون هیچ گونه شکاف می شود:26 نولپ
  40. شما می توانید زمان انتقال را با جایگزینی حلقه خالی در انتهای GenerateTestSPISignal () با حلقه سیگنال NSS را تصحیح کنید (فراموش نکنید پیکربندی PA4 را به عنوان GPIO_MODE_OUTPUT_PP):
  41. کد به روزرسانی را اجرا کنید. مشاهده کنید که مقدار سیگنال NSS برای یک زمان کوتاه تغییر می کند (در حالیکه یکی از عملکردهای CpltCallback در حال اجرا است)، اما انتقال SPI بدون وقفه انجام می شود:27-intgap
  42. شما می توانید نقطه توقف در یکی از توابع CpltCallback را تنظیم کنید و از پنجره Call Stack برای دیدن زنجیره ای از توابع درگیر در وقفه استفاده کنید:ایزو