Это неправильный код, и его можно сделать более простым и читаемым способом.
- Вам следует избавиться от двоичной записи, поскольку она трудна для чтения и не соответствует стандарту C.
- Вы должны читать аппаратные регистры только один раз и писать в них один раз. Доступ к одному и тому же регистру в длинной цепочке
if else if
, как это сделано здесь, является большим нет-нет. Состояние порта может меняться между чтениями.
При работе с любыми типами переключателей, будь то физические кнопки, DIP-переключатели, реле и т. Д., Вы должны обязательно реализовать какой-либо способ отвода сигнала . При нажатии кнопки происходит электромеханический отскок, который проявляется в виде шипа на линии до тех пор, пока он не станет устойчивым. Вы можете просмотреть это с помощью осциллографа, подключив одну сторону кнопки для питания через резистор, а другую сторону к земле.
Неспособность отклонить такой сигнал - очень распространенная ошибка для начинающих. Чаще всего это делается в программном обеспечении, несколько раз прочитав кнопку, прежде чем принять решение. Или через аппаратный RC-фильтр, но это требует дополнительных компонентов.
У вас должен быть такой код:
#define LED0 (1u << 0) // corresponding to PORTx:0
#define LED1 (1u << 1) // corresponding to PORTx:1
...
Затем вы можете объявить выходную матрицу, такую как эта:
const uint8_t LED_OUTPUT [16] =
{
[0] = LED1 | LED2 | LED3,
[1] = LED0 | LED2 | LED3,
...
};
Ввод считывается из PIND один раз, обрабатывается с помощью периодического чтения, возможно, с помощью простого цифрового фильтра (например, медиана 3 чтения), затем сдвигается на месте (смещение вправо на 4 шага), так что оно соответствует числу от 0 до 15:
uint8_t index = get_buttons(); // function that returns the debounced valued read from PIND
PORTB = LED_OUTPUT[index];
И это все.