STM32 Rtos Kurulumu

Başlatan Mucit23, 28 Ocak 2013, 17:57:58

Mucit23

Arkadaşlar Merhaba

Size danışmak istediğim bir konu var.

STM32F10X için hazırladığım bir programda DS18b20 sıcaklık, harici rtc , ADC okuma, Tuş takımı taraması gibi işlerle uğraşıyorum.

Normalde Tuş takımını Kesmeyle sürekli taradığım için tuş takımının çalışmasında bir problem olmuyor. Ama main programı içerisinde Alt alta birden fazla işlem yaptığım zaman yapılan işlemlerin bitmesi 1sn den daha uzun sürüyor. Dolayısıyla RTC den okuduğum saat bilgisi düzgün olarak güncellenmiyor. Bazen saat ikişer atlıyor. Gerekirse tuş takımı dahil tüm işlemlerimi task lara bölüp öyle yapmak istiyorum.

Burada yazdığım programa Rtos gibi bir yapı kurmak istiyorum.

Mesela Sıcaklık okumasını çok sık yapmak istemiyorum 5 sn aralıklarla bile ölçüm yapılabilir. Aynı şekilde ADC okumasıda çok sık olması gerekmiyor.
Bunları Rtos ile ayarlayabilirmiyim merak ediyorum.

Rtos konusunda biraz teorik bilgi edindim. Fakat Tecrübem hiç yok.

Örnek programlara bakarak bir iki çalışma yaptım  ama bir türlü derleyemedim.
Yazdığım programa rtos yapısını kurmak için sırayla hangi işlemleri yapmalıyım?

Bu konuda Tecrübeli abilerim biraz yol gösterirse sevinirim gerçekten

Klein

RTOS ile yaparsın muhakkak. Ama Bu sorunu çözmek için RTOS şart değil.
Eğer programı hiç bir yerde bekletmez, beklemeleri sayaçlar ile, program adımlarını switch-case  yapısı ile halledersen (Sanırım state-machine deniyor) gayet rahat halledersin.

örnek:

adc_oku;
while( adc_okundu);

gibi bir yapın olursa ADC okunana kadar beklersin.Bu da loop zamanını uzatır. Özellikle DS18B20 okurken program yerlerde sürünür. 

ama bu yapıyı şuna benzer bir  hale getirisen

adc_okuma_islemi()
{
static int pc=0;
static int time=1000;
     switch(pc){
      case 0:
                if(--time==0) 
                {   
                    pc++;
                 }
                break;
       case 1: 
                adc_oku();
                pc++;
                break;
        case 2:
               if(!adc_okundu)
               {
                    pc++;
                }
         case 3:
               time=1000;
               pc=0;
               break;
          default: 
                  pc=0;
     }

}


bu kodu her 1 milisaniyede bir çağırırsan saniyede 1 kez ADC okursun. time değişkenine yüklenen değeri değiştirerek istediğin zamanı elde edersin. 
Bu yöntemi kullanarak, display yazma, eeprom yazma gibi daha uzun beklemeler gerektiren yerlerde çok daha etkin zamanlamalar elde edersin. Özellikle  OneWire için önerebileceğinm en etkin yol bu. 
STM32F103 kullanıyorsan eğer , loop zamanın mikrosaniyeleri geçmez.

pisayisi

Systick kesmesini ve gecikmesini referans olarak kullan istediğin yenileme hızı ile yapmak istediğin görevleri tamamla, bütün rtos larda systick kesmesi kullanmakta...
Murat

Mucit23

Klein Hocam üzerinde yazılımın çok çalışmam lazım. Özellikle Şuanda ADC çok vaktimi alıyor. Çıkışlarımı kontrol altında tutan 15-20 parametre var. Bu parametrelerinde kontrolünü yapmam gerekecek. Bunlardada daha uğraşmadım ama bir sürü if else kullanmam gerekebilir.

Yazılımı iyi bir şekilde organize ederek bu sorunlara aşarım büyük ihtimal ama yinede ben Rtos üzerinde çalışmak istiyorum(Daha önce çok merak ediyordum deneme fırsatım olacak işte :))

Klein hocam Vaktiniz varsa eğer keil kendi rtos unu programıma adapte etmem için yapmam gerekenleri adım adım anlatabilirmisiniz

Erol YILMAZ

#4
Araştırılması gereken konu öncelikle "State Machine" dir.

Ben de çok görevli yazılımlarımı ekseriyetle bu teknikle yaptım,  çok ta verimli çalıştığını düşünüyorum.

Ayrıca şunu özellikle düşünmek gerekli,
   Gerçekten mcu yu meşgul eden ne var ?
   - ADC çevrimi uzun sürüyorsa bitince kesme oluşturacak şekilde ayarlanabilir.
   - Uart RX TX zaten kesmeli
   - Buton vs kontrolü kesmeli,
   - Sanırım halen "Brute delay" kullanmıyoruz. Systick ve diğer timer lar bu iş için yapılmış.

   - Veri gönderimi alımı vs uzun sürebilir. (TFT vs)
   - Float Matematiksel işlemler uzun sürebilir.

bunların da işe uygun çözümü bulunur sanıyorum.

Mucit23

Hocam bu state machine dediğiniz yapı çok kafamı karıştırdı açıkçası.

Şuanda ADC çevrimi çok vaktimi almıyor. Yani Çevrimin kendisi vakit almıyor. Yoksa ard arda 300'e yakın örnek alıp ortalamasını alarak filtre uyguluyorum. Ama her ölçüm arası 1ms beklemem gerekiyor. Bu yüzden tüm ölçümün bitmesini beklemek çok vakit alır. Bunun yerine her bir ölçüm arası gidip başka iş yapmam gerekiyor.

Beni ençok düşündüren aslında Sıcaklık sensörü. Sıcaklık sensörü işlemcinin elini kolunu bağlıyor. Bu konudada ete hoca bir çözüm getirmişti. Diyelim sıcaklık sensörü okunurken Sensöre çevrim emri verip geri dönmek gerekiyor. Çevrim işlemi bittikten sonra yani yaklaşık 700ms sonra gidip sensörü okumak gerekiyor.

Buradada aklımı kurcalayan bir konu bu zaman işlemlerini nasıl tutmak. Burada ikinici bir timermi kullanmak gerekir?

@Allegro

Hocam State Machine dediğiniz yapı hakkın bazı diyagramlar buldum. İşleyişi biraz kafamda canlandırabiliyorum ama tam oturmadı...

Siz uyguladıysanız nasıl yapmam gerektiğini anlatırsanız hemen deneyebilirim.

f_machine

ADC den 300 örnek alma işini DMA ile yapabilirsin . DMA işlemciyi rahatsız etmeden 300 ADC değerini hafızaya yazar , daha sonra cpu birimine kesme atar . Böylece burada hiç vakit kaybetmemiş olursun.

muhittin_kaplan

mucit elimdeki iş belli bir yere geldiğinde ilk işim http://www.coocox.com/EXAMPLE/ST_Keil_ARMCC.htm inceleyip kullanmak olacak.

memo333

Gömülü Linux Notları --> http://linuxedu.xyz/

z

"Sequential logic" devre tasarımını öğrenmeden mikroişlemci öğrenirseniz böyle olur işte.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Mucit23

#10
Alıntı yapılan: memo333 - 29 Ocak 2013, 11:30:44
http://www.state-machine.com/index.php

bakalım ne imiş state-machine?

Sağol Teşekkür ederim. Şimdi State Machine Kavramı biraz daha netleşti. Fakat ben bu yapıyı baştan itibaren sistemime oturturabilirmiyim. Burada sistemi kurmak için farklı bir bilgisayar ortamı var. Birazcık Google un Appİnventor yapısına benzettim.

Ben şimdilik kodumu optimize etmeye çalışacağım. İyi bir organizasyonla bunlara gerek kalmayabilir.

Birde Rtos u sisteme oturturdum. Derliyorum fakat çalıştıramıyorum. İşlemci donuyor.

Main içeisinde yine sonsuz döngü var. Acep ondanmı kaynakanıyor?

Alıntı yapılan: z - 29 Ocak 2013, 12:03:58
"Sequential logic" devre tasarımını öğrenmeden mikroişlemci öğrenirseniz böyle olur işte.

Yapımızda var hocam. Tersten gidiyoruz.. :D

haydarpasamikro

Yöntem:

Mikrodenetleyicinizin Timer ını 1 saniye kesme oluşturacak şekilde ayarlayın.
Kesme içerisinde 1 saniye sonunda TimerFlag aktif edin.

RTC 1 saniye de bir donanım kesmesi göndermeye ayalanabilir.

Ana programda.
Tuş takımını tarayın. Basılan tuş ile ilgili işlem yapın. Ancak tarama sırasında veya bir bekleme fonksiyonun içerisinde gelen kesmelere ait flag leri denetleyin. Kesme varsa ilgili öncelikli işleri fonksiyon olarak yaptırın. RTC den zamanı okumak gibi. ADC okumak gibi. Sonra aciliyeti olmayan diğer işlere devam edin.

Timer kesmesi sizin için 1 saniyelik periyotta mutlaka yapılması gereken işler için geniş bir zaman dilimi sağlar.
Mikro Dünyası.Haydarpaşa Teknik ve Endüstri Meslek Lisesi Mikrodenetleyici Atl. Şefi

Mucit23

Arkadaşlar bugün biraz Rtos a bakayım dedim. Derliyorum ama işlemci hiç çalışmıyor.

Rtos konusunda, daha doğrusu keilin kendi rtos kütüphanesinin kullanımı hakkında bilgim yok, Copy paste ile deneme yapıyorum.

Kodlarım bu şekilde,
#include "stm32f107.h"
#include "string.h"
#include "RTL.h"

OS_TID t_phaseA;                        /* assigned task id of task: phase_a */
OS_TID t_phaseB;                        /* assigned task id of task: phase_b */

__task void phaseA (void) {
  for (;;) {
		output(portC,0xFFFF);
		os_dly_wait (400);
		output(portC,0x0000);
		os_dly_wait (400);
  }
}

/*----------------------------------------------------------------------------
 *        Task 2 'phaseB': Phase B output
 *---------------------------------------------------------------------------*/
__task void phaseB (void) {
  for (;;) {
    os_evt_wait_and (0x0001, 0xffff);    /* wait for an event flag 0x0001    */     
		output(portE,0xFFFF);
		os_dly_wait (400);
		output(portE,0x0000);
		os_dly_wait (400);
  }
}

__task void init (void) {

  os_mut_init(phaseA);

  t_phaseA = os_teşekkür_create (phaseA, 0);  
  t_phaseB = os_teşekkür_create (phaseB, 0);  
  os_evt_set (0x0001, t_phaseA);        
  os_teşekkür_delete_self ();
}

int main()
{
		 SystemInit();
		 setOutMode(portA,0xFFFF);  //A portunun tamami çikis yapildi. 
		 setOutMode(portC,0xFFFF);  //C portunun tamami çikis yapildi.
		 setInMode(portD,0xFFFF);  //D portunun tamami Giris
		 setOutMode(portE,0xFFFF);  //D portunun tamami çikis yapildi.        
	
	   //output(portE,0xffff);
	 os_sys_init (init);
//    while(1){
//     outputBit(portE,0x0000,readPortBit(portD,0x0080));
//     outputBit(portE,0x0002,readPortBit(portD,0x0040));
//    }
}


Proje ağacıda bu şekilde

photo sharing websites
Acaba nereleri eksik yapıyorum?

Mucit23

Değerli Hocamlarım, Yorum yapacak olan yokmu?

yamak

Hocam init task'ın da PhaseA ye event gönderiyosun ama PhaseA taskı'ını başına event bekleme koyamamışsın. 0x0001 nolu event'i PhaseB de bekliyosun.