Sebelum memulai, saya ingin segera membuat reservasi bahwa kode itu tidak ditulis oleh saya dan diambil dari sini . Program ini ditulis dalam Arduino IDE dan bersama dengan arduino pro mini dan nrf24l01 + memungkinkan Anda untuk mengontrol multicopters mainan (dengan chip radio XN297, klon nrf24l01) dari peralatan kontrol apa pun yang memiliki output PPM. Semua informasi tentang multicopter yang didukung dapat ditemukan di tautan di atas.Saya memutuskan untuk menulis ulang kode ini untuk mengontrol mini copter Eachine H8 dari peralatan Radiolink AT9. Saya meminta detail di bawah kucing.MSP430 dipilih karena memiliki tegangan suplai 3,3 volt, tegangan suplai nrf24l01 juga 3,3 volt, dan saya suka MPS430. Di dalam peralatan ada 3V3, OUT, kontak GND, yang akan kita sambungkan.Jika tidak ada keinginan untuk membongkar peralatan, maka Anda dapat menghubungkan ke konektor pelatihan, tetapi tegangan di atasnya = tegangan baterai, sehingga penstabil tegangan ditambahkan ke sirkuit.Mari kita lanjutkan ke kode
Pertama-tama, buka proyek di IDE Energia (klon Arduino IDE untuk MSP430 dan chip lain dari TI) dan cobalah untuk mengompilasinya, tetapi segera lihat kesalahan kompilasi. Proyek ini menggunakan perpustakaan tambahan dan akses ke register, dan hal pertama yang Anda perlukan untuk memulainya. Jadi, kami melanjutkan ke analisis terperinci.Perpustakaan
Kami akan mengedit file nRF24_multipro.ino dan mulai dengan include'ov. Proyek ini menggunakan pustaka atom dan EEPROM.atom
Kami menghapus garis#include <util/atomic.h>
dan pada fungsi void update_ppm () kita hapusATOMIC_BLOCK(ATOMIC_RESTORESTATE)
Alih-alih kawat gigi yang kita tulis__disable_interrupt();
dan__enable_interrupt();
Fungsi ATOMIC_BLOCK () mematikan interupsi sementara kode dalam "tubuh" dijalankan dan, tergantung pada parameter, mengaktifkan interupsi atau mengembalikan nilai flag interrupt ke keadaan sebelum fungsi ATOMIC_BLOCK () dipanggil.Eeprom
MSP430 tidak memiliki memori EEPROM, tetapi ada memori FLASH dan ada perpustakaan MspFlash untuk bekerja dengannya. Karena itu, kami menghapus garis#include <EEPROM.h>
dan tambahkan perpustakaan MspFlash (Sketch-> Import Library ... -> MspFlash), tambahkan ke segmen mana dari memori FLASH kami akan menulis data#define flash SEGMENT_D
Dalam fungsi selectProtocol () kosong, ubah bariselse
current_protocol = constrain(EEPROM.read(ee_PROTOCOL_ID),0,PROTO_END-1);
EEPROM.update(ee_PROTOCOL_ID, current_protocol);
pada
Flash.write(flash+ee_PROTOCOL_ID, & current_protocol,1);
Kami sepenuhnya menghapus pembacaan pengidentifikasi protokol (mengapa, baca di bawah).Dalam kekosongan set_txid (perpanjangan bool), Anda perlu melakukan sedikit lebih banyak daripada mengganti dua baris. Dalam memori FLASH kita hanya bisa nol bit. Untuk menetapkan nilai 1 dalam bit memori FLASH, Anda harus menghapus seluruh segmen (maka nilai 1 akan dituliskan padanya). Fungsi ini (set_txid) disebut lebih awal dari selectProtocol, jadi kami akan menghapus segmen di sini.Itu: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]);
}
}
}
Itu menjadi: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);
}
}
}
Di sini kita membaca nilai pengidentifikasi pemancar dan protokol, menghapus segmen, dan jika perintah diberikan untuk memperbarui pengenal pemancar, kita menulis nilai baru, jika tidak kita mencatat yang lama. Byte FLASH dari memori dengan alamat flash + ee_PROTOCOL_ID tetap bersih (0xFF), jadi kami tidak membacanya di fungsi selectProtocol (), tetapi segera menulis pengenal protokol di sana.Daftar
Pertama, mari kita berurusan dengan pin. Dalam proyek ini, implementasi perangkat lunak SPI digunakan, di mana makro digunakan untuk "berkedut" kaki melalui register.Tulis ulang definisi pin#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))
Dalam ATMEL MK, register PORTx dalam MSP430 PxOUT bertanggung jawab atas status output. Untuk status input, PINX dan PxIN masing-masing mendaftar. Omong-omong, tidak ada fungsi _BV (x) di IDE Energia, jadi tambahkan sendiri:#define _BV(val) 1<<val
Dalam fungsi void setup () kita mengubah nilai pin input analog menjadi gratisrandomSeed((analogRead(A4) & 0x1F) | (analogRead(A5) << 5));
misalnya padarandomSeed((analogRead(A0) & 0x1F) | (analogRead(A1) << 5));
Dalam MSP430, input analog A0, A1, A2, ..., A7 sesuai dengan pin P1_0, P1_1, P1_2, ..., P1_7.Saat menghubungkan perubahan interupsiattachInterrupt(PPM_pin - 2, ISR_ppm, CHANGE);
padaattachInterrupt(PPM_pin , ISR_ppm, CHANGE);
Di Arduino Uno, Nano, Mini, dll. Pada mega328, hanya 2 pin (2, 3) yang tersedia untuk menghubungkan interupsi, dan dalam fungsi attachInterrupt, argumen pertama adalah angka interrupt, bukan pin seperti pada MSP430. Lebih lanjut tentang attachInterrupt () .Timer
Ubah dalam pengaturan yang tidak berlaku ()TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << CS11);
AktifTACTL = TASSEL_2 + ID_3 + MC_2 + TACLR;
Pengatur waktu diperlukan untuk menentukan durasi pulsa dalam PPM. Kami mengaturnya ke mode penghitungan langsung dengan frekuensi 2 MHz (frekuensi clock 16 MHz dan pembagi 8).Dalam fungsi void ISR_ppm () kita berubahcounterPPM = TCNT1;
TCNT1 = 0;
padacounterPPM = TAR;
TAR = 0;
Register TCNT1 dan TAR adalah penghitung waktu.acak ()
Saya tidak tahu mengapa, tetapi fungsi acak () tidak dipanggil tanpa argumen di Energia, tetapi karena kami membutuhkan nomor byte tunggal acak, kami mengganti nRF24_multipro.ino dan Bayang.ino dalam filerandom() & 0xFF;
padarandom(0xFF);
danrandom() % 0x42;
padarandom(0x41);
???
Dan akhirnya, dalam file MJX.ino, dalam fungsi void MJX_bind (), kami menambahkan tanda kurung ke pemanggilan fungsi mjx_init2;Kami menyusun proyek dan mendapatkan kesimpulan yang sukses.Kode sumber proyekMengubah kode proyekUntuk berhasil mentransfer suatu program ke platform lain, Anda perlu memahami apa, bagaimana dan mengapa itu dieksekusi dalam kode ini, memahami fitur-fitur perpustakaan yang terhubung, tujuan register dan, dalam perjalanan kerja, sering melihat log kompilasi untuk menemukan kesalahan.Nah, jika Anda melakukan sesuatu yang baik, Anda perlu mentransfer proyek ke lingkungan pengembangan lain, hubungkan SPI perangkat keras dan hanya bekerja dengan register, tetapi ini adalah cerita yang sama sekali berbeda.