Arduino:Примеры/ShftIn22

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

Перевод: Максим Кузьмин (Cubewriter) Контакты:</br>* Skype: cubewriter</br>* E-mail: cubewriter@gmail.com</br>* Максим Кузьмин на freelance.ru
Проверка/Оформление/Редактирование: Мякишев Е.А.


Проверка разных комбинаций на двух комплектах переключателей[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 }

См.также

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