Вопросы по С/С++ (СИ)
- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
[uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696163#p3696163"]Billi34, мда, это Вам не GCC. У MikroC мозгов намного меньше и о таких косяках он предупреждать не умеет.[/uquote]

- Реклама
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696168#p3696168"]Напишите просто if(t)[/uquote]Думаешь это поможет пониманию? 
- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
[uquote="VladislavS",url="/forum/viewtopic.php?p=3696160#p3696160"]Компилятор, однозначно, в топку.[/uquote]
Что мне скачать ? AVR Studio я ставил для другого проекта- для меня слишком сложная среда разработки. Я еще не умею так разрабатывать.
Добавлено after 2 minutes 54 seconds:
[uquote="VladislavS",url="/forum/viewtopic.php?p=3696174#p3696174"][uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696168#p3696168"]Напишите просто if(t)[/uquote]Думаешь это поможет пониманию?
[/uquote]
Я понимаю что знак равно совсем не равно. Только компилятор "прожевал" это и никто не скажет что так нельзя.
Что мне скачать ? AVR Studio я ставил для другого проекта- для меня слишком сложная среда разработки. Я еще не умею так разрабатывать.
Добавлено after 2 minutes 54 seconds:
[uquote="VladislavS",url="/forum/viewtopic.php?p=3696174#p3696174"][uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696168#p3696168"]Напишите просто if(t)[/uquote]Думаешь это поможет пониманию?
Я понимаю что знак равно совсем не равно. Только компилятор "прожевал" это и никто не скажет что так нельзя.
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="Billi34",url="/forum/viewtopic.php?p=3696177#p3696177"]Только компилятор "прожевал" это и никто не скажет что так нельзя.[/uquote]Почему же нельзя? Можно! В ногу себе стрелять, в принципе, тоже можно...
[uquote="VladislavS",url="/forum/viewtopic.php?p=3696174#p3696174"][uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696168#p3696168"]Напишите просто if(t)[/uquote]Думаешь это поможет пониманию?
[/uquote]
Возможно. В любом случае, для приведенного кода это правильно )
Добавлено after 9 minutes 34 seconds:
[uquote="Billi34",url="/forum/viewtopic.php?p=3696177#p3696177"]Я понимаю что знак равно совсем не равно. Только компилятор "прожевал" это и никто не скажет что так нельзя.[/uquote]
В том то и дело, что так можно. Результат операции присваивания определен и равен присваиваемому значению.
Например, выражение:
совершенно корректно: сначала k будет присвоено значение 3, потом j значение 36 и l значение 10, а затем уже i - значение 46.
Вот только выражение t==1 принимает значение ложь, если t не равно единице, а выражение t=1 - всегда истинно.
Возможно. В любом случае, для приведенного кода это правильно )
Добавлено after 9 minutes 34 seconds:
[uquote="Billi34",url="/forum/viewtopic.php?p=3696177#p3696177"]Я понимаю что знак равно совсем не равно. Только компилятор "прожевал" это и никто не скажет что так нельзя.[/uquote]
В том то и дело, что так можно. Результат операции присваивания определен и равен присваиваемому значению.
Например, выражение:
Код: Выделить всё
uint8_t i,j,l,k;
i=((k=3),((j=k*12)+(l=k*3+1)));
Вот только выражение t==1 принимает значение ложь, если t не равно единице, а выражение t=1 - всегда истинно.
- Реклама
- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
таким образом : if(t==1)
{A}
B
если t равно единице выполняется А
если t равно нулю выполняется В
в моем случае
(t=1) при любом значении t выполняется А
{A}
B
если t равно единице выполняется А
если t равно нулю выполняется В
в моем случае
(t=1) при любом значении t выполняется А
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="Billi34",url="/forum/viewtopic.php?p=3696263#p3696263"]таким образом : if(t==1)
{A}
B[/uquote]
если t равно единице, то выполняется А, затем B и всё что дальше.
если t равно нулю, то В и всё что дальше.
{A}
B[/uquote]
если t равно единице, то выполняется А, затем B и всё что дальше.
если t равно нулю, то В и всё что дальше.
- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
Чуть чуть переделал. Теперь по ходу выполнения кода на строке 43 выполняется задержка 0.25 сек. Далее (строка 45) ожидается фронт по PIND.B1 для выполнения фиг. скобок следующих за этим условием: if(PIND.B1&&t). Но по факту фронт на PIND.B1 придет примерно через 0.25 сек. Естественно МК "пролетает" это условие. Как заставить МК ожидать фронт?
- Вложения
-
- NewUnit.c
- (3.26 КБ) 288 скачиваний
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="Billi34",url="/forum/viewtopic.php?p=3696923#p3696923"]Как заставить МК ...[/uquote]Поменять подход к реализации алгоритма.
Почитай про конечные автоматы. Запусти таймер и с определённой частотой анализируй состояние системы. Это тебе позволит точнее с временем работать. А состояния конечного автомата хорошо ложатся на оператор switch. Тебе останется только прописать условия перехода из каждого состояния в другое и соответствующие действия. Поверь, это куда проще отлаживать, чем блуждания по твоим goto с кучей неинформативных переменных-флагов. И не надо спорить, лучше день потерять, потом за 5 минут долететь. Ты и так уже на эту лабуду столько времени убил.
Почитай про конечные автоматы. Запусти таймер и с определённой частотой анализируй состояние системы. Это тебе позволит точнее с временем работать. А состояния конечного автомата хорошо ложатся на оператор switch. Тебе останется только прописать условия перехода из каждого состояния в другое и соответствующие действия. Поверь, это куда проще отлаживать, чем блуждания по твоим goto с кучей неинформативных переменных-флагов. И не надо спорить, лучше день потерять, потом за 5 минут долететь. Ты и так уже на эту лабуду столько времени убил.
- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
Ну я же учусь. goto уже не используются, если вы заметили. switch тоже весьма загадочный оператор, для меня.
1.4.6. Оператор break
Оператор break обеспечивает прекращение выполнения самого внутреннего из объединяющих его операторов switch, do, for, while. После выполнения оператора break управление передается оператору, следующему за прерванным.
очень интересная инфа. Чем то напоминает так не любимый вами goto. Это на самом деле так?
1.4.6. Оператор break
Оператор break обеспечивает прекращение выполнения самого внутреннего из объединяющих его операторов switch, do, for, while. После выполнения оператора break управление передается оператору, следующему за прерванным.
очень интересная инфа. Чем то напоминает так не любимый вами goto. Это на самом деле так?
[uquote="Billi34",url="/forum/viewtopic.php?p=3697111#p3697111"]Чем то напоминает так не любимый вами goto. Это на самом деле так?[/uquote]это на самом деле так, это по сути псевдоним оператора goto, как и оператор continue.
у программистов всегда так: если что-то считается плохим, его можно или обозвать иначе, или прописать с стандарте, как хорошее - и проблема автоматически исчезает 
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
Представляете какой смачный многовариантный goto можно сделать с помощью оператора switch 
Кошмар.
Вот скажите, зачем Вам нужны такие паузы, когда вся система стоит колом?
Код: Выделить всё
Delay_ms(800) ; //пауза длиной 0.8 сек- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
Это как говорится "версия для радио". за эти 0.8 сек МК "дергает некоторыми своими ногами". Я сознательно убрал этот код что б вы не пытались его оптимизировать. А попытка оптимизации будет 100% Ваше мышление заточено под ужатие, оптимизацию-поиск изящных решений. А мне вполне достаточно такого вида как у меня. Объем кода очень маленький. Везде умещаюсь.
Лучше попробуйте делать всё это не в основном цикле, а в прерывании.
Заведите аппаратный таймер, для удобства так, чтобы прерывания срабатывали раз в 1мс. Заведите 1 переменную - счётчик, и 2 переменную - событие.
В прерывании от таймера проверяйте, нажата ли кнопка. Если нажата, счётчик нажатий увеличивайте на 1. Если не нажата, счётчик обнуляйте.
При обнулении счётчика (отпускании кнопки) нужно проверить счётчик, если там больше 100 - значит это было полноценное короткое нажатие. Записываем это короткое нажатие в переменную-событие.
Если кнопка нажата долго, и счётчик досчитал до 600 - значит, в переменную-событие нужно записать информацию о длинном нажатии.
Больше ничего в прерывании делать не надо. Только считать и, при необходимости, обновлять переменную-событие.
В основном цикле программы никаких задержек не нужно. Просто в начале цикла вычитываем переменную событие, с обнулением. Если что-то было - выполняем, если ничего не было - ничего и не делаем.
Всё просто. И ни одной задержки, МК 99.9% времени работает в основном полезном цикле.
Заведите аппаратный таймер, для удобства так, чтобы прерывания срабатывали раз в 1мс. Заведите 1 переменную - счётчик, и 2 переменную - событие.
В прерывании от таймера проверяйте, нажата ли кнопка. Если нажата, счётчик нажатий увеличивайте на 1. Если не нажата, счётчик обнуляйте.
При обнулении счётчика (отпускании кнопки) нужно проверить счётчик, если там больше 100 - значит это было полноценное короткое нажатие. Записываем это короткое нажатие в переменную-событие.
Если кнопка нажата долго, и счётчик досчитал до 600 - значит, в переменную-событие нужно записать информацию о длинном нажатии.
Больше ничего в прерывании делать не надо. Только считать и, при необходимости, обновлять переменную-событие.
В основном цикле программы никаких задержек не нужно. Просто в начале цикла вычитываем переменную событие, с обнулением. Если что-то было - выполняем, если ничего не было - ничего и не делаем.
Всё просто. И ни одной задержки, МК 99.9% времени работает в основном полезном цикле.
Ну, если не нужен _понятный_ код, вдвое меньше по размеру и без задержек, в которых МК просто бесполезно висит - то дело хозяйское.
P.S. Вот упрощённый пример для понимания, как это должно работать:
P.S. Вот упрощённый пример для понимания, как это должно работать:
Спойлер
Код: Выделить всё
// Кнопки
#define BTN0 PIND.B0
#define BTN1 PIND.B1
// События
#define EVT_NO 0
#define EVT_BTN0 0x01 // 00000001
#define EVT_BTN1 0x02 // 00000010
#define EVT_BTN0_LONG (EVT_BTN0 << 4) // 00010000
#define EVT_BTN1_LONG (EVT_BTN1 << 4) // 00100000
// Длительность нажатий
#define LONG_PRESS 600
#define SHORT_PRESS 100
static volatile uint8_t event = EVT_NO; // Переменная для хранения события
void isr_timer(void) // Аппаратное прерывание от таймера, каждые 1мс
{
static uint16_t btnCounter = 0; // Cчётчик нажатий
static uint8_t btnPrev = 0; // Предыдущее нажатие
uint8_t btnNow = 0;
// Опрашиваем кнопки
if (!BTN0) // нажата кнопка 0
btnNow |= EVT_BTN0;
if (!BTN1) // нажата кнопка 1
btnNow |= EVT_BTN1;
if (btnNow) { // Если кнопка нажата
if (btnNow == btnPrev) { // если это всё та же кнопка
btnCounter++; // просто наращиваем счётчик
if (btnCounter == LONG_PRESS) {
event = (btnNow << 4); // сохраняем "длинное" событие
}
} else {
btnPrev = btnNow; // кнопка сменилась, запоминаем
}
} else {
if (btnCounter > SHORT_PRESS && btnCounter < LONG_PRESS) {
event = btnNow; // короткое нажатие - сохраняем событие
}
btnCounter = 0; // сбрасываем счётчик
}
}
uint8_t getEvent(void)
{
uint8_t ret = event; // значение для возврата
event = 0; // событие "забрали", можно обнулять
return ret;
}
int main(void)
{
// настраиваем порты
// ...
// настраиваем таймер на прерывания раз в 1мс
// ..
// поехали...
uint8_t evt;
while (1) {
evt = getEvent();
switch (evt) {
case EVT_BTN0:
// обрабатываем короткое нажатие кнопки 0
break;
case EVT_BTN1:
// обрабатываем короткое нажатие кнопки 1
break;
case EVT_BTN0_LONG:
// обрабатываем длинное нажатие кнопки 0
break;
case EVT_BTN1_LONG:
// обрабатываем длинное нажатие кнопки 1
break;
}
}
return 0;
}
- Сообщения: 64
- Зарегистрирован: Чт июн 09, 2016 18:24:41
Я обязательно по изучаю Ваш пример. Уже появились идейки "нарастить" функционал программы.
Сопутствующий вопрос: это всё ещё на Си или уже С++? Будут ли работать операторы из вашего кода в моем компиляторе?


