Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Arduino:Примеры/ShftIn22

Материал из Онлайн справочника
Перейти к: навигация, поиск

Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Проверка разных комбинаций на двух комплектах переключателей[1]

Это скетч для платы Arduino и двух сдвиговых регистров CD4021B. Он считывает данные с переключателей, подключенных к сдвиговым регистрам, сравнивает их с заданными настройками и сообщает, соответствуют ли считанные данные заданным настройкам. «Настройками» служат разные ноты и накладываемые на них звуковые эффекты. Кроме того, скетч определяет, какие переключатели находятся в положении «вкл».

Код

  1. //**************************************************************//
  2. //  Название    : Проверка разных комбинаций                    //
  3. //              : на двух комплектах переключателей             //                                
  4. //  Автор       : Кэрлин Мо                                     //
  5. //  Дата        : 25 января 2007 года                           //
  6. //  Версия      : 1.0                                           //
  7. //  Примечания  : Скетч для использования с двумя сдвиговыми    //
  8. //              : регистрами CD4021B                            //
  9. //**************************************************************//
  10.  
  11. // задаем номера для интерфейсных контактов:
  12. int latchPin = 8;
  13. int dataPin = 9;
  14. int clockPin = 7;
  15.  
  16. // задаем переменные, которые будут хранить данные для
  17. // каждого сдвигового регистра; в целях отладки лучше начать
  18. // со значений без «0»:  
  19. byte switchVar1 = 72;  //01001000
  20. byte switchVar2 = 159; //10011111
  21.  
  22. // задаем массив со значениями для каждого контакта
  23. // на первом сдвиговом регистре:
  24. char note2sing[] = {
  25.   'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};
  26.  
  27. // задаем массив со значениями для 1-7 (не 0) контактов
  28. // на втором сдвиговом регистре; без 0, потому что этот контакт
  29. // будет использоваться для флагового значения:
  30. byte settingVal[] = {
  31.   0, 0, 0, 0, 0, 0, 0};  
  32.  
  33. // флаговая переменная для определения того, находится ли скетч
  34. // в режиме обновления настроек:
  35. byte settingSwitch = 0;  
  36.  
  37. void setup() {
  38.   // запускаем последовательную коммуникацию:
  39.   Serial.begin(9600);
  40.  
  41.   // задаем режимы для контактов:
  42.   pinMode(latchPin, OUTPUT);
  43.   pinMode(clockPin, OUTPUT);
  44.   pinMode(dataPin, INPUT);
  45.  
  46. }
  47.  
  48. void loop() {
  49.  
  50.   // подаем импульс на контакт-защелку;
  51.   // чтобы собрать параллельные данные, задаем ему значение «1»:
  52.   digitalWrite(latchPin,1);
  53.   // ждем:
  54.   delayMicroseconds(20);
  55.   // задаем ему «0», чтобы передать последовательные данные:
  56.   digitalWrite(latchPin,0);
  57.  
  58.   // пока сдвиговые регистры переключены в последовательный режим,
  59.   // собираем все их данные в байт; сначала это делает регистр,
  60.   // подключенный к чипу:
  61.   switchVar1 = shiftIn(dataPin, clockPin);
  62.   switchVar2 = shiftIn(dataPin, clockPin);
  63.  
  64.   // показываем результат; если первый контакт получит значение HIGH,
  65.   // то «0», стоящий в старшей части байта (7, 6, 5 и т.д.),
  66.   // будет удален:  
  67.   Serial.println(switchVar1, BIN);
  68.   Serial.println(switchVar2, BIN);
  69.  
  70.  
  71.   // этот цикл loop() бит за битом прочесывает байт,
  72.   // содержащий данные сдвигового регистра; найдя значение HIGH (1),
  73.   // он печатает соответствующее место в массиве:
  74.   for (int n=0; n<=7; n++)
  75.   {
  76.     // таким образом, когда «n» равно «3», код сравнивает биты
  77.     // в switchVar1 и двоичное число «00001000», возвращая «true»
  78.     // лишь в том случае, если в этом бите (т.е. контакте)
  79.     // есть значение «1», присланное от сдвигового регистра:
  80.     if (switchVar1 & (1 << n) ){
  81.       // печатаем значение из этого места в массиве:
  82.       Serial.println(note2sing[n]);
  83.     }
  84.   }
  85.  
  86. // далее изучаем весь байт и создаем комбинации настроек;
  87.  
  88. // эти настройки (читай, разные ситуации) создаются при помощи
  89. // оператора switch, которому «скармливается» переменная switchVar1;
  90. // далее switchVar1 сравнивается с несколькими заданными
  91. // числовыми значениями:
  92.  
  93.   switch (switchVar1) {
  94.   case B00101010:
  95.     Serial.println("D minor");  //  "Ре минор"
  96.     break;
  97.   case B00010101:
  98.     Serial.println("C major");  //  "До мажор"
  99.     break;
  100.   case B01010100:
  101.     Serial.println("E minor");  //  "Ми минор"
  102.     break;
  103.   case B00101001:
  104.     Serial.println("F major")  //  "Фа мажор";
  105.     break;    
  106.   case B01010010:
  107.     Serial.println("G major");  //  "Соль мажор"
  108.     break;        
  109.   case B00100101:
  110.     Serial.println("A minor");  //  "Ля минор"
  111.     break;    
  112.   case B01001010:
  113.     Serial.println("B diminished");  //  "Си (полтона)"
  114.     break;    
  115.   default:
  116.     // если ничего не подходит, пишем следующее:
  117.     Serial.println("Play It, Joe");  //  "Сыграй-ка сам, Василий!"
  118.   }
  119.  
  120.  
  121. //--- ВТОРОЙ СДВИГОВЫЙ РЕГИСТР
  122. // он ведет себя чуть сложнее
  123.  
  124.  
  125. // если переключатель, подключенный к контакту 7,
  126. // находится в состоянии HIGH:
  127.   if (switchVar2 & (1 << 7) ){
  128.     // печатаем сообщение о том, что идет обновление настроек:
  129.     Serial.println("Check, Check");  //  «Идет обновление настроек»
  130.     // задаем флаговой переменной значение «1», чтобы сообщить скетчу,
  131.     // что идет обновление настроек:
  132.     settingSwitch = 1;
  133.  
  134.     // пока переключатель на контакте 7 имеет значение HIGH,
  135.     // берем оставшиеся 7 битов и загружаем их в массив;
  136.     // так будет удобнее до них «дотянуться» в дальнейшем,
  137.     // когда они понадобятся:
  138.     for (int v=6; v>=0; v--)
  139.     {
  140.       if (switchVar2 & (1 << v) ){
  141.         settingVal[v] = 1;
  142.       }
  143.       else {
  144.         settingVal[v] = 0;
  145.       }
  146.     }
  147.   }
  148.   // если переключатель находится в состоянии LOW...
  149.   else {
  150.     // ...и если в последний раз при проверке оператором if()
  151.     // этот переключатель находился в состоянии HIGH (т.е. если
  152.     // переменная settingSwitch по-прежнему имеет значение «1»):
  153.     //set to "1"):
  154.     if (settingSwitch) {
  155.       // ...то задаем переменной settingSwitch значение «0»:
  156.       settingSwitch=0;
  157.  
  158.       // печатаем текущие настройки:
  159.       Serial.println("___SETTINGS___");  //  "___НАСТРОЙКИ___"
  160.  
  161.       for (int s=0; s<=6; s++)
  162.       {
  163.  
  164.       // печатаем названия настроек;
  165.       // поскольку на февраль 2007 года в язык Arduino
  166.       // еще не были встроены строковые массивы,
  167.       // это делается с помощью оператора «case»:
  168.         switch (s) {
  169.         case 0:
  170.           Serial.print("Mute");  //  "Выключение звука"
  171.           break;
  172.         case 1:
  173.           Serial.print("Octave Shift");  //  "Смещение октавы"
  174.           break;
  175.         case 2:
  176.           Serial.print("Delay");  //  "Задержка"
  177.           break;
  178.         case 3:
  179.           Serial.print("Reverb");  //  "Реверберация"
  180.           break;    
  181.         case 4:
  182.           Serial.print("Vibrato");  //  "Вибрация"
  183.           break;        
  184.         case 5:
  185.           Serial.print("Funkify");  //  "Фанкизация"
  186.           break;    
  187.         case 6:
  188.           Serial.print("Dampen");  //  "Приглушение"
  189.           break;    
  190.         default:
  191.           // если соответствий нет, пишем сообщение по умолчанию:
  192.           Serial.println("Not Defined");  //  "Не определено"
  193.         }
  194.  
  195.         // печатаем статус:
  196.         if (settingVal[s]) {
  197.           Serial.print(" On");    //  " вкл."
  198.           }
  199.         else {
  200.           Serial.print(" Off") ;   //  " выкл."    
  201.          }
  202.  
  203.          // пустое место:
  204.          Serial.println();
  205.  
  206.       }
  207.     }
  208.   }
  209.  
  210.  
  211. // пустое место:
  212. Serial.println("-------------------");
  213. // вставляем задержку, чтобы все как следует допечаталось:
  214. delay(500);
  215.  
  216. }
  217.  
  218. //------------------------------------------------конец главного цикла
  219.  
  220. ////////// ----------------------------------- функция shiftIn()
  221. ///// в качестве аргументов ей требуются лишь контакт для данных
  222. ///// и контакт-защелка; возвращает байт, у которого каждый бит
  223. ///// соответствует какому-либо контакту сдвигового регистра:
  224. ///// 7-ой бит – это 7-ой контакт, 0-ой бит – это 0-ой контакт
  225.  
  226. byte shiftIn(int myDataPin, int myClockPin) {
  227.   int i;
  228.   int temp = 0;
  229.   int pinState;
  230.   byte myDataIn = 0;
  231.  
  232.   pinMode(myClockPin, OUTPUT);
  233.   pinMode(myDataPin, INPUT);
  234. // 8 раз подаем на тактовый контакт значение HIGH (0,..,7),
  235. // т.е. при каждом прохождении цикла for();
  236.  
  237. // в начале каждого цикла мы задаем тактовому контакту значение LOW;
  238. // это нужно для последующего перехода из LOW в HIGH, чтобы сдвиговый
  239. // регистр поменял состояние на основе значения в следующем бите
  240. // последовательного потока данных;
  241.  
  242. // регистр передает информацию о контактах в порядке с 7-го по 0-ой,
  243. // поэтому наша функция ведет отсчет в обратном порядке:
  244.  
  245.   for (i=7; i>=0; i--)
  246.   {
  247.     digitalWrite(myClockPin, 0);
  248.     delayMicroseconds(2);
  249.     temp = digitalRead(myDataPin);
  250.     if (temp) {
  251.       pinState = 1;
  252.       // несмотря ни на что, задаем биту значение «0»:
  253.       myDataIn = myDataIn | (1 << i);
  254.     }
  255.     else {
  256.       pinState = 0;
  257.     }
  258.  
  259.     // печатаем отладочную информацию (если отладка не нужна,
  260.     // оставьте эти строчки закоментированными):
  261.     //Serial.print(pinState);
  262.     //Serial.print("     ");
  263.     //Serial.println (dataIn, BIN);
  264.  
  265.     digitalWrite(myClockPin, 1);
  266.  
  267.   }
  268.   // печатаем пустое место, разделяющее отладочные данные:
  269.   //Serial.println();
  270.   //Serial.println(myDataIn, BIN);
  271.   return myDataIn;
  272. }

См.также

Внешние ссылки

  1. www.arduino.cc - ShftIn22