Arduino Uno, Mega2560, Leonardo ve benzeri kartlara referansla:
- Seri iletişim nasıl çalışır?
- Seri ne kadar hızlı?
- Bir gönderen ve alıcı arasında nasıl bağlantı kurabilirim?
Lütfen dikkat: Bu referans bir soru olarak düşünülmüştür.
Arduino Uno, Mega2560, Leonardo ve benzeri kartlara referansla:
Lütfen dikkat: Bu referans bir soru olarak düşünülmüştür.
Yanıtlar:
Asenkron seri (genellikle seri olarak adlandırılır) iletişim, bir cihazdan diğerine bayt göndermek için kullanılır. Bir cihaz aşağıdakilerden biri veya daha fazlası olabilir:
SPI / USB / I2C'nin aksine seri iletişimde saat sinyali yoktur. Örnekleme saati, üzerinde anlaşmaya varılmış bir numune oranıdır (baud hızı olarak bilinir). Hem gönderenin hem de alıcının aynı hızı kullanacak şekilde yapılandırılması gerekir ya da alıcı anlamsız veriler alacaktır (bitlerin gönderildikleri hızda örneklenmemesi nedeniyle).
İletim eşzamansızdır, bu da temel olarak baytların her zaman aralarında değişen boşluklarla gönderilebileceği anlamına gelir. Bu grafik gönderilen tek bir baytı göstermektedir:
Yukarıdaki grafik iletilen 'F' harfini göstermektedir. ASCII'de bu 0x46 (onaltılık) veya 0b01000110 (ikili olarak) şeklindedir. En az anlamlı bir (düşük değerli) biraz sırayla gelen bit görmek, böylece grafik yukarıdaki birinci iletilir: 01100010
.
Baytlar arasındaki "boşta" süre sürekli "1" bit olarak iletilir (etkin bir şekilde iletim hattı sürekli olarak yüksek tutulur).
Bir baytın başlangıcını belirtmek için, Başlangıç Biti daima çizgiyi grafikte gösterildiği gibi aşağı çekerek gösterilir. Alıcı başlangıç bitini gördükten sonra, numune süresinin 1.5 katı kadar bekler ve sonra veri bitlerini örnekler. 1.5 kez bekler, böylece:
Örneğin, baud hızı 9600 baud ise, örnekleme hızı 1/9600 = 0.00010416
saniye (104.16 µs) olacaktır.
Böylece, 9600 baud'da, bir başlangıç biti alındıktan sonra alıcı 156.25 µs bekler ve sonra her 104.16 µs'de numune alır.
Stop Bit'in amacı, her bayt arasında kesinlikle 1 bit olmasını sağlamaktır. Durdurma biti olmadan, bir bayt sıfırla biterse, donanımın bu ile bir sonraki baytın başlangıç biti arasındaki farkı anlatması imkansızdır.
Yukarıdaki çıktıyı bir Uno'da üretmek için bu kodu yazabilirsiniz:
void setup()
{
Serial.begin(9600);
Serial.print("F");
}
void loop ()
{
}
İletim süresinden tasarruf etmek için (eski günlerde, heh) farklı sayıda veri biti belirtmenize izin verildi. AtMega donanımı, 5'ten 9'a kadar olan veri bitlerini destekler. Açıkça daha az veri, daha az bilgi gönderebilir, ancak daha hızlı olacaktır.
İsteğe bağlı olarak bir eşlik bitiniz olabilir. Bu, gerekirse, karakterdeki 1'lerin sayısını sayarak ve sonra bu sayının tek olduğundan emin olunarak veya hatta eşlik bitini gerektiği gibi 0 veya 1'e ayarlayarak hesaplanır.
Örneğin, "F" harfi (veya 0x46 veya 0b01000110) için orada 3 tane olduğunu görebilirsiniz (01000110'da). Böylece zaten garip paritemiz var. Yani, parite biti aşağıdaki gibi olacaktır:
Eşlik biti, varsa, son veri bitinden sonra ancak durdurma bitinden önce görünür.
Alıcı doğru eşlik bitini alamazsa buna "eşlik hatası" denir. Bazı problemler olduğunu gösterir. Muhtemelen gönderici ve alıcı farklı baud (bit) hızları kullanacak şekilde yapılandırılmıştır veya hatta sıfıra bire dönüşen veya tam tersi bir gürültü vardı.
Bazı erken sistemlerde ayrıca "işaret" paritesi (verilerden bağımsız olarak parite bitinin her zaman 1 olduğu) veya "boşluk" paritesi (verilerden bağımsız olarak parite bitinin her zaman 0 olduğu) kullanıldı.
Bazı iletişim ekipmanı 9 bit veri kullanır, bu nedenle parite biti 9. bite dönüştürülür. Bu 9. biti göndermek için özel teknikler vardır (kayıtlar 8 bit kayıtlardır, bu nedenle 9. bit başka bir yere konulmalıdır).
İlk ekipman elektronik olarak biraz daha yavaş olma eğilimindeydi, bu nedenle alıcıya gelen baytı işlemek için zaman vermek için bazen gönderenin iki durdurma biti göndereceği belirtildi. Bu, temel olarak bir sonraki başlangıç bitinin görünmesi için veri hattının yüksek tutulduğu (daha bir bit zamanı) daha fazla zaman ekler. Bu ekstra bit süresi alıcıya son gelen baytı işlemek için zaman tanır.
Eğer durdurma bitinin olması gerektiği zaman alıcı mantıksal 1 almazsa buna "çerçeveleme hatası" denir. Bazı problemler olduğunu gösterir. Büyük olasılıkla gönderici ve alıcı farklı baud (bit) hızlarını kullanacak şekilde yapılandırılmıştır.
Genellikle, seri iletişim size hızı, veri bitlerinin sayısını, eşlik tipini ve durdurma bitlerinin sayısını söyleyerek gösterilir:
9600/8-N-1
Bu bize şunu söylüyor:
Gönderenin ve alıcının yukarıdakiler üzerinde anlaşması önemlidir, aksi takdirde iletişimin başarılı olması olası değildir.
Arduino Uno, donanım seri için 0 ve 1 dijital pinlerine sahiptir:
İki Arduino'yu bağlamak için Tx ve Rx'i şu şekilde değiştirebilirsiniz :
Çok çeşitli hızlar desteklenir (aşağıdaki grafiğe bakın). "Standart" hızlar genellikle 300 baudun katlarıdır (örn. 300/600/1200/2400 vb.).
Diğer "standart dışı" hızlar, uygun kayıtlar ayarlanarak işlenebilir. HardwareSerial sınıfı bunu sizin için yapar. Örneğin.
Serial.begin (115200); // set speed to 115200 baud
Pratik bir kural olarak, 8 bit veri kullandığınızı varsayarsak, baud hızını 10'a bölerek saniyede iletebileceğiniz bayt sayısını tahmin edebilirsiniz (başlangıç biti ve durdurma biti nedeniyle).
Böylece, 9600 baud'da 9600 / 10 = 960
saniyede 960 bayt ( ) iletebilirsiniz .
Atmega'daki baud hızı, sistem saatini bölerek ve sonra önceden ayarlanmış bir sayıya kadar sayarak üretilir. Veri sayfasındaki bu tablo, 16 MHz'lik bir saat için (Arduino Uno'daki gibi) kayıt değerlerini ve hata yüzdelerini gösterir.
U2Xn biti saat hızı bölücüsünü etkiler (0 = 16'ya bölün, 1 = 8'e bölün). UBRRn kaydı, işlemcinin saydığı sayıyı içerir.
Yukarıdaki tablodan, 16 MHz'lik bir saatten 9600 baud aldığımızı görüyoruz:
16000000 / 16 / 104 = 9615
Sayaç sıfır göreli olduğundan 103'e değil 104'e böleriz. Dolayısıyla, buradaki hata, 15 / 9600 = 0.0016
yukarıdaki tabloda söylediklerine yakındır (% 0.02).
Bazı baud hızlarının hata miktarının diğerlerinden daha yüksek olduğunu fark edeceksiniz.
Veri sayfasına göre 8 veri biti için maksimum hata yüzdesi% 1.5 ila% 2.0 arasındadır (daha fazla ayrıntı için veri sayfasına bakın).
Arduino Leonardo ve Micro, seri bağlantı noktasına değil, doğrudan USB üzerinden ana bilgisayara bağlandıklarından, seri iletişim için farklı bir yaklaşıma sahiptir.
Bu nedenle, Seri'nin "hazır" olmasını beklemelisiniz (yazılım bir USB bağlantısı kurarken), aşağıdaki gibi fazladan birkaç satırla:
void setup()
{
Serial.begin(115200);
while (!Serial)
{} // wait for Serial comms to become ready
Serial.print("Fab");
}
void loop ()
{
}
Ancak, D0 ve D1 pinleri aracılığıyla (USB kablosu yerine) gerçekten iletişim kurmak istiyorsanız, Seri yerine Serial1 kullanmanız gerekir. Bunu şöyle yapıyorsun:
void setup()
{
Serial1.begin(115200);
Serial1.print("Fab");
}
void loop ()
{
}
Arduino'nun seri iletişim için TTL seviyelerini kullandığını unutmayın. Bu beklediği anlamına gelir:
Bir bilgisayarın seri portuna takılmak üzere tasarlanmış daha eski seri ekipman muhtemelen RS232 voltaj seviyelerini kullanır:
Bu sadece TTL seviyelerine ("bir" bir "sıfır" dan daha negatif) "ters" değil, Arduino giriş pinleri üzerindeki negatif gerilimleri (5V'dan daha yüksek pozitif gerilimleri) kaldıramaz.
Bu nedenle, bu tür cihazlarla iletişim kurmak için bir arayüz devresine ihtiyacınız vardır. Yalnızca (Arduino'ya) giriş için, basit bir transistör, diyot ve birkaç direnç bunu yapar:
İki yönlü iletişim için negatif voltaj üretebilmeniz gerekir, bu nedenle daha karmaşık bir devre gereklidir. Örneğin, MAX232 yongası bunu dört adet 1 µF kapasitör ile birlikte şarj pompası devresi olarak görev yapar.
SoftwareSerial adı verilen ve donanımdan ziyade yazılımda seri iletişim (bir noktaya kadar) yapmanızı sağlayan bir kütüphane vardır. Bunun avantajı, seri iletişim için farklı pin yapılandırmalarını kullanabilmenizdir. Dezavantajı, yazılımda seri yapmanın daha fazla işlemci yoğunluğu ve hataya daha yatkın olmasıdır. Daha fazla bilgi için Yazılım Seri Numarası'na bakın.
Arduino "Mega" 3 ek donanım seri bağlantı noktasına sahiptir. Tahtada Tx1 / Rx1, Tx2 / Rx2, Tx3 / Rx3 olarak işaretlenmiştir. Mümkünse SoftwareSerial yerine kullanılmalıdır. Bu diğer bağlantı noktalarını açmak için Serial1, Serial2, Serial3 adlarını aşağıdaki gibi kullanırsınız:
Serial1.begin (115200); // start hardware serial port Tx1/Rx1
Serial2.begin (115200); // start hardware serial port Tx2/Rx2
Serial3.begin (115200); // start hardware serial port Tx3/Rx3
HardwareSerial kitaplığını kullanarak hem gönderme hem de alma kesintileri kullanır.
A yaptığınızda Serial.print
, yazdırmaya çalıştığınız veriler dahili bir "iletim" arabelleğine yerleştirilir. 1024 bayt veya daha fazla RAM'iniz varsa (Uno'da olduğu gibi) 64 baytlık bir tampon alırsınız, aksi takdirde 16 baytlık bir tampon alırsınız. Tamponda yer varsa, Serial.print
hemen geri döner, böylece kodunuzu geciktirmez. Eğer yer yoksa, tamponun oda olması için yeterince boşaltılmasını bekleyen "engeller".
Daha sonra, her bayt donanım tarafından iletildikçe bir kesme denir ("USART, Veri Kaydı Boş" kesme) ve kesme rutini tampondan seri porttan sonraki baytı gönderir.
Gelen veriler alındıkça bir kesme rutini denir ("USART Rx Complete" kesme) ve gelen bayt bir "alma" tamponuna (yukarıda belirtilen iletim tamponu ile aynı boyutta) yerleştirilir.
Aradığınızda Serial.available
bunu mevcuttur kaç bayt öğrenmek "alma" tampon. Aradığınızda Serial.read
bir bayt alma arabelleğinden kaldırılır ve kodunuza geri döner.
1000 bayt veya daha fazla RAM içeren Arduinos'ta, veriyi doldurmasına izin vermemeniz koşuluyla, alma arabelleğindeki verileri kaldırmak için acele yoktur. Doldurulursa, gelen diğer veriler atılır.
Bu arabellek boyutu nedeniyle, çok sayıda baytın gelmesini beklemenin bir anlamı olmadığını unutmayın, örneğin:
while (Serial.available () < 200)
{ } // wait for 200 bytes to arrive
Bu asla işe yaramaz, çünkü arabellek bu kadar tutamaz.
Okumadan önce verilerin daima mevcut olduğundan emin olun. Örneğin, bu yanlış:
if (Serial.available ())
{
char a = Serial.read ();
char b = Serial.read (); // may not be available
}
Serial.available
Test Sadece sahip sağlayan bir ancak kod ikisini okumaya çalışır, bayt kullanılabilir. Tamponda iki bayt varsa işe yarayabilir, değilse -1 döndürülür ve yazdırılırsa 'ÿ' gibi görünür.
Veri göndermenin ne kadar sürdüğünün farkında olun. Yukarıda belirtildiği gibi, 9600 baud'da saniyede sadece 960 bayt iletirsiniz, bu nedenle 9600 baud'da bir analog bağlantı noktasından 1000 okuma göndermeye çalışmak çok başarılı olmaz.