Elektronik / Mikrodenetleyici Projeleri/

DS75 Isı Sensör Bilgilerinin SMS Protokolü İle İletimi

Sponsorlu Bağlantılar

Hazırlayan: Engin Karabulut – Projeyi uygulamak bir yana pic16f876 hakkında detaylı Türkçe bilgiler işinize yarayacaktır Emeği geçen Kişilere Teşekkürler

Projenin Kısa Özeti: Bu proje daha önceki “ds75 I2C sayısal sıcaklık sensörü ile sıcaklık ölçümü ve dısplay’de görüntülenmesi” adlı proje1 çalışmasının devamı niteliğindedir. Yapılan tasarım ile daha önceki projede elde edilen sayısal sıcaklık verilerinin SMS(short message service) aracılığı ile GSM (Groupe Special Mobile) ağı üzerinden iletilmesi sağlanmıştır.Projenin donanım kısmını ana olarak PIC16F876A serisi bir microcontroller ve bir Siemens S25 GSM telefon oluşturur.Software ise PDU encoding, interrupt driven usart ve I2C bus modüllerinden oluşmaktadır.

pic16f876a sms protokol veri iletimi

Giriş: SMS günümüzde yaygın olarak kullanılmaktadır,telefon görüşmelerine göre maliyetinin düşük olması kullanımını yaygınlaştırmıştır.SMS mesajlaşmak dışında veri aktarımı için kullanılabilir buna en iyi örnek logo melodi servisleridir.Bu servisler gönderilecek logo veya melodiyi SMS ile iletirler,sonuçta bunlarda bir veridir.Bu sayede alıcı telefon wap(wireless application protocol) veya gprs(general packet radio service) özelliklerine sahip olmasa bile bu servislerden yararlanabilir.

Bu projede SMS’in ülkemizde pek bilinmeyen data aktarma yönü kullanıldı ve yapılan denemelerde maliyeti düşürmek için ikinci el bir GSM telefon ile tasarım yapıldı ve maliyette önemli düşüşler sağlandı.

SMS roaming(uluslararası dolaşım) sistemine dahildir,yani istenilen veriler karşı alıcı, dünyanın neresinde olursa olsun eğer GSM,TDMA,CDMA veya Globalstar kapsama alanları içerisinde bulunuyorsa iletilebilir,aksine GPRS sistemi gelişmekte olan ülkelerde çok nadir desteklenmekte ve roaming desteği gelişmemiştir.Bu yüzden projede SMS kullanılmıştır.

PIC16F876A microcontroller

Sistem mikrodenetleyici tabanlıdır,mikrodenetleyiciler mikroişlemci,RAM,ROM,I/O,ADC ve daha bir çok birimin tek bir entegreye yerleştirilmesiyle tasarlanmıştır.Mikrodenetleyicilerin yaptığı her işi aslında mikroişlemcide yapabilir(zaten mikrodenetleyicide kendi içinde basit bir mikroişlemci içerir) fakat bu durumda diğer yan üniteler haricen eklenmek zorundadır,bu nedenle hem maliyet aşırı artar hemde tasarım zorlaşır.Tüm bu nedenlerden dolayı günümüzde yüksek işlem gücü gerektirmeyen endüstriyel ortamlarda %99 mikrodenetleyiciler kullanılmaktadır.

Şekil1:16F876A
pic16f876a

PIC16F876A, Microchip™ Technology Inc. tarafından üretilen bir mikrodenetleyicidir.Arizona’da kurulu olan şirket dünya mikrodenetleyici pazarından önemli bir pay almaktadır.

Mikrodenetleyici yanında seri(I2C) E²PROM, analog devre elemanları üretmektedir.16F876A midrange serisinin en güçlü üyelerinden biridir.0-20Mhz clock frekansında çalışabilir.Z80 gibi mikroişlemcilerin aksine statik yapıdadır yani üzerinde DRAM(Dynamic Ram) bulunmaz,bu yüzden herhangi bir altsınır clock frekansı yoktur.DRAM’ler ise her 15.6µs’de bir tazelenmelidir,daha yüksek bir tazeleme periyodunda içerdiği veriler silinir,bu yüzden PIC serisi mikrodenetleyiciler SRAM(Static Ram) kullanırlar.

Bu SRAM 368Byte genişliğindedir ve çalışan programlar bunun üzerinde yürütülür. 16F876A 14.2K Flash ROM’a sahiptir.Derlenen programlar hex formatına çevirilerek buraya kaydedilir,bu hafıza besleme kesilse dahi silimez,bu alana okuma yazma gerçekleştirmek için mikrodenetleyici programlayıcılar kullanılır.Bu projede P16PRO programlayıcı kullanılmıştır.Son olarak 256Byte dahili E² PROM içerir,buraya programcı enerji kesintisinde silinmesini istemediği verileri saklayabilir.

Dahili Çevre Birimleri:

3 adet donanımsal sayıcı( 2 adet 8bit,1 adet 16bit) : Bu sayıcıların sayma periyodu prescaler(bölme fonksiyonu) yardımıyla kolaylıkla ayarlanabilir. Ayrıca sayıcılardan bir adeti harici bir interrupt(TOCKI) ile tetiklenebilir,bu suretle harici bir etkiyle(bu bir sensör olabilir) saydırılabilir.

MSSP(master-slave synchronous serial port) : MSSP senkronize yani bir clock eşliğinde seri bilgi göndermek amacıyla kullanılır.Hem I²C hemde SPI formatlarını destekler.

USART(Universal synchronous asynchronous receiver-transmitter) : USART modülü microcontroller’a entegre iki seri I/O modülünden biridir.USART aynı zamanda seri iletişim arayüzü veya SCI(serial commmunication interface) olarak bilinir.USART CRT terminaller, kişisel bilgisayar ve GSM telefonlar gibi çevre birimleri ile iletişim kurmak için full-duplex(çift yönlü) konfigüre edilebilir.Bunun yanında A/D veya D/A dönüştürücüler,seri eeprom gibi çevre birimleri ile iletişim kurabilmek için half-duplex(tek yönlü) olarak konfigüre edilebilir.

Analog Birimler:
5 adet 10bit Analog/Sayısal dönüştürücü.
2 adet donanımsal analog karşılaştırıcı.

Flash ROM: Dahili program flash belleği 100000 defa silinip yazılabilir, dahili verilerin saklandığı E²PROM tipik olarak 1000000 kez yazılıp silinebilir ve her iki bellekte enerji uygulanmasa dahi içerdikleri verileri 40 yıldan fazla saklayabilir.

Program korsanlığına karşı code protection korumalıdır.Mikrodenetleyici’nin içerisine kayıtlı program bu özellik açılırsa kesinlikle okunamaz.

PIC16F87X serisi “In circuit serial programming” özelliğine sahiptir,buna göre son kullanıcı herhangi bir programlayıcıya ihtiyaç duymadan tasarımcı tarafından devreye entegre edilmiş MAX232 türü bir RS232-TTL dönüştürücü yardımıyla sadece seri port kullanarak kendi programını yükleyebilir,fakat bu işlem için daha önceden “bootloader” gibi bir program mikrodenetleyiciye yüklenmiş olmalıdır,bunun yardımıyla PIC kendi kendini programlayabilir.

Tüm bu üstünlüklerin yanında 2.0-5.0V arasında çalışabilen PIC16F876A CMOS teknolojisiyle üretilmiştir ve sadece 2µA tüketir,hem piyasada yaygın olarak bulunabilmesi ve geniş teknik üstünlükleriyle PIC serisi mikrodenetleyiciler günümüzde oldukça popülerdir

USART(Universal synchronous asynchronous receiver-transmitter) : Projede 19200 baud hızında RS232 formatıyla Siemens S25 GSM telefon ile iletişim kurulmuşur.GSM telefonun baud hızı sabittir ve tasarım aşamasında 19200baud/sn olarak seçilmiştir.RS232 iletişim USART ile donanımsal olarak yapılmaktadır.

RS232 asenkron bir iletişim şeklidir yani iletime bir clock sinyali eşlik etmez,fakat bu durumda alıcıya vericinin baud oranı daha önceden bildirilmelidir ve hız bir kez belirlendikten sonra değiştirilemez.I2C gibi senkron iletişimde bir clock ve bir data hattı bulunur,karşı tarafın gönderme hızını bilmesine gerek yoktur,master yani verici clock hızını değiştirerek gönderim hızını dinamik olarak değiştirebilir. R232’de senkronizasyon start ve stop bitleriyle yapılır,bu sisteme 8N1 sistemi denir.

Şekil2 : TTL/CMOS RS232 Dalgaformu
TTL CMOS RS232 Dalgaformu

8N1 8 data biti,1 stop biti ve parite biti kullanılmadığını belirtir.İletim şekil2’de görüldüğü gibi bir start(0V) biti ile başlar.Daha sonra 8bit sırayla gönderilir,son olarak bir stop(5V) biti ile iletim bitirilir.Hattan bir şey gönderilmiyorsa yani boşsa lojik1(5V) seviyesinde tutulur,eğer stop biti(5V) yerine lojik0(0V) alınırsa hata oluşur ve buna “framing error” adı verilir RS232 verileri şekil2’deki gibi TTL seviyesinde iletim hattından iletilmez bunun yerine şekil3’teki sistem kullanılır.

Şekil3:RS232 lojik dalgaformu
RS232 lojik dalgaformu

Burada -3V’tan -25V’a kadar olan aralık lojik1,+3V’tan +25V’a kadar olan aralık ise lojik0 olarak kullanlır. -3V’tan +3V’a kadar olan aralık ise tanımsızdır.

Bunun avantajı iletim hattındaki kaybın TTL sisteme göre çok düşük olmasıdır,öyleki TTL bir iletim hattı maksimum 3m ile sınırlıyken,RS232 20m’ye kadar sorunsuz kullanlabilir.Projede ise RS232 iletim hattı sadece 1m olduğu için TTL seviyesi kullanıldı,böylece USART ile iletişim kurarken ayrıca bir çevirici kullanılmasına gerek kalmadı. PIC16F876A’ya entegre USART 2 ana register ile konfigüre edilir.Bunlar TXSTA ve RXSTA’dır.

TXSTA: (Transmit Status And Control Register) (ADDRESS 98h)

TXSTA Transmit Status And Control Register ADDRESS 98h

CSRC: Clock kaynağı seçim biti
Asenkron mod için:
Etkisizdir
Senkron mod için:
1 = Master modu (clock sinyali BRG(baud rate generator)’den dahili olarak üretilir.
0 = Slave modu (clock sinyali harici olarak verici tarafından üretilir)

TX9: 9-bit (parite) iletim seçimi
1 = 9-bit(pariteli) iletimi modu
0 = 8-bit(paritesiz) iletim modu

TXEN: veri iletimini başlatır
1 = veri iletimini başlatır
0 = veri iletimini durudurur

SYNC: USART Modu seçim biti
1 = Senkron mod
0 = Asenkron mod

BRGH: Yüksek hızlı baud oranı seçim biti
Asenkron modunda:
1 = Yüksek hızlı
0 = Düşük hızlı
Senkron modunda:
Etkisizdir.

TRMT: İletim Shift register durumu
1 = TSR(iletim shift register’ı) boş
0 = TSR(iletim shift register’ı ) dolu

TX9D: Parite bitinin değeri burada belirleniyor.

RCSTA: (RECEIVE STATUS AND CONTROL REGISTER) (ADDRESS 18h)

RCSTA RECEIVE STATUS AND CONTROL REGISTER ADDRESS 18h

SPEN: Seri Port açma-kapama
1 = Seri port devrede (RC7/RX/DT ve RC6/TX/CK pinleri seri port olarak ayarlandı)
0 = Seri port devre dışı (RC7/RX/DT ve RC6/TX/CK pinleri sayısal I/O olarak ayarlandı)

RX9: 9-bit(parite) alış modu
1 = 9bit(parite) alış aktif
0 = 8bit(paritesiz) mod (8N1)

SREN: Single Receive Enable bit
Asenkron mod:
Etkisiz.

CREN: Sürekli veri alma açık/kapalı
Asenkron mod:
1 = Sürekli alış aktif
0 = Sürekli alış pasif

ADDEN: Adres sezme açık/kapalı
Asenkron mod 9-bit (RX9 = 1):
1 = Adres sezme aktif
0 = Adres sezme pasif

FERR: Framing Error biti
1 = Framing error oluştu(RCREG register’ı okunarak update edilebilir.)
0 = Framing error oluşmadı

OERR: Overrun Error biti
1 = Overrun error oluştu (CREN bitini kapatıp açarak hata düzeltilebilir.)
0 = Overrun error oluşmadı

RX9D: Alınan verinin 9.(parite) biti

USART Baud Rate Generator(BRG) : BRG USART’ın hem asenkron hemde senkron modunu destekler ve sadece 8bit baud rate üreteci olarak kullanılır. SPBRG register’ı TXREG’in shift işlemi için kullanılan 8bit timer’ın periyodunu belirler. Asenkron modda BRGH (TXSTA<2>) bitide baud rate üzerinde etkilisidir. Senkron modda, BRGH biti etkisizdir.

Şekil6:Baud rate hesap tablosu
Baud rate hesap tablosu

Şekil6 değişik USART modları için baud oranı hesap tablosunu göstermektedir.Bu tablo kullanılarak hesaplanan değer SPBRG register’ına girilir ve Fosc burada kristal frekansıdır.

BRGH=1 modu yüksek hızlı iletişim için kullanılsada düşük hızlar için kullanılması avantajlı olabilir,çünkü FOSC/(16(X+1)) eşitliği ile hesaplanan baud rate ile istenen baud rate arasındaki hata oranı en aza düşürülebilir.SPBRG register’ına yeni bir değer girilmesi BRG timer’ı resetler ve USART’ı başlangıç durumuna getirir.Şekil7’de çeşitli kristal hızları için hesaplanmış bir baud rate tablosu verilmiştir.

INTCON REGISTER (ADDRESS 0Bh, 8Bh, 10Bh, 18Bh) : Intcon register’ı PIC’te oluşan bütün donanımsal kesmeleri kontrol eder.Donanımsal kesmeler buradan gerekli bitler kullanılarak açıp kapatılabilir.

Şekil7: Intcon register yapısı
Intcon register yapısı

GIE: Tüm kesmeleri aç/kapa
1 = Tüm kesmeler devrede
0 = Tüm kesmeler devre dışı

PEIE: Çevre birim kesmeleri aç/kapa
1 = Tüm çevre birim kesmeleri devrede
0 = Tüm çevre birim kesmeleri devre dışı

TMR0IE: TMR0 taşma kesmesi aç/kapa
1 = TMR0 kesmesi aktif
0 = TMR0 kesmesi devre dışı

INTE: RB0/INT harici kesme aç/kapa
1 = RB0/INT harici kesmesi aktif
0 = RB0/INT harici kesmesi devre dışı

RBIE: RB Port değişim kesmesi aç/kapa
1 = RB(4:7) port değişim kesmesi aktif
0 =RB(4:7) port değişim kesmesi devre dışı

TMR0IF: TMR0 taşma kesmesi flag biti
1 = TMR0 register’ı taştı (yazılım ile sıfırlanmalı)
0 = TMR0 register’ı taşmadı

INTF: RB0/INT harici kesmesi flag biti
1 = RB0/INT harici kesmesi oluştu (yazılım ile sıfırlanmalı)
0 = RB0/INT harici kesmesi oluşmadı

RBIF: RB Port(4:7) değişim kesmesi flag biti
1 = RB7:RB4 pinlerinden en az birisi durum değiştirdi (port değerleri okunarak kesme
durumundan çıkılmalıdır)
0 = RB7:RB4 pinlerinden durum değiştiren olmadı

PIE1 REGISTER (ADDRESS 8Ch) : Çevre birimlere ait kesmeleri açıp kapatmak için kullanılır.

Şekil8:Pie1 Register
Pie1 Register

PSPIE: 16F876A için kullanılmıyor.

ADIE: A/D dönüştürücü kesmesi biti
1 = A/D dönüştürücü kesmesi aktif
0 = A/D dönüştürücü kesmesi devre dışı

RCIE: USART alış kesmesi biti
1 = USART alış kesmesi aktif
0 = USART alış kesmesi devre dışı

TXIE: USART iletim kesmesi biti
1 = USART iletim kesmesi aktif
0 = USART iletim kesmesi devre dışı

SSPIE: Senkron Seri Port (SSP) kesmesi biti
1 = SSP kesmesi aktif
0 = SSP kesmesi devre dışı

CCP1IE ve TMR2IE 16F876A tarafından kullanılmıyor.

TMR1IE: TMR1(timer1) taşma kesmesi
1 = TMR1 taşma kesmesi aktif
0 = TMR1 taşma kesmesi devre dışı

PIR1 REGISTER (ADDRESS 0Ch) : PIR1 regesiter’ı çevre birimlere ait kesmelerin gerçekleşip gerçekleşmediği hakkında bilgi verir.

Şekil9:PIR1 Register
PIR1 Register

PSPIF: 16F876A için kullanılmıyor

ADIF: A/D dönüştürücü kesmesi flag biti
1 = Bir A/D dönüşümtamamlandı
0 = Bir A/D dönüşüm işlemi sürüyor,henüz tamamlanmadı.

RCIF: USART alış kesmesi flag biti
1 = USART alış tampon belleği dolu
0 = USART alış tampon belleği boş

TXIF: USART iletim kesmesi flag biti
1 = USART iletim tampon belleği boş
0 = USART iletim tampon belleği dolu

SSPIF: Senkron Seri Port (SSP) kesmesi flag biti
1 = SSP kesme durumu oluştu ve kesme alt programında dönülürken yazılımsal olarak sıfırlanmalı.

• SPI modunda: Bir iletim veya veri alışı meydana geldi.
• I2C Slave modunda: Bir iletim veya veri alışı meydana geldi.
• I2C Master modunda:
– Bir iletim veya veri alışı meydana geldi.
– Başlatılan Start durumu SSP modülü tarafından tamamlandı.
– Başlatılan Stop durumu SSP modülü tarafından tamamlandı.
– Başlatılan Restart durumu SSP modülü tarafından tamamlandı.
– Başlatılan Acknowledge durumu SSP modülü tarafından tamamlandı.
0 =SSP interrupt durumu oluşmadı.

CCP1IF, TMR2IF: Bu flagler 16F876A tarafından kullanılmıyor.

TMR1IF: TMR1 taşma kesmesi flag biti
1 = TMR1 register’ı taştı (yazılım tarafından sıfırlanmalıdır.)
0 = TMR1 register’ı taşmadı

USART’ı başlangıç durumuna getiren ‘rs232init’ altprogramı


void rs232init()
{
   BRGH = 1;    //BRGH=1 yapılarak hi-speed modu seçiliyor
   SPBRG = 12;  //19200 baud/sn hızı için SPBRG=12 seçiliyor(BaudRate=FOSC/(16(X+1))
   TX9 = 0;     //parite biti gönderimi TX9=0 yapılarak kapatılıyor.
   RX9 = 0;     //parite biti alımı TX9=0 yapılarak kapatılıyor.
   SYNC = 0;    //SYNC=0 yapılarak asenkron mod seçiliyor.
   SPEN = 1;    //seri port devreye alınıyor.
   RCIE = 1;    //Usart alış kesmesi açılıyor. 
   TXEN = 1;    //iletim aktif hale getiriliyor.
   PEIE = 1;    //çevre birimlere ait kesmeler aktif hale getiriliyor.
   CREN = 1;    //sürekli alış aktif hale getiriliyor.
}


USART ile 8bit(8N1) veri gönderen ‘rs232send’ altprogramı

void rs232send(unsigned char sendvalue)
{
 while(TRMT == 0)     // İletim Shift Register ‘ı boşalana kadar bekleniyor
 {                    //
 nop();               //
 }                    //  
 TXREG = sendvalue;   //gönderilecek 8bit değer TXREG’e giriliyor ve gönderiliyor 
}     

USART’tan veri alımı için yazılan interrupt altprogramı

void interrupt isr (void)
{
RX2flag = 0;  //RCREG çift katlı tampon,bu yüzden kaç katın dolu olduğu RX2flag   
              //register’ı üzerinde tutuluyor.Başlangıçta sıfıra çekiliyor.   

GIE = 0;  //kesme sırasında başka kesme oluşmaması için GIE=0 ile tüm kesmeler
          //kapatılıyor
if(GIE == 0)  //son bir kez GIE=0’mı bakılıyor.
  {
  if(RCIF == 1)  //kesmenin USART’tan gelip gelmediğine bakılıyor.
    {
    RXreg = RCREG;  //RCREG tamponundan 8bit gelen data alınıyor.
    if(RCIF == 1)   //eğer hala RCIF=1 ise RCREG’in ikinci katıda doludur.
      {             
      RXreg2 = RCREG; //bu yüzden 2.kattaki 8bit data da alınıyor.
      RX2flag = 1;    //2. 8bit data’da alındığı için RX2flag biti 1 yapılıyor.
      }	 
    lcdputch(RXreg);  //alınan ilk byte LCD’ye yazılıyor
    if(RX2flag ==1)   //RX2flag=1’mi? 
      {
      lcdputch(RXreg2);  //eğer alındıysa 2. byte LCD’ye yazılıyor.
      RX2flag = 0;       //çıkışta RX2flag biti 0 yapılıyor.
      if(OERR == 1)      //ezme(overrun) hatası oldumu? programcının notu:
        {                //ezme olursa framing error’da gerçekleşir  
        CREN = 0;        //hatayı gidermek için USART resetlenmeli,bunun
        FERR = 0;        //için CREN=0 yapılıp tekran CREN=1 yapılmalı
        CREN = 1;        //bu arada FERR=0 yapılıp framing error’da girerilmeli.
        }     
      } 
    GIE = 1;             //GIE kesme çıkışında açılıyor.
    }
  }   
}

Pic ile SMS gönderimi

GSM kısa mesaj servisi(SMS), mobil ile GSM sistemi arasında veya hücresel sistemler ile kısa mesaj gönderme ve opsiyonel olarak alma yeteneğine sahip olan harici cihazlar arasında kısa alfanünerik mesajlar göndermeye izin vermektedir.

GSM iki tür kısa mesaj servisini destekler. Birincisi, kullanıcıların mesajı sisteme girmek amacıyla Kısa Mesaj Entitisi(SME) ile etkileşimli olarak mesaj gönderdikleri durum olan noktadan noktaya servistir.

Kullanıcı SME ile e-posta yoluyla mesajı alan ve onu sisteme giren operatör içerisinde telefon çağrısı veya DTMF(Dual-Tone Multifrequency) tonlarını kabul eden ses cevap sistemini arayarak karşılıklı etkileşim içine girebilir. İkincisi ise SMS çağrı yayınıdır. Bu serviste birçok mobil istasyon aynı mesajı, mesaj yayma yoluyla iletmektedir. Servisin amacı sistemde aynı bilgiyi eşzamanlı olarak birçok mobil istasyona sağlamaktır. Bilgiler, haberleri veya spor sonuçlarını, borsa bilgilerini ve daha fazlasını içerebilir.

AB’ye bağlı ETSI organizasyon’nun GSM 03.40 and GSM 03.38 dökümanlarında tanımlanan SMS(short message system) ile 7bit alfabe ile 160 karaktere kadar ulaşılabilir. 7bit alfabenin yanında 8bit(140 karakter) ve 16bit(70 karakter) sistemlerde SMS tarafından desteklenir.

8 bit sistem ASCII tablosu ile uyumlu olması sebebiyle genelde logo,melodi ve wap(wireless application protocol) ayar servisleri için kullanılır.16bit sistem ise genelde alfabeleri binlerce harf içeren uzakdoğu ülkeleri tarafından kullanılır.

7bit SMS alfabesi

Yukarıdaki tablodaki bazı karakterlerin karşılığı 8bit Ascii tablosunda bulunmayabilir veya tam terside olabilir,tablo tasarlanırken SMS ile kullanılabilecek karakterlere öncelik verilmiştir. Örnek olarak Ascii tablosundaki ‘bell’ (hex 07) karakterine burada yer verilmemiştir.

Şekil10: SMS veri katarı
SMS veri katarı

SCA: Bu bölüm mesaj merkezi numarasını içerir ve ulusal bir numaryamı yoksa uluslar arası bir numarayamı mesaj gönderilecek burada belirtilir.

PDU type: Mesaj gönderimine ait opsiyonlar burada belirtilir,buradaki flagler kullanılarak örnek olarak statü raporu istenebilir.

MR(message reference): 00H olarak bırakılmalıdır.

DA(destination address): Alıcının telefon numarası buraya girilir.

PID(protocol identifier): Standart SMS gönderimi için 00H olarak bırakılmalıdır.

DCS(data coding scheme): 7bit standardında alfabe için 00H kullanılmalıdır.

VP(validity period): SMS’in ne kadar süre SMSC(mesaj merkezi)’inde tutulacağını belirtir,buraya girilen değere göre eğer sms zamanında teslim edilemezse otomatik olarak silinir.

UDL(user data length): gönderilecek pdu(protocol data unit) katarının uzunluğu burada belirtilmelidir.

UD(user data): 7bit alfabe kullanan harf dizilerinden hesaplanan PDU dizisi.

PDU dizisinin 7bit alfabe kullanan harf dizisinden hesaplanması

Şekil11:PDU dizisi hesabı
PDU dizisi hesabı

İlk yedili(h) ikinici yedilinin(e) 0. bitinin başına eklenmesiyle 8bit haline getirilir.Bu açık olarak 1 + 1101000 = 11101000 (“E8”) şeklinde yapılır.Daha sonra ikici yedili sağa doğru bir bit kaydırılarak ilk yediliye eklenen 0. bit elenir.Bu işlemden sonra üçüncü yedilinin son iki biti ikinci yedilinin başına eklenir (00+ 110010 = 00110010 (“32”).Bu işlem sekizinci yediliye kadar şekil11’deki gibi yapılır
sonuç şekil12’deki gibi elde edilir.

Şekil12:Hesaplanan PDU dizisi
Hesaplanan PDU dizisi

PDU hesabı için kullanılan algoritma

#define PIC_CLK 4000000


#include <pic.h>
#include "always.h"

#include "delay.h"
#include "delay.c"

#include "lcd.h"
#include "lcd.c"

#include "877_i2c.h"

__CONFIG(HS & WDTDIS & PWRTEN & BOREN & LVPDIS & DUNPROT & DEBUGDIS & UNPROTECT);


void init_ports(void)
{
#if defined(_16F876A)
	ADCON0 = 0;
	ADCON1 = 0B00000110;	// Analog girisleri dijital yap E0, E1, E2	
#endif	

	TRISA = 0B11110001; //Data1-2 giris ve CLK1-2 cikis
	TRISB = 0B11000000;
	TRISC = 0xFF;
	

	PORTA = 0x00;
	PORTB = 0;
	PORTC = 0;
	

	TMR0   = 0;
	
	OPTION = 0b10000111;	// Prescaler 111 -> 1/256
        INTCON = 0b00000000;	// GIE ve Peripheral Interrupt pasif
        PIR1 = 0x00;
        PIR2 = 0x00;
        
}


/////////////////////////////////////////////////////////////////////////////
unsigned char data2,data1,swap1,swap2,k;
unsigned char On1,On2,On3,On4,Z;
unsigned char RXreg,RXreg2;
bit RX2flag;
bank1 unsigned char p[17] = {'s','i','c','a','k','l','i','k',':'};
bank1 unsigned char hexsonuc[30];
bank2 unsigned char smsheader[] = {'0','7','9','1','0','9','4','5','9','2','0','8','0','0','3','3','1','1','0','0','0','C','9','1','0','9','3','5','5','2','3','9','6','0','9','7','0','0','0','0','A','A','1','1'};

char bin2bcd(char);
void ondalik(void);
void nop(void);
void rs232send(unsigned char);
void rs232init(void);
void smsinit(void);
void pduconv(unsigned char *,unsigned char *);
/////////////////////////////////////////////////////////////////////////////
void interrupt isr (void)
{
RX2flag = 0;
GIE = 0;
if(GIE == 0)
  {
  if(RCIF == 1)
    {
    RXreg = RCREG;
    if(RCIF == 1)
      {
      RXreg2 = RCREG;
      RX2flag = 1;
      }	 
    //RSflag = 1;
    RCIE = 0;
    lcdputch(RXreg);
    if(RX2flag ==1)
      {
      lcdputch(RXreg2);
      RX2flag = 0;
      if(OERR == 1)
        {
        CREN = 0;
        FERR = 0;
        CREN = 1;
        }     
      } 
    RCIE = 1;
    }
  }   
}
/////////////////////////////////////////////////////////////////////////////


void main()
{
        
	init_ports();	
        rs232init();
       	lcd_init();
	lcd_inittr();
	lcd_clear();
        i2c_init();
        i2c_start(); 
        i2c_write(0x90); 
        DelayMs(10);
        i2c_write(0x01);
        DelayMs(10);
        i2c_write(0x60);
        DelayMs(10);
        i2c_stop();
        DelayMs(11);
        i2c_start();
        DelayMs(10);
        i2c_write(0x90);
        DelayMs(10);
        i2c_write(0x00);
        DelayMs(10);
        i2c_stop();
while(1)        
{

        i2c_start();
        i2c_write(0x91);
	while (RA0 == 0)
        {
          RA1=hi;   
          GIE=1;

		            PEIE=1;
          pduconv(p,hexsonuc);
          DelayMs(250);
          rs232send('A');
          rs232send('T');
          rs232send('+');
          rs232send('C');
          rs232send('M');
          rs232send('G');
          rs232send('S');
          rs232send('=');
          rs232send('1');
          rs232send('4');
          rs232send('0');
          rs232send(0x0D);
          DelayMs(250);
          smsinit();
          for(k=0;k<30;++k)
          {
          rs232send( hexsonuc[k] );
          }
          rs232send(26);
          PEIE=0;
          GIE=0;
          DelayS(3);
          RA1=lo;
        }
        DelayS(1);
        lcd_clear();
        data1=i2c_read(1);
        DelayMs(1);
        data2=i2c_read(0);
        i2c_stop();  
        lcd_putch('S');
        lcd_putch(0x02);
        lcd_putch('c');
        lcd_putch('a');
        lcd_putch('k');
        lcd_putch('l');
        lcd_putch(0x02);
        lcd_putch('k');       
        lcd_putch(':');
        lcd_goto(64);
        data1= (data1 & 0x7F);
	data1= bin2bcd(data1);
	swap1=data1;
	swap1 = swap1 & 0x0F;
	swap1 = swap1 | 0x30;
	swap2=data1;
	swap2= swap2 >> 4; 
	swap2 = swap2 | 0x30;
        ondalik();
        lcd_putch(swap2);
	lcd_putch(swap1);
        lcd_putch('.');
        lcd_putch(On1);
        lcd_putch(On2);
        lcd_putch(On3);
        lcd_putch(On4);
        lcd_putch(0xDF);    
        lcd_putch('C');
	p[9] = swap2;
        p[10] = swap1;
        p[11] = '.';
        p[12] = On1;
        p[13] = On2;
        p[14] = On3;
        p[15] = On4;
        p[16] = 'C';  

}	
}

/////////////////////////////////////////////////////////////////////////////////////////////////
char bin2bcd(char binary_value) 
{ 

 {
 temp=p[sayac1*8+1+k]; //artik 7bitlik paketlerden bir sonraki deger olarak temp'e giriliyor.
 temp= temp << (7-k);  //orlanacak deger sola kaydirilarak hesaplaniyor.
 temp3=p[sayac1*8+k];  //simdiki deger temp3'e giriliyor
 temp3=temp3 >>(k);    //temp3 orlama için saga kaydiriliyor.
 temp3=temp | temp3;   //simdiki deger ile sonraki degerden hesaplanmis deger orlaniyor.
 s[log+1+k]=temp3;     //simdiki deger log degerlendirilerek s'e yaziliyor.
 }
for(k=0;k<15;k++) 
 {
  temp = s[k];
  temp = temp & 0x0F;
  hexsonuc[k*2+1] = hex[temp];
  temp = s[k];
  temp = temp >> 4;
  hexsonuc[k*2] = hex[temp];
 }
}       
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void nop(void)
{
  #asm
  nop
  #endasm
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void rs232init()
{
   BRGH = 1;
   SPBRG = 12;
   TX9 = 0;
   RX9 = 0;
   SYNC = 0;
   SPEN = 1;
   RCIE = 1;
   TXEN = 1;
   PEIE = 1;
   CREN = 1;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void rs232send(unsigned char sendvalue)
{
 while(TRMT == 0)
 {
 nop();
 } 
 TXREG = sendvalue;
}     
///////////////////////////////////////////////////////////////////////////////////////////////////       
void smsinit(void)
{	     
  
   for(k=0;k<44;++k)
   {
    rs232send( smsheader[k] );
   }
   k=0;

}



RS232 ile mesaj gönderimi : Modemler ve Cep telefonu gibi haberleşme cihazlarına RS232 üzerinden ‘Hayes’ komutları ile komut verilir.Hayes komutları standartlaştırılmıştır ve her zaman AT(attention) ile başlarlar,örnek olarak hücresel telefonun pil durumu öğrenilmek isteniyorsa; AT+CBC komutu gönderilmelidir,alınacak komut şu şekilde olur.

+CBC: 0,100

OK

Burada 0,100 terimi pilin %100 dolu olduğunu belirtir. diğer bir örnek ise AT+GMI komutudur bu komut ile telefonun markası öğrenilebilir. alınan cevap,

ERICSSON

OK
şeklindedir,daha yüzlerce AT komutu çeşitli işlemler için kullanılmaktadır, daha geniş bilgi *ETSI’nin sitesinden edinilebilir.

projede “at+cmgs” komutu kullanılmıştır.Bu komut ile üretilen pdu dizisi telefona iletilir. aşağıda pic ile telefon arasında geçen örnek bir iletişim verilmiştir.

pic komutu gönderiyor: at+cmgs=140 ( pic 140byte göndereceğini bildiriyor.)

alınan cevap: > ( telefon gönderilecek byte dizisini talep ediyor.)

pic pdu veri dizisini gönderiyor: 0011000781214365F70000AA05E8329BFD06
alınan cevap: OK (mesaj gönderildi)

Proje için yazılan programın tamamı

#define PIC_CLK 4000000


#include  <pic.h>
#include "always.h"

#include "delay.h"
#include "delay.c"

#include "lcd.h"
#include "lcd.c"

#include "877_i2c.h"

__CONFIG(HS & WDTDIS & PWRTEN & BOREN & LVPDIS & DUNPROT & DEBUGDIS & UNPROTECT);


void init_ports(void)
{
#if defined(_16F876A)
	ADCON0 = 0;
	ADCON1 = 0B00000110;	// Analog girisleri dijital yap E0, E1, E2	
#endif	

	TRISA = 0B11110001; //Data1-2 giris ve CLK1-2 cikis
	TRISB = 0B11000000;
	TRISC = 0xFF;
	

	PORTA = 0x00;
	PORTB = 0;
	PORTC = 0;
	

	TMR0   = 0;
	
	OPTION = 0b10000111;	// Prescaler 111 -> 1/256
        INTCON = 0b00000000;	// GIE ve Peripheral Interrupt pasif
        PIR1 = 0x00;
        PIR2 = 0x00;
        
}


/////////////////////////////////////////////////////////////////////////////
unsigned char data2,data1,swap1,swap2,k;
unsigned char On1,On2,On3,On4,Z;
unsigned char RXreg,RXreg2;
bit RX2flag;
bank1 unsigned char p[17] = {'s','i','c','a','k','l','i','k',':'};
bank1 unsigned char hexsonuc[30];
bank2 unsigned char smsheader[] = {'0','7','9','1','0','9','4','5','9','2','0','8','0','0','3','3','1','1','0','0','0','C','9','1','0','9','3','5','5','2','3','9','6','0','9','7','0','0','0','0','A','A','1','1'};
char bin2bcd(char);
void ondalik(void);
void nop(void);
void rs232send(unsigned char);
void rs232init(void);
void smsinit(void);
void pduconv(unsigned char *,unsigned char *);
/////////////////////////////////////////////////////////////////////////////
void interrupt isr (void)
{
RX2flag = 0;
GIE = 0;
if(GIE == 0)
  {
  if(RCIF == 1)
    {
    RXreg = RCREG;
    if(RCIF == 1)
      {
      RXreg2 = RCREG;
      RX2flag = 1;
      }	 
    //RSflag = 1;
    RCIE = 0;
    lcdputch(RXreg);
    if(RX2flag ==1)
      {
      lcdputch(RXreg2);
      RX2flag = 0;
      if(OERR == 1)
        {
        CREN = 0;
        FERR = 0;
        CREN = 1;
        }     
      } 
    RCIE = 1;
    }
  }   
}
/////////////////////////////////////////////////////////////////////////////


void main()
{
        
	init_ports();	
        rs232init();
       	lcd_init();
	lcd_inittr();
	lcd_clear();
        i2c_init();
        i2c_start(); 
        i2c_write(0x90); 
        DelayMs(10);
        i2c_write(0x01);
        DelayMs(10);
        i2c_write(0x60);
        DelayMs(10);
        i2c_stop();
        DelayMs(11);
        i2c_start();
        DelayMs(10);
        i2c_write(0x90);
        DelayMs(10);
        i2c_write(0x00);
        DelayMs(10);
        i2c_stop();
while(1)        
{

        i2c_start();
        i2c_write(0x91);
	while (RA0 == 0)
        {
          RA1=hi;   
          GIE=1;
          PEIE=1;
          pduconv(p,hexsonuc);
          DelayMs(250);
          rs232send('A');
          rs232send('T');
          rs232send('+');
          rs232send('C');
          rs232send('M');
          rs232send('G');
          rs232send('S');
          rs232send('=');
          rs232send('1');
          rs232send('4');
          rs232send('0');
          rs232send(0x0D);
          DelayMs(250);
          smsinit();
          for(k=0;k<30;++k)
          {
          rs232send( hexsonuc[k] );
          }
          rs232send(26);
          PEIE=0;
          GIE=0;
          DelayS(3);
          RA1=lo;
        }
        DelayS(1);
        lcd_clear();
        data1=i2c_read(1);
        DelayMs(1);
        data2=i2c_read(0);
        i2c_stop();  
        lcd_putch('S');
        lcd_putch(0x02);
        lcd_putch('c');
        lcd_putch('a');
        lcd_putch('k');
        lcd_putch('l');
        lcd_putch(0x02);
        lcd_putch('k');       
        lcd_putch(':');
        lcd_goto(64);
        data1= (data1 & 0x7F);
	data1= bin2bcd(data1);
	swap1=data1;
	swap1 = swap1 & 0x0F;
	swap1 = swap1 | 0x30;
	swap2=data1;
	swap2= swap2 >> 4; 
	swap2 = swap2 | 0x30;
        ondalik();
        lcd_putch(swap2);
	lcd_putch(swap1);
        lcd_putch('.');
        lcd_putch(On1);
        lcd_putch(On2);
        lcd_putch(On3);
        lcd_putch(On4);
        lcd_putch(0xDF);    
        lcd_putch('C');
	p[9] = swap2;
        p[10] = swap1;
        p[11] = '.';
        p[12] = On1;
        p[13] = On2;
        p[14] = On3;
        p[15] = On4;
        p[16] = 'C';  

}	
}

/////////////////////////////////////////////////////////////////////////////////////////////////
char bin2bcd(char binary_value) 
{ 
char temp; 
char retval; 

temp = binary_value; 
retval = 0; 

while(1) 
{ 
if(temp >= 10) 
{ 
temp -= 10; 
retval += 0x10; 
} 
else 
{ 
retval += temp; 
break; 
} 
} 

return(retval); 
} 
/////////////////////////////////////////////////////////////////////////////////////////////////
void ondalik(void)
{
  data2 = data2&0xF0;
  switch(data2)
  {
      case 0x00:{On1=0x30; On2=0x30; On3=0x30; On4=0x30; break;}
      case 0x10:{On1=0x30; On2=0x36; On3=0x32; On4=0x35; break;}
      case 0x20:{On1=0x31; On2=0x32; On3=0x35; On4=0x30; break;}
      case 0x30:{On1=0x31; On2=0x38; On3=0x37; On4=0x35; break;}
      case 0x40:{On1=0x32; On2=0x35; On3=0x30; On4=0x30; break;}
      case 0x50:{On1=0x33; On2=0x31; On3=0x32; On4=0x35; break;}
      case 0x60:{On1=0x33; On2=0x37; On3=0x35; On4=0x30; break;}
      case 0x70:{On1=0x34; On2=0x33; On3=0x37; On4=0x35; break;}
      case 0x80:{On1=0x35; On2=0x30; On3=0x30; On4=0x30; break;}
      case 0x90:{On1=0x35; On2=0x36; On3=0x32; On4=0x35; break;}
      case 0xA0:{On1=0x36; On2=0x32; On3=0x35; On4=0x30; break;}
      case 0xB0:{On1=0x36; On2=0x38; On3=0x37; On4=0x35; break;}
      case 0xC0:{On1=0x37; On2=0x35; On3=0x30; On4=0x30; break;}
      case 0xD0:{On1=0x38; On2=0x31; On3=0x32; On4=0x35; break;}
      case 0xE0:{On1=0x38; On2=0x37; On3=0x35; On4=0x30; break;}
      case 0xF0:{On1=0x39; On2=0x33; On3=0x37; On4=0x35; }
  }
}
/////////////////////////////////////////////////////////////////////////////////////////
void pduconv(unsigned char *p,unsigned char *hexsonuc)
{
 unsigned char temp,temp3,sayac,sayac1,s1,log;
 unsigned char k=0;
 unsigned char s[15];
 unsigned char hex[16]= {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
 sayac=17;
 sayac1= sayac/8;
 sayac=(sayac-8*sayac1);     //paketlerden geriye kalan byte sayisi giriliyor
for(k=0;k<(sayac1);k++)      //paket secim dongusu
{
  s1=k*8;                    //isleme girecek paket grubunun baslangic numarasi hesaplaniyor
  for(;s1<(8*k+7);s1++)      //secilen paket grubu icin donusum islemi yapiliyor
  {
  temp=p[s1+1];               //bir sonraki 7bit sayi temp'e giriliyor
  temp= temp << (7-(s1-8*k)); //orlanacak deger sola kaydirilarak hesaplaniyor
  temp3=p[s1];                //simdiki deger temp3'e giriliyor
  temp3=temp3 >>(s1-8*k);     //temp3 orlama icin saga kaydiriliyor
  temp3=temp | temp3;         //simdiki deger ile sonraki degerden hesaplanmis deger orlaniyor.
  s[s1-k]=temp3;              //simdiki degere orlanan deger yaziliyor.
  log=s1-k;                   //dongu cikisinda sonuc dizisi s'e yazimin nerede kaldigi log degiskenine atiliyor,buna göre artik 7bit'leri degerlendiren döngüde s'e yazimin nereden baslanacagi belirleniyor.
  }
}
if(sayac != 0)   //paketlerden geriye kalan byte sayisi 0 degilse gerekli islem yapiliyor.
{
 for(k=0;k>(k);    //temp3 orlama için saga kaydiriliyor.
 temp3=temp | temp3;   //simdiki deger ile sonraki degerden hesaplanmis deger orlaniyor.
 s[log+1+k]=temp3;     //simdiki deger log degerlendirilerek s'e yaziliyor.
 }
for(k=0;k<15;k++) 
 {
  temp = s[k];
  temp = temp & 0x0F;
  hexsonuc[k*2+1] = hex[temp];
  temp = s[k];
  temp = temp >> 4;
  hexsonuc[k*2] = hex[temp];
 }
}       
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void nop(void)
{
  #asm
  nop
  #endasm
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void rs232init()
{
   BRGH = 1;
   SPBRG = 12;
   TX9 = 0;
   RX9 = 0;
   SYNC = 0;
   SPEN = 1;
   RCIE = 1;
   TXEN = 1;
   PEIE = 1;
   CREN = 1;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void rs232send(unsigned char sendvalue)
{
 while(TRMT == 0)
 {
 nop();
 } 
 TXREG = sendvalue;
}     
///////////////////////////////////////////////////////////////////////////////////////////////////       
void smsinit(void)
{	     
  
   for(k=0;k<44;++k)
   {
    rs232send( smsheader[k] );
   }
   k=0;

}

HITECH PICC COMPILER

Bu proje mikrodenetleyicilerin programlanmasında kullanılan klasik assembly yerine C dili ile yazılmıştır,C dilinin PIC serisi mikrodenetleyicilerde kullanımı oldukça yenidir ve ülkemizde pek bilinmemektedir,bu konuda internetten yararlandım ve sistemin nasıl çalıştığını irdeledim. C dili assembly’e göre çok güçlüdür,asm ortamında 5 adımda yapılacak bir işlem C’de sadece bir komutla yapılabilmektedir,en basitinden normalde pic’in sahip olduğu SFR(Special Function Register)’lar arasında geçiş yapmak için asm ortamında bank değiştirmek gerekir,C’de compiler bu tip işleri sizin yerinize yapar ve projeler tasarlamak çok kolaylaşır,fakat en önemli avantaj C’de taşınabilirliğin olmasıdır,normal bir X86 işlemci için yazılmış bir fonksiyon eğer gerekirse PIC için kolaylıkla port edilebilir,nitekim böyle bir uygulama yazılan programda binary’den bcd’ye dönüşümde yapılmıştır.PICC ile ufak ayrıntılarla uğraşmak çoğu zaman gerekmez mutlaka gereken işlem için hazır bir rutin bulunur,eğer bulunamazsa PIC serisi datasheet’leri incelenerek yeni bir rutin kolaylıkla yazılabilir.

Şekil14:Devre Şeması

pic16f876a-sms-devre

D1,D2: 1N4001
DISPLAY: HD44780U
U2: 78L05
C1: 100nF
U1: PIC16F876A
R2,R8,R9: 10k
R1,R10: 330ohm
R3,R4: 1K
Y1: 4MHz XTAL
U3: DS75
R5: 160ohm
Q1: 2N2222
C2,C3: 33pF
R6:1K
R7:1,5K
R11:2.2K
U7,U8: 74LS07N
U5:Siemens S25 cellular phone

Yararlanılan Kaynaklar:
http://www.maxim-ic.com
http://www.microchip.com
http://www.microchipc.com
http://www.hitachi.com
http://www.htsoft.com
http://www.elektroda.pl
http://www.picproje.com
http://www.fairchild.com
http://www.semiconductor.philips.com
16F876A Datasheet,Microchip Inc.Arizona(AZ)
AT Commands manual for the mobile phone Siemens S25,Siemens Gmbh.Berlin (confidential info)
SMS with the SMS PDU-modem Developer’s Guide,Siemens Gmbh.Berlin (confidential info)
http://www.dreamfabric.co.uk
http://www.cmail.cz/doveda/gsm/pdu_sms.htm
http://www.etsi.org

Yazının Kaynak Dosyaları DS75 Isı Sensör Bilgilerinin SMS Protokolü İle İletimi

Dosya indirme LINK listesi (HTML formatında) link-4056.zip şifre-pass: 320volt.com

  • isa_olcer

    teşekkürler. devrede kullanılan entegrelerinde geniş bir açıklaması verilmiş. tam bir proje olmuş. ama bu verilerin telefona hangi yolla verildiğinden bahsedilmemiş. her halde orasında işin sırrı :D

  • yalçın aygül

    picden gönderilen verileri cep telefon nasıl gönderiyoruz.bende picden sms gönderme konusunda sıkıntı çekiyorum,burda da nasıl gönderileceği yazmıyor…yardımcı olabilirmisinz,birde başka bi marka cep telefonu kullanılamaz mı?

  • kazim_19

    kardeş programa ait kütüphane dosyalarınıda eklesen iyi olur

  • kazim_19

    verilen programı hi-tech de derleyemiyorum. çünkü kendin bazı kütüphaneler oluşturmuşsun ama bunları vermemişsin. eklersen iyi olacak. teşekkürler.

    • Yazı güncellendi tekrar kontrol ediniz

  • Bu arada gözden kaçmış yazının kaynak dosyasınıda vermişim :) kaynakta ne varsa o arkadaşlar

  • kazim_19

    gew kardeş ilgin için teşekkürler. Galiba senin elinde sadece yazılı kaynak var. Ancak alttaki bazı kütüphaneler programcı (Engin Karabulut)tarafından oluşturulmuş. Bu dosyalar olmadan program derlenmiyor.Senin elinde bu dosyalar var mı? yada proje sahibinden bunları edinebilirmisin? Mail adresimden bilgilendirebilirsin…Teşekkürler.
    #include
    #include “always.h”
    #include “delay.h”
    #include “delay.c”
    #include “lcd.h”
    #include “lcd.c”
    #include “877_i2c.h”

    • Bildiğim kadarı ile derleyicinin içinde bu dosyalar mevcut özel olduklarını sanmıyorum gerci fazla bilgimde yok ama delay, lcd,877 hep tanıdık include dosyaları bir tek always.h tanıdık değil yazıda verilen kaynak dosyayı inceleyin açıklamaları okuyun çözüm çıkar iyi çalışmalar

  • ahmet aygün

    Assembly diliylede yapılabilirmi sms gönderme kısmı? nasıl:?