Одновременное обращение к цифровым пинам.
- Войдите на сайт для отправки комментариев
Пт, 29/01/2021 - 22:38
Вопрос начинающего.
Ардуинка UNO цифровыми выводами 2,3,4,5 должна перебрать адреса внешнего устройства. Считывая данные аналоговыми контактами. Как на цифровых выводах одновременно выставлять адреса, не изменяя состояние остальных цифровых выводов.
Насколько одновременно?
Выводы 2, 3, 4 и 5 подсоединены к одному и тому же порту. Соответственно, можно устанавливать их одновременно, изменяя содержимое порта по маске.
Собственно, в соседнем разделе прикрепленная тема: http://arduino.ru/forum/obshchii/pin-mapping-sootvetstvie-vyvodov-i-registrov
Просто 0000, 0001,0010,0011 .... 1100,1101,1110,1111 , а не сначала на пине 2, затем на пине 3, и тд.
Просто 0000, 0001,0010,0011 .... 1100,1101,1110,1111 , а не сначала на пине 2, затем на пине 3, и тд.
можно
Правильно ли DDRD =| B00111100; // Инициализирую
Затем в цикле PORTD = adr; / Где adr адрес на внешнем устройстве
или
PORTD |= adr;
Правильно ли DDRD =| B00111100; // Инициализирую
Затем в цикле PORTD = adr; / Где adr адрес на внешнем устройстве
или
PORTD |= adr;
чему равен adr ?
Не преувеличена ли опасность наличия гапа? 4 пина, прямой записью в регистры... Комар моргнуть не успеет даже.
Правильно ли DDRD =| B00111100; // Инициализирую
Затем в цикле PORTD = adr; / Где adr адрес на внешнем устройстве
или
PORTD |= adr;
Нет.
У Вас ведь младший бит адреса выводится не в 0-й, а во 2-й разряд порта. Значит, нужен сдвиг на 2 влево. И, если Вы собираетесь выводить адрес неоднократно, нужно не забывать и обнульять единицы от прошлых операций. Следовательно что-то вроде PORTD = (PORTD & 0xC3) | (adr << 2);
adr меняется от B00000100 до B00111100. Или что эквивалентно от 4 до 60 в десятичной системе.
В сообщениях №3 и №9 взаимоисключающая информация.
Точнее значения adr B0, B100, B1000, B1100, ..., B111100 или в десятичной системе 0, 4, 8, 12 .... 60.
Через обнуление: PORTD &= B11000011; PORTB |= adr<<2;
Либо с переменной, если нужно строго изменение: uint8_t x = PORTD; x &= B11000011; x |= adr<<2; PORTD = x;
При этом, на время операций с портом желательно запрещать прерывания.
Через обнуление: PORTD &= B11000011; PORTB |= adr<<2;
Либо с переменной, если нужно строго изменение: uint8_t x = PORTD; x &= B11000011; x |= adr<<2; PORTD = x;
При этом, на время операций с портом желательно запрещать прерывания.
Вы перепутали PORTD c PORTB, не читали сообщения №8 или и то и другое?
И зачем запрещать прерывания?
Ардуинка UNO цифровыми выводами 2,3,4,5 должна перебрать адреса внешнего устройства.
Та вроде не перепутал.)
Прерывания - затем, что бы никто не мог изменить состояние порта, пока мы с ним играемся. Очевидно же.
Но если всё под контролем, тогда не надо.)
"Сержант, стройте взвод. Нафига? Тогда не надо.")
Прерывания - затем, что бы никто не мог изменить состояние порта, пока мы с ним играемся. Очевидно же.
Что значит "пока играемся", если изменение состояния ног порта происходит один раз и одномоментно?
Играемся - от момента когда считали значение с порта и до момента когда его записали. А это, как раз, не одномоментно, к сожалению.
изменение состояния ног порта происходит один раз и одномоментно?
Не совсем. Всё равно компилятор сначала считывает значение порта в регистр, потом делает логическую операцию, потом записыват взат. Если прерывание, в котором изменяются ноги этого же порта случится сразу ПОСЛЕ того, как мы его считали, но ДО того, как записали взат, то после нашей записи мы потеряем то, что изменилось в прерывании. Поэтому, операция изменения регистра порта просто обязана быть атоммарной.
Немного не так. После выставления адреса происходит считывание данных и дальнейшая обработка. Посл обработки выставление нового адреса, считывание и новая обработка. Главное выставить одномоментно адрес на ногах. Я все понимаю, но почему нельзя просто обращаясь к регистру D т.е. PORTD нельзя выставить адрес без сдвигов и т.п. без затрагивания других ног. На других ногах стоят иные сигналы управления.
Сдвиги чисто для вашего удобства. Для того что бы вы в своей голове не вычисляли действительное значение. Они не порождают никаких дополнительных команд.
Почему? Вы ведь сами говорите что "на других ногах стоят иные сигналы управления". Если вы знаете какие, тогда можете сразу выставлять данные с этими "другими сигналами". Но это не есть универсально (как любит говорить andiano))).
Хорошо, а если перед установкой адресных данных считать состояние регистра, наложить маску и записать по новой с новым адресом?
Ну да, я ж вам пример приводил.
Либо с переменной, если нужно строго изменение: uint8_t x = PORTD; x &= B11000011; x |= adr<<2; PORTD = x;
Только обычно эта одновременность никому и нафиг не нужна.)
Нужна, если время поджимает.
Говорите какое время - тогда будет понятно.
Да, возьмите библиотеку DigitalPins - там есть групповые операции для пинов одного порта. Они именно эти и делают.
Убедили, задавили, разъяснили...... Всем спасибо, пошел экспериментировать. Ещё раз всем спасибо и не обижайтесь, я только учусь, а это не стыдно!!
Так библиотеку-то попробовали? Сработало?
Ушел пробовать. Позднее отпишусь если интересно.
почему нельзя просто обращаясь к регистру D т.е. PORTD нельзя выставить адрес без сдвигов и т.п. без затрагивания других ног. На других ногах стоят иные сигналы управления.
Потому, что к порту подключено 8 ног, а изменить сигналы Вам нужно только на четырех. А на остальных четырех, где "иные сигналы управления", ничего меняться не должно.
Хорошо, а если перед установкой адресных данных считать состояние регистра, наложить маску и записать по новой с новым адресом?
Именно это я Вам советовал еще в сообщениях №2 и №8.
Всем огромное спасибо!!! Все получилось. Собака порылась в том, что в сообщении № 13 говорилось об обнулении. У меня этого не было и получалось, что предыдущие значения оставались на ногах. Короче в цикле делалось Сброс вначале сброс значений на 4 ногах, затем установка нового значения, чтение аналогового сигнала, обработка и все по новой.
Еще раз всем спасибо. Одна голова хорошо, а подзатыльник лучше!.