Как адресуются контакты порта arduino, если я хочу получить к ним доступ с помощью указателя?
Итак, допустим, я хочу получить доступ к цифровому Pin 13. Это контакт порта B. Есть ли адрес памяти, связанный с этим выводом 13 Arduino Uno r3?
Как контакты порта B адресуются соответствующими номерами контактов, например, каков адрес цифрового вывода 13?
В настоящее время я предполагаю, что его PIN-адрес равен 0x05
, поэтому мой указатель выглядит следующим образом
uint8_t *adr=0x00+0x05;
Теперь, если я это сделаю
*adr |= 0x20;
тогда должен ли я ожидать, что я пишу на какой-то PIN, поэтому я хотел бы знать, на какой технический паспорт я должен ссылаться для получения pin-адресов порта B?
В настоящее время мой код не работает, потому что независимо от того, к какому контакту я подключаю светодиод, он мигает. Что делать, если я не хочу использовать какую-либо библиотеку и просто пишу в адрес, и мне нужен контактный адрес ПОРТА B, как ссылаться на разные контакты?
Теперь предположим, что у меня есть код, который использует avr gcc
#include <avr/iom328p.h>//avr/io.h
#include <util/delay.h>
#include <avr/sfr_defs.h>
#define BLINK_DELAY_MS 18000
int main (void)
{
DDRB |= _BV(DDB5);
while(1)
{
PORTB |= _BV(PORTB5);
_delay_ms(BLINK_DELAY_MS);
PORTB &= ~_BV(PORTB5);
_delay_ms(BLINK_DELAY_MS);
}
return 0;
}
Каким значениям соответствуют DDRB
и _BV(DDB5);
и PORTB
и _BV(PORTB5);
? Мне нравится делать это с помощью указателей, поэтому мне нужны адреса ПОРТА B для всех контактов, я знаю макросы, но мне нравятся фактические адреса. там должно быть какое-то техническое описание для этого, как оно называется. Есть ли у arduino то, что выдает адреса, отображенные в памяти?
Приведенный выше код предназначен просто для мигания светодиодного индикатора
@user786, 👍5
Обсуждение1 ответ
Лучший ответ:
Адрес PORTB
можно найти в техническом описании ATmega328P,
раздел “Порты ввода-вывода”, подраздел “Описание регистра”. Он повторяется
ближе к концу раздела “Сводка реестра”, где он задокументирован
следующим образом:
0x05 (0x25)
По общему признанию, это сбивает с толку: есть два адреса! Существует сноска, которая дает некоторый намек на причину:
При использовании специальных команд ввода-вывода IN и OUT адреса ввода-вывода необходимо использовать 0x00 - 0x3F. При адресации регистров ввода-вывода как пространства данных с использованием инструкций LD и ST к этим адресам необходимо добавить 0x20.
Чтобы уточнить, этот регистр отображается в двух разных адресных пространствах:
Он имеет адрес ввода
-вывода 0x05
. Адресное пространство ввода-вывода является небольшим (6 бит). адресное пространство, выделенное для регистров ввода-вывода. На самом деле он слишком мал, чтобы вместить все регистры ввода-вывода. К нему можно получить доступ спомощью инструкций ввода и вывода. Адреса ниже 32 также могут быть адресованы по битам с помощью инструкций
sbi
,cbi
,sbis
иsbic
.Он имеет адрес данных
0x25
. Это гораздо большее адресное пространство, которое предоставляет доступ ко всем регистрам ввода-вывода и к оперативной памяти. Он используется с семействоминструкций ld
/st
.
Поскольку языки C и C ++ не знают об адресном пространстве ввода-вывода, предполагается, что обычный указатель данных всегда указывает на адресное пространство данных. Таким образом, если вы хотите создать указатель на этот регистр, вы можете написать:
volatile uint8_t *adr = 0x25; // PORTB
Обратите внимание на определитель volatile. Это необходимо для того, чтобы компилятор
не был слишком “умным” и не оптимизировал некоторые ваши записи в
предположении, что это просто оперативная память.
Затем вы можете включить светодиод с помощью:
*adr |= 1 << 5; // установить ПОРТB5
С правильными параметрами оптимизации компилятор может
оптимизировать это в sbi 0x05, 0x05
, если он может доказать, что адрес
, сохраненный в указателе, не изменяется.
Мне нужны адреса ПОРТА B для всех контактов, я знаю макросы, но мне нравятся фактические адреса.
Я бы порекомендовал вот что:
volatile uint8_t *adr = &PORTB;
Это позволяет избежать использования магических чисел в вашем коде и проясняет намерения программиста.
Еще одно последнее замечание. При компиляции вашего кода я получил:
include/avr/iom328p.h: [...]
error "Include <avr/io.h> instead of this file."
Просто включите <avr/io.h>
: этот заголовок заботится о том, чтобы включить как
правильные <avr/iomXXX.h>
, так и <avr/sfr_defs.h>
.
Я только что оставил комментарий о сопоставлении памяти с частью SBI в другом ответе. Это все равно, что читать мои мысли., @timemage
re: "если это может доказать, что адрес, сохраненный в указателе, не изменяется": вы можете помочь ему, сделав указатель const , например, volatile uint8_t * const adr
, @mbrig
- Несколько условий оператора if
- Светодиоды: разница между общим анодом и общим катодом
- Как вызвать функции C из скетча ардуино?
- Остановить мигание светодиодов
- max7219 связанный дисплей, показывающий зеркальный текст
- Интеграция 2 кнопок для включения и выключения светодиода.
- Управление цифровой адресной светодиодной лентой RGB 12 В с помощью Arduino
- Код Arduino для управления 4 светодиодами с 4 кнопок
Что вы обнаружили, когда заглянули во включенные заголовочные файлы? Что вы обнаружили, когда прочитали документацию avr-libc? Что вы обнаружили, когда заглянули в технический паспорт Mega128? Почему это вам не помогло?, @the busybee
@thebusybee что для меня не имеет смысла, так это
PORTB |= _BV (PORTB5)
иDDRB |= _BV (DDB5);
почему используется общий адрес PORTB и что, черт возьми, такоеDDRB |= _BV (DDB5);
где документация по этому вводу-выводу с отображением памяти. Это простой вопрос. Я проверил gcc avr, у него есть адреса. Но разве не должно быть какого-то описания для этих макросов и адресов. Это должно быть в листе данных, но подождите, что я на самом деле нашел, так это настройки страниц о макетах контактов при поиске таблицы данных arduino uno r3., @user786Вот почему этот вопрос. Это должно было быть довольно просто для того, что я ищу, но, похоже, информации не хватает. Мне нужны объяснения, @user786
Используйте свои навыки веб-поиска и найдите "лист данных atmega128p" и "avr-libc". Возможно, вам придется немного почитать и подумать, ведь не на все в реальном мире даны ответы сразу в первой ссылке специально для вас. Мы ожидаем, что вы приложите немного усилий сами., @the busybee
Я думаю, ваша проблема заключается в каком-то неправильном представлении о том, как обрабатываются контакты ввода-вывода. Порт предназначен для нескольких выводов ввода-вывода. Один порт ввода-вывода обрабатывается одним битом регистра порта., @Juraj