Dalam sistem saya, saya menggunakan I2C dan saya menyadari di bawah beban interupsi yang berat (dari sumber lain), komunikasi I2C mudah terganggu. Apakah ini perilaku yang diharapkan untuk I2C? Saya akan berharap meskipun beban interupsi, masih akan baik-baik saja karena I2C bukan antarmuka waktu kritis, jam dilengkapi dengan data.
Memperbarui:
Prosesornya adalah STM32. Interupsi disebabkan oleh ADC, saya tidak dapat menonaktifkan interupsi selama peristiwa baca karena itu saya harus menemukan solusi di mana saya dapat membuat komunikasi i2c lebih stabil. STM32 adalah master dan slave adalah perangkat lain (accelerometer).
Pembaruan2:
Ketika saya menghubungkan penganalisa logika ke jam dengan kabel terbang kecil, masalahnya hilang. Menariknya, tidak ada interupsi, baca tulis berfungsi dengan baik, ketika ada interupsi, mereka tidak. Namun, jika saya lampirkan probe ke jam, baca karya tulis di bawah beban interupsi juga. Saya pikir, ada masalah kapasitansi di suatu tempat.
Jawaban:
Ini adalah masalah perangkat lunak, Anda menghabiskan terlalu banyak waktu untuk menyela & rutin I2C Anda tidak dapat mengatasinya (jadi itu adalah dua hal yang tidak benar). Saya telah melalui beberapa situasi yang serupa.
Pertama: Anda harus melakukan sesedikit mungkin dalam interupsi, hanya membaca & menyimpan data, jangan melakukan pemrosesan apa pun yang dapat Anda lakukan di luar ISR, matematika dapat mengambil banyak siklus CPU dan CPU tidak dapat melakukan hal lain sementara di interupsi itu.
Kedua: Selidiki DMA untuk mengotomatisasi hal-hal, sehingga gangguan Anda hampir menjadi proses otomatis latar belakang.
Ketiga: Jika I2C penting, masukkan ITU dalam interupsi juga, tetapi pastikan Anda menentukan prioritas!
Keempat: Cari tahu mengapa rutinitas I2C Anda gagal, I2C itu sendiri bisa tahan terhadap timing yang sangat terputus-putus, jeda & menunggu dll. Sehingga rutin Anda mungkin perlu memodifikasi untuk memungkinkan ini.
Kelima: Lihat apakah Anda dapat "rantai" menyela, Anda mungkin menemukan bahwa Anda dapat memperbaiki ADC membaca lebih efisien, atau menempatkan ADC dalam mode yang berbeda di mana ia bekerja lebih baik sebelum menginterupsi (EG tunggu semua bacaan tersedia, kemudian baca semua dalam satu hit, daripada 8 interupsi terpisah untuk 8 kanal ADC terpisah dibaca).
Keenam: Gunakan osiloskop atau penganalisis logika, dan simpan pin IO di papan tulis, untuk melacak berapa banyak waktu yang Anda habiskan di setiap bit kode, untuk melihat apakah Anda dapat mempercepatnya. (Tetapkan pin tinggi ketika Anda memasukkan fungsi / ISR, atur rendah lagi saat keluar).
Ketujuh: Putuskan jika Anda benar-benar perlu membaca ADC, akankah semakin lambat memperburuk keadaan? Ini kontra-intuitif tetapi kadang-kadang berjalan lebih lambat benar-benar memberikan hasil yang lebih baik, melakukan pekerjaan rata-rata sinyal untuk Anda dan mengurangi lonjakan / transien yang dapat menyebabkan masalah atau memerlukan pemrosesan ekstra untuk menghapus. Kami meningkatkan rutin kontrol PID motor dengan hanya menjalankannya 1/4 kecepatan, membebaskan banyak waktu CPU dalam proses.
sumber
Budak bus yang sibuk dengan hal-hal lain memiliki kemampuan untuk meregangkan jam untuk mengulur waktu hingga mampu menjalankan komunikasi yang terakhir. Ini dilakukan dengan tidak segera mengirim pulsa clock ACK / NACK, menjaga komunikasi dalam keadaan menengah sampai siap untuk menjawab.
Peregangan jam adalah cara yang tepat untuk menghadapi situasi semacam ini. Perangkat yang tidak melakukan peregangan dan melakukan hal-hal buruk lainnya (bus hang / restart, NACKs alamat atau perintah yang valid, dll.) Dapat bermasalah, dan membuat beban tambahan pada master untuk menjaga hal-hal diurutkan (harus mengulangi perintah , pantau NACK, dll.)
sumber
Bergantung pada kemampuan STM32 (saya belum pernah menggunakannya), Anda bisa mencoba salah satu pendekatan berikut. Jika Anda dapat memberikan rincian lebih lanjut tentang apa yang Anda coba lakukan, dan memiliki argumen yang meyakinkan tentang mengapa setiap interupsi diperlukan dalam bentuk yang Anda miliki sekarang, maka jawaban yang lebih spesifik mungkin dipikirkan. Khususnya dalam kasus Anda, I2C cukup lambat untuk ini sehingga tidak menjadi masalah dengan rutinitas interupsi yang ditulis dengan baik.
Interupsi untuk apa pun biasanya dapat dinonaktifkan. Paling banyak ada satu atau dua Non-Maskable Interrupts di dalam pengontrol biasa, salah satunya di-reset. Jika Anda tidak memerlukan kontrol yang didorong oleh sesuatu (ADC atau I2C, dalam kasus Anda), maka ubah kode perangkat itu menjadi kode yang tidak menggunakan interupsi, kemudian nonaktifkan interupsi.
Penanganan interrupt tidak harus lama. Coba lakukan sesedikit mungkin dari vektor interupsi itu sendiri. Pendekatan minimalis yang ekstrim terhadap interupsi adalah dengan hanya mengatur flag dari dalam rutinitas interrupt handler dan memiliki, katakanlah, loop utama melakukan semua pekerjaan berat sejak saat itu. Apa yang dibutuhkan oleh aplikasi spesifik Anda dan arsitektur firmware mungkin tidak sesederhana seperti itu, tetapi benar-benar bermanfaat untuk melakukan upaya untuk melihat berapa banyak yang harus dilakukan dari dalam interupsi.
Jika Anda memiliki DMA periferal, gunakan itu alih-alih memotong pada setiap byte. Biasanya, akan lebih mudah untuk menempatkan ADC pada DMA sebagai lawan I2C, tetapi chip yang berbeda memiliki implementasi yang berbeda. Saya tidak akan terkejut jika ada cara bersih untuk menidurkan pertukaran I2C ke DMA juga. DMA memungkinkan Anda mengurangi jumlah interupsi dan membiarkan inti prosesor Anda bebas dari keharusan menangani setiap blok data.
Cobalah untuk mengidentifikasi contoh spesifik di mana Anda melihat kerusakan data, dan mekanisme di mana korupsi data terjadi. Ini jauh lebih sulit untuk dilakukan, tetapi dengan penggunaan kreatif osiloskop / penganalisa logika modern Anda mungkin dapat melihat beberapa masalah. Secara khusus, pastikan masalahnya ada pada pengaturan waktu dan bukan memori (yang merupakan kemungkinan dengan kombinasi kode yang buruk dan kompiler liberal)
EDIT: Beberapa catatan khusus tentang masalah ini, dari komentar Anda pada pertanyaan:
sumber
Dalam sistem yang diberikan, mungkin ada kebisingan memasuki jam dan bus data. Fakta bahwa logika Anda menghapus masalah menunjukkan ini. Untuk implementasi yang praktis dan tercepat, ikuti saja petunjuk yang diberikan oleh pengamatan Anda. Pada bus i2c dengan implementasi 400kbits / detik, berdasarkan pengamatan yang sama, saya menghubungkan 2M yang paralel dengan 12pf ke ground dari titik jam dan data dan menemukan bahwa masalah telah terpecahkan. Ini menghilangkan / menyaring kebisingan di luar jalur minat yang diperlukan untuk komunikasi i2c tertentu. Silakan coba dan beri saran.
sumber