Kiat Firmware Tertanam:Cara Menginisialisasi Array di C dengan Bentuk Gelombang Sinyal dan Data File Lainnya
Artikel ini menunjukkan cara menginisialisasi array dalam program C dengan nilai dari file teks.
Artikel ini menunjukkan cara menginisialisasi array dalam program C dengan nilai dari file teks. Data tidak disimpan dalam file sumber. File dibaca ketika program dikompilasi. Array satu dimensi dan multi-dimensi dipertimbangkan. Contoh juga menunjukkan cara mengontrol penempatan array di RAM atau memori non-volatil dan memilih file data mana yang akan digunakan untuk inisialisasi.
Compiler yang digunakan untuk contoh adalah GCC untuk ARM dengan mikrokontroler 32-bit sebagai target. Semua contoh menggunakan C standar dan bekerja dengan kompiler ini.
Dasar-dasar Inisialisasi Array
Sebuah array dapat diinisialisasi dengan nilai-nilai ketika "dideklarasikan". Sebuah deklarasi khas ditampilkan di sini. Nilai dalam kurung kurawal disebut "initializers".
Jika ukuran array tidak ditentukan di dalam tanda kurung, ukurannya akan menjadi jumlah inisialisasi. Jika ada lebih sedikit inisialisasi daripada ukuran larik, elemen tambahan disetel ke 0. Merupakan kesalahan jika memiliki lebih banyak penginisialisasi daripada ukuran larik.
Ruang Putih
Inisialisasi harus dipisahkan dengan koma. Menambahkan "spasi putih" tidak masalah. Dalam hal ini, ruang putih adalah “kosong” atau spasi. Kumpulan karakter spasi putih termasuk kosong (atau spasi), tab, baris baru, carriage return, tab vertikal, dan umpan formulir. Baris baru dan carriage return digunakan untuk menunjukkan akhir baris dalam kode sumber C. Saya tahu umpan formulir tetapi tab vertikal?
Secara umum, C tidak peduli jika pernyataan berisi spasi atau dilanjutkan pada baris lain. Pernyataan di sini setara dengan yang di atas. Adalah umum untuk melihat banyak baris inisialisasi untuk array besar. Bahkan mungkin halaman. Pada titik tertentu, kita mungkin berkata, “Apakah ada cara yang lebih baik?”
Menginisialisasi Array dari File
Kode sumber C dijalankan melalui preprosesor sebelum kompilasi. Fitur preprosesor C yang umum digunakan adalah "penyertaan file". Berikut adalah kutipan dari buku terkenal “The C Programming Language” oleh Kernighan dan Ritchie.
“Penyimpanan file memudahkan untuk menangani koleksi #defines dan deklarasi (antara lain ).”
Saya menambahkan huruf miring untuk "antara lain". Meskipun kami biasanya menyertakan file ".c" dan ".h", praprosesor tidak peduli dengan ekstensi nama file. File teks apa pun tidak masalah. Jadi, sintaks berikut berfungsi untuk menginisialisasi array.
File tidak boleh berisi karakter khusus yang terkadang disembunyikan untuk memformat dokumen. Tetap sederhana. Tidak ada format teks kaya. Tidak ada header kolom. Hanya angka, koma, dan spasi. Ini adalah file yang dibuat dengan Windows Notepad.
Berikut adalah array dalam memori yang ditampilkan dengan debugger. Dalam hal ini, array berada dalam RAM seperti yang ditunjukkan oleh alamat tinggi di kolom Lokasi.
Menyimpan Array dalam Memori Non-Volatile dan Memilih File Data
Dalam contoh di atas, array adalah variabel global dan tidak ada yang menentukan di mana harus meletakkan array. Compiler dan linker menganggap array dapat dimodifikasi oleh program, dan ditempatkan di RAM. Nilai awal dalam memori non-volatile ("NVM", biasanya memori Flash), dan array di RAM diinisialisasi dari data ini dengan kode yang berjalan sebelum program utama. Data dalam NVM ini tidak diakses oleh program. Jika larik tidak akan diubah (ini adalah "konstanta"), ia hanya diletakkan di NVM dan diakses langsung oleh program. Ini menghemat RAM yang sering kekurangan pasokan. Memberi tahu compiler dan linker bahwa array tidak akan diubah dan untuk menemukannya di NVM biasanya dilakukan dengan "const ” kualifikasi. Berikut adalah contoh dan lihat hasilnya. Kolom Lokasi menunjukkannya rendah di peta memori yang untuk mikrokontroler ini adalah memori Flash.
#define dan #jika pernyataan preprocessing dapat digunakan untuk memberikan opsi untuk menemukan array dan memilih file data mana yang digunakan untuk inisialisasi. Berikut adalah contoh yang memberikan pilihan penempatan array di RAM atau NVM.
#jika konstruk adalah contoh dari "inklusi bersyarat". Dalam hal ini, ini mengontrol apakah “const ” qualifier digunakan saat mendeklarasikan array. Ini berfungsi karena deklarasi dapat berada di lebih dari satu baris atau, dengan kata lain, spasi putih boleh saja.
Berikut adalah contoh penggunaan penyertaan bersyarat untuk memilih file untuk inisialisasi.
Menguji dengan Array Besar
Saya memiliki file besar data acak yang menggambarkan bentuk gelombang noise dan menggunakannya untuk menguji inisialisasi array besar di NVM. Berikut adalah plot data dan deklarasi.
Ini adalah awal dari file.
File csv asli tidak memiliki koma setelah nilainya. Ini mudah ditambahkan dengan menggunakan editor yang dapat menggunakan ekspresi dalam operasi Temukan/Ganti. Dalam hal ini, saya menggunakan ekspresi untuk pembatas baris, “\R”. Temukan adalah "\ R" dan Ganti adalah ",\R". Satu operasi Temukan/Ganti menambahkan semua koma untuk 10.000 nilai.
Semuanya bekerja dengan baik dan dikompilasi dengan sangat cepat! Berikut adalah awal dari array di memori. Debugger dengan baik memecah tampilan menjadi kelompok-kelompok yang masing-masing terdiri dari 100 elemen.
Array Multi-Dimensi
Bagaimana jika data diatur dalam dua atau lebih dimensi? Mari kita lihat array dua dimensi yang dideklarasikan sebagai uint16_t test[2][3] . Dalam C, subskrip kanan (3) adalah larik satu dimensi dengan elemen yang berdekatan dalam memori. Subskrip kiri (2) berarti ada dua dari larik tiga elemen ini. Ini adalah susunan memori dari enam elemen:
[0,0] [0,1] [0,2] [1,0] [1,1] [1,2]
Pengurutan dalam memori penting karena mengakses elemen berurutan dalam memori dengan menambah subskrip kanan lebih cepat daripada mengakses elemen dengan menambah subskrip kiri yang membutuhkan "hop" melalui memori. Jika array menampung dua vektor dari 1.000 elemen, organisasi harus test[2][1000] untuk akses tercepat.
Berikut adalah contoh inisialisasi array dua dimensi. Perhatikan inisialisasi dikelompokkan dengan kurung kurawal tambahan yang mengelompokkan inisialisasi untuk array satu dimensi dari subskrip kanan.
Format ini menimbulkan masalah untuk file data yang hanya dapat memiliki angka, koma, dan spasi. Apa yang terjadi jika kurung kurawal tambahan dihilangkan?
Kompiler mengisi array dengan pergi kiri-ke-kanan melalui inisialisasi dengan subskrip kanan mengisi terlebih dahulu. Kompiler yang saya gunakan memberikan peringatan:“tanda kurung hilang di sekitar penginisialisasi ”. Tidak ada masalah jika jumlah inisialisasi sama persis dengan jumlah elemen dalam array. Namun, jika tidak sama, tidak jelas bagaimana mengisi array jika tidak ada kurung kurawal sebagai pemandu.
Array dapat diisi dari beberapa file dengan beberapa #include pernyataan. Berikut adalah contoh di mana inisialisasi sepenuhnya dikurung dengan pasangan kurung kurawal. Saya mengabaikan detail yang ditunjukkan pada contoh sebelumnya.
Menginisialisasi Array dalam Serikat
Union adalah variabel yang dapat menampung objek dari berbagai jenis yang berbagi memori yang sama dan kompiler melacak objek seolah-olah mereka adalah hal yang berbeda. Pengaturan ini dapat berguna untuk aplikasi tertanam yang kekurangan memori. Berikut adalah contoh dengan vektor[6] dengan satu dimensi dan matriks[2][3] dengan dua dimensi. Mereka adalah dua array yang menempati lokasi yang sama dalam memori.
Aturan untuk menginisialisasi serikat adalah hal pertama dalam serikat (vektor[6] ) diisi dengan inisialisasi. Jika urutan array dibalik, kompilator memberikan peringatan karena inisialisasi tidak sepenuhnya dikurung dengan kurung kurawal. Perhatikan tanda kurung kurawal di sekitar #include digandakan. Saya pikir set luar menyertakan inisialisasi apa pun untuk serikat pekerja dan set dalam adalah untuk tipe array.
Ini filenya. Saya memiliki dua baris tetapi itu tidak masalah. Hanya lebih banyak ruang kosong.
Berikut adalah array dalam memori. Perhatikan Lokasi awal vektor[ ] dan matriks[ ][ ] adalah sama.
Apakah ada cara lain untuk menginisialisasi array multidimensi dari satu file dengan hanya angka, koma, dan spasi? Tolong beri tahu kami dengan menambahkan komentar.
Kiat Bonus:String
Bagaimana dengan string? Berikut adalah contoh inisialisasi string.
Sebuah #include dalam tanda kutip tidak berfungsi. Editor saya, yang mengetahui sintaks C, memberi saya banyak tanda tanya dan garis bawah berlekuk-lekuk. Karakter untuk baris baru dan #include itu sendiri adalah inisialisasi! Editor yang malang itu bingung. Kekacauan ini dikompilasi tetapi string diisi dengan karakter yang kita lihat di sini dan bukan dari file.
Solusinya adalah dengan memberikan tanda kutip pada file tersebut.
Kemudian, gunakan pernyataan seperti ini.
Perhatikan, tanda kutip di sekitar nama file adalah bagian dari #include sintaks dan tidak mengontrol inisialisasi. Ini hasilnya di RAM.
Penting untuk dicatat bahwa semua contoh harus bekerja dalam teori dengan kompiler apa pun. Namun, beberapa contoh mungkin tidak umum dan dapat menimbulkan masalah dengan beberapa kompiler. Beri tahu kami di komentar jika Anda menemukan masalah.