Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Сообщение Rtmip »

Здравствуйте всем!
Язык "С" не знаю, но заинтересовала меня вот эта прога, та что во вложении, отсюда.Полное описание и схема тут, на схеме ошибка, перепутаны столбцы клавиатуры,
но это не суть. Как она работает разобрался, вообщем, перегнал ее в формат WinAvr, добавил возможность ввода кода охраны... Переделал
под Atmega8, все хорошо работает, однако есть там недоработка, позволяющая легко подобрать код охранной системы!
Решил ее тоже исправить, однако не получается, уперся в то, что не понимаю, как работает этот кусок:
Спойлер

Код: Выделить всё

// HOLD WHILE KEYDOWN
scn = 0;
while (scn != 45) {
scn = 0;
PORTD.4 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.4 = 1;
PORTD.5 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.5 = 1;
PORTD.6 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.6 = 1;
}
Целиком он в этом блоке:
Спойлер

Код: Выделить всё

// **********************************************************************************************
// **** READ KEYPAD AND RETURN ASCII VALUE
// **********************************************************************************************
unsigned char KEYPAD() {
unsigned char key;
unsigned char scn;
key = 0;

// SCAN KEYS IN COLUMN 1
PORTD.4 = 0;
delay_ms(1);
scn = (PIND & 15);
PORTD.4 = 1;
// CONVERT KEY TO ASCII
if (scn == 14) key = '1';
if (scn == 13) key = '4';
if (scn == 11) key = '7';
if (scn == 7) key = '*';

// SCAN KEYS IN COLUMN 2
PORTD.5 = 0;
delay_ms(1);
scn = (PIND & 15);
PORTD.5 = 1;
// CONVERT KEY TO ASCII
if (scn == 14) key = '2';
if (scn == 13) key = '5';
if (scn == 11) key = '8';
if (scn == 7) key = '0';

// SCAN KEYS IN COLUMN 3
PORTD.6 = 0;
delay_ms(1);
scn = (PIND & 15);
PORTD.6 = 1;
// CONVERT KEY TO ASCII
if (scn == 14) key = '3';
if (scn == 13) key = '6';
if (scn == 11) key = '9';
if (scn == 7) key = '#';

// SEND KEY BEEP
if (key != 0){
for (scn = 0; scn < 50; scn++) {
PORTC.0 = 0;
PORTC.1 = 1;
delay_us(200);
PORTC.0 = 1;
PORTC.1 = 0;
delay_us(200);
}
}

// HOLD WHILE KEYDOWN
scn = 0;
while (scn != 45) {
scn = 0;
PORTD.4 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.4 = 1;
PORTD.5 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.5 = 1;
PORTD.6 = 0;
delay_ms(1);
scn = scn + (PIND & 15);
PORTD.6 = 1;
}

// RETURN KEY VALUE
delay_ms(100);
return(key);
}
Как сканируются клавиатура понимаю, но как тут работает часть блока, ответственная за удержание кнопок не пойму, растолкуйте, пожалуйста! :)
PS: начало обсуждения было здесь
UPD:Кажется понял как работает: пока нажата любая клавиша будет крутиться в этом цикле, если нет нажатой кнопки, то пройдет его один раз и дальше по программе.
Вопрос снят :)
Вложения
WIDE C Source File.c
(8.06 КБ) 231 скачивание
Реклама
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Всех приветствую!
Интересует грамотный и корректный алгоритм взамиодействия МК с GSM/GPS-модулями SIM900/SIM908.
Во всех примерах в интернете либо шлют модулю 1 команду и на этом успокаиваются, либо заливают ему несколько команд с задержкой. Данный метод мне лично кажется неправильным и делать так мне не хочется. Придумал следующий алгоритм:

Создаем переменную Шаг = 0;

В основной процедуре делаем

while(шаг < 250)
{
если (шаг == 0) {Отсылаем модулю "AT";}
Case

Шаг == 0 : дожидаемся и принимаем ответ, если (ответ == "OK") {Шаг = 5; Отсылаем "AT+CREG?";}
Шаг == 5 : дожидаемся и принимаем ответ, если (ответ == "+CREG: 1,1") {Шаг = 10; Отсылаем "AT+CMGF=1";}
Шаг == 10 : дожидаемся и принимаем ответ, если (ответ == "OK") {Шаг = 15; Отсылаем "AT+CSCS="GSM"";}
Шаг == 15 дожидаемся и принимаем ответ, если (ответ == "OK") {Шаг = 20; Отсылаем ... }
...
_delay_ms(3000);
}

Таким образом модулю отправляется команда и ожидается конкретный ответ. Если ответ не тот, который ожидается, команда отправляется ещё раз, и так до получения ожидаемого ответа.

Прошу покритиковать данный алгоритм или предложить алгоритм лучше.
Контактная информация:
Реклама
Родился
Сообщения: 9
Зарегистрирован: Чт июн 05, 2014 22:09:46

Сообщение Zhevagin »

А если где-то сбой и правильный ответ никак не приходит? у Вас программа зависнет на этом месте? Тогда уж вводите количество попыток, прежде чем программа выйдет из цикла и сообщит о критической ошибке
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Zhevagin
Хорошее замечание, спасибо. У меня в схеме ещё будет стоять ATTiny13A, управляющий питанием модуля и основного контроллера. Он всё время спит в Power-down, просыпается 1 раз в 8 секунд по Watchdog и в нужный момент включает модуль и контроллер. Я планировал ограничить время сессии 15 минутами, после чего ATTiny13A вырубил бы питание и МК, и SIM. Теперь ещё соединю основной МК и ATTiny13A несколькими ножками напрямую. При подъеме одной ATTiny13A будет перезагружать SIM, а при подъеме второй будет выключать всё до следующего сеанса связи.

Есть ли ещё какие-то замечания?
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 830
Зарегистрирован: Пт ноя 16, 2007 11:21:37

Сообщение Pavel_1978 »

А ты уверен что за 15 секунд у тебя модуль зарегестририруется в сети, поднимит GPRS соединение и законектится с сервером?
У меня В москве при уровне сигнала +QSC 28,9 регистрация в сети происходит за 5-10 сек, установка GPRS от 5 сек. Так что ваш алгоритм бред полный.
Реклама
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Pavel_1978 писал(а):А ты уверен что за 15 секунд у тебя модуль зарегестририруется в сети, поднимит GPRS соединение и законектится с сервером?
У меня В москве при уровне сигнала +QSC 28,9 регистрация в сети происходит за 5-10 сек, установка GPRS от 5 сек. Так что ваш алгоритм бред полный.
А мне не нужен GPRS, только звонки и SMS. И при чем здесь 15 секунд? По моему алгоритму раз в 3 секунды у модуля будут спрашивать AT+CREG? до тех пор, пока не получат правильный ответ +CREG: 1,1, и только после этого начнется работа со звонками и СМС.
А как вы работаете с модулями SIM90x?
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 830
Зарегистрирован: Пт ноя 16, 2007 11:21:37

Сообщение Pavel_1978 »

И что произойдет если модуль так и не ответит 1,1 или 1,0 пришлет???
Если работаете смс - включен ли отчет о доставке? Если у оператора затык и смска будет доставлена только завтра? что в это время ваш модуль будет делать? точнее МК который модулем рулит. Опять же пока идет ожидание ответа от модуля по Вашему алгоритму МК должен забить на все остальное - и нафига в такой системе модуль?
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Pavel_1978 писал(а):И что произойдет если модуль так и не ответит 1,1 или 1,0 пришлет???
Если работаете смс - включен ли отчет о доставке? Если у оператора затык и смска будет доставлена только завтра? что в это время ваш модуль будет делать? точнее МК который модулем рулит. Опять же пока идет ожидание ответа от модуля по Вашему алгоритму МК должен забить на все остальное - и нафига в такой системе модуль?
Ожидание отчета о доставке не требуется. И у МК как раз и нет других задач кроме отправки СМС в нужный момент. Плюс таймаут работы 15 минут, после которого и МК, и модуль будут отключены.
И ещё раз спрошу: как работаете с модулем вы? Или это великий секрет?
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 830
Зарегистрирован: Пт ноя 16, 2007 11:21:37

Сообщение Pavel_1978 »

У меня модули передают измеренные данные с прибора и текущие координаты на сервер.
В программе прописан алгоритм соединения с сервером, передача пакета (256-512байт) на сервер получение подтвеждения приема от сервера переход в ожидания новой порции данных от прибора.
собственно все по ДШ и семплам от производителя.
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Pavel_1978 писал(а):У меня модули передают измеренные данные с прибора и текущие координаты на сервер.
В программе прописан алгоритм соединения с сервером, передача пакета (256-512байт) на сервер получение подтвеждения приема от сервера переход в ожидания новой порции данных от прибора.
собственно все по ДШ и семплам от производителя.
Так вот я и хочу узнать как именно написано у вас. Не код, а описание алгоритма, наподобие того, что я сделал в первом сообщении.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 830
Зарегистрирован: Пт ноя 16, 2007 11:21:37

Сообщение Pavel_1978 »

1. включаю модуль жду от него готовность.
2. передаю АТЕ) чтоб отрубить эхо.
3. проверяю регистрацию и уровень сигнала сети.
в это время отупляется GPS
4. в зависимости от оператора подключаю GPRS и проверяю выданый IP
5. включаю TCP соединение с сервером.
после каждого пакета запращиваю статус соединения...
Открыл глаза
Сообщения: 43
Зарегистрирован: Чт май 24, 2012 09:19:34
Откуда: Ярославль

Сообщение holy_0dmin »

Pavel_1978
Так, уже лучше. Но это общая последовательность, а меня интересует алгоритм с учетом архитектуры AVR, т.е. бесконечный главный цикл, прием данных по UART через прерывания и т.п.
Допустим, отправили команду. Дальше что? Цикл, в котором собираем по символам строку ответа и смотрим, всё ли правильно?
Или в прерывании посимвольно собирается строка ответа и потом каким-то образом определяется на какой именно запрос был ответ?
Контактная информация:
aam
Собутыльник Кота
Аватара пользователя
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Сообщение aam »

Здравствуйте!
Скажите, а как в текстовую строку подставить препроцессорную константу?
В девайсе есть строка, определяющая его название и двухзначный номер. Вот как всунуть туда этот номер, определенный через #define ?
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Вложенным макросом через конкатерацию строк попробуй
Fucking static initialization order fiasco
Контактная информация:
aam
Собутыльник Кота
Аватара пользователя
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Сообщение aam »

Пытался писать так:

Код: Выделить всё

#define LD_NUM 3
#define TO_STR(s) # s
#define CONCAT_STR(a, b) a ## b
char const str_Dev_Info[]=TO_STR(CONCAT_STR(MDIOv1.0 LD, LD_NUM));
В итоге выводится строка

Код: Выделить всё

CONCAT_STR(MDIOv
(...закончился индикатор)
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Это по макросам
Конкатенацию нужно во внешний макрос пихать, чтобы она первой выполнялась. Если так попробовать?:

Код: Выделить всё

#define LD_NUM 3
#define TO_STR(s) # s
#define CONCAT_STR(a, b, c) a ## b ## c
char const str_Dev_Info[]=CONCAT_STR(<TO_STR(MDIOv1.0 LD,>,LD_NUM,<)>)
Точно не помню, как запятую и скобку в аргумент макроса вкорячить, если не получится, как я написал - можно скобку и запятую тоже через макросы определить
Fucking static initialization order fiasco
Контактная информация:
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Код: Выделить всё

#define LD_NUM 3
#define str(s) #s
#define TO_STR(s) str(s)
char const str_Dev_Info[]= "MDIOv1.0 LD" TO_STR(LD_NUM);
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

В последнем варианте 2 и 3 строки можно объединить в одну.
Контактная информация:
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

если делать вот так:

Код: Выделить всё

#define LD_NUM 3
#define TO_STR(s) # s
char const str_Dev_Info[]= "MDIOv1.0 LD" TO_STR(LD_NUM);
то получится MDIOv1.0 LDLD_NUM вместо MDIOv1.0 LD3
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

a_skr, в Вашем случае тоже также получится. Т.к. TO_STR(LD_NUM) превратиться в #LD_NUM, затем в исходный код подставится "LD_NUM", за место ожидаемого "3".

А

Код: Выделить всё

#define TO_STR(s) str(s)
вообще бессмысленный макрос. Он будет просто клонировать один в один.
Контактная информация:
Ответить

Вернуться в «Разные вопросы по МК»