توضیحات برنامه:
آپدیت: 96/08/17
ابتدا تنظیمات کد ویزارد رو به صورت زیر انجام میدیم:

سپس در برنامه اصلی هدر string رو اضافه میکنیم به همراه متغیر های مورد نیاز که جلوتر توضیح داده خواهند شد:
کد:
#include <mega32a.h>
#include <delay.h>
#include <string.h>
char c=0;
char i=0;
char * pch;
char a;
char ctrlz=0x1A;
char at[]={"AT\r"};
char ATE0[]={"ATE0\r"};
char text_mode[]={"AT+CMGF=1\r"};
char cpbs[]={"AT+CPBS=\"ME\"\r"};
char csmp[]={"AT+CSMP=17,167,0,0\r"};
char cpms[]={"AT+CPMS=\"ME\",\"ME\",\"ME\"\r"};
char cnmi[]={"AT+CNMI=2,1,0,0,0\r"};
char gsm[]={"AT+CSCS=\"GSM\"\r"};
char save_on_sim[]={"AT+CSAS=0\r"};
char ATW[]={"AT&W\r"};
char send_sms[]={"AT+CMGS=\"+98911213----\"\r"};
char sms_ok[]={"sim800 was turned on"};
char cmgda[]= {"AT+CMGDA=\"DEL ALL\"\r"};
char cmgr[]={"AT+CMGR="};
به کد های تولید شده کدویزارد دست نمیزنیم،به جز خط زیر که مربوط به یوزارته:
کد:
UCSRB=(1<<RXCIE) | (1<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
در این کد RXEN رو صفر میکنیم
سپس قبل حلقه while یه تاخیر 10 ثانیه ای قرار میدیم برای اینکه sim800 شبکه رو پیدا کنه(میتونید این زمان رو کمترش کنید) و سپس دوباره RXEN رو فعال میکنیم:
کد:
//wait for initiallizing sim900
delay_ms(10000);
UCSRB=(1<<RXCIE) | (1<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
در کد زیر AT میفرستیم تا اینکه OK دریافت کنیم
توجه کنید sim800 به صورت auto baudrate می باشد یعنی اگر AT براش بفرستیم خودش تشخیص میده که با چه باد ریتی براش دیتا فرستادیم و با همون بادریت برامون دیتا میفرسته که اینجا بادریت رو 9600 تنظیم کردیم
کد:
//checking serial connection
check:
for ( i=0 ; i<=2 ; i++)
{
putchar(at[i]);
}
delay_ms(3000);
pch=strstr(rx_buffer,"OK");
if(pch==NULL) goto check;
PORTB.1=0;
delay_ms(1000);
نکته مهم در این کد استفاده از تابع strstr می باشد.به کمک این تابع شما میتونید در بافر دریافت دیتا دنبال رشته مورد نظرتون بگردید که اگر پیدا شد مقدار اشاره گر pch عددی غیر صفر(غیر null) خواهد شد.
جلوتر در مورد این تابع توضیح بیشتری میدم.برای اطلاعات تکمیلی میتونید لینک های زیر رو هم ببینید
مهمان عزیز شما حق دیدن لینک ها را ندارید
عضویت
مهمان عزیز شما حق دیدن لینک ها را ندارید
عضویت
بعد از اینکه OK دریافت شد portb.1 صفر خواهد شد.
در خط زیر echo را خاموش میکنیم تا دیتاهایی که خودمون میفرستیم رو دیگه دریافت نکنیم:
کد:
//echo off
for ( i=0 ; i<=4 ; i++)
{
putchar(ATE0[i]);
}
delay_ms(2000);
با استفاده از خط زیر بافر دریافت را پاک میکنیم
کد:
// delete receive buffer
for(i=0;i<=128;i++) {
rx_buffer[i]=0;
}
با استفاده از کد زیر حالت پیامک را روی text mode قرارمیدهیم(دو حالت داریم pud و textmode که باید پیامک رو روی text mode تنظیم کنیم) و منتظر میمونیم تا OK دریافت کنیم:
کد:
// text mode sms
for ( i=0 ; i<=9 ; i++)
{
putchar(text_mode[i]);
}
//checking ok
while(pch==NULL) {
pch=strstr(rx_buffer,"OK");
}
درکد زیر مشکل ارسال پیامک از ایرانسل به همراه اول برطرف شده:
کد:
//17,167,0,0
for ( i=0 ; i<=18 ; i++)
{
putchar(csmp[i]);
}
delay_ms(500);
در کد زیر هم محل ذخیره پیام ها،خود ماژول انتخاب شده.
توجه نمایید که چون 15 حافظه اول برای سیم کارت می باشد،در این حالت اولین پیامک با شماره 16 نمایش داده خواهد شد.
کد:
//"ME","ME","ME"
for ( i=0 ; i<=22 ; i++)
{
putchar(cpms[i]);
}
delay_ms(500);
در کد زیر هم فرمت نمایش را انتخاب میکنیم که برای این برنامه حتماً باید به صورت زیر نمایش داده بشه:
کد:
//2,1,0,0,0
for ( i=0 ; i<=17 ; i++)
{
putchar(cnmi[i]);
}
delay_ms(500);
با استفاده از کد زیر هم ماژول رو در حالت gsm قرار میدهیم:
کد:
//gsm
for ( i=0 ; i<=13 ; i++)
{
putchar(gsm[i]);
}
delay_ms(500);
و در آخر هم با استفاده ازکد های زیر تنظیمات رو ذخیره میکنیم:
کد:
//save_on_sim
for ( i=0 ; i<=9 ; i++)
{
putchar(save_on_sim[i]);
}
delay_ms(1000);
//save all setting
for ( i=0 ; i<=4 ; i++)
{
putchar(ATW[i]);
}
delay_ms(1500);
با استفاده از کد زیر پیامک sim800 was turned on رو به شماره ای که از قبل تعیین کردیم میفرستیم:
کد:
//send turning on sms
for ( i=0 ; i<=23 ; i++)
{
putchar(send_sms[i]);
}
delay_ms(1000);
for ( i=0 ; i<=20 ; i++)
{
putchar(sms_ok[i]);
}
putchar('\r');
putchar(ctrlz);
delay_ms(1000);
با استفاده از کد زیر پیامک های ذخیره شده در ماژول را پاک میکنیم:
کد:
//delete all messege
for ( i=0 ; i<=18 ; i++)
{
putchar(cmgda[i]);
}
i=0;
در کد زیر میاد میبینه که اگر تعداد پیام به بیشتر از 40 رسید کل پیام های ماژول رو پاک میکنه:
توجه کنید c موقعی یک میشه که شماره پیام دو رقمی باشه.
کد:
if(c == 1) {
if(a>=52){ //if a>='4'
c=0;
//delete all messege
for ( i=0 ; i<=18 ; i++)
{
putchar(cmgda[i]);
}
i=0;
delay_ms(10000);
}
}
فرمت رشته دریافتی در صورتی که پیام جدید بیاد به صورت زیره:
که با استفاده از کد زیر منتظر دریافت پیام جدید میمونیم:
کد:
//waiting for +CMTI: from sim800
while(pch==NULL) {
pch=strstr(rx_buffer,"+CMTI:");
}
delay_ms(1000);
در صورتی که میخواهید کارهای دیگه هم در حلقه while انجام بدید در کد بالا به جای while میتونید از if استفاده کنید و در صورتی که شرط if برقرار بود یه فلگ رو یک کنید و کد های دیگه مربوط به پیامک رو در صورت یک بودن فلگ اجرا کنید و در آخر دوباره فلگ رو صفر کنید.
سیزدهمین کاراکتر شماره خونه ایه که پیام در اون ذخیره شده(در صورت دو رقمی بودن سیزدهمین و چهاردهمین) که یعنی pch[12] (و در صورت دو رقمی بودن [13]pch هم اضافه می شود)برابر شماره خونه پیامک دریافتی میشه
بنابر این میایم با کد زیر پیام اون خونه رو میخونیم(درواقع همون پیام جدید)
//show messege request
کد:
for ( i=0 ; i<=7 ; i++)
{
putchar(cmgr[i]);
}
putchar(pch[12]);
if(pch[13]>47 && pch[13]<58){
putchar(pch[13]);
c=1;
}
putchar('\r');
a=pch[12];
با استفاده از کد زیر هم میاد بررسی میکنه که اگر on# اومد رله رو وصل و اگر off# اومد رله رو قطع میکنه
کد:
//checking on
pch=strstr(rx_buffer,"#on");
if(pch != NULL){
PORTB.0=1;
pch=NULL;
rx_wr_index=0;
}
//checking off
pch=strstr(rx_buffer,"#off");
if(pch != NULL) {
PORTB.0=0;
pch=NULL;
rx_wr_index=0;
}
الّلهُمَّ صَلِّ عَلی مُحَمَّد وَآلِ مُحَمَّد وَعَجِّل فَرَجَهُم