Halo teman-teman!Dalam artikel sebelumnya, saya
berbicara tentang proyek saya dan
bagian perangkat lunaknya . Pada artikel ini saya akan memberi tahu Anda cara membuat generator sinyal sederhana untuk 4 saluran - dua saluran analog dan dua saluran PWM.

Saluran analog
Mikrokontroler
STM32F415RG menggabungkan 12-bit
DAC (digital-to-analog) converter menjadi dua saluran independen, yang memungkinkan menghasilkan sinyal yang berbeda. Anda dapat langsung memuat data ke register konverter, tetapi ini tidak terlalu cocok untuk menghasilkan sinyal. Solusi terbaik adalah menggunakan array yang digunakan untuk menghasilkan satu gelombang sinyal, dan kemudian jalankan DAC dengan pemicu dari timer dan DMA. Dengan mengubah frekuensi timer, Anda dapat mengubah frekuensi sinyal yang dihasilkan.
Bentuk gelombang "
Klasik " meliputi: sinusoidal, berliku-liku, segitiga dan gigi gergaji.

Fungsi menghasilkan gelombang ini di buffer adalah sebagai berikut Dalam fungsinya, Anda perlu meneruskan pointer ke awal array, ukuran array, nilai maksimum dan bentuk gelombang yang diinginkan. Setelah panggilan, array akan diisi dengan sampel untuk satu gelombang dari bentuk yang diperlukan dan Anda dapat memulai timer untuk secara berkala memuat nilai baru ke dalam DAC.
DAC dalam mikrokontroler ini memiliki batasan: waktu penyelesaian yang khas (
waktu dari memuat nilai baru ke DAC dan ketika muncul pada output ) adalah 3 ms. Tapi tidak semuanya begitu sederhana - kali ini maksimum, mis. berubah dari minimum ke maksimum dan sebaliknya. Ketika mencoba menarik keluar berliku-liku, bidang-bidang yang berserakan ini sangat jelas terlihat:

Jika gelombang sinusoidal dihasilkan, maka obstruksi front tidak lagi terlihat karena bentuk gelombang. Namun, jika frekuensinya meningkat, sinyal sinusoidal berubah menjadi segitiga, dan dengan peningkatan lebih lanjut, amplitudo sinyal berkurang.
Generasi 1 KHz ( amplitudo 90% ):
Generasi 10 KHz ( amplitudo 90% ):
Generasi pada 100 KHz ( amplitudo 90% ):
Langkah-langkahnya sudah terlihat - karena data baru dimuat ke DAC pada frekuensi 4 MHz.
Selain itu, tepi jejak sinyal gigi gergaji berantakan dan dari bawah sinyal tidak mencapai nilai yang seharusnya. Ini karena sinyal tidak punya waktu untuk mencapai level rendah yang ditentukan, dan perangkat lunak memuat nilai-nilai baru
Generasi pada 200 KHz ( amplitudo 90% ):
Di sini Anda sudah bisa melihat bagaimana semua gelombang berubah menjadi segitiga.
Saluran digital
Dengan saluran digital, semuanya jauh lebih sederhana - di hampir semua mikrokontroler ada timer yang memungkinkan Anda untuk mengeluarkan sinyal PWM ke output mikrokontroler. Cara terbaik adalah menggunakan timer 32-bit - dalam hal ini, Anda tidak perlu menghitung timer pra-timer, cukup memuat periode dalam satu register dan memuat siklus tugas yang diperlukan dalam register lain.
Antarmuka pengguna
Diputuskan untuk mengatur antarmuka pengguna menjadi empat persegi panjang, masing-masing dengan gambar sinyal output, frekuensi dan siklus amplitudo / tugas. Untuk saluran yang saat ini dipilih, data teks ditampilkan dalam warna putih, sisanya berwarna abu-abu.

Diputuskan untuk melakukan kontrol terhadap enkoder: yang kiri bertanggung jawab atas frekuensi dan saluran yang dipilih saat ini (
berubah ketika tombol ditekan ), yang kanan bertanggung jawab atas siklus amplitudo / tugas dan bentuk gelombang (
perubahan ketika tombol ditekan ).
Selain itu, dukungan untuk layar sentuh diterapkan - ketika Anda mengklik pada saluran yang tidak aktif, itu menjadi aktif, ketika Anda mengklik pada saluran yang aktif, bentuk gelombang berubah.
Tentu saja, DevCore terbiasa melakukan semua ini. Kode untuk menginisialisasi antarmuka pengguna dan memperbarui data di layar terlihat seperti ini:
Struktur yang berisi semua objek UI Kode inisialisasi antarmuka pengguna Kode pembaruan layar for(uint32_t i = 0U; i < CHANNEL_CNT; i++) { ch_dsc[i].img.SetImage(waveforms[ch_dsc[i].waveform]); snprintf(ch_dsc[i].freq_str_data, NumberOf(ch_dsc[i].freq_str_data), "Freq: %7lu Hz", ch_dsc[i].frequency); if(IsAnalogChannel(i)) snprintf(ch_dsc[i].duty_str_data, NumberOf(ch_dsc[i].duty_str_data), "Ampl: %7d %%", ch_dsc[i].duty); else snprintf(ch_dsc[i].duty_str_data, NumberOf(ch_dsc[i].duty_str_data), "Duty: %7d %%", ch_dsc[i].duty);
Implementasi yang menarik dari klik tombol diimplementasikan (itu
adalah persegi panjang di mana elemen yang tersisa diambil ). Jika Anda melihat kode, Anda seharusnya memperhatikan hal seperti itu:
ch_dsc [i] .box.SetCallback (& ββCallback, this, nullptr, i); disebut dalam satu lingkaran. Ini adalah tugas fungsi panggilan balik yang akan dipanggil saat tombol ditekan. Berikut ini ditransfer ke fungsi: alamat fungsi statis dari fungsi statis kelas, pointer ini, dan dua parameter pengguna yang akan diteruskan ke fungsi callback - pointer (
tidak digunakan dalam kasus ini - nullptr dilewatkan ) dan nomor (
nomor saluran ditransmisikan ).
Dari bangku universitas, saya ingat postulat: "
Fungsi statis tidak memiliki akses ke anggota kelas yang tidak statis ." Jadi ini
tidak benar . Karena fungsi statis adalah anggota kelas, ia
memiliki akses ke semua anggota kelas jika memiliki tautan / penunjuk ke kelas ini. Sekarang lihat fungsi callback:
Di baris pertama dari fungsi ini, "
sihir " terjadi, setelah itu Anda dapat mengakses anggota kelas mana pun, termasuk yang pribadi.
Omong-omong, fungsi ini dipanggil dalam tugas lain (
menampilkan layar ), jadi di dalam fungsi ini Anda perlu menjaga sinkronisasi. Dalam proyek "
pasangan malam " sederhana ini, saya tidak melakukan ini, karena dalam kasus khusus ini tidak penting.
Kode sumber generator yang diunggah ke GitHub:
https://github.com/nickshl/WaveformGeneratorDevCore sekarang dialokasikan ke repositori terpisah dan dimasukkan sebagai submodule.
Nah, mengapa saya membutuhkan generator sinyal, itu akan ada di artikel berikutnya (
atau salah satu dari berikut ).