AVR-GSM Sms ile Röle Kontrol

Arduino ile tanışanların çoğunluğu ev otomasyonu adı altında sms ile röle kontrolü işleri yapmaktadır. Ben benzer bir devreyi kendi arazilerimizin sulanması için yaptım. Bu blog içerisinde paylaştım. İlk çalışmalarımı Arduino fonksiyonlarıyla ve hazır kütüphanelerle yaptım. Sistemin çalışması oldukça sorunlu bir haldeydi. Geç cevap veren ve mesajları kaçıran kararsız bir projeydi.
Arduino da kullandığımız Software serial’ in sorunlara neden olabileceğini öğrendim. İncelediğim hazır kütüphanelerin gereksiz kontroller ve beklemelerle dolu olduğunu fark ettiğimde de kütüphane kullanmayı bıraktım. Tüm hazır kütüphaneleri çöpe attım, donanım iyileştirmeleri yaptım. C diliyle baştan yaptığımda hızı hissedilir şeklide arttı. Bu yazıda size hazır kütüphane olmadan Sms alıp-verme ve bir röleyi kontrol etmeyi anlatmaya çalışacağım. İlk olarak Gsm modüllerden kabaca bahsetmek istiyorum.

Gsm Modül

SimCom Sim800 ve Sim900 serileriyle Quectel M66 ve M95 en çok karşılaşacağımız ve İmei kayıtlı olarak satın alabileceğimiz modüllerdir. Bu modülleri hazır kullanabileceğimiz halde bulmak mümkün. Bazı ürünlerin harici beslemeye ihtiyaçları olmaktadır. Bu nedenle ürünlerin bilgi sayfalarını incelemek gerekiyor. Sim800l modülü bunlardan birisidir. Bilgilerini incelediğimizde 3,4-4,4V aralığında çalıştığını ve en yüksek 2A akım ihtiyacı olabildiğini görebiliriz. Bilgi sayfasında beslemenin nasıl yapılacağı ilişkin bilgiler mevcut. Bir diğer önemli konu, modülün Rx bacağını denetleyicinin Tx bacağına doğrudan bağlamamak gerekiyor. 3V üstünde bir voltaj verilmesi durumunda modül bozulabilir. Bunun için voltaj bölücü kullanmak gerekir. Birçok modülde buna gerek yoktur kart üstünde bu işlemler yapılmıştır. 

AT Komutları

Attention kısaltması AT ile başlayan komutlardır. Gsm ve Bluetooth gibi modüllerin iletişiminde kullanılır, modem iletişim komutlarıdır. İlk olarak "AT" komutu UART iletişimini kontrol için gönderilir. İletişim varsa OK cevabı gelir. Belli başlı komutları aşağıda paylaşıyorum. Buna geçmeden önce AT komutlarını gönderirken “AT<CR> “ (CR= satır başı )şeklinde göndeririz, modül cevap olarak “OK<CR><LF>” (LF= yeni satır) şeklinde dönüş yapar. “AT+CMGF=?<CR>” gönderdiğinizde cevap olarak seçenekleri gösterir. “AT+CMGF?<CR>” gönderdiğinizde cevap olarak ayarlı durumu gösterir. “AT+CMGF=1<CR>” gönderdiğinizde ayarı değiştirir ve geçerliyse “OK<CR><LF>” cevabını gönderir. Tüm komutlar için yazım kuralı böyledir.
CR: Satır başı ascii decimal (13)
LF: Yeni satır ascii decimal (10)
Ctrl+Z: Dosya sonu (EOF) ascii decimal (26)

AT: İletişim başlatma- kontrol komutu gönderilir. OK cevabı ile iletişimin durumu kontrol edilir.
AT&W: yapılan ayarları hafızaya alır.
AT+IPR: Baud rate ayarlanır. “0” otomatik ayarlanır.
ATE: Komutları tekrar eder ATE0 olursa tekrar kapatılır.
ATA: Gelen çağrıyı cevaplar.
ATH: Çağrıyı sonlandırır.
ATD: Girilen numaraya çağrı başlatır. “ATD05012345678; <CR>” şeklinde gönderilir.
AT+CMGF: Mesaj format ayarı AT+CMGF=1 yapılırsa metin mesajı alır-verir.
AT+CNMI: Mesaj alındığında modül bildirim gönderir. Bu bildirimin tipi doğrudan iletilmesi ya da hafızada tutulması, mesaj taşıyıcı tipi seçenekleri ayarlanır. AT+CNMI=2,1,0,0,0 ayarladığınızda mesaj hafızaya alınır ve bu bildirim +CMTI: "SM",1<CR><LF> şeklinde olur. CMTI taşıyıcı, Sm kullanılan hafıza ve “1” sıra numarasıdır. “AT+CNMI=2,2,0,0,0” ayarladığımızda (M66)
+CMT: "+905012345678",,"2019/06/01 12:30:00+12"<CR><LF>Gelen Mesaj<CR><LF> şeklinde bildirim gelir. (Bu sıralama ya da biçim modüller arası farklı olabilir. Ayrıca farklı ayarlar ile farklı bilgiler içeren bildirimler alınabilir.) CMT taşıyıcı, gönderen numara, tarih, saat ve mesaj içeriği doğrudan iletilir. Bu taşıyıcılar kontrol edilerek mesaj ayrıştırılıp işlem yapılır.
AT+CMGL: Hafızadaki mesaj listesini verir. AT+CMGL="REC UNREAD" okunmamış mesajları gösterir.
AT+CMGR: Sıra numarası girilen mesajı okunmasını sağlar. “AT+CMGR=1” sıra numarası 1 olan mesajı gösterir.
AT+CMGS: Mesaj gönderme komutudur. AT+CMGS=”05012345678” <CR><LF> komutu ile mesaj gönderilecek numara girilir. Sonrasında “>” işareti cevap olarak gelir. Gönderilmek istenen mesaj girilir. “TEST MESAJ (ctrl+Z)” ile işlem tamamlanır.
AT+CMGD: Hafızadaki mesajları silen komut. “AT+CMGD=1,4” 1 numaralı hafıza bölümündeki tüm mesajları siler.
Bu komutlar birçok işlemi yapmamıza yeterli olacaktır. Komut setini inceleyerek farklı ihtiyaçlar için gerekli komutları bulabilirsiniz. İletişim için gerekli komutlardan sonra artık programa geçebiliriz.

Röle Kontrol

Atmega328p de tek UART birimi olduğundan mesajları LCD ekran üstünde gösterdim. Buradan ekran kullanımıyla ilgili bilgileri paylaştım bakabilirsiniz. Ben kodları test ederken Atmega2560 kullandım, bu denetleyicide birden fazla USART birimi bulunmakta. Tek yapmanız gereken register isimlerini değiştirmek ve her UART birimi için farklı fonksiyonlar oluşturmak. Örn: uart0_basla() ve uart1_basla gibi ve UCSR0B ve UCSR1B gibi registerlere dikkat etmek gerekiyor. Bu şekilde seri ekran ile işlem yapabilirsiniz.
Sms kontrolün çalışma mantığını açıklayayım. Gsm modülü başlatıp gerekli ayarlamaları yaptıktan sonra UART iletişimini kesmeler ile yürütüyoruz. Mesaj geldiğinde kesme devreye giriyor ve ring buffer kullanarak gelen veriyi kaydediyoruz. Veri geldiğinde bir bayrak tanımlıyoruz. Bayrak aktif olduğunda gelen veriyi kontrol ediyoruz. Bu bayrak alınan veride (LF) yeni satır varsa aktif olacak şekilde ayarlıyoruz. Sms taşıyıcı olarak CMT kullandım. Eğer verinin içinde CMT varsa sms geldiğini gösteren bir bayrak daha tanımlıyoruz. Bu bayrakta aktifse mesajı çözüyor gönderen numarayı ve mesaj içeriğini ayrıştırıyoruz. Yukarıda paylaştığım örnekte CMT sonrası numara ve tarih gibi bilgilerin sonunda yeni satır (LF) geliyor ardından mesaj içeriği yer alıyor. Ayrıştırma işlemini bu bilgilere göre yapıyoruz. Tüm bu numara ve mesaj içeriğini dizi olarak alıyoruz. Çalışma mantığı bu şekilde artık fonksiyonlara geçip fonksiyonlarla birlikte açıklamaya devam edebilirim.

UART Fonksiyonları

Gsm modülü için gerekli olan ve daha önce UART kullanımı bölümünde kullanmadığım ya da değişiklik yaptığım fonksiyonları açıklamaya çalışacağım. Öncelikle UART ile ilgili fonksiyonlardan başlayacağım.
ISR (USART_RX_vect){
 uint8_t gelen;
 gelen=UDR0;
 if (gelen!='\n'){
  rx_bas=(rx_bas+1) & UART_Rx_Mask;
  rx_ring[rx_bas]=gelen;
  }else{
  uaflag=1;
 }
}
ISR (USART_UDRE_vect){
 tx_son=(tx_son+1)&UART_Tx_Mask;
 UDR0=tx_ring[tx_son];
 if (tx_son==tx_bas)
 UART_Bos_Off;
}

Modül ile iletişimi UART Rx ve Udre kesmelerini kullanarak gerçekleştiriyoruz. Rx rutininde gelen veriyi diziye alıyoruz farklı olarak " \n" (LF) yeni satır geldiğinde "uaflag" isimli bayrak değişkenini "1" yapıyoruz. Modül veri gönderirken son olarak LF gönderecektir. Böylece iletişimi sonlandırdığını anlamış oluyoruz. Kod içinde bu bayrak kontrol edilerek devamında diğer işlemleri gerçekleştireceğiz.
void uart_dizi_al(char*str){
 uint8_t gdata=0;
 uint8_t poz=0;
 do
 { gdata=uart_oku();  
   str[poz]=gdata;
   poz++;    
 } while (!(rx_bas==rx_son));
    str[poz]='\0';
 uaflag=0;
}

Yeni bir fonksiyon olan uart_dizi_al fonksiyonu ring buffer' a kayıtlı veriyi işlem yapabilmemiz için oluşturacağımız bir diziye almayı sağlıyor. Baş ve son sıra eşit olana kadar tüm bilgiyi diziye alıyoruz. Uart_oku ile veri karakter karakter okunuyor her seferinde pozisyon artırılarak kayıt işlemi tamamlanıyor.

Gsm Fonksiyonları

void gsm_reset(){
 GSM_HIGH;
 _delay_ms(1000);
 GSM_LOW; 
 _delay_ms(1000);
}
void gsm_basla(){
 uart_dizi_gonder("AT\r");
 _delay_ms(500);
 uart_dizi_al(veri);
 if (strstr(veri,"OK")=='\0'){
  do {   
   gsm_reset();   
   _delay_ms(1000);
   uart_dizi_gonder("AT\r");
   _delay_ms(300);
   uart_dizi_al(veri);   
  } while (strstr(veri,"OK")=='\0');
 }
 _delay_ms(500);
 uart_dizi_gonder("AT+CMGF=1\r");
 _delay_ms(500);
 uart_dizi_gonder("AT+CNMI=2,2,0,0,0\r");
 _delay_ms(500);
 uart_dizi_gonder("AT&W\r");
 _delay_ms(500);
 uart_dizi_gonder("AT+CMGD=1,4\r");
}

Enerji verildiğinde modül kapalı olacağından iletişim kurulamayacaktır. Ayrıca modülün otomatik baud rate ve diğer ayarlarının yapılması için gsm_basla() fonksiyonuna ihtiyaç vardır. İlk olarak "AT" komutunu gönderiyoruz ve "OK" cevabını bekliyoruz. Bilgi sayfalarında bu komutlar için en fazla 300ms bir gecikme olabileceği belirtilmiş. Ben 500ms bekleme yapıyorum. İlk başlangıç aşamasında çalışacağından bekleme konusunda takıntılı davranmadım. "OK" cevabı gelmediğinde modülü sıfırlayan (gsm_reset) ve tekrar komut gönderip "OK" cevabını yoklayan Do-While döngüsüne giriyoruz. İletişim başladığında mesajın metin formatı (CMGF) ve mesaj bildirim (CNMI) ayarlarını yapıyoruz. Kullanılan profile bu ayarları kaydedip varsa tüm mesajları siliyoruz (CMGD). Böylelikle modül ile iletişim başlamış gerekli ayarlar yapılmış oluyor.
void mesaj_kontrol(){
  uart_dizi_al(veri);  
  if (strstr(veri,"CMT:")!='\0'){
   smsflag=1;
   for (uint8_t i=0;i<11;i++){
    gonderenno[i]=veri[i+10];
   }
   gonderenno[11]='\0';
   for (uint8_t i=0;i<24;i++){
    sms[i]=veri[i+49];    
   }
  }
}

Modül ile iletişim tamamlandığında "uaflag"  "1" oluyordu, bu durumda mesaj_kontrol() fonksiyonunu çağırıyoruz. Bu çağırma işlemini yapmadan önce küçük bir bekleme yapıyorum. Modül mesaj bildirimini yaptıktan sonra mesajı denetleyiciye gönderiyor. Bu çok hızlı olsa da denetleyici daha hızlı olduğundan mesajı alamadan taşıyıcı metnini alıyor. Bunun başka yöntemleri varsa da ben bilmiyorum ve bu yöntemi kullanıyorum. Mesaj_kontrol fonksiyonu öncelikle veri isimli diziye gelen veriyi alıyor.
Strstr fonksiyonuyla  veri dizisinde CMT taşıyıcısını sorguluyoruz. Eğer dizi içinde CMT varsa bir mesaj  alınmış demektir ve "smsflag" isimli mesaj geldiğini gösteren bayrak değişkeni "1" yapılıyor. AT komutları kısmında verdiğim örnekten gördüğünüz gibi bu bildirim içinde mesaj gönderen numara da vardır. Bilgi sayfasındaki şablona göre 9. karakterden itibaren numara bilgisi yer almakta. C de dizi sonuna "\0" NULL karakteri koyuluyor. Diziye alırken ring bufferda ilk karakter bir önceki mesajın Null karakteri olduğundan biz bir artırarak 10. karakterden numarayı başlatıyoruz. "gonderenno[i]=veri[i+10];" Burada yapılan gönderen no dizisinin i=0 olduğundan "0" yani ilk karakterini Veri dizisinin 10. karakterine eşitlemektir. "i" her döngüde bir artarak devam edecek ve numara kayıt tamamlanacaktır. Sms metnini de aynı mantıkla diziye alıyoruz.
void sms_gonder (char *num,char *str){
 uart_dizi_gonder("AT+CMGS=\"");
 uart_dizi_gonder(num);
 uart_dizi_gonder("\"\r");
 _delay_ms(10);
 uart_dizi_gonder(str);
 uart_dizi_gonder("\r");
 uart_gonder(26);
 _delay_ms(10);
 uart_dizi_gonder("AT+CMGD=1,4\r");
}
void numara_ara(char *num){
 uart_dizi_gonder("ATD");
 uart_dizi_gonder(num);
 uart_dizi_gonder(";\r");
}

İstenen numaraya mesaj gönderme ya da arama için fonksiyonlar bu şekildedir. Gördüğünüz gibi belli karakterleri belli sıralarda göndermek gerekiyor. Bu modüle göre değişiklik gösterebilir bilgi sayfasını kontrol etmek gerekiyor. Modüle gönderim yaparken bir konuyu açıklık getireyim. uart_dizi_gonder("\"\r"); satırında “ kırmızı” tırnak işareti dizi olduğunu belirtmek için var. Biz tırnak işareti göndermek istediğimizde \ ters bölme işareti sonra tırnak işareti koymalıyız.

Main Fonksiyonu

int main(void)
{
 CMD_OUT;
 GSM_OUT;
 ROLE_OUT;
 _delay_ms(1000);
 lcd_basla();
 _delay_ms(500);
 uart_basla(9600);
 _delay_ms(500); 
 lcd_git(0,0);
 lcd_dizi("GSM...");
 gsm_basla();
 lcd_git(0,0);
 lcd_dizi("GSM HAZIR");
 _delay_ms(1000);  
  LCD_CL;
  _delay_ms(2);
    while (1) 
    {
  if (uaflag==1){
   _delay_ms(100);   
   mesaj_kontrol();   
  }
  if (smsflag==1){
   smsflag=0;   
   lcd_git(0,0);
   lcd_dizi(gonderenno);
   lcd_git(0,1);
   lcd_dizi(sms);
   if (strstr(sms,"ROLE ON")!='\0'){
    ROLE_HIGH;
    sms_gonder(gonderenno,"Role Acildi");
    }else if (strstr(sms,"ROLE OFF")!='\0'){
    ROLE_LOW;
    sms_gonder(gonderenno,"Role Kapandi");
   }
   _delay_ms(2000);
   LCD_CL;
   _delay_ms(2);
  }
 }
}
Main fonksiyonu port ayarlamalarıyla başlıyor ardından LCD, UART ve Gsm modülü başlatarak döngü içine giriyoruz. Yukarıda bahsettiğim bayrakları kontrol ediyoruz. Uaflag bir olduğunda gsm modülden veri geldiğini anlıyor ve mesaj kontrol fonksiyonu ile bu verinin durumunu kontrol ediyoruz. Sms mesajı gelmişse mesaj ve gönderen numarayı ekrana yazıyoruz. Eğer mesaj içeriğinde ROLE ON/ROLE OFF varsa duruma göre röleyi açıyor-kapatıyoruz. Mesaj gönderen kişiye röle durumunu mesaj olarak gönderiyoruz.
Umarım faydalı olmuştur…
/*
 * sms_role_kontrol.c
 *
 * Created: 25.05.2019 18:38:14
 * Author : haluk
 */ 

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>

//port
#define CMD_PORT PORTB
#define DATA_PORT PORTD
#define ROLE_PORT PORTD
#define GSM_PORT PORTD
//pin
#define EN_ PB1
#define RS_ PB0
#define DATA_7 PD7
#define DATA_6 PD6
#define DATA_5 PD5
#define DATA_4 PD4
#define ROLE PD3
#define GSMRES PD2
//
#define CMD_OUT DDRB|=(1<<RS_)|(1<<EN_)
#define DATA_OUT DDRD|=(1<<DATA_7)|(1<<DATA_6)|(1<<DATA_5)|(1<<DATA_4)
#define GSM_OUT DDRD|=(1<<GSMRES)
#define ROLE_OUT DDRD|=(1<<ROLE)
// komutlar 
#define EN_HIGH CMD_PORT|=(1<<EN_)
#define EN_LOW CMD_PORT&=~(1<<EN_)
#define RS_HIGH CMD_PORT|=(1<<RS_)
#define RS_LOW CMD_PORT&=~(1<<RS_)
#define GSM_HIGH GSM_PORT|=(1<<GSMRES)
#define GSM_LOW GSM_PORT&=~(1<<GSMRES)
#define ROLE_HIGH ROLE_PORT|=(1<<ROLE)
#define ROLE_LOW ROLE_PORT&=~(1<<ROLE)
// lcd
#define LCD_CL lcd_kmt(0x01)
#define LCD_HOME lcd_kmt(0x02)
#define LCD_NSCR_RL lcd_kmt(0x04)
#define LCD_SCR_RL lcd_kmt(0x05)
#define LCD_NSCR_LR lcd_kmt(0x06)
#define LCD_SCR_LR lcd_kmt(0x07)
#define LCD_DOFF lcd_kmt(0x08)
#define LCD_DON lcd_kmt(0x0C)
#define LCD_DBON lcd_kmt(0x0D)
#define LCD_DCON lcd_kmt(0x0E)
#define LCD_DCBON lcd_kmt(0x0F)
#define LCD_CR_L lcd_kmt(0x10)
#define LCD_CR_R lcd_kmt(0x14)
#define LCD_SC_L lcd_kmt(0x18)
#define LCD_SC_R lcd_kmt(0x1C)
#define LCD_4L1 lcd_kmt(0x20)
#define LCD_4L2 lcd_kmt(0x28)
//uart
#define UART_Rx_Boyut 128
#define UART_Tx_Boyut 128
#define UART_Rx_Mask (UART_Rx_Boyut-1)
#define UART_Tx_Mask (UART_Tx_Boyut-1)
#define UART_Bos_On UCSR0B|=(1<<UDRIE0)
#define UART_Bos_Off UCSR0B&=~(1<<UDRIE0)
// değişkenler
char veri[160], sms[30], gonderenno[12];
uint8_t smsflag=0;
volatile uint8_t uaflag=0;
static volatile uint8_t rx_bas=0,rx_son=0,tx_bas=0,tx_son=0;
static volatile unsigned char rx_ring[UART_Rx_Boyut];
static volatile unsigned char tx_ring[UART_Tx_Boyut];
//fonksiyonlar
void lcd_basla();
void lcd_data(uint8_t  gelen);
void lcd_kmt(uint8_t  cmd);
void lcd_git(uint8_t  x, uint8_t y);
void lcd_yaz(uint8_t  data);
void lcd_dizi (char *str);
void uart_basla(uint32_t baud);
uint8_t uart_oku();
void uart_gonder(uint8_t uData);
void uart_dizi_gonder(char*str);
void uart_dizi_al(char*str);
void gsm_basla();
void gsm_reset();
void mesaj_kontrol();
void sms_gonder (char *num,char *str);

ISR (USART_RX_vect){
 uint8_t gelen;
 gelen=UDR0;
 if (gelen!='\n'){
  rx_bas=(rx_bas+1) & UART_Rx_Mask;
  rx_ring[rx_bas]=gelen;
  }else{
  uaflag=1;
 }
}
ISR (USART_UDRE_vect){
 tx_son=(tx_son+1)&UART_Tx_Mask;
 UDR0=tx_ring[tx_son];
 if (tx_son==tx_bas)
 UART_Bos_Off;
}
int main(void)
{
 CMD_OUT;
 GSM_OUT;
 ROLE_OUT;
 _delay_ms(1000);
 lcd_basla();
 _delay_ms(500);
 uart_basla(9600);
 _delay_ms(500); 
 lcd_git(0,0);
 lcd_dizi("GSM...");
 gsm_basla();
 lcd_git(0,0);
 lcd_dizi("GSM HAZIR");
 _delay_ms(1000);  
  LCD_CL;
  _delay_ms(2);
    while (1) 
    {
  if (uaflag==1){
   _delay_ms(100);   
   mesaj_kontrol();   
  }
  if (smsflag==1){
   smsflag=0;   
   lcd_git(0,0);
   lcd_dizi(gonderenno);
   lcd_git(0,1);
   lcd_dizi(sms);
   if (strstr(sms,"ROLE ON")!='\0'){
    ROLE_HIGH;
    sms_gonder(gonderenno,"Role Acildi");
    }else if (strstr(sms,"ROLE OFF")!='\0'){
    ROLE_LOW;
    sms_gonder(gonderenno,"Role Kapandi");
   }
   _delay_ms(2000);
   LCD_CL;
   _delay_ms(2);
  }
 }
}
void lcd_basla(){
 CMD_OUT;
 DATA_OUT;
 _delay_ms(150);
 lcd_data(0x30);
 _delay_us(4100);
 lcd_data(0x30);
 _delay_us(100);
 lcd_data(0x30);
 _delay_us(100);
 lcd_data(0x20);
 _delay_us(100);
 LCD_4L2;
 _delay_us(50);
 LCD_DON;
 _delay_us(50);
 LCD_NSCR_LR;
 _delay_us(50);
 LCD_HOME;
 _delay_ms(2);
 LCD_CL;
 _delay_ms(2);
}
void lcd_data(uint8_t  gelen){
 DATA_PORT=(DATA_PORT&0x0f)|(gelen & 0xF0);
 EN_HIGH;
 _delay_us(1);
 EN_LOW;
 _delay_us(100);
}
void lcd_kmt(uint8_t  cmd){
 RS_LOW;
 lcd_data(cmd);
 lcd_data(cmd<<4);
}
void lcd_yaz(uint8_t  data){
 RS_HIGH;
 lcd_data(data);
 lcd_data(data<<4);
}
void lcd_git(uint8_t  x, uint8_t y){
 if (y==0)
 lcd_kmt(0x80+x);
 if (y==1)
 lcd_kmt(0xC0+x);
 if (y==2)
 lcd_kmt(0x94+x);
 if (y>=3)
 lcd_kmt(0xD4+x);
}
void lcd_dizi (char *str)
{
 uint8_t i=0;
 while(str[i]){
  lcd_yaz (str[i]);
  i++;
 }
}
void uart_basla(uint32_t baud){
 uint16_t baudRate=F_CPU/baud/16-1;
 UBRR0H=(baudRate>>8);
 UBRR0L=baudRate;
 UCSR0B|=(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
 UCSR0C|=(1<<UCSZ01)|(1<<UCSZ00);
 sei();
}
uint8_t uart_oku(){
 rx_son=(rx_son+1) & UART_Rx_Mask;  
 return rx_ring[rx_son];
}
void uart_gonder(uint8_t uData){
 tx_bas=(tx_bas+1)&UART_Tx_Mask;
 tx_ring[tx_bas]=uData;
 UART_Bos_On;
}
void uart_dizi_al(char*str){
 uint8_t gdata=0;
 uint8_t poz=0;
 do
 { gdata=uart_oku();  
   str[poz]=gdata;
   poz++;    
 } while (!(rx_bas==rx_son));
    str[poz]='\0';
 uaflag=0;
}
void uart_dizi_gonder(char*str){
 uint8_t i=0;
 while(str[i]){
  uart_gonder (str[i]);
  i++;
 }
}
void gsm_reset(){
 GSM_HIGH;
 _delay_ms(1000);
 GSM_LOW; 
 _delay_ms(1000);
}
void gsm_basla(){
 uart_dizi_gonder("AT\r");
 _delay_ms(500);
 uart_dizi_al(veri);
 if (strstr(veri,"OK")=='\0'){
  do {   
   gsm_reset();   
   _delay_ms(1000);
   uart_dizi_gonder("AT\r");
   _delay_ms(300);
   uart_dizi_al(veri);   
  } while (strstr(veri,"OK")=='\0');
 }
 _delay_ms(500);
 uart_dizi_gonder("AT+CMGF=1\r");
 _delay_ms(500);
 uart_dizi_gonder("AT+CNMI=2,2,0,0,0\r");
 _delay_ms(500);
 uart_dizi_gonder("AT&W\r");
 _delay_ms(500);
 uart_dizi_gonder("AT+CMGD=1,4\r");
}
void mesaj_kontrol(){
  uart_dizi_al(veri);  
  if (strstr(veri,"CMT:")!='\0'){
   smsflag=1;
   for (uint8_t i=0;i<11;i++){
    gonderenno[i]=veri[i+10];
   }
   gonderenno[11]='\0';
   for (uint8_t i=0;i<24;i++){
    sms[i]=veri[i+49];    
   }
  }
}
void sms_gonder (char *num,char *str){
 uart_dizi_gonder("AT+CMGS=\"");
 uart_dizi_gonder(num);
 uart_dizi_gonder("\"\r");
 _delay_ms(10);
 uart_dizi_gonder(str);
 uart_dizi_gonder("\r");
 uart_gonder(26);
 _delay_ms(10);
 uart_dizi_gonder("AT+CMGD=1,4\r");
}