ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

В پہلا حصہ میں نے شوق الیکٹرانکس انجینئرز کو بتانے کی کوشش کی جو Arduino پتلون سے پروان چڑھے ہیں کہ انہیں مائیکرو کنٹرولرز کے لیے ڈیٹا شیٹس اور دیگر دستاویزات کو کیسے اور کیوں پڑھنا چاہیے۔ متن بڑا نکلا، اس لیے میں نے ایک الگ مضمون میں عملی مثالیں دکھانے کا وعدہ کیا۔ ٹھیک ہے، اس نے خود کو ایک دودھ مشروم کہا ...

آج میں آپ کو دکھاؤں گا کہ ڈیٹا شیٹس کو حل کرنے کے لیے کس طرح استعمال کیا جائے کافی آسان، لیکن بہت سے پروجیکٹس، STM32 (Blue Pill) اور STM8 کنٹرولرز کے کاموں کے لیے ضروری ہے۔ تمام ڈیمو پروجیکٹس میرے پسندیدہ ایل ای ڈیز کے لیے وقف ہیں، ہم ان کو بڑی مقدار میں روشن کریں گے، جس کے لیے ہمیں ہر طرح کے دلچسپ پیری فیرلز استعمال کرنے ہوں گے۔

متن پھر بہت بڑا نکلا، اس لیے سہولت کے لیے میں مواد بنا رہا ہوں:

STM32 بلیو پِل: DM16 ڈرائیور کے ساتھ 634 LEDs
STM8: چھ PWM پن سیٹ کرنا
STM8: تین پنوں پر 8 RGB LEDs، انٹرپٹس

دستبرداری: میں انجینئر نہیں ہوں، میں الیکٹرانکس میں گہرا علم رکھنے کا بہانہ نہیں کرتا، مضمون میرے جیسے شوقیہ افراد کے لیے ہے۔ اصل میں، میں نے دو سال پہلے اپنے آپ کو ہدف کے سامعین کے طور پر سمجھا تھا. اگر کسی نے مجھے بتایا ہوتا کہ نامعلوم چپ پر ڈیٹا شیٹ پڑھنے میں خوفناک نہیں ہوتا، میں انٹرنیٹ پر کوڈ کے کچھ ٹکڑوں کو تلاش کرنے اور قینچی اور چپکنے والی ٹیپ سے بیساکھی ایجاد کرنے میں زیادہ وقت نہ گزارتا۔

اس مضمون کا فوکس ڈیٹا شیٹس پر ہے، پروجیکٹس پر نہیں، اس لیے کوڈ بہت صاف اور اکثر تنگ نہیں ہو سکتا۔ منصوبے خود بہت آسان ہیں، اگرچہ نئی چپ کے ساتھ پہلی واقفیت کے لیے موزوں ہیں۔

مجھے امید ہے کہ میرا مضمون شوق میں ڈوبنے کے اسی مرحلے پر کسی کی مدد کرے گا۔

ایس ٹی ایم 32

DM16 اور SPI کے ساتھ 634 ایل ای ڈی

بلیو پِل (STM32F103C8T6) اور DM634 LED ڈرائیور کا استعمال کرتے ہوئے ایک چھوٹا پروجیکٹ۔ ڈیٹا شیٹس کا استعمال کرتے ہوئے، ہم ڈرائیور، STM IO بندرگاہوں کا پتہ لگائیں گے اور SPI کو ترتیب دیں گے۔

DM634

16 16 بٹ PWM آؤٹ پٹ کے ساتھ تائیوانی چپ، زنجیروں میں منسلک کیا جا سکتا ہے. لو اینڈ 12 بٹ ماڈل گھریلو پروجیکٹ سے جانا جاتا ہے۔ لائٹ پیک. ایک وقت میں، DM63x اور معروف TLC5940 کے درمیان انتخاب کرتے ہوئے، میں نے کئی وجوہات کی بنا پر DM کا انتخاب کیا: 1) Aliexpress پر TLC یقینی طور پر جعلی ہے، لیکن یہ نہیں ہے۔ 2) ڈی ایم کے پاس خود مختار PWM ہے جس کا اپنا فریکوئنسی جنریٹر ہے۔ 3) علی سے پارسل کا انتظار کرنے کے بجائے اسے ماسکو میں سستے میں خریدا جا سکتا ہے۔ اور، یقیناً، یہ جاننا دلچسپ تھا کہ چپ کو کیسے کنٹرول کیا جائے، بجائے اس کے کہ کسی ریڈی میڈ لائبریری کو استعمال کریں۔ چپس اب بنیادی طور پر SSOP24 پیکج میں پیش کی جاتی ہیں؛ وہ ایک اڈاپٹر پر ٹانکا لگانا آسان ہیں۔

چونکہ کارخانہ دار تائیوان ہے، ڈیٹا شیٹ چپ چینی انگریزی میں لکھی ہوئی ہے، جس کا مطلب ہے کہ یہ مزہ آئے گا۔ پہلے ہم پن آؤٹ کو دیکھتے ہیں (پن کنکشنیہ سمجھنے کے لیے کہ کس ٹانگ کو کس سے جوڑنا ہے، اور پنوں کی تفصیل (پن کی تفصیل)۔ 16 پن:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
ڈی سی سنک کے ذرائع (اوپن ڈرین)

سنک / اوپن ڈرین آؤٹ پٹ - نالی؛ بہنے والے کرنٹ کا ذریعہ؛ آؤٹ پٹ فعال حالت میں زمین سے جڑا ہوا ہے - ایل ای ڈی کیتھوڈس کے ذریعے ڈرائیور سے جڑے ہوئے ہیں۔ برقی طور پر، یہ، بلاشبہ، "کھلی نالی" نہیں ہے (کھلی نالی)، لیکن ڈیٹا شیٹس میں ڈرین موڈ میں پنوں کے لیے یہ عہدہ اکثر پایا جاتا ہے۔

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
آؤٹ پٹ کرنٹ ویلیو سیٹ کرنے کے لیے REXT اور GND کے درمیان بیرونی ریزسٹرس

REXT پن اور گراؤنڈ کے درمیان ایک حوالہ ریزسٹر نصب ہے، جو آؤٹ پٹس کی اندرونی مزاحمت کو کنٹرول کرتا ہے، ڈیٹا شیٹ کے صفحہ 9 پر گراف دیکھیں۔ DM634 میں، اس مزاحمت کو سافٹ ویئر کے ذریعے بھی کنٹرول کیا جا سکتا ہے، مجموعی چمک (عالمی چمک); میں اس مضمون میں تفصیلات میں نہیں جاؤں گا، میں یہاں صرف 2.2 - 3 kOhm ریزسٹر رکھوں گا۔

چپ کو کنٹرول کرنے کا طریقہ سمجھنے کے لیے، آئیے ڈیوائس انٹرفیس کی تفصیل دیکھتے ہیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

جی ہاں، یہ ہے، چینی انگریزی اپنی پوری شان کے ساتھ۔ اس کا ترجمہ کرنا مشکل ہے، اگر آپ چاہیں تو اسے سمجھ سکتے ہیں، لیکن ایک اور طریقہ بھی ہے - دیکھیں کہ ڈیٹا شیٹ میں فعال طور پر اسی طرح کے TLC5940 سے کنکشن کو کس طرح بیان کیا گیا ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
... ڈیوائس میں ڈیٹا داخل کرنے کے لیے صرف تین پنوں کی ضرورت ہے۔ SCLK سگنل کا بڑھتا ہوا کنارہ SIN پن سے ڈیٹا کو اندرونی رجسٹر میں منتقل کرتا ہے۔ تمام ڈیٹا لوڈ ہونے کے بعد، ایک مختصر ہائی XLAT سگنل ترتیب وار منتقل کردہ ڈیٹا کو اندرونی رجسٹروں میں لیچ کرتا ہے۔ اندرونی رجسٹر وہ دروازے ہیں جو XLAT سگنل کی سطح سے شروع ہوتے ہیں۔ تمام اعداد و شمار سب سے اہم تھوڑا پہلے منتقل کیے جاتے ہیں۔

بیچ - latch/latch/lock.
بڑھتا ہوا کنارے - نبض کا اہم کنارہ
ایم ایس بی پہلے - سب سے اہم (بائیں طرف) تھوڑا آگے۔
ڈیٹا گھڑی کرنے کے لیے - ڈیٹا کو ترتیب وار منتقل کریں (تھوڑا سا)۔

کلام لنک اکثر چپس کی دستاویزات میں پایا جاتا ہے اور اس کا مختلف طریقوں سے ترجمہ کیا جاتا ہے، لہذا سمجھنے کی خاطر میں خود کو اجازت دوں گا

ایک چھوٹا تعلیمی پروگرامایل ای ڈی ڈرائیور بنیادی طور پر ایک شفٹ رجسٹر ہے۔ "شفٹ" (منتقل) کے نام میں - ڈیوائس کے اندر ڈیٹا کی بٹ وار حرکت: ہر ایک نیا بٹ جو اندر منتقل ہوتا ہے پوری چین کو اس کے سامنے دھکیل دیتا ہے۔ چونکہ کوئی بھی شفٹ کے دوران ایل ای ڈی کے انتشار سے ٹمٹمانے کا مشاہدہ نہیں کرنا چاہتا، اس لیے یہ عمل بفر رجسٹروں میں ہوتا ہے جو ڈیمپر کے ذریعے ورکنگ رجسٹروں سے الگ ہوتے ہیں۔لنک) ایک قسم کا انتظار گاہ ہے جہاں بٹس کو مطلوبہ ترتیب میں ترتیب دیا جاتا ہے۔ جب سب کچھ تیار ہو جاتا ہے، شٹر کھل جاتا ہے اور بٹس کام کرنے لگتے ہیں، پچھلے بیچ کو بدل کر۔ کلام لنک مائیکرو سرکٹس کی دستاویزات میں تقریباً ہمیشہ اس طرح کے ڈیمپر کا مطلب ہوتا ہے، اس سے کوئی فرق نہیں پڑتا ہے کہ اسے کن مجموعوں میں استعمال کیا گیا ہے۔

لہذا، DM634 میں ڈیٹا کی منتقلی اس طرح کی جاتی ہے: DAI ان پٹ کو دور ایل ای ڈی کے سب سے اہم بٹ کی قدر پر سیٹ کریں، DCK کو اوپر اور نیچے کھینچیں۔ DAI ان پٹ کو اگلے بٹ کی قدر پر سیٹ کریں، DCK کھینچیں۔ اور اسی طرح جب تک کہ تمام بٹس منتقل نہ ہو جائیں (میں گھڑی)، جس کے بعد ہم LAT کھینچتے ہیں۔ یہ دستی طور پر کیا جا سکتا ہے (بٹ بینگ)، لیکن اس کے لیے خاص طور پر تیار کردہ SPI انٹرفیس استعمال کرنا بہتر ہے، کیونکہ یہ ہمارے STM32 پر دو کاپیوں میں پیش کیا گیا ہے۔

نیلی گولی STM32F103

تعارفی: STM32 کنٹرولرز Atmega328 سے کہیں زیادہ پیچیدہ ہیں جتنا کہ وہ خوفناک لگ سکتے ہیں۔ مزید برآں، توانائی کی بچت کی وجہ سے، تقریباً تمام پیری فیرلز شروع میں بند کردیئے جاتے ہیں، اور گھڑی کی فریکوئنسی اندرونی ذریعہ سے 8 میگا ہرٹز ہے۔ خوش قسمتی سے، ایس ٹی ایم پروگرامرز نے کوڈ لکھا جو چپ کو "حساب شدہ" 72 میگا ہرٹز تک لاتا ہے، اور میں جانتا ہوں کہ تمام IDEs کے مصنفین نے اسے ابتدا کے طریقہ کار میں شامل کیا، لہذا ہمیں گھڑی کی ضرورت نہیں ہے (لیکن اگر آپ واقعی چاہتے ہیں تو آپ کر سکتے ہیں۔)۔ لیکن آپ کو پیری فیرلز کو آن کرنا پڑے گا۔

دستاویزی: بلیو پِل مقبول STM32F103C8T6 چپ سے لیس ہے، اس کے لیے دو مفید دستاویزات ہیں:

ڈیٹا شیٹ میں ہماری دلچسپی ہو سکتی ہے:

  • پن آؤٹس – چپ پن آؤٹ – اگر ہم خود بورڈ بنانے کا فیصلہ کرتے ہیں۔
  • میموری کا نقشہ - ایک مخصوص چپ کے لیے میموری کا نقشہ۔ حوالہ دستی میں پوری لائن کا نقشہ ہے، اور اس میں ان رجسٹروں کا ذکر ہے جو ہمارے پاس نہیں ہیں۔
  • پن کی تعریفوں کی میز - پنوں کے اہم اور متبادل افعال کی فہرست۔ "نیلی گولی" کے لیے آپ انٹرنیٹ پر پنوں اور ان کے افعال کی فہرست کے ساتھ زیادہ آسان تصاویر تلاش کر سکتے ہیں۔ لہذا، ہم فوری طور پر بلیو پِل پن آؤٹ گوگل کرتے ہیں اور اس تصویر کو ہاتھ میں رکھتے ہیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
نوٹ: انٹرنیٹ سے تصویر میں ایک خرابی تھی، جو کمنٹس میں نوٹ کی گئی تھی، اس کے لیے آپ کا شکریہ۔ تصویر کو تبدیل کر دیا گیا ہے، لیکن یہ ایک سبق ہے - ڈیٹا شیٹ سے نہیں بلکہ معلومات کی جانچ کرنا بہتر ہے۔

ہم ڈیٹا شیٹ کو ہٹاتے ہیں، حوالہ دستی کھولتے ہیں، اور اب سے ہم صرف اسے استعمال کرتے ہیں۔
طریقہ کار: ہم معیاری ان پٹ/آؤٹ پٹ سے نمٹتے ہیں، SPI کو ترتیب دیتے ہیں، ضروری پیری فیرلز کو آن کرتے ہیں۔

ان پٹ آؤٹ پٹ

Atmega328 پر، I/O کو انتہائی سادگی سے لاگو کیا جاتا ہے، یہی وجہ ہے کہ STM32 اختیارات کی کثرت الجھن کا باعث بن سکتی ہے۔ اب ہمیں صرف نتائج کی ضرورت ہے، لیکن یہاں تک کہ ان کے پاس چار اختیارات ہیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
اوپن ڈرین، پش پل، متبادل پش پل، متبادل اوپن ڈرین

"پل پش" (دباو کھینچو) Arduino سے معمول کی پیداوار ہے، پن قدر کو زیادہ یا کم لے سکتا ہے۔ لیکن "کھلی نالی" کے ساتھ موجود ہیں۔ مشکلات، اگرچہ حقیقت میں یہاں سب کچھ آسان ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
آؤٹ پٹ کنفیگریشن / جب پورٹ کو آؤٹ پٹ پر تفویض کیا جاتا ہے: / آؤٹ پٹ بفر فعال: / – اوپن ڈرین موڈ: آؤٹ پٹ رجسٹر میں "0" N-MOS کو فعال کرتا ہے، آؤٹ پٹ رجسٹر میں "1" پورٹ کو Hi-Z موڈ میں چھوڑ دیتا ہے ( P-MOS فعال نہیں ہے ) / – پش پل موڈ: آؤٹ پٹ رجسٹر میں "0" N-MOS کو چالو کرتا ہے، آؤٹ پٹ رجسٹر میں "1" P-MOS کو چالو کرتا ہے۔

کھلے نالے کے درمیان تمام فرق (کھلی نالی) "پش پل" سے (دباو کھینچو(اعلی مائبادا, ہائے زیڈ)۔ صفر لکھتے وقت، پن منطقی اور برقی دونوں طریقوں سے ایک جیسا برتاؤ کرتا ہے۔

عام آؤٹ پٹ موڈ میں، پن آسانی سے آؤٹ پٹ رجسٹر کے مواد کو نشر کرتا ہے۔ "متبادل" میں اس کو متعلقہ پیری فیرلز کے ذریعے کنٹرول کیا جاتا ہے (دیکھیں 9.1.4):

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
اگر پورٹ بٹ کو متبادل فنکشن پن کے طور پر کنفیگر کیا جاتا ہے، تو پن رجسٹر غیر فعال ہو جاتا ہے اور پن کو پیریفرل پن سے منسلک کر دیا جاتا ہے۔

ہر پن کی متبادل فعالیت میں بیان کیا گیا ہے۔ پن کی تعریفیں ڈیٹا شیٹ ڈاؤن لوڈ کی گئی تصویر پر ہے۔ اس سوال پر کہ اگر پن میں کئی متبادل افعال ہوں تو کیا کرنا ہے، اس کا جواب ڈیٹا شیٹ میں ایک فوٹ نوٹ کے ذریعے دیا گیا ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
اگر ایک سے زیادہ پیری فیرلز ایک ہی پن کا استعمال کرتے ہیں، متبادل افعال کے درمیان تصادم سے بچنے کے لیے، ایک وقت میں صرف ایک پیری فیرل استعمال کیا جانا چاہیے، پیری فیرل کلاک ایبل بٹ (مناسب RCC رجسٹر میں) کا استعمال کرتے ہوئے ٹوگل کیا جائے۔

آخر میں، آؤٹ پٹ موڈ میں پنوں میں بھی گھڑی کی رفتار ہوتی ہے۔ یہ توانائی کی بچت کی ایک اور خصوصیت ہے؛ ہمارے معاملے میں، ہم اسے زیادہ سے زیادہ پر سیٹ کرتے ہیں اور بھول جاتے ہیں۔

لہذا: ہم SPI استعمال کر رہے ہیں، جس کا مطلب ہے کہ دو پن (ڈیٹا اور گھڑی کے سگنل کے ساتھ) "متبادل پش پل فنکشن" ہونے چاہئیں، اور دوسرا (LAT) "باقاعدہ پش پل" ہونا چاہیے۔ لیکن ان کو تفویض کرنے سے پہلے، آئیے SPI سے نمٹ لیں۔

ایس پی آئی

ایک اور چھوٹا تعلیمی پروگرام

SPI یا سیریل پیریفرل انٹرفیس (سیریل پیریفرل انٹرفیس) ایک MK کو دوسرے MKs اور عام طور پر بیرونی دنیا سے جوڑنے کے لیے ایک سادہ اور بہت موثر انٹرفیس ہے۔ اس کے آپریشن کا اصول پہلے ہی اوپر بیان کیا جا چکا ہے، جہاں چینی ایل ای ڈی ڈرائیور کے بارے میں (حوالہ دستی میں، سیکشن 25 دیکھیں)۔ SPI ماسٹر ("ماسٹر") اور غلام ("غلام") موڈ میں کام کر سکتا ہے۔ SPI کے چار بنیادی چینلز ہیں، جن میں سے سبھی استعمال نہیں کیے جا سکتے:

  • MOSI، ماسٹر آؤٹ پٹ / غلام ان پٹ: یہ پن ماسٹر موڈ میں ڈیٹا منتقل کرتا ہے، اور غلام موڈ میں ڈیٹا وصول کرتا ہے۔
  • MISO، ماسٹر ان پٹ / غلام آؤٹ پٹ: اس کے برعکس، یہ ماسٹر میں حاصل کرتا ہے، اور غلام میں منتقل ہوتا ہے؛
  • SCK، سیریل کلاک: ماسٹر میں ڈیٹا ٹرانسمیشن کی فریکوئنسی سیٹ کرتا ہے یا غلام میں گھڑی کا سگنل وصول کرتا ہے۔ بنیادی طور پر دھڑکنوں کو مارنا؛
  • ایس ایس، غلام سلیکٹ: اس چینل کی مدد سے، غلام جانتا ہے کہ اس سے کچھ مطلوب ہے۔ STM32 پر اسے NSS کہا جاتا ہے، جہاں N = منفی، یعنی اگر اس چینل میں گراؤنڈ ہو تو کنٹرولر غلام بن جاتا ہے۔ یہ اوپن ڈرین آؤٹ پٹ موڈ کے ساتھ اچھی طرح سے جوڑتا ہے، لیکن یہ ایک اور کہانی ہے۔

ہر چیز کی طرح، STM32 پر SPI فعالیت سے بھرپور ہے، جس کی وجہ سے اسے سمجھنا کچھ مشکل ہو جاتا ہے۔ مثال کے طور پر، یہ نہ صرف SPI کے ساتھ، بلکہ ایک I2S انٹرفیس کے ساتھ بھی کام کر سکتا ہے، اور دستاویزات میں ان کی تفصیل کو ملایا گیا ہے، یہ ضروری ہے کہ بروقت ضرورت سے زیادہ کو کاٹ دیا جائے۔ ہمارا کام بہت آسان ہے: ہمیں صرف MOSI اور SCK کا استعمال کرتے ہوئے ڈیٹا بھیجنے کی ضرورت ہے۔ ہم سیکشن 25.3.4 (ہاف ڈوپلیکس کمیونیکیشن، ہاف ڈوپلیکس کمیونیکیشن) پر جاتے ہیں، جہاں ہمیں ملتا ہے۔ 1 گھڑی اور 1 یک طرفہ ڈیٹا وائر (1 گھڑی کا سگنل اور 1 یک طرفہ ڈیٹا سٹریم):

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
اس موڈ میں، ایپلیکیشن صرف ٹرانسمٹ یا صرف وصول کرنے کے موڈ میں SPI کا استعمال کرتی ہے۔ / صرف ٹرانسمٹ موڈ ڈوپلیکس موڈ کی طرح ہے: ڈیٹا ٹرانسمٹ پن پر منتقل کیا جاتا ہے (ماسٹر موڈ میں MOSI یا غلام موڈ میں MISO)، اور ریسیو پن (بالترتیب MISO یا MOSI) کو باقاعدہ I/O پن کے طور پر استعمال کیا جا سکتا ہے۔ . اس صورت میں، ایپلیکیشن کو صرف Rx بفر کو نظر انداز کرنے کی ضرورت ہے (اگر اسے پڑھا جائے تو وہاں کوئی منتقل شدہ ڈیٹا نہیں ہوگا)۔

بہت اچھا، MISO پن مفت ہے، آئیے LAT سگنل کو اس سے جوڑتے ہیں۔ آئیے Slave Select کو دیکھتے ہیں، جسے STM32 پر پروگرام کے لحاظ سے کنٹرول کیا جا سکتا ہے، جو کہ انتہائی آسان ہے۔ ہم اسی نام کے پیراگراف کو سیکشن 25.3.1 میں پڑھتے ہیں SPI جنرل وضاحت:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
سافٹ ویئر کنٹرول NSS (SSM = 1) / غلاموں کے انتخاب کی معلومات SPI_CR1 رجسٹر کے SSI بٹ میں موجود ہے۔ بیرونی NSS پن دیگر درخواست کی ضروریات کے لیے مفت رہتا ہے۔

رجسٹروں پر لکھنے کا وقت آگیا ہے۔ میں نے SPI2 استعمال کرنے کا فیصلہ کیا، ڈیٹا شیٹ میں اس کا بنیادی پتہ تلاش کریں - سیکشن 3.3 میموری میپ میں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

ٹھیک ہے، چلو شروع کرتے ہیں:

#define _SPI2_(mem_offset) (*(volatile uint32_t *)(0x40003800 + (mem_offset)))

سیکشن 25.3.3 کو خود وضاحتی عنوان "ماسٹر موڈ میں SPI کی تشکیل" کے ساتھ کھولیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

1. SPI_CR2 رجسٹر میں سیریل کلاک فریکوئنسی کو بٹس BR[0:1] کے ساتھ سیٹ کریں۔

رجسٹر اسی نام کے حوالہ دستی سیکشن میں جمع کیے جاتے ہیں۔ ایڈریس شفٹ (ایڈریس آفسیٹ) CR1 - 0x00 کے لیے، بطور ڈیفالٹ تمام بٹس صاف ہو جاتے ہیں (قدر کو دوبارہ ترتیب دیں۔ 0x0000):

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

بی آر بٹس کنٹرولر کلاک ڈیوائیڈر کو سیٹ کرتے ہیں، اس طرح اس تعدد کا تعین کرتے ہیں جس پر SPI کام کرے گا۔ ہماری STM32 فریکوئنسی 72 میگا ہرٹز ہوگی، ایل ای ڈی ڈرائیور، اس کی ڈیٹا شیٹ کے مطابق، 25 میگا ہرٹز تک کی فریکوئنسی کے ساتھ کام کرتا ہے، اس لیے ہمیں چار (BR[2:0] = 001) سے تقسیم کرنے کی ضرورت ہے۔

#define _SPI_CR1 0x00

#define BR_0        0x0008
#define BR_1        0x0010
#define BR_2        0x0020

_SPI2_ (_SPI_CR1) |= BR_0;// pclk/4

2. ڈیٹا کی منتقلی اور سیریل کلاک ٹائمنگ کے درمیان تعلق کی وضاحت کرنے کے لیے CPOL اور CPHA بٹس سیٹ کریں (صفحہ 240 پر خاکہ دیکھیں)

چونکہ ہم یہاں ڈیٹا شیٹ پڑھ رہے ہیں اور اسکیمیٹکس کو نہیں دیکھ رہے ہیں، آئیے صفحہ 704 (SPI جنرل تفصیل) پر CPOL اور CPHA بٹس کے متن کی تفصیل کو قریب سے دیکھیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
گھڑی کا مرحلہ اور قطبیت
SPI_CR1 رجسٹر کے CPOL اور CPHA بٹس کا استعمال کرتے ہوئے، آپ پروگرام کے لحاظ سے چار ٹائمنگ تعلقات منتخب کر سکتے ہیں۔ CPOL (کلاک پولرٹی) بٹ کلاک سگنل کی حالت کو کنٹرول کرتا ہے جب کوئی ڈیٹا منتقل نہیں ہوتا ہے۔ یہ بٹ ماسٹر اور غلام کے طریقوں کو کنٹرول کرتا ہے۔ اگر CPOL دوبارہ ترتیب دیا جاتا ہے، تو SCK پن باقی موڈ میں کم ہے۔ اگر CPOL بٹ سیٹ ہے تو، ریسٹ موڈ کے دوران SCK پن زیادہ ہے۔
جب CPHA (کلاک فیز) بٹ سیٹ ہوتا ہے، ہائی بٹ ٹریپ اسٹروب SCK سگنل کا دوسرا کنارہ ہوتا ہے (اگر CPOL واضح ہو تو گرتا ہے، اگر CPOL سیٹ ہو تو بڑھتا ہے)۔ ڈیٹا کو گھڑی کے سگنل میں دوسری تبدیلی کے ذریعے حاصل کیا جاتا ہے۔ اگر CPHA بٹ صاف ہے، تو ہائی بٹ ٹریپ اسٹروب SCK سگنل کا بڑھتا ہوا کنارہ ہے (اگر CPOL سیٹ ہو تو گرتا ہوا کنارہ، اگر CPOL صاف ہو جائے تو بڑھتا ہوا کنارے)۔ گھڑی کے سگنل میں پہلی تبدیلی پر ڈیٹا پکڑا جاتا ہے۔

اس علم کو جذب کرنے کے بعد، ہم اس نتیجے پر پہنچے ہیں کہ دونوں بٹس کو صفر ہی رہنا چاہیے، کیونکہ ہم چاہتے ہیں کہ جب استعمال میں نہ ہو تو SCK سگنل کم رہے، اور ڈیٹا کو نبض کے بڑھتے ہوئے کنارے پر منتقل کیا جائے (تصویر XNUMX دیکھیں)۔ رائزنگ ایج DM634 ڈیٹا شیٹ میں)۔

ویسے، یہاں ہمیں پہلی بار ST ڈیٹا شیٹس میں الفاظ کی ایک خصوصیت کا سامنا کرنا پڑا: ان میں جملہ "بٹ کو صفر پر دوبارہ ترتیب دیں" لکھا ہوا ہے۔ تھوڑا سا ری سیٹ کرنے کے لئےاور نہیں تھوڑا سا صاف کرنے کے لئے، جیسے، مثال کے طور پر، Atmega۔

3. ڈی ایف ایف بٹ کو سیٹ کریں کہ آیا ڈیٹا بلاک 8 بٹ فارمیٹ ہے یا 16 بٹ

میں نے خاص طور پر 16 بٹ DM634 لیا تاکہ DM12 کی طرح 633 بٹ PWM ڈیٹا منتقل کرنے میں پریشانی نہ ہو۔ DFF کو ایک پر سیٹ کرنا سمجھ میں آتا ہے:

#define DFF         0x0800

_SPI2_ (_SPI_CR1) |= DFF; // 16-bit mode

4. بلاک فارمیٹ کا تعین کرنے کے لیے SPI_CR1 رجسٹر میں LSBFIRST بٹ کو ترتیب دیں۔

LSBFIRST، جیسا کہ اس کے نام سے پتہ چلتا ہے، پہلے کم سے کم اہم بٹ کے ساتھ ٹرانسمیشن کو ترتیب دیتا ہے۔ لیکن DM634 سب سے اہم بٹ سے شروع ہونے والا ڈیٹا وصول کرنا چاہتا ہے۔ لہذا، ہم اسے دوبارہ ترتیب دیتے ہیں.

5. ہارڈویئر موڈ میں، اگر NSS پن سے ان پٹ کی ضرورت ہو تو، پورے بائٹ ٹرانسفر کی ترتیب کے دوران NSS پن پر ہائی سگنل لگائیں۔ NSS سافٹ ویئر موڈ میں، SPI_CR1 رجسٹر میں SSM اور SSI بٹس سیٹ کریں۔ اگر NSS پن کو آؤٹ پٹ کے طور پر استعمال کرنا ہے تو صرف SSOE بٹ کو سیٹ کرنے کی ضرورت ہے۔

NSS ہارڈویئر موڈ کو بھولنے کے لیے SSM اور SSI انسٹال کریں:

#define SSI         0x0100
#define SSM         0x0200

_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high

6. MSTR اور SPE بٹس کا سیٹ ہونا ضروری ہے (وہ صرف اس صورت میں سیٹ رہتے ہیں جب NSS سگنل زیادہ ہو)

دراصل، ان بٹس کے ساتھ ہم اپنے SPI کو بطور ماسٹر نامزد کرتے ہیں اور اسے آن کرتے ہیں:

#define MSTR        0x0004
#define SPE         0x0040

_SPI2_ (_SPI_CR1) |= MSTR; //SPI master
//когда все готово, включаем SPI
_SPI2_ (_SPI_CR1) |= SPE;

ایس پی آئی کو ترتیب دیا گیا ہے، آئیے فوری طور پر ایسے فنکشن لکھتے ہیں جو ڈرائیور کو بائٹس بھیجتے ہیں۔ 25.3.3 پڑھنا جاری رکھیں "ماسٹر موڈ میں SPI کو ترتیب دینا":

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
ڈیٹا ٹرانسفر آرڈر
ٹرانسمیشن تب شروع ہوتی ہے جب Tx بفر پر بائٹ لکھا جاتا ہے۔
ڈیٹا بائٹ کو شفٹ رجسٹر میں لوڈ کیا جاتا ہے۔ متوازی موڈ (اندرونی بس سے) پہلے بٹ کی ترسیل کے دوران، جس کے بعد اسے منتقل کیا جاتا ہے۔ ترتیب وار MOSI پن موڈ، CPI_CR1 رجسٹر میں LSBFIRST بٹ کی ترتیب کے لحاظ سے پہلا یا آخری بٹ فارورڈ۔ TXE جھنڈا ڈیٹا ٹرانسمیشن کے بعد سیٹ کیا جاتا ہے۔ Tx بفر سے شفٹ رجسٹر تک، اور اگر CPI_CR1 رجسٹر میں TXEIE بٹ سیٹ ہو تو ایک رکاوٹ بھی پیدا کرتا ہے۔

میں نے STM کنٹرولرز میں SPI کے نفاذ کی ایک خصوصیت کی طرف توجہ مبذول کرنے کے لیے ترجمے میں چند الفاظ پر روشنی ڈالی۔ Atmega پر TXE پرچم (Tx خالی، Tx خالی ہے اور ڈیٹا وصول کرنے کے لیے تیار ہے) پورے بائٹ بھیجے جانے کے بعد ہی سیٹ کیا جاتا ہے۔ باہر. اور یہاں یہ جھنڈا اندرونی شفٹ رجسٹر میں بائٹ ڈالنے کے بعد سیٹ کیا جاتا ہے۔ چونکہ اسے تمام بٹس کے ساتھ ایک ہی وقت میں (متوازی طور پر) دھکیل دیا جاتا ہے، اور پھر ڈیٹا کو ترتیب وار منتقل کیا جاتا ہے، اس لیے بائٹ مکمل طور پر بھیجے جانے سے پہلے TXE سیٹ کیا جاتا ہے۔ یہ اہم ہے کیونکہ ہمارے ایل ای ڈی ڈرائیور کے معاملے میں، ہمیں بھیجنے کے بعد LAT پن کو کھینچنا ہوگا۔ تمام ڈیٹا، یعنی صرف TXE جھنڈا ہمارے لیے کافی نہیں ہوگا۔

اس کا مطلب ہے کہ ہمیں ایک اور پرچم کی ضرورت ہے۔ آئیے 25.3.7 کو دیکھتے ہیں - "اسٹیٹس فلیگ":

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
<…>
ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
مصروف جھنڈا۔
BSY پرچم کو ہارڈ ویئر کے ذریعہ سیٹ اور صاف کیا جاتا ہے (اس پر لکھنے کا کوئی اثر نہیں ہوتا ہے)۔ BSY جھنڈا SPI کمیونیکیشن پرت کی حالت کی نشاندہی کرتا ہے۔
یہ دوبارہ ترتیب دیتا ہے:
جب ٹرانسفر مکمل ہو جائے (ماسٹر موڈ کے علاوہ اگر ٹرانسفر مسلسل ہو)
جب SPI غیر فعال ہے۔
جب ماسٹر موڈ کی خرابی واقع ہوتی ہے (MODF=1)
اگر منتقلی مسلسل نہیں ہے، تو ہر ڈیٹا کی منتقلی کے درمیان BSY پرچم صاف ہو جاتا ہے۔

ٹھیک ہے، یہ کام آئے گا۔ آئیے معلوم کریں کہ Tx بفر کہاں واقع ہے۔ ایسا کرنے کے لیے، "SPI ڈیٹا رجسٹر" پڑھیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
بٹس 15:0 DR[15:0] ڈیٹا رجسٹر
موصول ہونے والا ڈیٹا یا ڈیٹا منتقل کیا جانا ہے۔
ڈیٹا رجسٹر کو دو بفرز میں تقسیم کیا گیا ہے - ایک لکھنے کے لیے (ٹرانسمٹ بفر) اور ایک پڑھنے کے لیے (بفر وصول کرنا)۔ ڈیٹا رجسٹر پر لکھنا Tx بفر کو لکھتا ہے، اور ڈیٹا رجسٹر سے پڑھنے سے Rx بفر میں موجود قدر واپس آجائے گی۔

ٹھیک ہے، اور اسٹیٹس رجسٹر، جہاں TXE اور BSY کے جھنڈے پائے جاتے ہیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

ہم لکھتے ہیں:

#define _SPI_DR  0x0C
#define _SPI_SR  0x08

#define BSY         0x0080
#define TXE         0x0002

void dm_shift16(uint16_t value)
{
    _SPI2_(_SPI_DR) = value; //send 2 bytes
    while (!(_SPI2_(_SPI_SR) & TXE)); //wait until they're sent
}

ٹھیک ہے، چونکہ ہمیں ایل ای ڈی ڈرائیور آؤٹ پٹ کی تعداد کے مطابق 16 بار دو بائٹس منتقل کرنے کی ضرورت ہے، کچھ اس طرح:

void sendLEDdata()
{
    LAT_low();
    uint8_t k = 16;
    do
    {   k--;
        dm_shift16(leds[k]);
    } while (k);

    while (_SPI2_(_SPI_SR) & BSY); // finish transmission

    LAT_pulse();
}

لیکن ہم ابھی تک یہ نہیں جانتے کہ LAT پن کو کیسے کھینچنا ہے، لہذا ہم I/O پر واپس جائیں گے۔

پنوں کو تفویض کرنا

STM32F1 میں، پنوں کی حالت کے لیے ذمہ دار رجسٹر کافی غیر معمولی ہیں۔ یہ واضح ہے کہ Atmega سے زیادہ ان میں سے ہیں، لیکن وہ دیگر STM چپس سے بھی مختلف ہیں۔ سیکشن 9.1 GPIO کی عمومی تفصیل:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
عمومی مقصد I/O بندرگاہوں میں سے ہر ایک (GPIO) دو 32 بٹ کنفیگریشن رجسٹر (GPIOx_CRL اور GPIOx_CRH)، دو 32 بٹ ڈیٹا رجسٹر (GPIOx_IDR اور GPIOx_ODR)، ایک 32 بٹ سیٹ/ری سیٹ رجسٹر (GPIOx_BSRR)، ایک 16 بٹ ری سیٹ رجسٹر (GPIOx_32BR) بٹ بلاکنگ رجسٹر (GPIOx_LCKR)۔

پہلے دو رجسٹر غیر معمولی ہیں، اور کافی تکلیف دہ بھی ہیں، کیونکہ 16 پورٹ پن ان پر "چار بٹس فی برادر" فارمیٹ میں بکھرے ہوئے ہیں۔ وہ. صفر سے سات پن CRL میں ہیں، اور باقی CRH میں ہیں۔ ایک ہی وقت میں، بقیہ رجسٹروں میں کامیابی کے ساتھ پورٹ کے تمام پنوں کے بٹس ہوتے ہیں - اکثر آدھے "محفوظ" رہ جاتے ہیں۔

سادگی کے لیے، آئیے فہرست کے آخر سے شروع کرتے ہیں۔

ہمیں بلاکنگ رجسٹر کی ضرورت نہیں ہے۔

سیٹ اور ری سیٹ رجسٹر اس لحاظ سے کافی مضحکہ خیز ہیں کہ وہ جزوی طور پر ایک دوسرے کو نقل کرتے ہیں: آپ سب کچھ صرف BSRR میں لکھ سکتے ہیں، جہاں اعلیٰ 16 بٹس پن کو صفر پر ری سیٹ کر دیں گے، اور نیچے والے کو 1 پر سیٹ کر دیا جائے گا، یا آپ یہ بھی کر سکتے ہیں۔ BRR استعمال کریں، نچلے 16 بٹس جن میں سے صرف پن کو دوبارہ ترتیب دیا جاتا ہے۔ مجھے دوسرا آپشن پسند ہے۔ یہ رجسٹر اہم ہیں کیونکہ یہ پنوں تک جوہری رسائی فراہم کرتے ہیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
ایٹم سیٹ یا ری سیٹ
بٹ لیول پر GPIOx_ODR پروگرام کرتے وقت مداخلت کو غیر فعال کرنے کی ضرورت نہیں ہے: ایک یا زیادہ بٹس کو ایک ایٹم رائٹ آپریشن APB2 کے ساتھ تبدیل کیا جا سکتا ہے۔ یہ سیٹ/ری سیٹ رجسٹر (GPIOx_BSRR یا، صرف ری سیٹ کے لیے، GPIOx_BRR) پر "1" لکھ کر حاصل کیا جاتا ہے جسے تبدیل کرنے کی ضرورت ہے۔ دیگر بٹس غیر تبدیل شدہ رہیں گے.

ڈیٹا رجسٹروں میں کافی خود وضاحتی نام ہوتے ہیں - IDR = ان پٹ ڈائریکشن رجسٹر، ان پٹ رجسٹر؛ ODR = آؤٹ پٹ ڈائریکشن رجسٹر، آؤٹ پٹ رجسٹر۔ ہمیں موجودہ پروجیکٹ میں ان کی ضرورت نہیں ہوگی۔

اور آخر میں، کنٹرول رجسٹر. چونکہ ہم دوسرے SPI پنوں میں دلچسپی رکھتے ہیں، یعنی PB13، PB14 اور PB15، ہم فوراً CRH کو دیکھتے ہیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

اور ہم دیکھتے ہیں کہ ہمیں 20 سے 31 تک بٹس میں کچھ لکھنے کی ضرورت ہوگی۔

ہم نے پہلے ہی اوپر پتہ لگایا ہے کہ ہم پنوں سے کیا چاہتے ہیں، لہذا یہاں میں اسکرین شاٹ کے بغیر کروں گا، میں صرف اتنا کہوں گا کہ MODE سمت کا تعین کرتا ہے (ان پٹ اگر دونوں بٹس 0 پر سیٹ ہیں) اور پن کی رفتار (ہمیں 50MHz کی ضرورت ہے، یعنی۔ دونوں پن "1" پر، اور CNF موڈ سیٹ کرتا ہے: باقاعدہ "دھکا پل" - 00، "متبادل" - 10۔ پہلے سے طے شدہ طور پر، جیسا کہ ہم اوپر دیکھتے ہیں، تمام پنوں میں نیچے سے تیسرا بٹ ہوتا ہے (CNF0)، یہ انہیں موڈ پر سیٹ کرتا ہے۔ تیرتی ان پٹ.

چونکہ میں اس چپ کے ساتھ کچھ اور کرنے کا ارادہ رکھتا ہوں، اس لیے سادگی کے لیے میں نے نچلے اور اوپری کنٹرول دونوں رجسٹروں کے لیے تمام ممکنہ MODE اور CNF اقدار کی وضاحت کی ہے۔

کسی نہ کسی طرح

#define CNF0_0 0x00000004
#define CNF0_1 0x00000008
#define CNF1_0 0x00000040
#define CNF1_1 0x00000080
#define CNF2_0 0x00000400
#define CNF2_1 0x00000800
#define CNF3_0 0x00004000
#define CNF3_1 0x00008000
#define CNF4_0 0x00040000
#define CNF4_1 0x00080000
#define CNF5_0 0x00400000
#define CNF5_1 0x00800000
#define CNF6_0 0x04000000
#define CNF6_1 0x08000000
#define CNF7_0 0x40000000
#define CNF7_1 0x80000000
#define CNF8_0 0x00000004
#define CNF8_1 0x00000008
#define CNF9_0 0x00000040
#define CNF9_1 0x00000080
#define CNF10_0 0x00000400
#define CNF10_1 0x00000800
#define CNF11_0 0x00004000
#define CNF11_1 0x00008000
#define CNF12_0 0x00040000
#define CNF12_1 0x00080000
#define CNF13_0 0x00400000
#define CNF13_1 0x00800000
#define CNF14_0 0x04000000
#define CNF14_1 0x08000000
#define CNF15_0 0x40000000
#define CNF15_1 0x80000000

#define MODE0_0 0x00000001
#define MODE0_1 0x00000002
#define MODE1_0 0x00000010
#define MODE1_1 0x00000020
#define MODE2_0 0x00000100
#define MODE2_1 0x00000200
#define MODE3_0 0x00001000
#define MODE3_1 0x00002000
#define MODE4_0 0x00010000
#define MODE4_1 0x00020000
#define MODE5_0 0x00100000
#define MODE5_1 0x00200000
#define MODE6_0 0x01000000
#define MODE6_1 0x02000000
#define MODE7_0 0x10000000
#define MODE7_1 0x20000000
#define MODE8_0 0x00000001
#define MODE8_1 0x00000002
#define MODE9_0 0x00000010
#define MODE9_1 0x00000020
#define MODE10_0 0x00000100
#define MODE10_1 0x00000200
#define MODE11_0 0x00001000
#define MODE11_1 0x00002000
#define MODE12_0 0x00010000
#define MODE12_1 0x00020000
#define MODE13_0 0x00100000
#define MODE13_1 0x00200000
#define MODE14_0 0x01000000
#define MODE14_1 0x02000000
#define MODE15_0 0x10000000
#define MODE15_1 0x20000000

ہمارے پن پورٹ B (بیس ایڈریس - 0x40010C00) پر واقع ہیں، کوڈ:

#define _PORTB_(mem_offset) (*(volatile uint32_t *)(0x40010C00 + (mem_offset)))

#define _BRR  0x14
#define _BSRR 0x10
#define _CRL  0x00
#define _CRH  0x04

//используем стандартный SPI2: MOSI на B15, CLK на B13
//LAT пусть будет на неиспользуемом MISO – B14

//очищаем дефолтный бит, он нам точно не нужен
_PORTB_ (_CRH) &= ~(CNF15_0 | CNF14_0 | CNF13_0 | CNF12_0);

//альтернативные функции для MOSI и SCK
_PORTB_ (_CRH) |= CNF15_1 | CNF13_1;

//50 МГц, MODE = 11
_PORTB_ (_CRH) |= MODE15_1 | MODE15_0 | MODE14_1 | MODE14_0 | MODE13_1 | MODE13_0;

اور، اس کے مطابق، آپ LAT کے لیے تعریفیں لکھ سکتے ہیں، جو BRR اور BSRR رجسٹروں کے ذریعے مروڑا جائے گا:

/*** LAT pulse – high, then low */
#define LAT_pulse() _PORTB_(_BSRR) = (1<<14); _PORTB_(_BRR) = (1<<14)

#define LAT_low() _PORTB_(_BRR) = (1<<14)

(LAT_low صرف جڑت سے، یہ ہمیشہ ایسا ہی ہوتا ہے، رہنے دو)

اب سب کچھ بہت اچھا ہے، لیکن یہ کام نہیں کرتا. چونکہ یہ STM32 ہے، یہ بجلی بچاتے ہیں، جس کا مطلب ہے کہ آپ کو مطلوبہ پیری فیرلز کی کلاکنگ کو فعال کرنے کی ضرورت ہے۔

کلاکنگ آن کریں۔

گھڑی، جسے گھڑی بھی کہا جاتا ہے، گھڑی کے لیے ذمہ دار ہے۔ اور ہم پہلے ہی مخفف RCC کو دیکھ سکتے ہیں۔ ہم اسے دستاویزات میں تلاش کرتے ہیں: یہ ری سیٹ اور کلاک کنٹرول ہے۔

جیسا کہ اوپر کہا جا چکا ہے، خوش قسمتی سے کلاکنگ کے موضوع کا سب سے مشکل حصہ ہمارے لیے STM کے لوگوں نے کیا، جس کے لیے ہم ان کا بہت شکریہ ادا کرتے ہیں (ایک بار پھر میں اس کا لنک دوں گا۔ ڈی ہالٹ کی ویب سائٹ، یہ واضح کرنے کے لئے کہ یہ کتنا الجھا ہوا ہے)۔ ہمیں صرف پیریفرل کلاکنگ کو فعال کرنے کے لیے ذمہ دار رجسٹروں کی ضرورت ہے (پیری فیرل کلاک ان ایبل رجسٹرز)۔ سب سے پہلے، آر سی سی کا بنیادی پتہ تلاش کرتے ہیں، یہ "میموری میپ" کے بالکل شروع میں ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

#define _RCC_(mem_offset) (*(volatile uint32_t *)(0x40021000 + (mem_offset)))

اور پھر یا تو اس لنک پر کلک کریں جہاں آپ پلیٹ میں کچھ تلاش کرنے کی کوشش کرتے ہیں، یا، بہت بہتر، ان سیکشنز سے فعال کرنے والے رجسٹروں کی تفصیل کو دیکھیں۔ رجسٹروں کو فعال کریں. جہاں ہمیں RCC_APB1ENR اور RCC_APB2ENR ملے گا:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

اور اس کے مطابق، وہ بٹس پر مشتمل ہوتے ہیں جن میں SPI2، IOPB (I/O پورٹ B) اور متبادل افعال (AFIO) کی کلاکنگ شامل ہوتی ہے۔

#define _APB2ENR 0x18
#define _APB1ENR 0x1C

#define IOPBEN 0x0008
#define SPI2EN 0x4000
#define AFIOEN 0x0001

//включаем тактирование порта B и альт. функций
_RCC_(_APB2ENR) |= IOPBEN | AFIOEN;

//включаем  тактирование SPI2
_RCC_(_APB1ENR) |= SPI2EN;

حتمی کوڈ پایا جا سکتا ہے۔ یہاں.

اگر آپ کو ٹیسٹ کرنے کا موقع اور خواہش ہے تو DM634 کو اس طرح جوڑیں: DAI سے PB15، DCK سے PB13، LAT سے PB14۔ ہم ڈرائیور کو 5 وولٹ سے پاور دیتے ہیں، گراؤنڈز کو جوڑنا نہ بھولیں۔

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

STM8 PWM

STM8 پر PWM

جب میں صرف اس مضمون کی منصوبہ بندی کر رہا تھا، میں نے مثال کے طور پر فیصلہ کیا کہ صرف ایک ڈیٹا شیٹ کا استعمال کرتے ہوئے کسی ناواقف چپ کی کچھ فعالیت میں مہارت حاصل کرنے کی کوشش کروں، تاکہ میں بغیر جوتے کے جوتا بنانے والا نہ بنوں۔ STM8 اس کردار کے لیے مثالی تھا: سب سے پہلے، میرے پاس STM8S103 کے ساتھ چند چینی بورڈز تھے، اور دوسری بات، یہ زیادہ مقبول نہیں ہے، اور اس لیے انٹرنیٹ پر پڑھنے اور حل تلاش کرنے کا لالچ انہی حلوں کی کمی پر منحصر ہے۔

چپ بھی ہے۔ ڈیٹا شیٹ и حوالہ دستی RM0016، پہلے میں پن آؤٹ اور رجسٹر ایڈریس ہے، دوسرے میں - باقی سب کچھ۔ STM8 کو ایک خوفناک IDE میں C میں پروگرام کیا گیا ہے۔ ST بصری ترقی.

کلاکنگ اور I/O

پہلے سے طے شدہ طور پر، STM8 2 MHz کی فریکوئنسی پر کام کرتا ہے، اسے فوری طور پر درست کیا جانا چاہیے۔

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
HSI (تیز رفتار اندرونی) گھڑی
HSI کلاک سگنل ایک اندرونی 16 MHz RC آسیلیٹر سے حاصل کیا گیا ہے جس میں قابل پروگرام ڈیوائیڈر (1 سے 8) ہے۔ اسے کلاک ڈیوائیڈر رجسٹر (CLK_CKDIVR) میں سیٹ کیا گیا ہے۔
نوٹ: شروع میں، 8 کے ڈیوائیڈر کے ساتھ ایک HSI RC آسکیلیٹر کو کلاک سگنل کے اہم ذریعہ کے طور پر منتخب کیا جاتا ہے۔

ہمیں ڈیٹا شیٹ میں رجسٹر کا پتہ، ریف مین میں تفصیل ملتی ہے اور دیکھتے ہیں کہ رجسٹر کو صاف کرنے کی ضرورت ہے:

#define CLK_CKDIVR *(volatile uint8_t *)0x0050C6

CLK_CKDIVR &= ~(0x18);

چونکہ ہم PWM چلانے اور LEDs کو جوڑنے جا رہے ہیں، آئیے پن آؤٹ کو دیکھیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

چپ چھوٹی ہے، ایک ہی پن پر کئی فنکشنز معطل ہیں۔ مربع بریکٹ میں جو ہے وہ "متبادل فعالیت" ہے، اسے "آپشن بائٹس" کے ذریعے تبدیل کیا جاتا ہے (آپشن بائٹس) – Atmega فیوز جیسی کوئی چیز۔ آپ ان کی اقدار کو پروگرام کے لحاظ سے تبدیل کر سکتے ہیں، لیکن یہ ضروری نہیں ہے، کیونکہ نئی فعالیت صرف ریبوٹ کے بعد چالو ہوتی ہے۔ ایس ٹی ویژول پروگرامر (بصری ڈیولپ کے ساتھ ڈاؤن لوڈ) استعمال کرنا آسان ہے، جو ان بائٹس کو تبدیل کر سکتا ہے۔ پن آؤٹ سے پتہ چلتا ہے کہ پہلے ٹائمر کے CH1 اور CH2 پن مربع بریکٹ میں چھپے ہوئے ہیں۔ STVP میں AFR1 اور AFR0 بٹس کو سیٹ کرنا ضروری ہے، اور دوسرا بھی دوسرے ٹائمر کے CH1 آؤٹ پٹ کو PD4 سے PC5 میں منتقل کر دے گا۔

اس طرح، 6 پن ایل ای ڈی کو کنٹرول کریں گے: پہلے ٹائمر کے لیے PC6، PC7 اور PC3، دوسرے کے لیے PC5، PD3 اور PA3۔

STM8 پر خود I/O پنوں کو ترتیب دینا STM32 کے مقابلے میں آسان اور زیادہ منطقی ہے:

  • Atmega DDR ڈیٹا ڈائریکشن رجسٹر سے واقف (ڈیٹا ڈائریکشن رجسٹر): 1 = آؤٹ پٹ؛
  • پہلا کنٹرول رجسٹر CR1، جب آؤٹ پٹ، پش پل موڈ (1) یا اوپن ڈرین (0) سیٹ کرتا ہے۔ چونکہ میں ایل ای ڈی کو چپ سے کیتھوڈس سے جوڑتا ہوں، میں یہاں صفر چھوڑتا ہوں۔
  • دوسرا کنٹرول رجسٹر CR2، جب آؤٹ پٹ، گھڑی کی رفتار سیٹ کرتا ہے: 1 = 10 MHz

#define PA_DDR     *(volatile uint8_t *)0x005002
#define PA_CR2     *(volatile uint8_t *)0x005004
#define PD_DDR     *(volatile uint8_t *)0x005011
#define PD_CR2     *(volatile uint8_t *)0x005013
#define PC_DDR     *(volatile uint8_t *)0x00500C
#define PC_CR2     *(volatile uint8_t *)0x00500E

PA_DDR = (1<<3); //output
PA_CR2 |= (1<<3); //fast
PD_DDR = (1<<3); //output
PD_CR2 |= (1<<3); //fast
PC_DDR = ((1<<3) | (1<<5) | (1<<6) | (1<<7)); //output
PC_CR2 |= ((1<<3) | (1<<5) | (1<<6) | (1<<7)); //fast

PWM ترتیب

سب سے پہلے، شرائط کی وضاحت کرتے ہیں:

  • PWM تعدد - فریکوئنسی جس کے ساتھ ٹائمر ٹکتا ہے؛
  • خودکار دوبارہ لوڈ، AR - آٹو لوڈ ایبل قدر جس تک ٹائمر شمار کرے گا (نبض کی مدت)؛
  • اپ ڈیٹ ایونٹ، UEV - ایک واقعہ جو اس وقت ہوتا ہے جب ٹائمر نے AR میں شمار کیا ہوتا ہے۔
  • پی ڈبلیو ایم ڈیوٹی سائیکل - PWM ڈیوٹی سائیکل، جسے اکثر "ڈیوٹی فیکٹر" کہا جاتا ہے۔
  • کیپچر/قدر کا موازنہ کریں۔ - کیپچر/موازنے کی قدر، جس میں ٹائمر نے شمار کیا ہے۔ کچھ کریں گے؟ (PWM کے معاملے میں، یہ آؤٹ پٹ سگنل کو الٹ دیتا ہے)؛
  • پری لوڈ ویلیو - پہلے سے بھری ہوئی قیمت۔ قدر کا موازنہ کریں۔ ٹائمر کے ٹک ٹک کے دوران تبدیل نہیں ہو سکتا، ورنہ PWM سائیکل ٹوٹ جائے گا۔ لہذا، نئی منتقل شدہ اقدار کو بفر میں رکھا جاتا ہے اور اس وقت نکالا جاتا ہے جب ٹائمر اپنی الٹی گنتی کے اختتام پر پہنچ جاتا ہے اور اسے دوبارہ ترتیب دیا جاتا ہے۔
  • کنارے سے منسلک и مرکز سے منسلک موڈز - سرحد کے ساتھ اور مرکز میں سیدھ، Atmel کی طرح فاسٹ پی ڈبلیو ایم и فیز درست PWM.
  • OCiREF، آؤٹ پٹ کمپیئر ریفرنس سگنل - حوالہ آؤٹ پٹ سگنل، حقیقت میں، PWM موڈ میں متعلقہ پن پر کیا ظاہر ہوتا ہے۔

جیسا کہ پن آؤٹ سے پہلے ہی واضح ہے، دو ٹائمرز میں PWM کی صلاحیتیں ہوتی ہیں – پہلا اور دوسرا۔ دونوں 16 بٹ ہیں، پہلی میں بہت ساری اضافی خصوصیات ہیں (خاص طور پر، یہ اوپر اور نیچے دونوں کو گن سکتا ہے)۔ ہمیں دونوں کو یکساں طور پر کام کرنے کی ضرورت ہے، لہذا میں نے واضح طور پر غریب دوسرے سے شروع کرنے کا فیصلہ کیا، تاکہ غلطی سے کوئی ایسی چیز استعمال نہ کی جائے جو وہاں نہیں ہے۔ کچھ مسئلہ یہ ہے کہ حوالہ دستی میں تمام ٹائمرز کی PWM فعالیت کی تفصیل پہلے ٹائمر (17.5.7 PWM موڈ) کے باب میں ہے، اس لیے آپ کو ہر وقت دستاویز میں آگے پیچھے کودنا پڑتا ہے۔

STM8 پر PWM کا Atmega پر PWM پر ایک اہم فائدہ ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
باؤنڈری الائنڈ PWM
نیچے سے اوپر تک اکاؤنٹ کی ترتیب
اگر TIM_CR1 رجسٹر میں DIR بٹ کو صاف کیا جاتا ہے تو نیچے کی گنتی فعال ہے
مثال کے طور پر
مثال پہلے PWM موڈ کا استعمال کرتی ہے۔ PWM حوالہ سگنل OCiREF کو TIM1_CNT < TIM1_CCRi تک زیادہ رکھا جاتا ہے۔ بصورت دیگر یہ ایک نچلی سطح لیتا ہے۔ اگر TIM1_CCRi رجسٹر میں موازنہ کی قدر آٹو لوڈ ویلیو (TIM1_ARR رجسٹر) سے زیادہ ہے، تو OCiREF سگنل 1 پر رکھا جاتا ہے۔ اگر موازنہ کی قدر 0 ہے تو، OCiREF صفر پر رکھا جاتا ہے۔...

کے دوران STM8 ٹائمر اپ ڈیٹ ایونٹ پہلے چیک کرتا ہے۔ قدر کا موازنہ کریں، اور تب ہی ایک حوالہ سگنل پیدا کرتا ہے۔ Atmega کا ٹائمر سب سے پہلے اسکروز کرتا ہے اور پھر موازنہ کرتا ہے، جس کے نتیجے میں compare value == 0 آؤٹ پٹ ایک سوئی ہے، جس سے کسی نہ کسی طرح نمٹا جانا چاہیے (مثال کے طور پر، پروگرام کے ذریعے منطق کو الٹ کر)۔

تو ہم کیا کرنا چاہتے ہیں: 8 بٹ PWM (AR == 255)، نیچے سے اوپر تک گنتی، سرحد کے ساتھ سیدھ۔ چونکہ روشنی کے بلب کیتھوڈس کے ذریعے چپ سے جڑے ہوتے ہیں، اس لیے PWM کو 0 (LED آن) تک آؤٹ پٹ کرنا چاہیے۔ قدر کا موازنہ کریں اور 1 کے بعد.

ہم پہلے ہی کچھ کے بارے میں پڑھ چکے ہیں۔ PWM وضع، لہذا ہمیں اس جملے (18.6.8 - TIMx_CCMR1) کے حوالہ جات میں تلاش کرکے دوسرے ٹائمر کا مطلوبہ رجسٹر مل جاتا ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
110: پہلا PWM موڈ - نیچے سے اوپر تک گنتے وقت، پہلا چینل فعال ہوتا ہے جبکہ TIMx_CNT < TIMx_CCR1۔ بصورت دیگر، پہلا چینل غیر فعال ہے۔ [مزید دستاویز میں ٹائمر 1 سے ایک غلط کاپی پیسٹ ہے] 111: دوسرا PWM موڈ – جب نیچے سے اوپر تک گنتی ہے تو پہلا چینل غیر فعال ہوتا ہے جبکہ TIMx_CNT < TIMx_CCR1۔ دوسری صورت میں، پہلا چینل فعال ہے.

چونکہ ایل ای ڈی ایم کے سے کیتھوڈس کے ذریعے جڑے ہوئے ہیں، اس لیے دوسرا موڈ ہمارے لیے موزوں ہے (پہلا موڈ بھی، لیکن ہم ابھی تک نہیں جانتے)۔

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
بٹ 3 OC1PE: پن 1 پری لوڈ کو فعال کریں۔
0: TIMx_CCR1 پر پری لوڈ رجسٹر غیر فعال ہے۔ آپ کسی بھی وقت TIMx_CCR1 کو لکھ سکتے ہیں۔ نئی قدر فوری طور پر کام کرتی ہے۔
1: TIMx_CCR1 پر پری لوڈ رجسٹر فعال ہے۔ پڑھنے/لکھنے کے آپریشنز پری لوڈ رجسٹر تک رسائی حاصل کرتے ہیں۔ پہلے سے لوڈ کردہ قدر TIMx_CCR1 کو ہر اپ ڈیٹ ایونٹ کے دوران شیڈو رجسٹر میں لوڈ کیا جاتا ہے۔
*نوٹ: PWM موڈ کے صحیح طریقے سے کام کرنے کے لیے، پری لوڈ رجسٹروں کا فعال ہونا ضروری ہے۔ سنگل سگنل موڈ میں یہ ضروری نہیں ہے (OPM بٹ TIMx_CR1 رجسٹر میں سیٹ ہے)۔

ٹھیک ہے، آئیے دوسرے ٹائمر کے تین چینلز کے لیے درکار ہر چیز کو آن کرتے ہیں:

#define TIM2_CCMR1 *(volatile uint8_t *)0x005307
#define TIM2_CCMR2 *(volatile uint8_t *)0x005308
#define TIM2_CCMR3 *(volatile uint8_t *)0x005309

#define PWM_MODE2   0x70 //PWM mode 2, 0b01110000
#define OCxPE       0x08 //preload enable

TIM2_CCMR1 = (PWM_MODE2 | OCxPE);
TIM2_CCMR2 = (PWM_MODE2 | OCxPE);
TIM2_CCMR3 = (PWM_MODE2 | OCxPE);

اے آر دو آٹھ بٹ رجسٹروں پر مشتمل ہے، سب کچھ آسان ہے:

#define TIM2_ARRH  *(volatile uint8_t *)0x00530F
#define TIM2_ARRL  *(volatile uint8_t *)0x005310

TIM2_ARRH = 0;
TIM2_ARRL = 255;

دوسرا ٹائمر صرف نیچے سے اوپر تک گن سکتا ہے، سرحد کے ساتھ سیدھ میں، کچھ بھی تبدیل کرنے کی ضرورت نہیں ہے۔ آئیے فریکوئنسی ڈیوائیڈر کو سیٹ کریں، مثال کے طور پر، 256۔ دوسرے ٹائمر کے لیے، ڈیوائیڈر TIM2_PSCR رجسٹر میں سیٹ کیا گیا ہے اور اس کی طاقت دو ہے:

#define TIM2_PSCR  *(volatile uint8_t *)0x00530E

TIM2_PSCR = 8;

جو کچھ باقی ہے وہ نتیجہ اخذ کرنا اور خود دوسرا ٹائمر آن کرنا ہے۔ پہلا مسئلہ رجسٹروں سے حل ہوتا ہے۔ کیپچر/ موازنہ کریں۔ فعال کریں: ان میں دو، تین چینلز غیر متناسب طور پر بکھرے ہوئے ہیں۔ یہاں ہم یہ بھی سیکھ سکتے ہیں کہ سگنل کی قطبیت کو تبدیل کرنا ممکن ہے، یعنی اصولی طور پر، PWM موڈ 1 کا استعمال ممکن تھا۔ ہم لکھتے ہیں:

#define TIM2_CCER1 *(volatile uint8_t *)0x00530A
#define TIM2_CCER2 *(volatile uint8_t *)0x00530B

#define CC1E  (1<<0) // CCER1
#define CC2E  (1<<4) // CCER1
#define CC3E  (1<<0) // CCER2

TIM2_CCER1 = (CC1E | CC2E);
TIM2_CCER2 = CC3E;

اور آخر میں، ہم TIMx_CR1 رجسٹر میں ٹائمر شروع کرتے ہیں:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

#define TIM2_CR1   *(volatile uint8_t *)0x005300

TIM2_CR1 |= 1;

آئیے AnalogWrite() کا ایک سادہ اینالاگ لکھتے ہیں، جو موازنہ کے لیے اصل قدروں کو ٹائمر میں منتقل کر دے گا۔ رجسٹروں کا نام متوقع طور پر رکھا گیا ہے۔ رجسٹروں کی گرفتاری/ موازنہ کریں۔ہر چینل کے لیے ان میں سے دو ہیں: TIM8_CCRxL میں کم آرڈر والے 2 بٹس اور TIM2_CCRxH میں ہائی آرڈر والے۔ چونکہ ہم نے 8 بٹ PWM بنایا ہے، اس لیے یہ صرف کم سے کم اہم بٹس لکھنا کافی ہے:

#define TIM2_CCR1L *(volatile uint8_t *)0x005312
#define TIM2_CCR2L *(volatile uint8_t *)0x005314
#define TIM2_CCR3L *(volatile uint8_t *)0x005316

void setRGBled(uint8_t r, uint8_t g, uint8_t b)
{
    TIM2_CCR1L = r;
    TIM2_CCR2L = g;
    TIM2_CCR3L = b;
}

دھیان سے پڑھنے والا یہ محسوس کرے گا کہ ہمارے پاس PWM قدرے خراب ہے، جو 100% بھرنے سے قاصر ہے (زیادہ سے زیادہ قیمت 255 پر، سگنل ایک ٹائمر سائیکل کے لیے الٹا ہے)۔ ایل ای ڈی کے لیے اس سے کوئی فرق نہیں پڑتا، اور دھیان سے پڑھنے والا پہلے ہی اندازہ لگا سکتا ہے کہ اسے کیسے ٹھیک کیا جائے۔

دوسرے ٹائمر پر پی ڈبلیو ایم کام کرتا ہے، آئیے پہلے کی طرف چلتے ہیں۔

پہلے ٹائمر کے ایک ہی رجسٹر میں بالکل وہی بٹس ہوتے ہیں (یہ صرف اتنا ہے کہ وہ بٹس جو دوسرے ٹائمر میں "محفوظ" رہ گئے ہیں وہ ہر طرح کی جدید چیزوں کے لئے پہلے میں فعال طور پر استعمال ہوتے ہیں)۔ لہذا، ڈیٹا شیٹ میں انہی رجسٹروں کے پتے تلاش کرنا اور کوڈ کاپی کرنا کافی ہے۔ ٹھیک ہے، فریکوئنسی ڈیوائیڈر کی قدر کو تبدیل کریں، کیونکہ... پہلا ٹائمر دو کی طاقت نہیں بلکہ دو رجسٹروں میں 16 بٹ کی درست قدر حاصل کرنا چاہتا ہے۔ Prescaler ہائی и لو. ہم سب کچھ کرتے ہیں اور... پہلا ٹائمر کام نہیں کرتا۔ کیا معاملہ ہے؟

مسئلہ صرف ٹائمر 1 کے کنٹرول رجسٹر کے بارے میں پورے حصے کو دیکھ کر ہی حل کیا جا سکتا ہے، جہاں ہم اسے تلاش کرتے ہیں جو دوسرے ٹائمر کے پاس نہیں ہے۔ وہاں ہو جائے گا 17.7.30 بریک رجسٹر (TIM1_BKR)، جہاں یہ بٹ ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
مین آؤٹ پٹ کو فعال کریں۔

#define TIM1_BKR   *(volatile uint8_t *)0x00526D

TIM1_BKR = (1<<7);

یہ سب یقینی طور پر اب ہے، کوڈ وہاں.

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

STM8 ملٹی پلیکس

STM8 پر ملٹی پلیکسنگ

تیسرا منی پروجیکٹ آٹھ RGB LEDs کو PWM موڈ میں دوسرے ٹائمر سے جوڑنا اور انہیں مختلف رنگ دکھانا ہے۔ یہ ایل ای ڈی ملٹی پلیکسنگ کے تصور پر مبنی ہے، جس کا مطلب یہ ہے کہ اگر آپ ایل ای ڈی کو بہت، بہت جلد آن اور آف کرتے ہیں، تو ہمیں ایسا لگتا ہے کہ وہ مسلسل آن ہیں (نقطہ نظر کی استحکام، بصری ادراک کی جڑت)۔ میں نے ایک بار کیا Arduino پر کچھ اس طرح.

کام کا الگورتھم اس طرح لگتا ہے:

  • پہلے آرجیبی ایل ای ڈی کے اینوڈ کو جوڑ دیا؛
  • کیتھوڈس کو ضروری سگنل بھیج کر اسے روشن کیا؛
  • PWM سائیکل کے اختتام تک انتظار کیا؛
  • دوسری آرجیبی ایل ای ڈی کے انوڈ سے منسلک؛
  • روشن کیا...

ٹھیک ہے، وغیرہ بلاشبہ، خوبصورت آپریشن کے لیے ضروری ہے کہ اینوڈ منسلک ہو اور LED کو ایک ہی وقت میں "جگایا" جائے۔ ٹھیک ہے، یا تقریبا. کسی بھی صورت میں، ہمیں ایک کوڈ لکھنے کی ضرورت ہے جو دوسرے ٹائمر کے تین چینلز میں اقدار کو آؤٹ پٹ کرے، UEV تک پہنچنے پر انہیں تبدیل کرے، اور ساتھ ہی ساتھ موجودہ فعال RGB LED کو بھی تبدیل کرے۔

چونکہ ایل ای ڈی سوئچنگ خودکار ہے، ہمیں ایک "ویڈیو میموری" بنانے کی ضرورت ہے جس سے انٹرپٹ ہینڈلر ڈیٹا وصول کرے گا۔ یہ ایک سادہ صف ہے:

uint8_t colors[8][3];

کسی مخصوص ایل ای ڈی کا رنگ تبدیل کرنے کے لیے، اس صف میں مطلوبہ قدریں لکھنا کافی ہوگا۔ اور متغیر فعال ایل ای ڈی کی تعداد کے لیے ذمہ دار ہو گا۔

uint8_t cnt;

ڈیمکس

مناسب ملٹی پلیکسنگ کے لیے، ہمیں، عجیب طور پر، ایک CD74HC238 ڈیملٹی پلیکسر کی ضرورت ہے۔ Demultiplexer - ایک چپ جو آپریٹر کو ہارڈ ویئر میں لاگو کرتی ہے۔ <<. تین ان پٹ پنوں (بٹس 0، 1 اور 2) کے ذریعے ہم اسے تین بٹ نمبر X فیڈ کرتے ہیں، اور اس کے جواب میں یہ آؤٹ پٹ نمبر کو چالو کرتا ہے (1<<X)۔ چپ کے بقیہ آدانوں کو پورے ڈیزائن کی پیمائش کے لیے استعمال کیا جاتا ہے۔ ہمیں اس چپ کی ضرورت نہ صرف مائیکرو کنٹرولر کے زیر قبضہ پنوں کی تعداد کو کم کرنے کے لیے ہے، بلکہ حفاظت کے لیے بھی ہے - تاکہ غلطی سے ممکن سے زیادہ ایل ای ڈی آن نہ ہو جائیں اور MK کو جل نہ جائے۔ چپ کی قیمت ایک پیسہ ہے اور اسے ہمیشہ آپ کی گھریلو ادویات کی کابینہ میں رکھنا چاہیے۔

ہمارا CD74HC238 مطلوبہ ایل ای ڈی کے اینوڈ کو وولٹیج فراہم کرنے کا ذمہ دار ہوگا۔ ایک مکمل ملٹی پلیکس میں، یہ P-MOSFET کے ذریعے کالم کو وولٹیج فراہم کرے گا، لیکن اس ڈیمو میں یہ براہ راست ممکن ہے، کیونکہ یہ 20 ایم اے ڈرا کرتا ہے، کے مطابق مطلق زیادہ سے زیادہ درجہ بندی ڈیٹا شیٹ میں سے ڈیٹا شیٹ CD74HC238 ہمیں پن آؤٹ اور اس چیٹ شیٹ کی ضرورت ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
H = ہائی وولٹیج کی سطح، L = کم وولٹیج کی سطح، X - پرواہ نہ کریں۔

ہم E2 اور E1 کو زمین سے، E3، A0، A1 اور A3 کو STM5 کے PD3، PC4، PC5 اور PC8 سے جوڑتے ہیں۔ چونکہ اوپر دی گئی جدول میں نچلی اور اعلیٰ دونوں سطحیں ہیں، اس لیے ہم ان پنوں کو پش پل پن کے طور پر ترتیب دیتے ہیں۔

پی ڈبلیو ایم

دوسرے ٹائمر پر PWM کو پچھلی کہانی کی طرح دو فرقوں کے ساتھ ترتیب دیا گیا ہے:

سب سے پہلے، ہمیں مداخلت کو فعال کرنے کی ضرورت ہے۔ ایونٹ کو اپ ڈیٹ کریں۔ (UEV) جو ایک فنکشن کو کال کرے گا جو فعال LED کو ٹوگل کرتا ہے۔ یہ بٹ کو تبدیل کرکے کیا جاتا ہے۔ اپ ڈیٹ انٹرپٹ کو فعال کریں۔ بتانے والے نام کے ساتھ ایک رجسٹر میں

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
انٹرپٹ فعال رجسٹر

#define TIM2_IER   *(volatile uint8_t *)0x005303

//enable interrupt
TIM2_IER = 1;

دوسرا فرق ملٹی پلیکسنگ کے رجحان سے متعلق ہے، جیسے اور ghosting - ڈایڈس کی پرجیوی چمک۔ ہمارے معاملے میں، یہ اس حقیقت کی وجہ سے ظاہر ہو سکتا ہے کہ ٹائمر، UEV میں رکاوٹ پیدا کرنے کے بعد، ٹک کرتا رہتا ہے، اور انٹرپٹ ہینڈلر کے پاس LED کو سوئچ کرنے کا وقت نہیں ہوتا ہے اس سے پہلے کہ ٹائمر پنوں پر کچھ لکھنا شروع کر دے۔ اس کا مقابلہ کرنے کے لیے، آپ کو منطق کو الٹنا ہوگا (0 = زیادہ سے زیادہ چمک، 255 = کچھ بھی روشن نہیں ہے) اور انتہائی ڈیوٹی سائیکل اقدار سے بچنا ہوگا۔ وہ. اس بات کو یقینی بنائیں کہ UEV کے بعد LEDs ایک PWM سائیکل کے لیے مکمل طور پر باہر ہو جائیں۔

قطبیت کو تبدیل کرنا:

//set polarity 
    TIM2_CCER1 |= (CC1P | CC2P);
    TIM2_CCER2 |= CC3P;

r, g اور b کو 255 پر سیٹ کرنے سے گریز کریں اور انہیں استعمال کرتے وقت ان کو الٹنا یاد رکھیں۔

مداخلت کرتا ہے۔

مداخلت کا جوہر یہ ہے کہ کچھ خاص حالات میں چپ مرکزی پروگرام کو انجام دینا بند کر دیتی ہے اور کچھ بیرونی فنکشن کو کال کرتی ہے۔ رکاوٹیں بیرونی یا اندرونی اثرات کی وجہ سے ہوتی ہیں، بشمول ٹائمر۔

جب ہم نے سب سے پہلے ST Visual Develop میں ایک پروجیکٹ بنایا، اس کے علاوہ main.c ہمیں ایک پراسرار فائل والی ونڈو موصول ہوئی ہے۔ stm8_interrupt_vector.cخود بخود اس منصوبے میں شامل ہے۔ اس فائل میں، ہر رکاوٹ کو ایک فنکشن تفویض کیا جاتا ہے۔ NonHandledInterrupt. ہمیں اپنے فنکشن کو مطلوبہ مداخلت سے منسلک کرنے کی ضرورت ہے۔

ڈیٹا شیٹ میں مداخلت کرنے والے ویکٹرز کا ایک جدول ہے، جہاں ہمیں وہ چیزیں مل جاتی ہیں جن کی ہمیں ضرورت ہے:

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس
13 TIM2 اپ ڈیٹ/اوور فلو
14 TIM2 کیپچر/موازنہ

ہمیں UEV پر ایل ای ڈی کو تبدیل کرنے کی ضرورت ہے، لہذا ہمیں مداخلت #13 کی ضرورت ہے۔

اس کے مطابق، سب سے پہلے، فائل میں stm8_interrupt_vector.c انٹرپٹ نمبر 13 (IRQ13) کے لیے ذمہ دار فنکشن کا ڈیفالٹ نام تبدیل کریں:

{0x82, TIM2_Overflow}, /* irq13 */

دوسرا، ہمیں ایک فائل بنانا پڑے گی main.h مندرجہ ذیل مواد کے ساتھ:

#ifndef __MAIN_H
#define __MAIN_H

@far @interrupt void TIM2_Overflow (void);
#endif

اور آخر میں، اس فنکشن کو اپنے میں لکھیں۔ main.c:

@far @interrupt void TIM2_Overflow (void)
{
    PD_ODR &= ~(1<<5); // вырубаем демультиплексор
    PC_ODR = (cnt<<3); // записываем в демультиплексор новое значение
    PD_ODR |= (1<<5); // включаем демультиплексор

    TIM2_SR1 = 0; // сбрасываем флаг Update Interrupt Pending

    cnt++; 
    cnt &= 7; // двигаем счетчик LED

    TIM2_CCR1L = ~colors[cnt][0]; // передаем в буфер инвертированные значения
    TIM2_CCR2L = ~colors[cnt][1]; // для следующего цикла ШИМ
    TIM2_CCR3L = ~colors[cnt][2]; // 

    return;
}

جو کچھ باقی ہے وہ مداخلتوں کو فعال کرنا ہے۔ یہ اسمبلر کمانڈ کا استعمال کرتے ہوئے کیا جاتا ہے۔ rim - آپ کو اسے تلاش کرنا پڑے گا۔ پروگرامنگ دستی:

//enable interrupts
_asm("rim");

ایک اور اسمبلر کمانڈ ہے۔ sim - رکاوٹوں کو بند کر دیتا ہے۔ جب "ویڈیو میموری" میں نئی ​​قدریں لکھی جا رہی ہوں تو انہیں آف کرنا ضروری ہے، تاکہ غلط لمحے پر ہونے والا رکاوٹ صف کو خراب نہ کرے۔

تمام کوڈ - GitHub پر.

ڈیٹا شیٹ پڑھنا 2: STM32 پر SPI؛ STM8 پر PWM، ٹائمر اور انٹراپٹس

اگر کم از کم کسی کو یہ مضمون کارآمد معلوم ہوتا ہے تو میں نے اسے بیکار نہیں لکھا۔ مجھے تبصرے اور ریمارکس حاصل کرنے میں خوشی ہوگی، میں ہر چیز کا جواب دینے کی کوشش کروں گا۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں