реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> вопрос по Си небольшой.
Метценгерштейн
сообщение Sep 6 2006, 06:13
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



У меня организован такой цикл case:

switch(State) {
...
case IDLE: // этот код выполняется если снято с охраны
off(LED);

if( one_wire_main () ) { //если что-то приложили (ключ)

if(USER_KEYS()) {
State = IDLE_HAS_KEY;
}
}

break;

case IDLE_HAS_KEY:
...

Вопрос- вот иду я по проге, приложили USER_KEYS, я сразу прыгаю на метку IDLE_HAS_KEY? Или дохожу до оператора break, потом компилятор анализирует что там было раньше и после break прыгает уже на метку?
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 6 2006, 06:24
Сообщение #2


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Что значит цикл case???

на case IDLE_HAS_KEY: вы попадете только когда оператор switch(State) выполнится заново и при этом State будет = IDLE_HAS_KEY

switch - это всего лишь переключатель в зависимости от State делается JUMP в нужную точку

если хотите в этой же итерации попасть туда используйте goto

например так:
Код
switch(State) {
...
case IDLE: // этот код выполняется если снято с охраны
  off(LED);

  if( one_wire_main () ) { //если что-то приложили (ключ)

    if(USER_KEYS()) {
      State = IDLE_HAS_KEY;
      goto _IDLE_HAS_KEY:
    }
  }

break;


case IDLE_HAS_KEY:
_IDLE_HAS_KEY:
...


Сообщение отредактировал KRS - Sep 6 2006, 06:28
Go to the top of the page
 
+Quote Post
Harvester
сообщение Sep 6 2006, 06:55
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(KRS @ Sep 6 2006, 10:24) *
Что значит цикл case???

на case IDLE_HAS_KEY: вы попадете только когда оператор switch(State) выполнится заново и при этом State будет = IDLE_HAS_KEY

switch - это всего лишь переключатель в зависимости от State делается JUMP в нужную точку

если хотите в этой же итерации попасть туда используйте goto

например так:
Код
switch(State) {
...
case IDLE: // этот код выполняется если снято с охраны
  off(LED);

  if( one_wire_main () ) { //если что-то приложили (ключ)

    if(USER_KEYS()) {
      State = IDLE_HAS_KEY;
      goto _IDLE_HAS_KEY:
    }
  }

break;


case IDLE_HAS_KEY:
_IDLE_HAS_KEY:
...


Совет правильный, но вообще-то использование команды goto является плохим стилем программирования и очень затрудняет отладку. Лично я построил бы диспетчер следующим образом:
Код
do{

  State = IDLE;
  off(LED); // этот код выполняется если снято с охраны
  ...

  if( one_wire_main ()  && USER_KEYS())  //если приложили правильный ключ
    State = IDLE_HAS_KEY;

  if( ... ) //другое событие
    State = ...;

  if( ... ) //n-е событие
    State = ...;

}while(State == IDLE);

switch(state)
{
  case IDLE_HAS_KEY:
    ...
    break;

  case ...:
    ...
    break;
  
  default:
    ...
    break;
}

Ну и все это, разумеется, крутится в бесконечном цикле.


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Sep 6 2006, 08:29
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



ясно, с этим вроде разобрался, вот ещё не ясно как лучше сделать.
Уже, наверное, понятно, что я пишу под ключ- таблетку. У меня есть мастер ключ, и есть юзер ключи. Теперь я хочу, чтобы если приложил кратковременно мастер, просто поменяло состояние на другое, а если его удерживаю хотя бы 5 сек, сразу попадаю в др. подпрограмму записи USER ключа. Как это лучше реализовать?

if( MasterKey () ) { //здесь- что, если приложен мастер
//здесь опишем процесс, записи новых ключей, только из IDLE
//если прижали мастер на 5 сек

CntT0= 0;
while (CntT0 !=95) //если в теч. 5 сек. приложили мастер, вызываю запись USERa
...
WRITE_KEY();
...
State = IDLE_HAS_KEY;
...

State = IDLE_HAS_KEY; это состояние, куда я должен попать если кратковременно приложил- отпучтил ключ, а если 5 сек. удерживаю, то в ф-ю WRITE_KEY();

как бы это завернуть покрасивше?

Сообщение отредактировал Метценгерштейн - Sep 6 2006, 08:32
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Sep 6 2006, 09:22
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



так корректно будет?

CntT0= 0;
if( !one_wire_main () ) { //если отпустили ключ
if (CntT0 !=95) //если не досчитал до 5 сек., то меняю сост. на IDLE_HAS_KEY
State = IDLE_HAS_KEY;
else
WRITE_KEY();
}
Go to the top of the page
 
+Quote Post
Harvester
сообщение Sep 6 2006, 11:41
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(Метценгерштейн @ Sep 6 2006, 12:29) *
ясно, с этим вроде разобрался, вот ещё не ясно как лучше сделать.
Уже, наверное, понятно, что я пишу под ключ- таблетку. У меня есть мастер ключ, и есть юзер ключи. Теперь я хочу, чтобы если приложил кратковременно мастер, просто поменяло состояние на другое, а если его удерживаю хотя бы 5 сек, сразу попадаю в др. подпрограмму записи USER ключа. Как это лучше реализовать?
...


Кстати, а как Вы собираетесь определять, что в течение всех этих 5 секунд был приложен мастер ключ? Постоянно считывать и проверять его код? - неудобно.

В многих подобных системах используется след. алгоритм:
1. При кратковременном замыкании контактов считывателя переходим в режим ожидания мастер-ключа.
2. Если в течение заданного интервала обнаружили мастер - переходим в режим записи USER-ключа, иначе - возвращаемся в режим ожидания.
3. Ну, и если в режиме программирования в течение разумного промежутка не был обнаружен новый ключ или же при повтороном замыкании контактов считывателя - также возвращаемся в дежурный режим.


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Sep 8 2006, 07:35
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



немного конкретизирую задачу- при приложении мастер- ключа, устойчиво переходит из состояний охрана- снято. Но, я хочу, чтобы если подержал подольше мастер- ключ- секунды 4, то попадаю в ф-ю записи юзер- ключа. Для начала, надо, чтобы я устойчиво попадал в эту прогу, а там мигал хитро светодиодом. Подскажите, плз. Вот образец куска проги общей.

if( MasterKey () ) { //здесь- что, если приложен мастер
//здесь опишем процесс, записи новых ключей, только из IDLE
//если прижали мастер на 5 сек
//**************************** ***************** *******************************
/* CntT0= 0;
if( !one_wire_main () ) { //если отпустили ключ
if (CntT0 < 95) //если не досчитал до 5 сек., то меняю сост. на IDLE_HAS_KEY
State = IDLE_HAS_KEY;
else
WRITE_KEY();
} */
//************************************* **************** ************************
State = IDLE_HAS_KEY;
}
}

здесь закомментировано, так оно просто переключается между состояниями, ф-я записи ключей WRITE_KEY();
попав в неё, я хочу помигать лампочкой.
Как лучше тут описать? Чтобы я держал ключ, как только время достигло 4 сек, оно прыгал в ту ф-ю, а не ждало пока я ключ отпущу, и потом только прыгало?
Go to the top of the page
 
+Quote Post
Harvester
сообщение Sep 8 2006, 12:41
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Цитата(Метценгерштейн @ Sep 8 2006, 11:35) *
...
Как лучше тут описать? Чтобы я держал ключ, как только время достигло 4 сек, оно прыгал в ту ф-ю, а не ждало пока я ключ отпущу, и потом только прыгало?

По логике нужно использовать 1-й вариант - а то как пользователь узнает, что мастер-ключ уже можно отпускать.


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Sep 11 2006, 10:23
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



while ( MasterKey () ) { //пока ещё приложен ключ
CntT0= 0;
if (CntT0 == 95) { //если не досчитал до 5 сек., то меняю сост. на IDLE_HAS_KEY
WRITE_KEY ();
}
}

такая конструкция была бы правильной? В ф-ии WRITE_KEY (); я просто мигаю лампочкой.
Но вот что- то оно не мигает.... sad.gif
Go to the top of the page
 
+Quote Post
PaulS
сообщение Sep 11 2006, 10:54
Сообщение #10





Группа: Новичок
Сообщений: 9
Регистрация: 28-01-05
Пользователь №: 2 265



Цитата(Метценгерштейн @ Sep 11 2006, 14:23) *
while ( MasterKey () ) { //пока ещё приложен ключ
CntT0= 0;
if (CntT0 == 95) { //если не досчитал до 5 сек., то меняю сост. на IDLE_HAS_KEY
WRITE_KEY ();
}
}

такая конструкция была бы правильной? В ф-ии WRITE_KEY (); я просто мигаю лампочкой.
Но вот что- то оно не мигает.... sad.gif


Не так это делается
После проверки ключа на валидность надо секунды на три блокировать ввод.
Иначе можно нарваться на двойное переключение состояния, люди по разному
ключ прикладывают. smile.gif
После ввода ключа, блокируешь ввод,
очищаешь счетчик в таймерном прерывании,
отсчитываешь 3 - 4 секунды
и разрешаешь ввод ключа.
Если ключ все еще приложен, он тут же считается и вот тут то и надо принимать решение
о переходе в режим ввода новых ключей.
Успехов
Go to the top of the page
 
+Quote Post
Shurmas
сообщение Sep 11 2006, 13:41
Сообщение #11


Местный
***

Группа: Новичок
Сообщений: 232
Регистрация: 24-06-06
Пользователь №: 18 332



Пример с сетью 1-wire с "таблеткой" и другими DSxxxx есть в симуляторе PROTEUS - вы можете отладить код на ПК.
Пример находится в папке:
SAMPLES\One-Wire\NETWORK
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Sep 14 2006, 11:17
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



ещё вопрос по Си (простой)
в таком виде

case ARMED: // этот код выполняется под охраной

if(signal(SENS)) {

on(SIRENA);

CntT0= 0;
if (CntT0 == 700) { // продолжительность воя сирены - подобрать
off(SIRENA);
}
}

это фрагмент, попал я в режим под охраной, как только поступил сигнал с датчика, включаю сирену, теперь надо, чтобы она либо сама отключилась через время, либо я ключом её выключил. Считает счетчик, если равно количесву прерываний счетчика 700, сирена выключается. Не понятно по скобкам, этот таймер у меня внутри ф-ии, я туда всегда буду попадать по прерыванию счетчика? или я там буду, пока SENS (датчик) сработал? Вот здесь непонятность небольшая
Go to the top of the page
 
+Quote Post
dezzer
сообщение Sep 14 2006, 11:44
Сообщение #13


Участник
*

Группа: Свой
Сообщений: 66
Регистрация: 27-09-05
Пользователь №: 9 012



Цитата
Не понятно по скобкам, этот таймер у меня внутри ф-ии, я туда всегда буду попадать по прерыванию счетчика?

Таймера внутри функции лично я не вижу. По прерыванию от него вы будете попадать в соответствующую ISR (программу обслуживания прерываний). А вот, что вы будуте в этой ISR делать (просто отключать сирену, флаг какой-то устанавливать, что пора бы её выключить) - это уже ваше дело.
Go to the top of the page
 
+Quote Post
Метценгерштейн
сообщение Sep 14 2006, 12:02
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 357
Регистрация: 12-04-05
Из: Петербург
Пользователь №: 4 079



всё правильно, я немного не так выразился, по прерыванию от таймера я попадаю сюда

#pragma vector = TIMER0_OVF0_vect
__interrupt void overflow_timer1(void)
{
CntT0++;
}

Здесь увеличиваю переменную
А что у меня получилось? Сначала сработал датчик, я попал в эту ф-ю, включил сирену, обнулил
CntT0=0;
теперь надо, чтобы при проверке при количеству подсчетов =700, выполнялось отключить сирену. Уже вижу, что запутался. Я хотел вот что спросить, здесь
if(signal(SENS)) {
я буду считать до 700 если это условие постоянно истина? Т.е. все время идет сигнал от датчика? как только нет, я вываливаюсь из цикла и уже не проверяю на 700?
Go to the top of the page
 
+Quote Post
_Bill
сообщение Sep 14 2006, 12:21
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Метценгерштейн @ Sep 14 2006, 15:02) *
всё правильно, я немного не так выразился, по прерыванию от таймера я попадаю сюда

#pragma vector = TIMER0_OVF0_vect
__interrupt void overflow_timer1(void)
{
CntT0++;
}

Здесь увеличиваю переменную
А что у меня получилось? Сначала сработал датчик, я попал в эту ф-ю, включил сирену, обнулил
CntT0=0;
теперь надо, чтобы при проверке при количеству подсчетов =700, выполнялось отключить сирену. Уже вижу, что запутался. Я хотел вот что спросить, здесь
if(signal(SENS)) {
я буду считать до 700 если это условие постоянно истина? Т.е. все время идет сигнал от датчика? как только нет, я вываливаюсь из цикла и уже не проверяю на 700?

Может невпопад, за веткой не слежу. Я бы сделал так:
Код
#pragma vector = TIMER0_OVF0_vect
__interrupt void overflow_timer1(void)
       {
        static CntT0 = 0;

        if (State == ST_DELAY)
                 {
                 if (++CntT0 >= DELAY_5S)
                          {
                          CntT0 = 0;
                          State = ST_WRITE;
                          }
                 }
        }
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 00:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.01441 секунд с 7
ELECTRONIX ©2004-2016