Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить

Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 12:32:43

Всем привет. :)
Решил сделать некую сигнализацию, которая будет отправлять смс по получению сигнала. И все, больше никаких функций.
Дождался модуль из Китая, собрал плату, на макетке и даже нагулялся в терминале ком порта компьютера.
СпойлерИзображение

И, не поверите... Даже смс отправляю по получению сигнала.
Но это все ерунда, по сравнению с опухшей головой от не понимания работы USART.
Вернее, что то удалось понять, но проблема осталась. :?

А суть собственно в том, что я не могу получить ответа от модуля. Даже не представляю как это сделать.
Я перепробовал кучу вариантов, находящихся в инете, но там в основном под ардуину....
Ай, ладно, разнылся.

Вот так я принимаю данные. (Александр Писанец)
Спойлер
Код:
ISR(USART_RXC_vect)
{
   register unsigned char Temp = UDR;  // забираем принятый байт данных
   if (( Temp != 0x0d) & (Temp != 0x0a))  // пропускаем символы \r\n
   {
      bufGsm1[numberRX++] = Temp;         // сохраняем принятые данные
   }
   if ( numberRX > addressTemp)          // не проверяем первые два символа 0x0d,0x0a
   {
      if ( Temp == 0x0a)                // принят 0x0A, зафиксирован конец пакета данных
      {
         bufGsm1[numberRX++] = '$';     // разделительный символ
         addressTemp = numberRX;
         the_data_has++;                // принятое количество команд
      }
   }
}


И все, дальше мне надо узнать что я тут принял,
К примеру, я должен получить ответ на какую то команду - ОК
Как мне понять что ОК пришел???
Помогите пожалуйста. А то ведь так и лопнет башка, :facepalm: не поняв элементарного.
Спасибо...

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. ПОМОГИТЕ

Вт фев 06, 2018 13:00:11

the_data_has у вас, судя по всему, хранит количество принятых команд. если эта переменная не равна 0, вам надо анализировать буфер bufGsm1, где будут все принятые строки, разделенные долларом.

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. ПОМОГИТЕ

Вт фев 06, 2018 14:22:25

В главной функции опрашиваю.
Но
Код:
detect_
не присваивается 1. что не так??

Код:
void usart_detect_OK()
 {
    if (the_data_has != 0)
    {
       if(bufGsm1[0] == 'O')
       {
          if (bufGsm1[1] == 'K')
          {
             detect_ = 1;
          }
       }
    }
 }


Добавлено after 5 minutes 3 seconds:
Ком порт компа показывает и вопрос и ответ.

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. ПОМОГИТЕ

Вт фев 06, 2018 14:26:07

не так прежде всего то, что вы показываете кусочки кода, а проблема наверняка где-то еще.
например, не ясно, даёте ли вы достаточно времени на приход ответа или нет, как именно вы опрашиваете - в цикле или нет и т.п.

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. ПОМОГИТЕ

Вт фев 06, 2018 14:36:24

Даю по секунде. Я наверное не правильно сравниваю. Но тогда как сравнить буфер ??

Спойлер
Код:
#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

unsigned char button = 0,sm1 = 0;
#define But            (PINA&(1 << 6))
#define LED_red_on      PORTC |= (1 << 5);
#define LED_red_off      PORTC &=~  (1 << 5);
#define LED_green_on   PORTC |= (1 << 4);
#define LED_green_off   PORTC &=~  (1 << 4);
#define LED_yellov_on   PORTC |= (1 << 3);
#define LED_yellov_off   PORTC &=~  (1 << 3);



#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
//////////////////////////////////////////////////////////////////////////

char bufGsm1[60] = {};  // буфер для приема
volatile unsigned char Temp_gsm,numberRX = 0,the_data_has,addressBufGsm1,addressTemp = 0, num = 0;
volatile unsigned char detect_ = 0;

   // прием данных
//*****************************//
ISR(USART_RXC_vect)
{
   register unsigned char Temp = UDR;  // забираем принятый байт данных
   if (( Temp != 0x0d) & (Temp != 0x0a))  // пропускаем символы \r\n
   {
      bufGsm1[numberRX++] = Temp;         // сохраняем принятые данные
   }
   if ( numberRX > addressTemp)          // не проверяем первые два символа 0x0d,0x0a
   {
      if ( Temp == 0x0a)                // принят 0x0A, зафиксирован конец пакета данных
      {
         bufGsm1[numberRX++] = '$';     // разделительный символ
         addressTemp = numberRX;
         the_data_has++;                // принятое количество команд
      }
   }
}
//************************//
 void usart_detect_OK()
 {
    if (the_data_has != 0)
    {
       if(bufGsm1[0] == 'O')
       {
          if (bufGsm1[1] == 'K')
          {
             detect_ = 1;
          }
       }
       else
       {
          bufGsm1[0] = 0;
          bufGsm1[1] = 0;
       }
    }
 }
   
   




/////////////////////////////////////////////////////////////////
void USART_Init()
{
   UCSRB |= (1 << RXEN) | (1 << TXEN);
   // Включение передачи и приема
   UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);
   // Использовать 8-битный символ
   UBRRL = BAUD_PRESCALE;
   UBRRH = (BAUD_PRESCALE >> 8);
}


void USART_Char(unsigned char d)
{
   while ((UCSRA & (1 << UDRE)) == 0);{}// ожидание UDR
   UDR = d; // отправка данных
}   
   
void USART_String(const char *msg)
{
   while(*msg!='\0')
      {
      USART_Char(*msg);
      msg++;
      }
   USART_Char(0x0D);
}



void Wait(int j) // функция задержки
{
   uint8_t i;
   for(i=0;i<j;i++)
   _delay_ms(250);
}
   

   
void presets()// Головні налаштування процесора
{
   DDRB   |=   (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   PORTB   &=~ (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   
   DDRA   |=   (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 7);
   PORTA   &=~ (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 7);
   
   DDRA   &=~ (1 << 6);
   PORTA   |=   (1 << 6);
   
   DDRC   |=   (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   PORTC   &=~ (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   
   TCCR1B|=(1<<CS12)|(1<<CS10);//Предделитель = 1024
   TIMSK|=(1<<TOIE1);//Разрешить прерывание по переполнению таймера 1
   //TIMSK &=~ (1 << TOIE1);//запретить прерывание по переполнению таймера 1
   TCNT1=61630;//Начальное значение таймера
   UCSRC |= (1 << URSEL)|(1 << UCSZ1)|(1 << UCSZ0);
   PORTD |=(1<<1);
   DDRD |=(1<<1);
   PORTD &=~(1<<0);
   sei();                        // enable interrupts
   
   
}

ISR(TIMER1_OVF_vect)// сигнал
{
   num++;
   TCNT1=61630;//Начальное значение таймера
}



void SMS_ON()
{   
   USART_String("AT+CMGS=\"+НОМЕР\"\r");
   USART_Char(0x0D);
   Wait(12);
   USART_String("Sensor ON");
   USART_Char(0x0D);
   USART_Char(0x1A);
   Wait(2);
   
   
}

void SMS_OFF()
{
   USART_String("AT+CMGS=\"+НОМЕР\"\r");
   USART_Char(0x0D);
   Wait(12);
   USART_String("Sensor OFF");
   USART_Char(0x0D);
   USART_Char(0x1A);
   Wait(2);
   
}


   
   
int main(void)
{
   
   USART_Init();            //Инициализация UART
   
   sei();                  //Глобально разрешаем прерывания
   presets();
      
   _delay_ms(1000);
   LED_red_on;
   
   while(1)
   {
      USART_String("AT\r");
      USART_Char(0x0D);
      _delay_ms(1000);
      usart_detect_OK();
      _delay_ms(1000);
      if (detect_ == 1)
      {
         LED_red_off; // Диот должен погаснуть!!!
      }
      switch(button)
      {
         case 0:
         {
            if (But == 0)
            {
               _delay_ms(3000);
               if (But == 0)
               {
                  LED_yellov_on;
                  SMS_ON();
                  button = 1;
               }
               else
               {
                  button = 0;
               }
               
               
               
            }
         };break;
         
         case 1:
         {
            _delay_ms(3000);
            if ( But == 0)
            {
               button = 1;
            }
            else
            {
               button = 2;
            }
         };break;
         
         case 2:
         {
            _delay_ms(3000);
            if (But != 0)
            {
               LED_yellov_off;
               SMS_OFF();
               _delay_ms(5000);
               button = 0;
            }
         } ;break;
      }
   }
}

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. ПОМОГИТЕ

Вт фев 06, 2018 14:43:29

Но
Код:
detect_
не присваивается 1. что не так??

Что отвечает модуль? "\r\nOK\r\n"? Тогда посмотрите свой код внимательно, "OK" будет не в начале буфера.
Ну и кода установки индексов в начальное состояние Вы не приводите.

PS
Контроль переполнения буфера отсутствует (надеюсь, там ничего не переполняется).
Код:
 if (( Temp != 0x0d) & (Temp != 0x0a))

& и && разные операции, несмотря что, скорей всего в этом конкретном случае у Вас работает, я бы настоятельно рекомендовал не путать & и &&

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. ПОМОГИТЕ

Вт фев 06, 2018 14:52:08

Конкретно приходит 0D 0A 4F 4B 0D 0a

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. ПОМОГИТЕ

Вт фев 06, 2018 15:07:11

Конкретно приходит 0D 0A 4F 4B 0D 0a


Первый ответ "OK" вроде должен в начале буффера быть. А второй, третий (и так далее до переполнения буфера)....

Код:
      USART_String("AT\r");
      USART_Char(0x0D);

'\r' - это и есть 0x0D, а '\n' (0x0A) не надо посылать?

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 15:27:43

Достаточно
Код:
USART_String("AT\r");


Добавлено after 6 minutes 28 seconds:
:shock: Прерывание не работает!
Поместил LED_yellov_on; в тело прерывания и он не зажегся :o

Код:
ISR(USART_RXC_vect)
{
   LED_yellov_on;
   register unsigned char Temp = UDR;  // забираем принятый байт данных
   if (( Temp != 0x0d) && (Temp != 0x0a))  // пропускаем символы \r\n
   {
      bufGsm1[numberRX++] = Temp;         // сохраняем принятые данные
   }
   if ( numberRX > addressTemp)          // не проверяем первые два символа 0x0d,0x0a
   {
      if ( Temp == 0x0a)                // принят 0x0A, зафиксирован конец пакета данных
      {
         bufGsm1[numberRX++] = 0x24;     // разделительный символ
         addressTemp = numberRX;
         the_data_has++;                // принятое количество команд
      }
   }
   
}

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 16:42:35

:shock: Прерывание не работает!

А прерывание от приемника USART разрешены? ткни в код, где разрешаются прерывания.

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 16:55:21

Попробовал разрешить.
Код:
UCSRB |= (1<<RXEN);  // разрешаем работу приема по USART  !!!

Не помогло.
Или не так разрешаю???

Код:
#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

unsigned char button = 0,sm1 = 0;
#define But            (PINA&(1 << 6))
#define LED_red_on      PORTC |= (1 << 5);
#define LED_red_off      PORTC &=~  (1 << 5);
#define LED_green_on   PORTC |= (1 << 4);
#define LED_green_off   PORTC &=~  (1 << 4);
#define LED_yellov_on   PORTC |= (1 << 3);
#define LED_yellov_off   PORTC &=~  (1 << 3);



#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
//////////////////////////////////////////////////////////////////////////

char bufGsm1[60] = {};  // буфер для приема
volatile unsigned char Temp_gsm,numberRX = 0,the_data_has,addressBufGsm1,addressTemp = 0, num = 0;
volatile unsigned char detect_ = 0;

// прием данных
ISR(USART_RXC_vect)
{
   LED_yellov_on;
   register unsigned char Temp = UDR;  // забираем принятый байт данных
   if (( Temp != 0x0d) && (Temp != 0x0a))  // пропускаем символы \r\n
   {
      bufGsm1[numberRX++] = Temp;         // сохраняем принятые данные
   }
   if ( numberRX > addressTemp)          // не проверяем первые два символа 0x0d,0x0a
   {
      if ( Temp == 0x0a)                // принят 0x0A, зафиксирован конец пакета данных
      {
         bufGsm1[numberRX++] = '$';     // разделительный символ
         addressTemp = numberRX;
         the_data_has++;                // принятое количество команд
      }
   }
}

void usart_detect_OK()
{
   
   
   if (the_data_has != 0)
   {
      if(bufGsm1[0] == 'O')
      {
         if (bufGsm1[1] == 'K')
         {
            detect_ = 1;
         }
      }
      else
      {
         bufGsm1[0] = 0;
         bufGsm1[1] = 0;
      }
   }
}


void USART_Init()
{
   UCSRB |= (1 << RXEN) | (1 << TXEN);
   // Включение передачи и приема
   UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);
   // Использовать 8-битный символ
   UBRRL = BAUD_PRESCALE;
   UBRRH = (BAUD_PRESCALE >> 8);
}


void USART_Char(unsigned char d)
{
   while ((UCSRA & (1 << UDRE)) == 0);{}// ожидание UDR
   UDR = d; // отправка данных
}

void USART_String(const char *msg)
{
   
   while(*msg!='\0')
   {
      USART_Char(*msg);
      msg++;
   }
   USART_Char(0x0D);
   
}



void presets()// Головні налаштування процесора
{
   DDRB   |=   (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   PORTB   &=~ (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   
   DDRA   |=   (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 7);
   PORTA   &=~ (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 7);
   
   DDRA   &=~ (1 << 6);
   PORTA   |=   (1 << 6);
   
   DDRC   |=   (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   PORTC   &=~ (1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7);
   
   
   PORTD |=(1<<1);
   DDRD |=(1<<1);
   PORTD &=~(1<<0);
   sei();                        // enable interrupts
}


int main(void)
{
   USART_Init();
   presets();
   _delay_ms(1000);
   LED_red_on;
   UCSRB |= (1<<RXEN);  // разрешаем работу приема по USART  !!!
   while(1)
   {
      USART_String("AT\r");
      _delay_ms(1000);
      usart_detect_OK();
      _delay_ms(1000);
      if (detect_ == 1)
      {
         LED_red_off; // Диот должен погаснуть!!!
      }
      
   }
}

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 17:08:21

Или не так разрешаю???


Вы битики наобум ставите? RXCIE такого битика нет? Разрешение работы приемника и разрешение прерываний по приему символу - это разные биты. В даташит лень лезть.

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 17:11:58

Я его не ставлю..

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 17:16:44

Я его не ставлю..

Чтобы прерывания возникали - надо ставить. :)) Иначе вечно можно ждать.

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 18:53:04

Прерывания, с вашей помощью запустил. А как же мне вытащить ОК из массива???
попробовал так

13 и 10 нашел, а вот О и К нет...
Спойлер
Код:
ISR(USART_RXC_vect)
{
   bufGsm1[numberRX] = UDR;
   numberRX++;
   
}

void usart_detect_OK()
{
   if (bufGsm1[0] == 13)
   {
      if (bufGsm1[1] == 10)
      {
         if (bufGsm1[2] == 0x4f)
         {
            LED_red_off;
            if (bufGsm1[3] == 75)
            {
               if (bufGsm1[4] == 13)
               {
                  if (bufGsm1[5] == 10)
                  {
                     detect_ = 1;
                  }
               }
            }
         }
      }
   }
   
   
//    for (int i = 0; i < 40; i++)
//    {
//       if (bufGsm1[i] == &#39;O&#39;)
//       {
//          detect_ = 1;
//          numberRX = 0;
//       }
//    }
}


Добавлено after 54 minutes 28 seconds:
Ничего не работпает. Как же узнать где в буфере, слово ОК ?????

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 19:15:53

воспользуйтесь стандартной функцией strstr или напишите свою

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 19:29:57

Я нохожу в буфере и 0х0А, и 0х0В.
А вот 0х4F и 0x4B не могу найти.
Будто они туда не пишутся (((

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 19:58:29

Код:
// прием данных
ISR(USART_RXC_vect)
{
   LED_yellov_on;
   register unsigned char Temp = UDR;  // забираем принятый байт данных
   if (( Temp != 0x0d) && (Temp != 0x0a))  // пропускаем символы \r\n
   {
      bufGsm1[numberRX++] = Temp;         // сохраняем принятые данные
   }
   if ( numberRX > addressTemp)          // не проверяем первые два символа 0x0d,0x0a
   {
      if ( Temp == 0x0a)                // принят 0x0A, зафиксирован конец пакета данных
      {
         bufGsm1[numberRX++] = '$';     // разделительный символ
         addressTemp = numberRX;
         the_data_has++;                // принятое количество команд
      }
   }
}
объясните мне, как в буфер попадают 0x0a и 0x0d, если согласно этому коду они туда не пишутся (6-я строка сверху)?

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Вт фев 06, 2018 20:17:34

Я уже другой пробовал. Напрямую в буфер писал. Минуя данные операции.
Таким способом отсеяв 0x0d 0x0a, вовсе не реагируя на них.
Искал именно О и К отдельно. И через свич, короче, их нет в буфере.
Но почему приходят 0x0d 0x0a?

И в терминале ОК есть. :dont_know:

Код:
ISR(USART_RXC_vect)
{
   //
   unsigned int Temp = UDR;  // забираем принятый байт данных
   //LED_yellov_on;
   switch(Temp)
   {
      case 0x4F: buffer[1] = 1;break;
      case 0x4B: buffer[2] = 1;break;
      
   }
}

 void usart_detect_OK()
 {
    if (buffer[1] == 1 )
    {
       if (buffer[2] == 1)
       {
          detect_  = 1;
       }
      
    }
 }

Re: Работа с GSM модулем SIM800L и ATmega16 на Си. Помогите

Ср фев 07, 2018 08:04:46

Расскажите , что у вас с RTS.
Подтянут к земле?
Ответить