قبل البدء ، أود أن أحجز على الفور أنني لم أكتب الرمز وأخذه من هنا . هذا البرنامج مكتوب في Arduino IDE وبالاشتراك مع arduino pro mini و nrf24l01 + يسمح لك بالتحكم في لعبة المروحيات المتعددة (مع رقائق راديو XN297 ، استنساخ nrf24l01) من أي معدات تحكم بها خرج PPM. يمكن العثور على جميع المعلومات حول طائرات الهليكوبتر المدعومة على الرابط أعلاه.قررت إعادة كتابة هذا الرمز للتحكم في المروحية الصغيرة Everyine H8 من معدات Radiolink AT9. أطلب تفاصيل تحت القط.تم اختيار MSP430 لأنه يحتوي على جهد إمداد يبلغ 3.3 فولت ، كما أن جهد الإمداد nrf24l01 هو أيضًا 3.3 فولت ، وأنا أحب MPS430 بطريقة أو بأخرى. يوجد داخل الجهاز جهات اتصال 3V3 و OUT و GND ، والتي سنتصل بها., , = , .
IDE Energia ( Arduino IDE MSP430 TI) , . , . , .
nRF24_multipro.ino include’. atomic EEPROM.
atomic
#include <util/atomic.h>
void update_ppm()
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
__disable_interrupt();
__enable_interrupt();
ATOMIC_BLOCK() , «» , , ATOMIC_BLOCK().
EEPROM
MSP430 EEPROM , FLASH MspFlash.
#include <EEPROM.h>
MspFlash (Sketch->Import Library…->MspFlash), FLASH
#define flash SEGMENT_D
void selectProtocol()
else
current_protocol = constrain(EEPROM.read(ee_PROTOCOL_ID),0,PROTO_END-1);
EEPROM.update(ee_PROTOCOL_ID, current_protocol);
Flash.write(flash+ee_PROTOCOL_ID, & current_protocol,1);
نزيل تمامًا قراءة معرف البروتوكول (لماذا ، اقرأ أدناه).في الفراغ set_txid (تجديد منطقي) ، تحتاج إلى القيام بأكثر من استبدال سطرين بقليل. في ذاكرة فلاش ، لا يمكننا سوى بتات صفر. لتعيين قيمة 1 في بتات ذاكرة FLASH ، تحتاج إلى مسح المقطع بالكامل (ثم ستتم كتابة القيم 1 عليه). تُسمى هذه الوظيفة (set_txid) في وقت سابق عن selectProtocol ، لذلك سنمحو المقطع هنا.كان:void set_txid(bool renew)
{
uint8_t i;
for(i=0; i<4; i++)
transmitterID[i] = EEPROM.read(ee_TXID0+i);
if(renew || (transmitterID[0]==0xFF && transmitterID[1]==0x0FF)) {
for(i=0; i<4; i++) {
transmitterID[i] = random() & 0xFF;
EEPROM.update(ee_TXID0+i, transmitterID[i]);
}
}
}
أصبح:void set_txid(bool renew)
{
uint8_t i;
unsigned char p;
for(i=0; i<4; i++) {
Flash.read(flash+ee_TXID0+i,&p,1);
transmitterID[i] =p;
}
Flash.read(flash+ee_PROTOCOL_ID,&p,1);
current_protocol = constrain(p,0,PROTO_END-1);
Flash.erase(flash);
if(renew || (transmitterID[0]==0xFF && transmitterID[1]==0x0FF)) {
for(i=0; i<4; i++) {
transmitterID[i] = random(0xff) & 0xFF;
p = transmitterID[i];
Flash.write(flash+ee_TXID0+i, &p,1);
}
}else{
for(i=0; i<4; i++) {
p = transmitterID[i];
Flash.write(flash+ee_TXID0+i, &p,1);
}
}
}
هنا نقرأ قيمة معرفات جهاز الإرسال والبروتوكول ، ونمسح المقطع ، وإذا تم إصدار أمر لتحديث معرف جهاز الإرسال ، فإننا نكتب قيمة جديدة ، وإلا فإننا نسجل القيمة القديمة. ظل فلاش FLASH للذاكرة مع فلاش العنوان + ee_PROTOCOL_ID نظيفًا (0xFF) ، لذلك لا نقرأه في وظيفة selectProtocol () ، ولكن نكتب معرف البروتوكول على الفور.يسجل
أولاً ، دعنا نتعامل مع الدبابيس. في هذا المشروع ، يتم استخدام تطبيق برنامج SPI ، حيث يتم استخدام وحدات الماكرو في "اهتزاز" الساقين من خلال التسجيلات.أعد كتابة تعريفات الدبابيس#define PPM_pin 2
#define MOSI_pin 3
#define SCK_pin 4
#define CE_pin 5
#define MISO_pin A0
#define CS_pin A1
#define ledPin 13
#define PPM_pin P1_5
#define MOSI_pin P2_0
#define SCK_pin P2_1
#define CE_pin P2_2
#define MISO_pin P2_3
#define CS_pin P2_4
#define ledPin P1_4
#define MOSI_on PORTD |= _BV(3)
#define MOSI_off PORTD &= ~_BV(3)
#define SCK_on PORTD |= _BV(4)
#define SCK_off PORTD &= ~_BV(4)
#define CE_on PORTD |= _BV(5)
#define CE_off PORTD &= ~_BV(5)
#define CS_on PORTC |= _BV(1)
#define CS_off PORTC &= ~_BV(1)
#define MISO_on (PINC & _BV(0))
#define MOSI_on P2OUT |= _BV(0)
#define MOSI_off P2OUT &= ~_BV(0)
#define SCK_on P2OUT |= _BV(1)
#define SCK_off P2OUT &= ~_BV(1)
#define CE_on P2OUT |= _BV(2)
#define CE_off P2OUT &= ~_BV(2)
#define CS_on P2OUT |= _BV(4)
#define CS_off P2OUT &= ~_BV(4)
#define MISO_on (P2IN & _BV(3))
في ATMEL MKs ، تكون سجلات PORTx في MSP430 PxOUT مسؤولة عن حالة الإخراج. بالنسبة لحالة الإدخال ، يسجل PINx و PxIN ، على التوالي. بالمناسبة ، لا توجد وظيفة _BV (x) في Energia IDE ، لذا أضفها بنفسك:#define _BV(val) 1<<val
في إعداد الفراغ الوظيفي () ، نغير قيم الدبوس للمدخلات التناظرية مجانًاrandomSeed((analogRead(A4) & 0x1F) | (analogRead(A5) << 5));
على سبيل المثال فيrandomSeed((analogRead(A0) & 0x1F) | (analogRead(A1) << 5));
في MSP430 ، تتوافق المدخلات التناظرية A0 و A1 و A2 و ... و A7 مع الدبابيس P1_0 و P1_1 و P1_2 و ... و P1_7.عند ربط تغيير المقاطعةattachInterrupt(PPM_pin - 2, ISR_ppm, CHANGE);
علىattachInterrupt(PPM_pin , ISR_ppm, CHANGE);
في Arduino Uno و Nano و Mini وما إلى ذلك على mega328 ، يتوفر فقط دبابيس (2 ، 3) لتوصيل المقاطعة ، وفي وظيفة attachInterrupt ، الوسيطة الأولى هي رقم المقاطعة ، وليس الدبوس كما هو الحال في MSP430. المزيد عن attachInterrupt () .مؤقت
التغيير في إعداد الفراغ ()TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << CS11);
مفعّلةTACTL = TASSEL_2 + ID_3 + MC_2 + TACLR;
مطلوب جهاز ضبط الوقت لتحديد مدة النبض في جزء في المليون. قمنا بضبطه على وضع العد المباشر بتردد 2 ميجاهرتز (تردد ساعة 16 ميجاهرتز ومقسم 8).في دالة الفراغ ISR_ppm () نغيرcounterPPM = TCNT1;
TCNT1 = 0;
علىcounterPPM = TAR;
TAR = 0;
السجلات TCNT1 و TAR هي عدادات عداد الوقت.عشوائي ()
لا أعرف السبب ، ولكن لا يتم استدعاء الوظيفة العشوائية () بدون وسيطات في Energia ، ولكن نظرًا لأننا نحتاج إلى رقم عشوائي واحد بايت ، فإننا نستبدل nRF24_multipro.ino و Bayang.ino في الملفاتrandom() & 0xFF;
علىrandom(0xFF);
وrandom() % 0x42;
علىrandom(0x41);
؟؟؟
وأخيرًا ، في ملف MJX.ino ، في دالة MJX_bind () باطلة ، نقوم بإضافة أقواس إلى استدعاء دالة mjx_init2 ؛نقوم بتجميع المشروع والحصول على نتيجة ناجحة.رمز مصدر المشروع تمتغيير رمز المشروعلنقل البرنامج بنجاح إلى نظام أساسي آخر ، تحتاج إلى فهم ما يتم تنفيذه في هذا الرمز وكيف ولماذا ، وفهم ميزات المكتبات المتصلة والغرض من التسجيلات ، وفي أثناء العمل ، غالبًا ما تبحث في سجل الترجمة للعثور على الأخطاء.حسنًا ، إذا فعلت شيئًا جيدًا ، فأنت بحاجة إلى نقل المشروع إلى بيئة تطوير أخرى ، وتوصيل SPI للأجهزة والعمل فقط مع السجلات ، لكن هذه قصة مختلفة تمامًا.