ProHoster > Blog > berita internet > Membaca lembaran data 2: SPI pada STM32; PWM, pemasa dan gangguan pada STM8
Membaca lembaran data 2: SPI pada STM32; PWM, pemasa dan gangguan pada STM8
В bahagian pertama Saya cuba memberitahu jurutera elektronik hobi yang membesar dari seluar Arduino bagaimana dan mengapa mereka harus membaca lembaran data dan dokumentasi lain untuk mikropengawal. Teksnya ternyata besar, jadi saya berjanji untuk menunjukkan contoh praktikal dalam artikel berasingan. Dia menamakan dirinya cendawan susu...
Hari ini saya akan menunjukkan kepada anda cara menggunakan lembaran data untuk menyelesaikan agak mudah, tetapi perlu untuk banyak projek, tugas pada STM32 (Pil Biru) dan pengawal STM8. Semua projek demo didedikasikan untuk LED kegemaran saya, kami akan menyalakannya dalam kuantiti yang banyak, yang mana kami perlu menggunakan semua jenis peranti yang menarik.
Teks sekali lagi ternyata besar, jadi untuk kemudahan saya membuat kandungannya:
Penafian: Saya bukan jurutera, saya tidak berpura-pura mempunyai pengetahuan mendalam dalam elektronik, artikel itu ditujukan untuk amatur seperti saya. Malah, saya menganggap diri saya dua tahun lalu sebagai penonton sasaran. Jika seseorang memberitahu saya bahawa lembaran data pada cip yang tidak dikenali tidak menakutkan untuk dibaca, saya tidak akan menghabiskan banyak masa mencari beberapa keping kod di Internet dan mencipta tongkat dengan gunting dan pita pelekat.
Fokus artikel ini adalah pada lembaran data, bukan projek, jadi kod mungkin tidak begitu kemas dan sering sempit. Projek itu sendiri sangat mudah, walaupun sesuai untuk kenalan pertama dengan cip baharu.
Saya berharap artikel saya akan membantu seseorang yang berada pada tahap yang serupa dalam hobi.
STM32
16 LED dengan DM634 dan SPI
Projek kecil menggunakan Pil Biru (STM32F103C8T6) dan pemacu LED DM634. Menggunakan lembaran data, kami akan mengetahui pemacu, port IO STM dan mengkonfigurasi SPI.
DM634
Cip Taiwan dengan 16 output PWM 16-bit, boleh disambungkan dalam rantai. Model 12-bit rendah diketahui daripada projek domestik Pek ringan. Pada satu masa, memilih antara DM63x dan TLC5940 yang terkenal, saya memilih DM atas beberapa sebab: 1) TLC pada Aliexpress pastinya palsu, tetapi yang ini tidak; 2) DM mempunyai PWM autonomi dengan penjana frekuensinya sendiri; 3) ia boleh dibeli dengan murah di Moscow, daripada menunggu bungkusan daripada Ali. Dan, tentu saja, adalah menarik untuk belajar bagaimana untuk mengawal cip itu sendiri, dan bukannya menggunakan perpustakaan siap pakai. Cip kini terutamanya dibentangkan dalam pakej SSOP24; ia mudah dipateri kepada penyesuai.
Oleh kerana pengeluarnya adalah warga Taiwan, Lembaran data cip itu ditulis dalam bahasa Inggeris Cina, yang bermaksud ia akan menjadi menyeronokkan. Mula-mula kita lihat pinout (Sambungan Pin) untuk memahami kaki mana yang hendak disambungkan, dan perihalan pin (Huraian Pin). 16 pin:
Sumber Sinki DC (Longkang Terbuka)
Sink / Keluaran longkang terbuka – longkang; punca arus masuk; output disambungkan ke tanah dalam keadaan aktif - LED disambungkan kepada pemacu oleh katod. Secara elektrik, ini, sudah tentu, bukan "longkang terbuka" (longkang terbuka), tetapi dalam lembaran data sebutan ini untuk pin dalam mod longkang sering dijumpai.
Perintang luar antara REXT dan GND untuk menetapkan nilai arus keluaran
Perintang rujukan dipasang di antara pin REXT dan tanah, yang mengawal rintangan dalaman output, lihat graf pada halaman 9 lembaran data. Dalam DM634, rintangan ini juga boleh dikawal oleh perisian, menetapkan kecerahan keseluruhan (kecerahan global); Saya tidak akan menerangkan butiran dalam artikel ini, saya hanya akan meletakkan perintang 2.2 - 3 kOhm di sini.
Untuk memahami cara mengawal cip, mari lihat penerangan antara muka peranti:
Ya, ini dia, Bahasa Inggeris Cina dalam segala kegemilangannya. Menterjemah ini bermasalah, anda boleh memahaminya jika anda mahu, tetapi ada cara lain - lihat bagaimana sambungan kepada TLC5940 yang serupa secara fungsi diterangkan dalam lembaran data:
... Hanya tiga pin diperlukan untuk memasukkan data ke dalam peranti. Tepi menaik isyarat SCLK mengalihkan data daripada pin SIN ke daftar dalaman. Selepas semua data telah dimuatkan, isyarat XLAT tinggi pendek menyelak data yang dipindahkan secara berurutan ke dalam daftar dalaman. Daftar dalaman ialah pintu yang dicetuskan oleh tahap isyarat XLAT. Semua data dihantar bit yang paling penting terlebih dahulu.
Selak – selak/selak/kunci. kelebihan yang semakin meningkat – bahagian hadapan nadi MSB dulu – bit paling ketara (paling kiri) ke hadapan. kepada data jam – menghantar data secara berurutan (sedikit demi sedikit).
Word selak sering dijumpai dalam dokumentasi untuk cip dan diterjemahkan dalam pelbagai cara, jadi demi pemahaman saya akan membenarkan diri saya
program pendidikan kecilPemacu LED pada asasnya adalah daftar syif. "Anjakan" (peralihan) dalam nama - pergerakan data secara bitwise di dalam peranti: setiap bit baharu yang ditolak ke dalam menolak keseluruhan rantai ke hadapan di hadapannya. Memandangkan tiada siapa yang mahu melihat LED berkelip huru-hara semasa peralihan, proses berlaku dalam daftar penimbal yang dipisahkan daripada daftar kerja oleh peredam (selak) ialah sejenis ruang menunggu di mana bit disusun mengikut urutan yang dikehendaki. Apabila semuanya sudah sedia, pengatup terbuka dan bit berfungsi, menggantikan kumpulan sebelumnya. Perkataan selak dalam dokumentasi untuk litar mikro hampir selalu membayangkan peredam sedemikian, tidak kira dalam kombinasi apa yang digunakan.
Jadi, pemindahan data ke DM634 dijalankan seperti ini: tetapkan input DAI kepada nilai bit paling ketara dari jauh LED, tarik DCK ke atas dan ke bawah; tetapkan input DAI kepada nilai bit seterusnya, tarik DCK; dan seterusnya sehingga semua bit telah dihantar (jam masuk), selepas itu kita tarik LAT. Ini boleh dilakukan secara manual (bit-bang), tetapi lebih baik menggunakan antara muka SPI yang disesuaikan khas untuk ini, kerana ia dibentangkan pada STM32 kami dalam dua salinan.
Pil Biru STM32F103
Pengenalan: Pengawal STM32 jauh lebih kompleks daripada Atmega328 daripada yang mungkin kelihatan menakutkan. Selain itu, atas sebab penjimatan tenaga, hampir semua peranti dimatikan pada permulaan, dan kekerapan jam ialah 8 MHz dari sumber dalaman. Nasib baik, pengaturcara STM menulis kod yang membawa cip sehingga 72 MHz "dikira", dan pengarang semua IDE yang saya tahu memasukkannya dalam prosedur permulaan, jadi kami tidak perlu jam (tetapi anda boleh jika anda benar-benar mahu). Tetapi anda perlu menghidupkan peranti peranti.
Dokumentasi: Pil Biru dilengkapi dengan cip STM32F103C8T6 yang popular, terdapat dua dokumen berguna untuknya:
Risalah Data untuk mikropengawal STM32F103x8 dan STM32F103xB;
Manual rujukan untuk keseluruhan talian STM32F103 dan banyak lagi.
Dalam lembaran data kami mungkin berminat dengan:
Pinout - pinout cip - sekiranya kami memutuskan untuk membuat papan sendiri;
Peta Memori – peta memori untuk cip tertentu. Manual Rujukan mempunyai peta untuk keseluruhan baris, dan ia menyebut daftar yang kami tidak miliki.
Jadual Definisi Pin – menyenaraikan fungsi utama dan alternatif pin; untuk "pil biru" anda boleh menemui gambar yang lebih mudah di Internet dengan senarai pin dan fungsinya. Oleh itu, kami segera menggoogle pinout Pil Biru dan menyimpan gambar ini di tangan:
NB: terdapat ralat dalam gambar dari Internet, yang dinyatakan dalam ulasan, terima kasih untuk itu. Gambar telah diganti, tetapi ini adalah pengajaran - lebih baik untuk menyemak maklumat bukan dari lembaran data.
Kami mengalih keluar lembaran data, membuka Manual Rujukan, dan mulai sekarang kami hanya menggunakannya.
Prosedur: kami berurusan dengan input/output standard, mengkonfigurasi SPI, menghidupkan peranti yang diperlukan.
Input Output
Pada Atmega328, I/O dilaksanakan dengan sangat ringkas, itulah sebabnya banyak pilihan STM32 boleh mengelirukan. Sekarang kita hanya memerlukan kesimpulan, tetapi ini mempunyai empat pilihan:
longkang terbuka, tolak-tarik, tolak-tolak alternatif, longkang terbuka alternatif
"Tarik tolak" (tolak tarik) ialah keluaran biasa daripada Arduino, pin boleh mengambil nilai sama ada HIGH atau LOW. Tetapi dengan "longkang terbuka" ada kesukaran, walaupun sebenarnya semuanya mudah di sini:
Konfigurasi output / apabila port ditetapkan kepada output: / penimbal output didayakan: / – mod saliran terbuka: “0” dalam daftar output membolehkan N-MOS, “1” dalam daftar output meninggalkan port dalam mod Hi-Z ( P-MOS tidak diaktifkan ) / – mod tolak-tarik: “0” dalam daftar output mengaktifkan N-MOS, “1” dalam daftar output mengaktifkan P-MOS.
Semua perbezaan antara longkang terbuka (longkang terbuka) daripada “tolak-tarik” (tolak tarik) ialah dalam pin pertama tidak boleh menerima keadaan TINGGI: apabila menulis satu ke daftar keluaran, ia masuk ke mod rintangan tinggi (impedans tinggi, Hai-Z). Apabila menulis sifar, pin berkelakuan sama dalam kedua-dua mod, secara logik dan elektrik.
Dalam mod keluaran biasa, pin hanya menyiarkan kandungan daftar keluaran. Dalam "alternatif" ia dikawal oleh peranti yang sepadan (lihat 9.1.4):
Jika bit port dikonfigurasikan sebagai pin fungsi ganti, daftar pin dinyahdayakan dan pin disambungkan ke pin persisian.
Kefungsian alternatif setiap pin diterangkan dalam Definisi Pin Lembaran data terdapat pada imej yang dimuat turun. Kepada soalan tentang apa yang perlu dilakukan jika pin mempunyai beberapa fungsi alternatif, jawapan diberikan oleh nota kaki dalam lembaran data:
Jika berbilang persisian menggunakan pin yang sama, untuk mengelakkan konflik antara fungsi alternatif, hanya satu persisian harus digunakan pada satu masa, ditogol menggunakan bit daya jam persisian (dalam daftar RCC yang sesuai).
Akhirnya, pin dalam mod output juga mempunyai kelajuan jam. Ini adalah satu lagi ciri penjimatan tenaga; dalam kes kami, kami hanya menetapkannya kepada maksimum dan melupakannya.
Jadi: kami menggunakan SPI, yang bermaksud bahawa dua pin (dengan data dan dengan isyarat jam) hendaklah "fungsi tolak-tarik alternatif", dan satu lagi (LAT) hendaklah "tarik-tolak biasa". Tetapi sebelum menugaskan mereka, mari kita berurusan dengan SPI.
SPI
Satu lagi program pendidikan kecil
SPI atau Serial Peripheral Interface (antara muka persisian bersiri) ialah antara muka yang mudah dan sangat berkesan untuk menyambungkan MK dengan MK lain dan dunia luar secara amnya. Prinsip operasinya telah diterangkan di atas, di mana mengenai pemacu LED Cina (dalam manual rujukan, lihat bahagian 25). SPI boleh beroperasi dalam mod induk (“tuan”) dan hamba (“hamba”). SPI mempunyai empat saluran asas, yang mana tidak semuanya boleh digunakan:
MOSI, Output Induk / Input Hamba: pin ini menghantar data dalam mod induk, dan menerima data dalam mod hamba;
MISO, Input Induk / Output Hamba: sebaliknya, ia menerima dalam tuan, dan menghantar dalam hamba;
SCK, Jam Bersiri: menetapkan kekerapan penghantaran data dalam induk atau menerima isyarat jam dalam hamba. Pada asasnya memukul rentak;
SS, Slave Select: dengan bantuan saluran ini, hamba tahu bahawa ada sesuatu yang dikehendaki daripadanya. Pada STM32 ia dipanggil NSS, di mana N = negatif, i.e. pengawal menjadi hamba jika terdapat tanah dalam saluran ini. Ia digabungkan dengan baik dengan mod Open Drain Output, tetapi itu cerita lain.
Seperti segala-galanya, SPI pada STM32 kaya dengan fungsi, yang menjadikannya agak sukar untuk difahami. Sebagai contoh, ia boleh berfungsi bukan sahaja dengan SPI, tetapi juga dengan antara muka I2S, dan dalam dokumentasi penerangan mereka bercampur-campur, adalah perlu untuk memotong lebihan tepat pada masanya. Tugas kami sangat mudah: kami hanya perlu menghantar data menggunakan MOSI dan SCK sahaja. Kami pergi ke bahagian 25.3.4 (komunikasi separuh dupleks, komunikasi separuh dupleks), di mana kami dapati 1 jam dan 1 wayar data satu arah (1 isyarat jam dan 1 aliran data satu arah):
Dalam mod ini, aplikasi menggunakan SPI sama ada dalam mod penghantaran sahaja atau terima sahaja. / Mod penghantaran sahaja adalah serupa dengan mod dupleks: data dihantar pada pin hantar (MOSI dalam mod induk atau MISO dalam mod hamba), dan pin terima (MISO atau MOSI masing-masing) boleh digunakan sebagai pin I/O biasa . Dalam kes ini, aplikasi hanya perlu mengabaikan penimbal Rx (jika ia dibaca, tidak akan ada data yang dipindahkan di sana).
Hebat, pin MISO adalah percuma, mari sambungkan isyarat LAT kepadanya. Mari kita lihat Slave Select, yang pada STM32 boleh dikawal secara pemrograman, yang sangat mudah. Kami membaca perenggan dengan nama yang sama dalam bahagian 25.3.1 Penerangan Umum SPI:
Kawalan perisian NSS (SSM = 1) / Maklumat pemilihan hamba terkandung dalam bit SSI daftar SPI_CR1. Pin NSS luaran kekal percuma untuk keperluan aplikasi lain.
Sudah tiba masanya untuk menulis kepada pendaftar. Saya memutuskan untuk menggunakan SPI2, cari alamat asasnya dalam lembaran data - dalam bahagian 3.3 Peta Memori:
Buka bahagian 25.3.3 dengan tajuk penjelasan sendiri "Mengkonfigurasi SPI dalam Mod Induk":
1. Tetapkan kekerapan jam bersiri dengan bit BR[2:0] dalam daftar SPI_CR1.
Daftar dikumpul dalam bahagian manual rujukan dengan nama yang sama. peralihan alamat (Alamat diimbangi) untuk CR1 – 0x00, secara lalai semua bit dikosongkan (Tetapkan semula nilai 0x0000):
Bit BR menetapkan pembahagi jam pengawal, dengan itu menentukan kekerapan di mana SPI akan beroperasi. Kekerapan STM32 kami ialah 72 MHz, pemacu LED, mengikut lembaran datanya, beroperasi dengan frekuensi sehingga 25 MHz, jadi kami perlu membahagikan dengan empat (BR[2:0] = 001).
2. Tetapkan bit CPOL dan CPHA untuk menentukan hubungan antara pemindahan data dan pemasaan jam bersiri (lihat rajah pada halaman 240)
Memandangkan kita sedang membaca lembaran data di sini dan tidak melihat skema, mari kita lihat dengan lebih dekat perihalan teks bit CPOL dan CPHA pada halaman 704 (Penerangan Umum SPI):
Fasa jam dan kekutuban
Menggunakan bit CPOL dan CPHA daftar SPI_CR1, anda boleh memilih empat perhubungan pemasaan secara pemrograman. Bit CPOL (kekutuban jam) mengawal keadaan isyarat jam apabila tiada data sedang dihantar. Bit ini mengawal mod tuan dan hamba. Jika CPOL ditetapkan semula, pin SCK rendah dalam mod rehat. Jika bit CPOL ditetapkan, pin SCK adalah tinggi semasa mod rehat.
Apabila bit CPHA (fasa jam) ditetapkan, strob perangkap bit tinggi ialah pinggir kedua isyarat SCK (jatuh jika CPOL jelas, meningkat jika CPOL ditetapkan). Data ditangkap oleh perubahan kedua dalam isyarat jam. Jika bit CPHA adalah jelas, strob perangkap bit tinggi ialah pinggir menaik bagi isyarat SCK (tepi jatuh jika CPOL ditetapkan, tepi meningkat jika CPOL dibersihkan). Data ditangkap pada perubahan pertama dalam isyarat jam.
Setelah menyerap pengetahuan ini, kami sampai pada kesimpulan bahawa kedua-dua bit mesti kekal sifar, kerana Kami mahu isyarat SCK kekal rendah apabila tidak digunakan, dan data dihantar pada pinggir nadi yang semakin meningkat (lihat Rajah. Rising Edge dalam lembaran data DM634).
Ngomong-ngomong, di sini kita mula-mula menemui ciri perbendaharaan kata dalam lembaran data ST: di dalamnya frasa "set semula bit kepada sifar" ditulis untuk menetapkan semula sedikitDan tidak untuk membersihkan sedikit, seperti, contohnya, Atmega.
3. Tetapkan bit DFF untuk menentukan sama ada blok data adalah format 8-bit atau 16-bit
Saya secara khusus mengambil DM16 634-bit supaya tidak mengganggu penghantaran data PWM 12-bit, seperti DM633. Masuk akal untuk menetapkan DFF kepada satu:
4. Konfigurasikan bit LSBFIRST dalam daftar SPI_CR1 untuk menentukan format blok
LSBFIRST, seperti namanya, mengkonfigurasi penghantaran dengan bit paling tidak ketara terlebih dahulu. Tetapi DM634 mahu menerima data bermula dari bit yang paling ketara. Oleh itu, kami biarkan ia ditetapkan semula.
5. Dalam mod perkakasan, jika input daripada pin NSS diperlukan, gunakan isyarat tinggi pada pin NSS semasa keseluruhan urutan pemindahan bait. Dalam mod perisian NSS, tetapkan bit SSM dan SSI dalam daftar SPI_CR1. Jika pin NSS hendak digunakan sebagai output, hanya bit SSOE perlu ditetapkan.
Pasang SSM dan SSI untuk melupakan mod perkakasan NSS:
#define SSI 0x0100
#define SSM 0x0200
_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high
6. Bit MSTR dan SPE mesti ditetapkan (ia kekal ditetapkan hanya jika isyarat NSS tinggi)
Sebenarnya, dengan bit ini kami menetapkan SPI kami sebagai induk dan menghidupkannya:
SPI dikonfigurasikan, mari segera menulis fungsi yang menghantar bait kepada pemacu. Teruskan membaca 25.3.3 “Mengkonfigurasi SPI dalam mod induk”:
Perintah pemindahan data
Penghantaran bermula apabila bait ditulis kepada penimbal Tx.
Bait data dimuatkan ke dalam daftar anjakan di selari mod (dari bas dalaman) semasa penghantaran bit pertama, selepas itu ia dihantar ke berurutan Mod pin MOSI, bit pertama atau terakhir ke hadapan bergantung pada tetapan bit LSBFIRST dalam daftar CPI_CR1. Bendera TXE ditetapkan selepas penghantaran data daripada Tx buffer kepada shift register, dan juga menjana gangguan jika bit TXEIE dalam daftar CPI_CR1 ditetapkan.
Saya menyerlahkan beberapa perkataan dalam terjemahan untuk menarik perhatian kepada satu ciri pelaksanaan SPI dalam pengawal STM. Pada Atmega bendera TXE (Tx Kosong, Tx kosong dan sedia untuk menerima data) ditetapkan hanya selepas keseluruhan bait telah dihantar keluar. Dan di sini bendera ini ditetapkan selepas bait telah dimasukkan ke dalam daftar anjakan dalaman. Oleh kerana ia ditolak ke sana dengan semua bit pada masa yang sama (selari), dan kemudian data dihantar secara berurutan, TXE ditetapkan sebelum bait dihantar sepenuhnya. Ini penting kerana dalam kes pemandu LED kami, kami perlu menarik pin LAT selepas menghantar Semua data, i.e. Bendera TXE sahaja tidak akan mencukupi untuk kita.
Ini bermakna kita memerlukan bendera lain. Mari lihat 25.3.7 - "Bendera Status":
<…>
bendera SIBUK
Bendera BSY ditetapkan dan dibersihkan oleh perkakasan (menulis kepadanya tidak mempunyai kesan). Bendera BSY menunjukkan keadaan lapisan komunikasi SPI.
Ia menetapkan semula:
apabila pemindahan selesai (kecuali dalam mod induk jika pemindahan berterusan)
apabila SPI dilumpuhkan
apabila ralat mod induk berlaku (MODF=1)
Jika pemindahan tidak berterusan, bendera BSY dikosongkan antara setiap pemindahan data
Okay, ini akan berguna. Mari ketahui di mana penimbal Tx berada. Untuk melakukan ini, baca "Daftar Data SPI":
Daftar Data Bit 15:0 DR[15:0].
Data yang diterima atau data yang akan dihantar.
Daftar data dibahagikan kepada dua buffer - satu untuk menulis (transmit buffer) dan satu untuk membaca (receive buffer). Menulis ke daftar data menulis kepada penimbal Tx, dan membaca dari daftar data akan mengembalikan nilai yang terkandung dalam penimbal Rx.
Nah, dan daftar status, di mana bendera TXE dan BSY ditemui:
Nah, kerana kita perlu menghantar 16 kali dua bait, mengikut bilangan output pemacu LED, seperti ini:
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();
}
Tetapi kami belum tahu cara menarik pin LAT lagi, jadi kami akan kembali ke I/O.
Menetapkan pin
Dalam STM32F1, daftar yang bertanggungjawab untuk keadaan pin agak luar biasa. Jelas bahawa terdapat lebih banyak daripada mereka daripada Atmega, tetapi mereka juga berbeza daripada cip STM yang lain. Bahagian 9.1 Penerangan Umum GPIO:
Setiap port I/O tujuan umum (GPIO) mempunyai dua daftar konfigurasi 32-bit (GPIOx_CRL dan GPIOx_CRH), dua daftar data 32-bit (GPIOx_IDR dan GPIOx_ODR), daftar set/set 32-bit (GPIOx_BSRR), daftar set semula 16-bit (GPIOx_BRR) dan 32- daftar penyekat bit (GPIOx_LCKR).
Dua daftar pertama adalah luar biasa, dan juga agak menyusahkan, kerana 16 pin port bertaburan merentasi mereka dalam format "empat bit setiap saudara". Itu. pin sifar hingga tujuh berada dalam CRL, dan selebihnya dalam CRH. Pada masa yang sama, daftar yang tinggal berjaya mengandungi bit semua pin port - selalunya tinggal separuh "terpelihara".
Untuk kesederhanaan, mari kita mulakan dari akhir senarai.
Kami tidak memerlukan daftar penyekat.
Daftar set dan set semula agak lucu kerana ia sebahagiannya menduplikasi antara satu sama lain: anda boleh menulis semuanya hanya dalam BSRR, di mana 16 bit yang lebih tinggi akan menetapkan semula pin kepada sifar, dan yang lebih rendah akan ditetapkan kepada 1, atau anda juga boleh gunakan BRR, 16 bit yang lebih rendah daripadanya hanya menetapkan semula pin . Saya suka pilihan kedua. Daftar ini penting kerana ia menyediakan akses atom kepada pin:
Set Atom atau Set Semula
Tidak perlu melumpuhkan gangguan apabila memprogramkan GPIOx_ODR pada tahap bit: satu atau lebih bit boleh ditukar dengan satu operasi tulis atom APB2. Ini dicapai dengan menulis "1" pada daftar set/set semula (GPIOx_BSRR atau, untuk set semula sahaja, GPIOx_BRR) bit yang perlu diubah. Bit lain akan kekal tidak berubah.
Daftar data mempunyai nama yang cukup jelas - IDR = Input Daftar Arah, daftar masukan; ODR = Output Daftar Arah, daftar keluaran. Kami tidak memerlukannya dalam projek semasa.
Dan akhirnya, daftar kawalan. Oleh kerana kami berminat dengan pin SPI kedua, iaitu PB13, PB14 dan PB15, kami segera melihat CRH:
Dan kita melihat bahawa kita perlu menulis sesuatu dalam bit dari 20 hingga 31.
Kami telah mengetahui di atas apa yang kami mahu daripada pin, jadi di sini saya akan lakukan tanpa tangkapan skrin, saya hanya akan mengatakan bahawa MODE menentukan arah (input jika kedua-dua bit ditetapkan kepada 0) dan kelajuan pin (kita memerlukan 50MHz, i.e. kedua-dua pin kepada "1"), dan CNF menetapkan mod: "tekan-tarik" biasa - 00, "alternatif" - 10. Secara lalai, seperti yang kita lihat di atas, semua pin mempunyai bit ketiga dari bawah (CNF0), ia menetapkan mereka kepada mod input terapung.
Oleh kerana saya bercadang untuk melakukan sesuatu yang lain dengan cip ini, untuk kesederhanaan saya telah menentukan semua nilai MODE dan CNF yang mungkin untuk kedua-dua daftar kawalan bawah dan atas.
(LAT_rendah hanya dengan inersia, ia sentiasa seperti itu, biarkan ia kekal)
Sekarang semuanya hebat, tetapi ia tidak berfungsi. Kerana ini adalah STM32, ia menjimatkan tenaga elektrik, yang bermaksud anda perlu mendayakan masa bagi peranti yang diperlukan.
Hidupkan jam
Jam tangan, juga dikenali sebagai Jam, bertanggungjawab untuk mencatat masa. Dan kita sudah dapat melihat singkatan RCC. Kami mencarinya dalam dokumentasi: ini ialah Reset dan Kawalan Jam.
Seperti yang dinyatakan di atas, mujurlah, bahagian yang paling sukar dalam topik masa telah dilakukan untuk kami oleh orang dari STM, yang mana kami mengucapkan ribuan terima kasih kepada mereka (sekali lagi saya akan memberikan pautan kepada laman web Di Halt, untuk menjelaskan betapa mengelirukannya). Kami hanya memerlukan daftar yang bertanggungjawab untuk mendayakan jam persisian (Jam Periferal Membolehkan Daftar). Mula-mula, mari kita cari alamat asas RCC, ia adalah pada permulaan "Peta Memori":
Dan kemudian sama ada klik pada pautan di mana anda cuba mencari sesuatu dalam pinggan, atau, lebih baik, pergi melalui penerangan tentang daftar yang membolehkan dari bahagian tentang membolehkan daftar. Di mana kita akan menemui RCC_APB1ENR dan RCC_APB2ENR:
Dan mereka, sewajarnya, mengandungi bit yang termasuk penyusunan masa SPI2, IOPB (I/O Port B) dan fungsi alternatif (AFIO).
Jika anda mempunyai peluang dan keinginan untuk menguji, kemudian sambungkan DM634 seperti ini: DAI ke PB15, DCK ke PB13, LAT ke PB14. Kami memberi kuasa kepada pemandu dari 5 volt, jangan lupa untuk menyambungkan alasan.
STM8 PWM
PWM pada STM8
Apabila saya baru merancang artikel ini, saya memutuskan, sebagai contoh, untuk cuba menguasai beberapa fungsi cip yang tidak dikenali hanya menggunakan lembaran data, supaya saya tidak akan berakhir dengan pembuat kasut tanpa but. STM8 adalah sesuai untuk peranan ini: pertama, saya mempunyai beberapa papan Cina dengan STM8S103, dan kedua, ia tidak begitu popular, dan oleh itu godaan untuk membaca dan mencari penyelesaian di Internet terletak pada kekurangan penyelesaian ini.
Secara lalai, STM8 beroperasi pada frekuensi 2 MHz, ini mesti diperbetulkan dengan segera.
Jam HSI (Dalaman Dalaman Berkelajuan Tinggi).
Isyarat jam HSI diperolehi daripada pengayun RC dalaman 16 MHz dengan pembahagi boleh atur cara (1 hingga 8). Ia ditetapkan dalam daftar pembahagi jam (CLK_CKDIVR).
Nota: pada permulaan, pengayun RC HSI dengan pembahagi 8 dipilih sebagai sumber utama isyarat jam.
Kami mencari alamat daftar dalam lembaran data, penerangan dalam refman dan melihat bahawa daftar perlu dikosongkan:
Oleh kerana kita akan menjalankan PWM dan menyambungkan LED, mari lihat pinout:
Cipnya kecil, banyak fungsi digantung pada pin yang sama. Apa yang terdapat dalam kurungan segi empat sama ialah "fungsi alternatif", ia ditukar oleh "bait pilihan" (bait pilihan) – sesuatu seperti Atmega fius. Anda boleh menukar nilai mereka secara pemrograman, tetapi ia tidak perlu, kerana Fungsi baharu diaktifkan hanya selepas but semula. Lebih mudah untuk menggunakan ST Visual Programmer (dimuat turun dengan Visual Develop), yang boleh menukar bait ini. Pinout menunjukkan bahawa pin CH1 dan CH2 pemasa pertama disembunyikan dalam kurungan segi empat sama; adalah perlu untuk menetapkan bit AFR1 dan AFR0 dalam STVP, dan yang kedua juga akan memindahkan output CH1 pemasa kedua dari PD4 ke PC5.
Oleh itu, 6 pin akan mengawal LED: PC6, PC7 dan PC3 untuk pemasa pertama, PC5, PD3 dan PA3 untuk yang kedua.
Menyediakan pin I/O sendiri pada STM8 adalah lebih mudah dan lebih logik daripada pada STM32:
biasa dari daftar arah data DDR Atmega (Daftar Arah Data): 1 = keluaran;
daftar kawalan pertama CR1, apabila output, menetapkan mod tolak-tarik (1) atau longkang terbuka (0); kerana saya menyambungkan LED ke cip dengan katod, saya meninggalkan sifar di sini;
daftar kawalan kedua CR2, apabila output, menetapkan kelajuan jam: 1 = 10 MHz
Muat semula automatik, AR – nilai autoloadable sehingga pemasa akan dikira (tempoh nadi);
Kemas kini Acara, UEV – peristiwa yang berlaku apabila pemasa telah dikira kepada AR;
Kitaran Tugas PWM – Kitaran tugas PWM, sering dipanggil "faktor tugas";
Tangkap/Bandingkan Nilai – nilai untuk tangkapan/perbandingan, yang pemasa telah dikira akan melakukan sesuatu (dalam kes PWM, ia menyongsangkan isyarat keluaran);
Nilai Pramuat – nilai pramuat. Bandingkan nilai tidak boleh berubah semasa pemasa berdetik, jika tidak, kitaran PWM akan pecah. Oleh itu, nilai yang dihantar baru diletakkan dalam penimbal dan ditarik keluar apabila pemasa mencapai penghujung kira detiknya dan ditetapkan semula;
Dijajarkan tepi и Mod sejajar tengah – penjajaran di sepanjang sempadan dan di tengah, sama seperti Atmel PWM pantas и PWM pembetulan fasa.
OCiREF, Output Bandingkan Isyarat Rujukan – isyarat keluaran rujukan, sebenarnya, apa yang muncul pada pin yang sepadan dalam mod PWM.
Seperti yang sudah jelas dari pinout, dua pemasa mempunyai keupayaan PWM - yang pertama dan yang kedua. Kedua-duanya adalah 16-bit, yang pertama mempunyai banyak ciri tambahan (khususnya, ia boleh mengira kedua-dua naik dan turun). Kami memerlukan kedua-duanya untuk bekerja sama, jadi saya memutuskan untuk memulakan dengan yang kedua yang jelas lebih miskin, supaya tidak menggunakan sesuatu yang tidak ada secara tidak sengaja. Beberapa masalah ialah perihalan fungsi PWM semua pemasa dalam manual rujukan adalah dalam bab tentang pemasa pertama (17.5.7 Mod PWM), jadi anda perlu melompat ke sana ke mari sepanjang dokumen sepanjang masa.
PWM pada STM8 mempunyai kelebihan penting berbanding PWM pada Atmega:
PWM Sejajar Sempadan
Konfigurasi akaun dari bawah ke atas
Pengiraan bawah ke atas aktif jika bit DIR dalam daftar TIM_CR1 dikosongkan
Contoh
Contoh menggunakan mod PWM pertama. Isyarat rujukan PWM OCiREF dipegang tinggi selagi TIM1_CNT < TIM1_CCRi. Jika tidak, ia memerlukan tahap yang rendah. Jika nilai perbandingan dalam daftar TIM1_CCRi lebih besar daripada nilai autoload (daftar TIM1_ARR), isyarat OCiREF dipegang pada 1. Jika nilai perbandingan ialah 0, OCiREF dipegang pada sifar....
Pemasa STM8 semasa acara kemas kini semak dulu bandingkan nilai, dan hanya kemudian menghasilkan isyarat rujukan. Pemasa Atmega mula-mula mengosongkan dan kemudian membandingkan, menghasilkan compare value == 0 output adalah jarum, yang mesti ditangani entah bagaimana (contohnya, dengan membalikkan logik secara pemrograman).
Jadi apa yang kita mahu lakukan: 8-bit PWM (AR == 255), mengira dari bawah ke atas, penjajaran di sepanjang sempadan. Memandangkan mentol lampu disambungkan kepada cip oleh katod, PWM harus mengeluarkan 0 (LED dihidupkan) sehingga bandingkan nilai dan 1 selepas.
Kami telah membaca tentang beberapa Mod PWM, jadi kami mencari daftar pemasa kedua yang diperlukan dengan mencari dalam manual rujukan untuk frasa ini (18.6.8 - TIMx_CCMR1):
110: Mod PWM pertama – apabila mengira dari bawah ke atas, saluran pertama aktif manakala TIMx_CNT < TIMx_CCR1. Jika tidak, saluran pertama tidak aktif. [selanjutnya dalam dokumen terdapat salinan-tampal yang salah dari pemasa 1] 111: Mod PWM kedua – apabila mengira dari bawah ke atas, saluran pertama tidak aktif manakala TIMx_CNT < TIMx_CCR1. Jika tidak, saluran pertama aktif.
Memandangkan LED disambungkan ke MK oleh katod, mod kedua sesuai dengan kita (yang pertama juga, tetapi kita belum tahu lagi).
Bit 3 OC1PE: Dayakan pramuat pin 1
0: Daftar pramuat pada TIMx_CCR1 dilumpuhkan. Anda boleh menulis kepada TIMx_CCR1 pada bila-bila masa. Nilai baharu berfungsi serta-merta.
1: Daftar pramuat pada TIMx_CCR1 didayakan. Operasi baca/tulis akses daftar pramuat. Nilai pramuat TIMx_CCR1 dimuatkan ke dalam daftar bayangan semasa setiap acara kemas kini.
*Nota: Untuk mod PWM berfungsi dengan betul, daftar pramuat mesti didayakan. Ini tidak diperlukan dalam mod isyarat tunggal (bit OPM ditetapkan dalam daftar TIMx_CR1).
Okey, mari hidupkan semua yang kita perlukan untuk tiga saluran pemasa kedua:
Pemasa kedua hanya boleh mengira dari bawah ke atas, penjajaran di sepanjang sempadan, tiada apa yang perlu diubah. Mari kita tetapkan pembahagi frekuensi, sebagai contoh, kepada 256. Untuk pemasa kedua, pembahagi ditetapkan dalam daftar TIM2_PSCR dan merupakan kuasa dua:
Apa yang tinggal ialah menghidupkan kesimpulan dan pemasa kedua itu sendiri. Masalah pertama diselesaikan dengan daftar Tangkap/Bandingkan enable: terdapat dua, tiga saluran yang bertaburan merentasinya secara tidak simetri. Di sini kita juga boleh mengetahui bahawa adalah mungkin untuk menukar kekutuban isyarat, i.e. pada dasarnya, adalah mungkin untuk menggunakan Mod PWM 1. Kami menulis:
Mari tulis analog mudah AnalogWrite(), yang akan memindahkan nilai sebenar kepada pemasa untuk perbandingan. Daftar-daftar tersebut dinamakan secara boleh diramalkan Tangkap/Banding daftar, terdapat dua daripadanya untuk setiap saluran: 8 bit tertib rendah dalam TIM2_CCRxL dan tertib tinggi dalam TIM2_CCRxH. Oleh kerana kami telah mencipta PWM 8-bit, cukup untuk menulis hanya bit yang paling tidak ketara:
Pembaca yang penuh perhatian akan menyedari bahawa kami mempunyai PWM yang sedikit rosak, tidak dapat menghasilkan isian 100% (pada nilai maksimum 255, isyarat diterbalikkan untuk satu kitaran pemasa). Untuk LED ini tidak penting, dan pembaca yang penuh perhatian sudah boleh meneka cara membetulkannya.
PWM pada pemasa kedua berfungsi, mari kita beralih kepada yang pertama.
Pemasa pertama mempunyai bit yang betul-betul sama dalam daftar yang sama (hanya bit yang kekal "terpelihara" dalam pemasa kedua secara aktif digunakan dalam yang pertama untuk semua jenis perkara lanjutan). Oleh itu, cukup untuk mencari alamat daftar yang sama dalam lembaran data dan menyalin kod. Nah, tukar nilai pembahagi frekuensi, kerana... pemasa pertama mahu menerima bukan kuasa dua, tetapi nilai 16-bit yang tepat dalam dua daftar Prescaler Tinggi и Rendah. Kami melakukan segala-galanya dan... pemasa pertama tidak berfungsi. Apa masalahnya?
Masalahnya hanya boleh diselesaikan dengan melihat seluruh bahagian mengenai daftar kawalan pemasa 1, di mana kita mencari yang tidak dimiliki oleh pemasa kedua. Akan ada 17.7.30 Daftar rehat (TIM1_BKR), di mana terdapat bit ini:
Projek mini ketiga adalah untuk menyambungkan lapan LED RGB ke pemasa kedua dalam mod PWM dan menjadikannya menunjukkan warna yang berbeza. Ia berdasarkan konsep pemultipleksan LED, iaitu jika anda menghidupkan dan mematikan LED dengan sangat, sangat cepat, nampaknya ia sentiasa hidup (kegigihan penglihatan, inersia persepsi visual). Saya pernah buat sesuatu seperti ini pada Arduino.
Algoritma kerja kelihatan seperti ini:
menyambungkan anod LED RGB pertama;
menyalakannya, menghantar isyarat yang diperlukan ke katod;
menunggu sehingga akhir kitaran PWM;
menyambungkan anod LED RGB kedua;
nyalakannya...
Nah, dll. Sudah tentu, untuk operasi yang indah diperlukan anod disambungkan dan LED "dinyalakan" pada masa yang sama. Nah, atau hampir. Walau apa pun, kita perlu menulis kod yang akan mengeluarkan nilai dalam tiga saluran pemasa kedua, menukarnya apabila UEV dicapai, dan pada masa yang sama menukar LED RGB yang sedang aktif.
Memandangkan pensuisan LED adalah automatik, kita perlu mencipta "memori video" dari mana pengendali gangguan akan menerima data. Ini adalah tatasusunan mudah:
uint8_t colors[8][3];
Untuk menukar warna LED tertentu, cukup untuk menulis nilai yang diperlukan ke dalam tatasusunan ini. Dan pembolehubah akan bertanggungjawab untuk bilangan LED aktif
uint8_t cnt;
Demux
Untuk pemultipleksan yang betul, kita memerlukan, anehnya, demultiplexer CD74HC238. Demultiplexer - cip yang melaksanakan operator dalam perkakasan <<. Melalui tiga pin input (bit 0, 1 dan 2) kami memberinya nombor tiga bit X, dan sebagai tindak balas ia mengaktifkan nombor output (1<<X). Baki input cip digunakan untuk menskalakan keseluruhan reka bentuk. Kami memerlukan cip ini bukan sahaja untuk mengurangkan bilangan pin mikropengawal yang diduduki, tetapi juga untuk keselamatan - supaya tidak sengaja menghidupkan lebih banyak LED daripada yang mungkin dan tidak membakar MK. Cip itu berharga satu sen dan hendaklah sentiasa disimpan dalam kabinet ubat rumah anda.
CD74HC238 kami akan bertanggungjawab untuk membekalkan voltan ke anod LED yang dikehendaki. Dalam pemultipleks penuh, ia akan membekalkan voltan ke lajur melalui P-MOSFET, tetapi dalam demo ini ia boleh dilakukan secara langsung, kerana ia menarik 20 mA, mengikut penilaian maksimum mutlak dalam lembaran data. daripada Lembaran Data CD74HC238 kami memerlukan pinout dan helaian cheat ini:
H = aras voltan tinggi, L = aras voltan rendah, X – tak kisah
Kami menyambungkan E2 dan E1 ke tanah, E3, A0, A1 dan A3 ke pin PD5, PC3, PC4 dan PC5 STM8. Memandangkan jadual di atas mengandungi kedua-dua aras rendah dan tinggi, kami mengkonfigurasi pin ini sebagai pin tolak tarik.
PWM
PWM pada pemasa kedua dikonfigurasikan dengan cara yang sama seperti dalam cerita sebelumnya, dengan dua perbezaan:
Pertama, kita perlu mendayakan gangguan dihidupkan Kemas kini Acara (UEV) yang akan memanggil fungsi yang menogol LED aktif. Ini dilakukan dengan menukar bit Kemas Kini Interrupt Enable dalam daftar dengan nama yang jelas
Perbezaan kedua adalah berkaitan dengan fenomena pemultipleksan, seperti ghosting – cahaya parasit diod. Dalam kes kami, ia mungkin muncul disebabkan oleh fakta bahawa pemasa, setelah menyebabkan gangguan pada UEV, terus berdetik, dan pengendali gangguan tidak mempunyai masa untuk menukar LED sebelum pemasa mula menulis sesuatu pada pin. Untuk memerangi ini, anda perlu menyongsangkan logik (0 = kecerahan maksimum, 255 = tiada yang menyala) dan mengelakkan nilai kitaran tugas yang melampau. Itu. pastikan selepas UEV LED padam sepenuhnya untuk satu kitaran PWM.
Elakkan menetapkan r, g dan b kepada 255 dan ingat untuk menyongsangkannya apabila menggunakannya.
menyampuk
Intipati gangguan ialah dalam keadaan tertentu cip berhenti melaksanakan program utama dan memanggil beberapa fungsi luaran. Gangguan berlaku disebabkan oleh pengaruh luaran atau dalaman, termasuk pemasa.
Apabila kami mula-mula mencipta projek dalam ST Visual Develop, sebagai tambahan kepada main.c kami menerima tetingkap dengan fail misteri stm8_interrupt_vector.c, disertakan secara automatik dalam projek. Dalam fail ini, fungsi diberikan kepada setiap gangguan NonHandledInterrupt. Kita perlu mengikat fungsi kita kepada gangguan yang dikehendaki.
Lembaran data mempunyai jadual vektor gangguan, di mana kami mencari yang kami perlukan:
Kami perlu menukar LED di UEV, jadi kami memerlukan gangguan #13.
Oleh itu, pertama sekali, dalam fail stm8_interrupt_vector.c tukar nama lalai bagi fungsi yang bertanggungjawab untuk gangguan No. 13 (IRQ13) kepada anda sendiri:
{0x82, TIM2_Overflow}, /* irq13 */
Kedua, kita perlu membuat fail main.h dengan kandungan berikut:
@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;
}
Yang tinggal hanyalah untuk membolehkan gangguan. Ini dilakukan menggunakan arahan assembler rim - anda perlu mencarinya Manual Pengaturcaraan:
//enable interrupts
_asm("rim");
Satu lagi arahan pemasang ialah sim – mematikan gangguan. Ia mesti dimatikan semasa nilai baharu sedang ditulis pada "memori video", supaya gangguan yang disebabkan pada masa yang salah tidak merosakkan tatasusunan.
Sekiranya sekurang-kurangnya seseorang mendapati artikel ini berguna, maka saya tidak menulisnya dengan sia-sia. Saya akan gembira menerima komen dan teguran, saya akan cuba menjawab segala-galanya.