Arduino:Примеры/ShftIn22
Перейти к навигации
Перейти к поиску
Поддержать проект | Содержание | Знакомство с Arduino | Продукты | Основы | Справочник языка Arduino | Примеры | Библиотеки | Хакинг | Изменения | Сравнение языков Arduino и Processing |
Перевод: Максим Кузьмин (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 }
См.также
Внешние ссылки