"Алгоритмы и блок-схемы - это что такое?" Помощь новичкам.
- Войдите на сайт для отправки комментариев
Здравствуйте!
В этой теме я расскажу как блок-схемы помогают облегчить жизнь. Она ориентированна на людей, которые малознакомы с программированием (вобще неважно каким).
Как известно, весь код выполняется последовательно. То есть абсолютно ВСЕ операции которые выполняются внутри наших микроконтроллеров, выполняются один за другим растягиваясь на такты - это те странные МегаГерцы которые можно увидеть в спецификациях плат arduino (в даташите можно посмотреть сколько тактов занимают простейшие операции).
В чём секрет программистов, которые пишут такое большое колличество строк кода и могут разобраться в том как ЭТО работает?
Первым чему учат программистов - "что такое алгоритм", это и есть их "секрет".
Вырезка из Вики -
Алгори́тм — набор инструкций, описывающих порядок действий исполнителя для достижения результата решения задачи за конечное число действий .
Возьмем для примера всем известный Blink.
digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000);
Его алгоритм будет выглядеть так:
1.Включаем светодиод. 2.Ждем секунду. 3.Выключаем светодиод. 4.Ждем секунду. 5.Возвращаемся к началу.
*Обратите внимание, что алгоритм может быть разной "глубины" - вместо того чтобы написать "Устанавливаем значение ноги в высокое состояние", я написал "Включаем светодиод". Также "delay(1000)" я заменил на "Ждем секунду.".
С помощью блок-схем мы можем представить графическое изображние алгоритма.
Графическое изображение воспринимается куда лучше чем текстовое, не так ли?:)
*Теория алгоритмов говорит, что в каждой программе обязательно должны быть начало и конец, который в данном примере отсутствует(в данном случае переход на этот блок будет осуществлен в случае отключения питания).
Блок-схемы бывают следующих типов:
- блок, который определяет начало и конец программы.Имеет вид начало/конец.
- блок, в котором выполняются какие-то действия.Имеет вид c=a+b;
- блок, в котором происходит проверка условия.Имеет вид a>b?
- блок, который подразумевает вызов функции.
- блок ввода/вывода информации. Может иметь вид вроде 'a = '+ a;
- используется для циклов while и for. (но как по мне пользоваться блоком условия проще).
Для соединения блоков используются стрелочки.
Возьмем пример посложнее!
На этот раз мы опишем программу, которая после нажатия кнопки будет выводить в последовательный порт значения массива.
int massiv[8]={1,2,3,4,5,6,7,8}; int button = 13;
И сам код, который находится в loop(){}
if(digitalRead(button)==1){ for(int i=0;i<8;i++) { Serial.println(massiv[i]); } }
В текстовом алгоритме это будет выглядеть так:
1. Кнопка нажата? Нет - вернуться к началу. Да - переходим к следующему пункту. 2. i=0; 3. i меньше чем 8 ? Нет - вернуться у началу. Да - переходим к следующему пункту. 4. Вывод в последовательный порт значения элемента массива с индексом i - (massiv[i]). 5. Прибавляем к i единицу - i++. 6. Возвращаемся к началу условия (пункт 3).
В графическом соответственно так:
Ну вроде всё должно работать как задумано.
Но что же это? Мы нажимаем на кнопку, но вместо того чтобы один раз вывести данные массива, они выводятся несколько раз.
С точки зрения логики алгоритма всё работает так как и задумано. Вся соль в том, что для Вас - это одно нажатие, а вот с точки зрения МК - это может оказаться целой вечностью(множество циклов).
Он видит это так:
10ms - О, нажата кнопка, пора приниматься за дело. 30ms - Всё сделано как надо, можно возвращаться обратно. 30ms - О, кнопка снова нажата! Опять есть чем заняться! 50ms - Всё сделано! Вернусь-ка я обратно! 50ms - Опять? Ну ладно...
Для того чтобы этого не происходило, нужно ввести переменную, которая будет показывать предыдущее состояние кнопки. Добавим её в наш код -
int massiv[8]={1,2,3,4,5,6,7,8}; int button = 13; boolean pressed = false;
if(digitalRead(button)==1 and pressed==false){ pressed=true; for(int i=0;i<8;i++) { Serial.println(massiv[i]); } } if(digitalRead(button)==0){ pressed=false; }
Теперь МК будет видеть всё так:
10ms - О, кнопочка! Пойду поработаю. 30ms - Готово! Вернусь я в начало. 30ms - Опять кнопочка нажата! Пора.... А неееет, кнопка до сих пор нажата, эту работу я уже выполнил, можно отдохнуть.
С помощью такой вот штуковины становится намного легче найти свою ошибку или даже точно уяснить для себя что должно делать устройство.
PS. для рисования блок-схем я использую онлайн сервис https://www.gliffy.com/ .
всё красиво на словах, но каким образом контроллеру становится понятно, что нужно делать 5.Возвращаемся к началу. ?
т.е. каким образом луп определяет, где у него начало, а где конец, и есть ли в этом смысл? - если по сути имеем кольцо команд. тогда и диаграмму алгоритма рисовать в виде кольца с обозначением точки старта.
В графиках у меня ошибки с точки зрения теории алгоритмов. В ней сказано, что обязательно должны быть начало и конец.
Конец же будет выглядеть настолько глупо, что я его не писал("глубина" алгоритма не та).
В данном случае начало начинается сразу после setup(){}. Ведь по сути алгоритм начинается с подачи питания на МК, а затем уже идет setup и loop. Loop представляет собой на уровне команд тот же цикл while - то есть если код для выполнения дальше отсутствует МК прыгает обратно к строке начала цикла.
Насколько я помню то в ассемблере while(1) выгдядит как команда безусловного перехода jump. Которая перескакивает на нужную строку. Получается круг, но как бы не круг.
И по сути указанные алгоритмы loop и есть те же круги.
А вот если придать ему вид кольца, то оно будет занимать куда больше места и будет восприниматься куда сложнее.
UPD. Если Вы имели ввиду то, что следовало написать "Возвращаемся к пункту 1" - то действительно так будет правильно.
Если это учебный материал, то зачем учить плохому?
Вообще то digitalRead возвращает HIGH или LOW и не важно, что
Давайте просто посмотрим в исходник и убедимся:
Если это помощь новичкам, то давайте будем корректно писать примеры.
IMHO, разумеется