Avr mikrodenetleyicilerinin C dilinde programlanması. AVR mikrodenetleyicilerinin C dilinde programlanması. Peki mikrodenetleyici nedir?

Mikrodenetleyici programlamaya ilk kez başlayanlar ve daha önce C diline aşina olmayanlar için kısa bir tanıtım yazısı yazmaya karar verdim. Detaylara girmeyeceğiz, CodeVisionAVR ile çalışma konusunda genel bir fikir edinmek için her şeyden biraz bahsedeceğiz.

Daha detaylı bilgi CodeVision Kullanım Kılavuzunda İngilizce olarak görüntülenebilir ve ayrıca mikrodenetleyiciler için C üzerine video dersleri ve Deitel'in "C'de Nasıl Programlanır" kitabını içeren http://somecode.ru sitesini tavsiye ederim, bu tek iyi kitaptır ben de bununla başladım.

Hangi eylemleri yaparsak yapalım, sonuçta her şeyin mikro denetleyicinin donanım yazılımına bağlı olduğu gerçeğiyle başlayalım. Firmware işleminin kendisi şu şekilde gerçekleşir: belirli bir program kullanılarak, bir firmware dosyası seçilir, parametreler seçilir, bir düğmeye basılır ve firmware doğrudan yanıp söner, bu aslında bir kopyadır. Tıpkı müzik veya belgeleri bilgisayardan flash sürücüye kopyalamanız gibi, sürecin fiziği de aynıdır.

Firmware'in kendisi bir .hex uzantısına sahiptir ve mikrodenetleyicinin anlayabileceği birler ve sıfırlar biçiminde bir dizi talimattır. Firmware'i nereden alabilirim? Elektronik sitelerinden indirebilir veya kendiniz yazabilirsiniz. Bunu geliştirme ortamı adı verilen özel programlara yazabilirsiniz. Benim için en çok bilinenler AVR Studio, IAR, CodeVision, WinAVR... Bu ortamlardan hangisinin daha iyi veya daha kötü olduğunu söylemek her birinin kendine göre imkansız. Bu programların temel olarak kolaylık, programlama dili ve fiyat açısından farklılık gösterdiğini söyleyebiliriz. Bu sitede yalnızca CodeVision dikkate alınmaktadır.

Ortamı çözdük, şimdi firmware yazma sürecine bakalım. CodeVision'da öncelikle bir proje oluşturmanız gerekir. Kod sihirbazı kullanılarak veya boş olarak oluşturulabilir. Her durumda, kullanılan mikrodenetleyicinin türünü seçmeniz ve frekansını belirtmeniz gerekir. Sihirbazı kullanırken başlangıç ​​ayarlarını seçmeniz ve ayarlarla kaynak kodu oluşturmanız istenecektir. Daha sonra bu kodu düzenleyebileceğiniz bir pencere açılacaktır. Kaynak kodunuzu Not Defteri'ne yazabilir ve ardından ayarlardaki projeye ekleyebilirsiniz.

Kaynak kod dosyası, bir programlama dilindeki bir dizi komuttur, CodeVision'ın görevi bu komutları ikili koda çevirmek, sizin göreviniz bu kaynak kodunu yazmaktır. CodeVision C dilini anlar, kaynak kod dosyaları “.c” uzantısına sahiptir. Ancak CodeVision'ın C'de kullanılmayan bazı yapıları vardır, bu yüzden birçok programcı bundan hoşlanmaz ve kullanılan dile C benzeri denir. Ancak bu sizin ciddi projeler yazmanıza engel değil. Çok sayıda örnek, bir kod oluşturucu ve geniş bir kitaplık seti CodeVision'a büyük bir avantaj sağlar. Tek olumsuz yanı, ücretli olmasına rağmen ücretsiz sürümler kod kısıtlaması ile.

Kaynak kodu, kullanılan mikro denetleyici tipini ve ana işlevi içeren bir başlık içermelidir. Örneğin ATtiny13 kullanılıyor

#katmak void main(void) ( ) ;

#katmak void main(void) ( );

Ana fonksiyondan önce gerekli kütüphaneleri bağlayabilir, global değişkenleri, sabitleri ve ayarları bildirebilirsiniz. Kitaplık, önceden yazılmış kodu içeren, genellikle ".h" uzantılı ayrı bir dosyadır. Bazı projelerde bu koda ihtiyacımız olabilir ancak bazılarında buna ihtiyacımız olmayabilir. Mesela bir projemizde LCD ekran kullanıyoruz, diğerinde kullanmıyoruz. “alcd.h” LCD ekranıyla çalışmak için kitaplığı şu şekilde bağlayabilirsiniz:

#katmak #katmak void main(void) ( ) ;

#katmak #katmak void main(void) ( );

Değişkenler, belirli değerlerin yerleştirilebildiği hafıza alanlarıdır. Örneğin, iki sayıyı toplarsanız, sonucu gelecekte kullanmak üzere bir yere kaydetmeniz gerekir. Öncelikle değişkeni bildirmeniz gerekir, yani. bunun için bellek ayırın, örneğin:
int ben=0;
onlar. i değişkenini bildirdik ve içine 0 değerini yerleştirdik, int değişkenin türü, daha doğrusu ayrılan belleğin boyutu anlamına geliyor. Her değişken türü yalnızca belirli bir değer aralığını saklayabilir. Örneğin int, -32768'den 32767'ye kadar sayılar olarak yazılabilir. Kesirli kısmı olan sayılar kullanmanız gerekiyorsa değişkenin kayan noktalı sayı olarak bildirilmesi gerekir; karakterler için char türünü kullanın.

bit, _bit 0 veya 1 -128 ila 127 char 0 ila 255 int -32768 ila 32767 arasında -2147483648 ila 2147483647 arasında -2147483648 ila 2147483647 ± 1.17 5- 38 ila ±3,402e38

Ana fonksiyonun içinde ana program zaten çalışıyor. Fonksiyonu çalıştırdıktan sonra program duracaktır, böylece aynı programı sürekli tekrarlayan sonsuz bir while döngüsü oluşturacaklar.

void main(void) ( while (1) ( ; ) ;

void main(void) ( while (1) ( ); );

Kaynak kodun herhangi bir yerine yorum yazabilirsiniz; programın çalışmasını hiçbir şekilde etkilemez ancak yazılı kod üzerinde not almanıza yardımcı olacaktır. Bir satırı iki eğik çizgiyle // yorumlayabilirsiniz, bundan sonra derleyici satırın tamamını veya birkaç satırı /**/ yok sayar, örneğin:

/*Temel matematik işlemleri:*/ int ben= 0; //i değişkenini tanımlayıp ona 0 değerini atayın//Ekleme: i = 2 + 2; //Çıkarma: i = 2 - 2; //bu ifadeyi çalıştırdıktan sonra i değişkeni 0'a eşit olacak//Çarpma: i = 2 * 2; //bu ifadeyi çalıştırdıktan sonra i değişkeni 4'e eşit olacak//Bölme: i = 2 / 2; //bu ifadeyi çalıştırdıktan sonra i değişkeni 1'e eşit olacak

/*Temel matematik işlemleri:*/ int i=0; //i değişkenini tanımlayıp ona 0 değerini atayın //Ekleme: i = 2+2; //bu ifadeyi çalıştırdıktan sonra i değişkeni 4'e eşit olacaktır //Çıkarma: i = 2-2; //bu ifadeyi çalıştırdıktan sonra i değişkeni 0'a eşit olacak //Çarpma: i = 2*2; //bu ifadeyi çalıştırdıktan sonra i değişkeni 4'e eşit olacak //Bölme: i = 2/2; //bu ifadeyi çalıştırdıktan sonra i değişkeni 1'e eşit olacak

Çoğu zaman, bir programın koşullara bağlı olarak bir kod parçasından diğerine geçmesi gerekir; bunun için koşullu if() işlemleri vardır, örneğin:

if(i>3) //eğer i 3'ten büyükse, o zaman i'ye 0 değerini atayın ( i=0; ) /*eğer i 3'ten küçükse, koşulun gövdesini takip eden koda gidin, yani. parantezlerden sonra ()*/

Ayrıca if else ile birlikte kullanılabilir - aksi takdirde

Eğer ben<3) //если i меньше 3, то присвоить i значение 0 { i=0; } else { i=5; //иначе, т.е. если i больше 3, присвоить значение 5 }

Ayrıca “=” atamasıyla karıştırılmaması gereken bir karşılaştırma operatörü “==” vardır. Ters işlem "!="'e eşit değil diyelim

if(i==3)//eğer i 3 ise, i'ye 0 değerini atayın ( i=0; ) if(i!=5) //i 5 değilse, i'ye 0 ( i=0;) değerini atayın )

Daha karmaşık şeylere, işlevlere geçelim. Diyelim ki birkaç kez tekrarlanan belirli bir kod parçanız var. Üstelik bu kodun boyutu oldukça büyük. Her seferinde yazmak sakıncalıdır. Örneğin, i değişkenini bir şekilde değiştiren bir programda, D bağlantı noktasının 0 ve 3 numaralı düğmelerine bastığınızda, i değişkeninin değerine bağlı olarak B bağlantı noktasının bacaklarını açan aynı kod yürütülür.

void main(void) ( if (PIND.0== 0 ) //PD0'daki butona basılıp basılmadığını kontrol edin( eğer (i== 0 ) //eğer i==0 ise PB0'ı etkinleştir( PORTB.0= 1 ; ) eğer (i== 5 ) // eğer i==5 PB1'i etkinleştirirse( PORTB.1= 1 ; ) ) … eğer (PIND.3== 0 ) // PD3 düğmesini kontrol ederken de aynı şeyi yapın( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; )) )

void main(void) ( if(PIND.0==0) //PD0 üzerindeki butona basılıp basılmadığını kontrol edin ( if(i==0) //if i==0 PB0'ı açın ( PORTB.0=1; ) if( i==5) // if i==5 PB1'i açın ( PORTB.1=1; ) ) ... if(PIND.3==0) // PD3 düğmesini kontrol ederken aynı şeyi yapın ( if(i==0 ) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; )) )

Genel olarak kod çok büyük değildir, ancak kat kat daha büyük olabilir, bu nedenle kendi işlevinizi oluşturmanız çok daha uygun olacaktır.
Örneğin:

void i_check() ( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ))

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; )) )

void, fonksiyonun hiçbir şey döndürmediği anlamına gelir, bununla ilgili daha fazla bilgiyi aşağıda i_check() - fonksiyonumuzun adıdır, onu istediğiniz gibi adlandırabilirsiniz, ben tam olarak böyle adlandırdım - check i. Artık kodumuzu yeniden yazabiliriz:

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) void main(void) ( if(PIND.0==0 ) //PD0'daki düğmeye basılıp basılmadığını kontrol edin ( i_check(); ) ... if(PIND.3==0) ( i_check(); ))

Kod i_check(); satırına ulaştığında daha sonra fonksiyonun içine atlayacak ve içindeki kodu çalıştıracaktır. Katılıyorum, kod daha kompakt ve daha net, yani. işlevler aynı kodun yalnızca bir satırla değiştirilmesine yardımcı olur. Lütfen fonksiyonun ana kodun dışında bildirildiğini unutmayın; ana fonksiyondan önce. Buna neden ihtiyacım olduğunu söyleyebilirsiniz, ancak dersleri incelerken sıklıkla işlevlerle karşılaşacaksınız, örneğin LCD ekranı temizlemek lcd_clear() - işlev hiçbir parametreyi kabul etmez ve hiçbir şey döndürmez, ancak ekran. Bazen bu işlev hemen hemen her satırda kullanılır, dolayısıyla kod tasarrufları açıktır.

Değer alırken bir fonksiyonu kullanmak çok daha ilginç görünüyor, örneğin bir c değişkeni var ve int türünde iki değer alan bir toplam fonksiyonu var. Ana program bu fonksiyonu çalıştırdığında, argümanlar zaten parantez içinde olacaktır, yani "a" ikiye, "b" ise 1'e eşit olacaktır. Fonksiyon yürütülecek ve "c" 3'e eşit olacaktır. .

int c= 0; void toplam(int a, int b) ( c= a+ b; ) void main(void ) ( toplam(2 , 1 ) ; )

intc=0; void toplam(int a, int b) ( c=a+b; ) void main(void) ( toplam(2,1); )

En yaygın benzer işlevlerden biri, imleci LCD ekran üzerinde hareket ettirmektir lcd_gotoxy(0,0); bu arada, bu aynı zamanda x ve y koordinatlarını da alıyor.

Bir fonksiyonu kullanmanın başka bir seçeneği, bir değer döndürdüğünde artık geçersiz olmayacaktır, iki sayıyı toplamaya yönelik önceki fonksiyon örneğini geliştirelim:

int c= 0; int toplam(int a, int b) ( return a+ b; ) void main(void) ( с= toplam(2, 1) ; )

intc=0; int toplam(int a, int b) ( return a+b; ) void main(void) ( с=sum(2,1); )

Sonuç, geçen seferki c=3 ile aynı olacaktır, ancak "c" değişkenine artık geçersiz olmayan, ancak int tipindeki iki sayının toplamını döndüren bir fonksiyonun değerini atadığımızı unutmayın. Bu şekilde belirli bir "c" değişkenine bağlı kalmayız, bu da işlevlerin kullanımında esneklik sağlar. Böyle bir fonksiyonun basit bir örneği ADC verilerini okumaktır; fonksiyon ölçülen değeri result=read_adc(); döndürür. Fonksiyonlarla bitirelim.

Şimdi dizilere geçelim. Bir dizi ilgili değişkenlerdir. Örneğin, birkaç noktadan oluşan bir sinüs tablonuz var, int sinüs1=0; değişkenleri oluşturmayacaksınız; int sinüs2=1; vesaire. Bunun için bir dizi kullanılır. Örneğin, aşağıdaki gibi üç öğeden oluşan bir dizi oluşturabilirsiniz:
int sinüs=(0,1,5);
Dizi elemanlarının toplam sayısı köşeli parantez içinde gösterilir. Üçüncü elemanın değerini “c” değişkenine şu şekilde atayabilirsiniz:
с=sinüs;
Lütfen dizi elemanlarının numaralandırmasının sıfırdan başladığını unutmayın; "c" beşe eşit olacak. Bu dizide sinüs elemanı yoktur!!!
Tek bir öğeye şu şekilde bir değer atayabilirsiniz:
sinüs=10;

CodeVision'ın dize değişkenlerine sahip olmadığını zaten fark etmiş olabilirsiniz. Onlar. bir değişken string hello=”hello” oluşturamazsınız; Bunu yapmak için bir dizi ayrı karakter oluşturmanız gerekecektir.

lcd_putchar(merhaba); lcd_putchar(merhaba); lcd_putchar(merhaba);

vesaire.
Oldukça hantal görünüyor, döngülerin kurtarmaya geldiği yer burası.
Örneğin while döngüsü

while(PINB.0!=0) ( )

Düğmeye basılana kadar hiçbir şey yapmayın; boş bir döngü çalıştırın.

Başka bir seçenek de for döngüsüdür

int ben; için (i= 0; ben< 6 ; i++ ) { lcd_putchar(hello[ i] ) ; }

int ben; for(i=0;i<6;i++) { lcd_putchar(hello[i]); }

Anlamı while ile tamamen aynıdır, yalnızca başlangıç ​​koşulu i=0 ve her i++ döngüsünde yürütülen koşul eklenir. Döngünün içindeki kod mümkün olduğunca basitleştirilmiştir.

Programınızı yazdıktan sonra kaynak kodu derlenir ve herhangi bir hata yoksa, proje klasöründe imrenilen ürün yazılımını alırsınız. Artık mikrodenetleyiciyi flaşlayabilir ve cihazın çalışmasının keyfini çıkarabilirsiniz.

Firmware'inizde döngüleri, dizileri ve işlevleri hemen kullanmaya çalışmamalısınız. Ana göreviniz ürün yazılımının çalışmasını sağlamaktır, bu nedenle bunu sizin için daha kolay olduğu için yapın ve kodun boyutuna dikkat etmeyin. Yalnızca çalışan kod yazmakla kalmayıp, onu güzel ve kompakt bir şekilde yazmak isteyeceğiniz zaman da gelecek. O zaman C dilinin vahşi doğalarına dalmak mümkün olacak. Her şeye hakim olmak isteyenler için bir kez daha “C'de Nasıl Programlanır” kitabını öneriyorum, birçok örnek ve görev var. Visual Studio'yu yükleyin, bir win32 konsol uygulaması oluşturun ve orada dilediğinizce pratik yapın.

Ders 0.

Bugün AVR ailesinin mikrodenetleyicilerinin programlanmasıyla ilgili bir dizi ders açıyoruz.

Bugün aşağıdaki sorular ele alınacaktır:

  1. Mikrodenetleyici nedir?
  2. Mikrodenetleyiciler nerelerde kullanılır?

Giriiş.

Mikrodenetleyiciler her yerdedir. Telefonlarda, çamaşır makinelerinde, “akıllı evlerde”, fabrikalardaki takım tezgahlarında ve daha sayısız teknik cihazda. Yaygın kullanımları, karmaşık analog devrelerin daha sıkıştırılmış dijital devrelerle değiştirilmesini mümkün kılar.

Peki mikrodenetleyici nedir?

Mikrodenetleyici (Mikro Kontrol Ünitesi, MCU) - elektronik cihazları kontrol etmek için tasarlanmış bir mikro devre.Bunu harici cihazlarla etkileşime girebilen basit bir bilgisayar olarak hayal edebilirsiniz.Örneğin, transistörleri açıp kapatmak, sıcaklık sensörlerinden veri almak, verileri LCD ekranlarda görüntülemek vb. Ek olarak mikrodenetleyici, tıpkı kişisel bilgisayarınız gibi, giriş verilerinin çeşitli işlemlerini gerçekleştirebilir.

Yani mikrodenetleyiciler, I/0 portlarının (giriş/çıkış portları) varlığı ve bunları programlama imkanı sayesinde bize herhangi bir cihazı kontrol etmek için neredeyse sınırsız olanaklar sunar.

Mikrodenetleyiciler nerelerde kullanılır?

  1. Ev aletleri (Çamaşır makineleri, mikrodalga fırınlar vb.).
  2. Mobil teknoloji (Robotlar, robotik sistemler, iletişim ekipmanları vb.).
  3. Endüstriyel ekipmanlar (makine kontrol sistemleri).
  4. Bilgisayar teknolojisi (Anakartlar, çevresel cihaz kontrol sistemleri).
  5. Eğlence ekipmanları (Çocuk oyuncakları, dekorasyonlar).
  6. Taşımacılık (Araba motor kontrol sistemleri, güvenlik sistemleri)

Bu, mikrodenetleyicilere yönelik uygulamaların tam listesi değildir. Basitleştirilmiş üretim ve azaltılmış güç tüketimi nedeniyle, bir dizi kontrol yongasını tek bir mikro denetleyiciyle değiştirmek çoğu zaman çok karlı olur.

AVR'ye başlarken

AVR- Atmel'den bir mikrodenetleyici ailesi. Çoğu amatör cihaz için yeterli performansa sahiptirler. Endüstride de yaygın olarak kullanılırlar.

LPT bağlantı noktası programlayıcısının şematik diyagramı şekilde gösterilmiştir. Otobüs sürücüsü olarak 74AC 244 veya 74HC244 (K1564AP5), 74LS244 (K555AP5) veya 74ALS244 (K1533AP5) mikro devresini kullanın.

LED VD1 mikro denetleyicinin kayıt modunu gösterir,

LED VD2 - okuma,

LED VD3 - devreye güç kaynağının varlığı.

Devre, güç kaynağı için gereken voltajı ISP konektöründen alır; programlanabilir cihazdan Bu devre yeniden tasarlanmış bir STK200/300 programlayıcı devresidir (işletim kolaylığı için LED'ler eklenmiştir), dolayısıyla STK200/300 devresiyle çalışan tüm PC programcı programlarıyla uyumludur. Bu programcıyla çalışmak için programı kullanın CVVR

Programlayıcı, şekillerde gösterildiği gibi baskılı devre kartı üzerine yapılabilir ve LPT konnektör muhafazasına yerleştirilebilir:




Programcıyla çalışmak için, kendinizin yapması kolay olan bir LPT bağlantı noktası uzantısını kullanmak uygundur (örneğin, bir yazıcı için Centronix kablosundan), asıl mesele iletkenleri toprak için ayırmamaktır (18- 25 konektör ayağı) veya satın alın. Programlayıcı ile programlanabilir çip arasındaki kablo 20-30 cm'yi geçmemelidir.

Bitsel işlemler daha önce ele aldığımız mantıksal işlemlere dayanmaktadır. AVR ve diğer mikro denetleyici türlerinin programlanmasında önemli bir rol oynarlar. Neredeyse hiçbir program bitsel işlemler kullanılmadan yapamaz. Bundan önce MK programlamayı öğrenme sürecini kolaylaştırmak için bunlardan kasıtlı olarak kaçındık.

Önceki makalelerin tümünde, yalnızca G/Ç bağlantı noktalarını programladık ve zamanlayıcılar, analogdan dijitale dönüştürücüler, kesintiler ve MK'nin tüm gücünü kaybettiği diğer dahili cihazlar gibi ek yerleşik bileşenler kullanmadık.

MK'nin yerleşik cihazlarına hakim olmaya geçmeden önce, AVR MK kayıtlarının ayrı ayrı bitlerini nasıl kontrol edeceğinizi veya kontrol edeceğinizi öğrenmeniz gerekir. Daha önce tüm kaydın rakamlarını tek seferde kontrol ediyor veya ayarlıyorduk. Farkın ne olduğunu bulalım ve sonra devam edelim.

Bitsel işlemler

Çoğu zaman, AVR mikrodenetleyicilerini programlarken, acemi MK programcılarıyla karşılaştırıldığında daha görsel olduğundan ve onlar için iyi anlaşıldığından bunu kullandık. Örneğin, D portunun sadece 3. bitini ayarlamamız gerekiyor. Bunu yapmak için zaten bildiğimiz gibi aşağıdaki ikili kodu kullanabiliriz:

PORTD = 0b00001000;

Ancak bu komutla 3. haneyi bire ayarlayıp diğerlerini (0, 1, 2, 4, 5, 6 ve 7.) sıfıra sıfırlamış oluyoruz. Şimdi 6. ve 7. bitlerin ADC girişi olarak kullanıldığı ve bu sırada karşılık gelen MK pinlerinde bir cihazdan sinyal alındığı ve bu sinyalleri sıfırlamak için yukarıdaki komutu kullandığımız bir durumu hayal edelim. Sonuç olarak mikrodenetleyici onları görmez ve sinyallerin gelmediğine inanır. Dolayısıyla böyle bir komut yerine kalan bitleri etkilemeden sadece 3. biti bire ayarlayacak başka bir komut kullanmalıyız. Bunu yapmak için genellikle aşağıdaki bitsel işlem kullanılır:

PORTD |= (1<<3);

Sözdizimini aşağıda ayrıntılı olarak tartışacağız. Ve şimdi başka bir örnek. Diyelim ki PIND kaydının 3. basamağının durumunu kontrol etmemiz gerekiyor, böylece düğmenin durumunu kontrol etmemiz gerekiyor. Bu bit sıfırlanırsa, düğmeye basıldığını ve ardından basılan düğmenin durumuna karşılık gelen komut kodunun yürütüldüğünü biliyoruz. Daha önce aşağıdaki gösterimi kullanıyorduk:

eğer (PIND == 0b00000000)

(herhangi bir kod)

Ancak onun yardımıyla sadece 3. biti değil, PIND kaydının tüm bitlerini aynı anda kontrol ediyoruz. Bu nedenle, düğmeye basılsa ve istenen bit sıfırlansa bile, ancak bu sırada D bağlantı noktasının başka bir pininden bir sinyal alındığında, karşılık gelen değer bire ayarlanacak ve parantez içindeki koşul yanlış olacaktır. Sonuç olarak küme parantezlerinin içindeki kod, butona basıldığında bile çalıştırılmayacaktır. Bu nedenle, PIND kaydının bireysel 3. bitinin durumunu kontrol etmek için bit bazında bir işlem kullanılmalıdır:

if (~PIND & (1<<3))

(herhangi bir kod)

Mikrodenetleyicinin ayrı ayrı bitleriyle çalışmak için C programlama dili, bir veya daha fazla ayrı bitin durumunu aynı anda değiştirmek veya kontrol etmek için kullanılabilecek araçlara sahiptir.

Tek bir bit ayarlama

Bağlantı noktası D gibi tek bir biti ayarlamak için bit düzeyinde VEYA işlemi kullanılır. Makalenin başında kullandığımız şey budur.

PORTD = 0b00011100; // başlangıç ​​değeri

PORTD = PORTD | (1<<0); применяем побитовую ИЛИ

PORTD |= (1<<0); // сокращенная форма записи

PORTD == 0b00011101; // sonuç

Bu komut sıfır biti ayarlar ve gerisini değiştirmeden bırakır.

Örneğin, D bağlantı noktasına başka bir 6. bit takalım.

PORTD = 0b00011100; // başlangıç ​​bağlantı noktası durumu

PORTD |= (1<<6); //

PORTD == 0b01011100; // sonuç

Bir veya birkaç ayrı biti aynı anda yazmak için; örneğin sıfır, altıncı ve yedinci bağlantı noktaları B Aşağıdaki gösterim geçerlidir.

PORTB = 0b00011100; // başlangıç ​​değeri

PORTB |= (1<<0) | (1<<6) | (1<<7); //

PORTB == 0b1011101; // sonuç

Bireysel bitlerin sıfırlanması (sıfırlanması)

Tek bir biti sıfırlamak için daha önce tartışılan üç komut aynı anda kullanılır: .

PORTC yazmacının 3. bitini sıfırlayalım ve gerisini değiştirmeden bırakalım.

PORTC = 0b00011100;

PORTC &= ~(1<<3);

PORTC == 0b00010100;

Benzer işlemleri 2. ve 4. rakamlar için de yapalım:

PORTC = 0b00111110;

PORTC &= ~((1<<2) | (1<<4));

PORTC == 0b00101010;

Bit değiştirme

Ayarlama ve sıfırlamaya ek olarak, tek bir biti ters duruma geçiren kullanışlı bir komut da kullanılır: birden sıfıra ve tam tersi. Bu mantıksal işlem, örneğin bir Yeni Yıl çelengi gibi çeşitli aydınlatma efektlerinin oluşturulmasında yaygın olarak kullanılır. PORTA örneğine bakalım

PORTA = 0b00011111;

PORTA ^= (1<<2);

PORTA == 0b00011011;

Sıfır, ikinci ve altıncı bitlerin durumunu değiştirelim:

PORTA = 0b00011111;

PORTA ^= (1<<0) | (1<<2) | (1<<6);

PORTA == 0b01011010;

Bireysel bir bitin durumu kontrol ediliyor. Bir G/Ç bağlantı noktasının kontrolünün (yazmak yerine) PIN kaydından veri okunarak gerçekleştirildiğini hatırlatmama izin verin.

Çoğu zaman test iki döngü ifadesinden biriyle gerçekleştirilir: if ve while. Bu operatörlere daha önceden aşinaydık.

Bitin mantıksal sıfırın (sıfırlama) varlığı açısından kontrol edilmesi eğer

if (0==(PIND & (1<<3)))

D portunun üçüncü biti temizlenirse Kod1 yürütülür. Aksi takdirde Kod2 yürütülür.

Bu kayıt biçimiyle benzer eylemler gerçekleştirilir:

if (~PIND & (1<<3))

Bitin mantıksal bir birimin (ayar) varlığı açısından kontrol edilmesi eğer

if (0 != (PIND & (1<<3)))

eğer (PIND & (1<<3))

Yukarıdaki iki döngü benzer şekilde çalışır ancak C programlama dilinin esnekliği nedeniyle farklı bir gösterim biçimine sahip olabilir. != operatörü eşit değil anlamına gelir. PD G/Ç bağlantı noktasının üçüncü biti (bir) ayarlanmışsa Kod1 yürütülür; değilse Kod2 yürütülür.

Bitin sıfırlanması bekleniyor sırasında

while (PIND & (1<<5))

PIND kaydının 5. biti ayarlandığı sürece Kod1 yürütülecektir. Sıfırladığınızda Code2 çalışmaya başlayacaktır.

Bitin ayarlanması bekleniyor sırasında

Burada C sözdizimi, kodu en yaygın iki yoldan yazmanıza olanak tanır. Uygulamada her iki kayıt türü de kullanılmaktadır.

Mikrodenetleyiciler (bundan sonra MK olarak anılacaktır) hayatımıza sıkı bir şekilde girmiştir, internette MK üzerinde yürütülen birçok ilginç devre bulabilirsiniz. Bir MK'de birleştiremeyeceğiniz şeyler: çeşitli göstergeler, voltmetreler, ev aletleri (koruma cihazları, anahtarlama cihazları, termometreler...), metal dedektörleri, çeşitli oyuncaklar, robotlar vb. Liste çok uzun sürebilir. Mikrodenetleyici üzerindeki ilk devreyi 5-6 yıl önce bir radyo dergisinde görmüştüm ve kendi kendime "Hala onu birleştiremeyeceğim" diye düşünerek hemen sayfayı çevirdim. Aslında o zamanlar MK'ler benim için çok karmaşık ve yanlış anlaşılan bir cihazdı; nasıl çalıştıkları, nasıl flaş edileceği ve yanlış yazılım durumunda onlarla ne yapılacağı hakkında hiçbir fikrim yoktu. Ancak yaklaşık bir yıl önce ilk devremi bir MK üzerine kurdum; 7 segmentli göstergelere ve bir ATmega8 mikrokontrolörüne dayanan bir dijital voltmetre devresiydi. Tesadüfen bir mikrodenetleyici satın aldım, radyo bileşenleri bölümünde durduğumda, önümdeki adam bir MK satın alıyordu ve ben de onu satın alıp bir şeyler toplamaya karar verdim. Yazılarımda size anlatacağım AVR mikrodenetleyicileri, Size onlarla nasıl çalışılacağını öğreteceğim, firmware programlarına bakacağız, basit ve güvenilir bir programcı yapacağız, firmware sürecine bakacağız ve en önemlisi ortaya çıkabilecek sorunlara bakacağız. sadece yeni başlayanlar için.

AVR ailesindeki bazı mikrodenetleyicilerin temel parametreleri:

Mikrodenetleyici

Flaş bellek

RAM belleği

EEPROM belleği

G/Ç Bağlantı Noktaları

Güç

AVR mega MK'nin ek parametreleri:

Çalışma sıcaklığı: -55…+125*С
Depolama sıcaklığı: -65…+150*С
RESET pinindeki GND'ye göre voltaj: maksimum 13V
Maksimum besleme voltajı: 6,0V
Maksimum G/Ç hat akımı: 40mA
Maksimum güç kaynağı akımı VCC ve GND: 200mA

ATmega 8X Model Bağlantıları

ATmega48x, 88x, 168x modelleri için pin çıkışları

ATmega8515x modelleri için pin düzeni

ATmega8535x modelleri için pin düzeni

ATmega16, 32x modelleri için pin düzeni

ATtiny2313 modelleri için pin düzeni

Makalenin sonunda bazı mikrodenetleyiciler için veri sayfalarının bulunduğu bir arşiv eklenmiştir.

MK AVR kurulumu SİGORTA bitleri

Unutmayın, programlanmış sigorta 0, programlanmamış sigorta ise 1'dir. Sigortaları ayarlarken dikkatli olmalısınız, yanlış programlanmış bir sigorta mikrodenetleyiciyi bloke edebilir. Hangi sigortayı programlamanız gerektiğinden emin değilseniz, ilk kez MK'yi sigortasız olarak flaşlamak daha iyidir.

Radyo amatörleri arasında en popüler mikrodenetleyiciler ATmega8'dir ve bunu ATmega48, 16, 32, ATtiny2313 ve diğerleri takip etmektedir. Mikrodenetleyiciler TQFP ve DIP paketlerinde satılmaktadır; yeni başlayanlar için DIP satın almalarını öneririm. TQFP satın alırsanız, bunları flaşlamak daha sorunlu olacaktır; kartı satın almanız veya lehimlemeniz gerekecek çünkü bacakları birbirine çok yakın yerleştirilmiştir. Mikrodenetleyicileri özel soketlere DIP paketlerine kurmanızı tavsiye ederim, kullanışlı ve pratiktir, yeniden flaşlamak istiyorsanız MK'yi lehimlemenize veya başka bir tasarım için kullanmanıza gerek yoktur.

Hemen hemen tüm modern MK'ler devre içi ISP programlama yeteneğine sahiptir; Mikrodenetleyiciniz karta lehimlenmişse, ürün yazılımını değiştirmek için onu karttan sökmemize gerek kalmayacaktır.

Programlama için 6 pin kullanılır:
SIFIRLA- MK'ye giriş yapın
VCC- Artı güç kaynağı, 3-5V, MK'ye bağlıdır
GND- Ortak kablo, eksi güç.
MOSI- MK girişi (MK'deki bilgi sinyali)
MİSO- MK çıkışı (MK'den bilgi sinyali)
SCK- MK girişi (MK'de saat sinyali)

Bazen XTAL 1 ve XTAL2 pinlerini de kullanırlar; MK harici bir osilatör tarafından çalıştırılıyorsa bu pinlere kuvars eklenir; ATmega 64 ve 128'de MOSI ve MISO pinleri ISP programlama için kullanılmaz; bunun yerine MOSI pinleri PE0 pinine ve MISO PE1 pinine bağlanır. Mikrodenetleyiciyi programlayıcıya bağlarken bağlantı kabloları mümkün olduğu kadar kısa olmalı, programlayıcıdan LPT portuna giden kablo da çok uzun olmamalıdır.

Mikrodenetleyicinin işareti, Atmega 8L 16PU, 8 16AU, 8A PU vb. Gibi sayıların bulunduğu garip harfler içerebilir. L harfi, MK'nin, L harfi olmayan MK'den daha düşük bir voltajda, genellikle 2,7V çalıştığı anlamına gelir. Kısa çizgi veya boşluk 16PU veya 8AU'dan sonraki sayılar, MK'deki jeneratörün dahili frekansını gösterir. Sigortalar harici bir kuvarstan çalışacak şekilde ayarlanmışsa, kuvars veri sayfasına göre maksimumu aşmayacak bir frekansa ayarlanmalıdır; bu, ATmega48/88/168 için 20 MHz ve diğer atmegalar için 16 MHz'dir.


Tepe