Как получить значение из 15-го вывода 32-битного порта в ARM?
-
05-07-2019 - |
Вопрос
Я использую микросхему DS1620 для считывания 1-битных последовательных данных, поступающих в одной строке.Мне нужно прочитать эти данные, используя один из портов микроконтроллера ARM (LPC2378).Порты ARM являются 32-разрядными.Как мне преобразовать это значение в 1-битную переменную?
Редактировать:Другими словами, мне нужна прямая ссылка на pin-код порта.
Решение
нет 1-битных переменных, но вы можете выделить конкретный бит, например:
uint32_t original_value = whatever();
uint32_t bit15 = (original_value >> 15) & 1; /*bit15 now contains either a 1 or a 0 representing the 15th bit */
Примечание. Я не знаю, считали ли вы битовые числа, начиная с 0 или 1, поэтому > > 15
может быть выключен один, но вы поняли.
Другой вариант - использовать битовые поля, но это становится беспорядочным, и IMO не стоит того, чтобы каждый бит в значении был каким-то образом полезен. Если вам нужен только один или два бита, лучше всего использовать сдвиг и маскировку.
В целом эта статья может быть вам полезна.
Другие советы
Для вашего процессора следует использовать ответ от Evan Teran. Я просто хотел упомянуть о битовой полосе некоторых других процессоров ARM, таких как Cortex-M3. Для некоторого региона ОЗУ / Периферийные устройства все биты отображаются на отдельный адрес для легкого доступа.
См. http: / /infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/Behcjiic.html для получения дополнительной информации.
Это просто, если вы можете получить доступ к регистру порта напрямую (у меня нет никакого опыта работы с ARM), просто поразрядно И это с двоичной маской, которая соответствует требуемому разряду:
var = (PORT_REGISTER & 0x00008000);
Теперь var содержит 0, если 15-й бит равен 0, или 0x00008000, если 15-й бит равен 1.
Кроме того, вы можете сдвинуть его, если хотите, чтобы у вас было «0» или «1»:
var = ((PORT_REGISTER & 0x00008000) >> 15);
Заголовочные файлы, которые поставляются с вашим компилятором, будут содержать объявления для всех регистров микроконтроллера и биты в этих регистрах.
В этой конкретной статье давайте представим, что регистр ввода порта называется PORTA
, а для нужного бита для него определена маска с именем PORTA15
.
Затем, чтобы прочитать состояние этого вывода:
PinIsSet = (PORTA & PORTA15) == PORTA15;
Или аналогичным образом, используя троичный оператор :
PinIsSet = (PORTA & PORTA15) ? 1 : 0;
В общем, обратитесь к справочному руководству, чтобы узнать, что делают все регистры и биты. Также посмотрите на некоторые примеры. ( Эта страница на веб-сайте Keil содержит и то, и другое. примеры в Интернете.)
В LPC2378 (как и в другом семействе микроконтроллеров LPC2xxxx ) порты ввода-вывода находятся в системной памяти, поэтому вам нужно объявить некоторые переменные следующим образом:
#define DALLAS_PIN (*(volatile unsigned long int *)(0xE0028000)) /* Port 0 data register */
#define DALLAS_DDR (*(volatile unsigned long int *)(0xE0028008)) /* Port 0 data direction reg */
#define DALLAS_PIN (1<<15)
Пожалуйста, обратите внимание, что 0xE0028000 - это адрес регистра данных порта 0, а 0xE0028008 - адрес регистра направления данных для порта 0.Вам нужно изменить это в соответствии с портом и битом, используемыми в вашем приложении.После этого в вашей функции code код или макросы для write 1, write 0 и read должны быть примерно такими:
#define set_dqout() (DALLAS_DDR&=~DALLAS_PIN) /* Let the pull-up force one, putting I/O pin in input mode */
#define reset_dqout() (DALLAS_DDR|=DALLAS_PIN,DALLAS_PORT&=~DALLAS_PIN) /* force zero putting the I/O in output mode and writing zero on it */
#define read_dqin() (DALLAS_DDR&=~DALLAS_PIN,((DALLAS_PORT & DALLAS_PIN)!= 0)) /* put i/o in input mode and test the state of the i/o pin */
Я надеюсь, что это может помочь.
С уважением!
Если вы проверяете биты, хорошо иметь в виду порядок оценки оператора C, например, Р>
if( port & 0x80 && whatever() )
может привести к неожиданному поведению, как вы только что написали
if( port & (0x80 && whatever()) )
но, вероятно, мент
if( (port & 0x80) && whatever() )