Сообщение от JekaKey
|
|
Что в итоге мы получаем в _RA1?
|
Получаем число, беззнаковый один байт, конкретно для _RA1 = 41.
Тут дело в следующем. Нужна была формализация обращения к портам как к элементам массива.
Вот порт PORTA, объявлен как переменная типа беззнаковый байт с фиксированным адресом 0x005. Аналогично для остальных портов.
|
Код:
|
static volatile unsigned char PORTA @ 0x005;
static volatile unsigned char PORTB @ 0x006;
static volatile unsigned char PORTC @ 0x007;
static volatile unsigned char PORTD @ 0x008;
static volatile unsigned char PORTE @ 0x009; |
То есть адреса 5, 6, 7, 8 и 9 легко укладываются в 1 байт и остаётся ещё куча места в байте.
Самая главная идея заключается в том, что обращаться к порту можно двояко
|
Код:
|
PORTA = 0x85;// просто записали 0x85 в переменную
или так
*(unsigned char *)0x05 = 0x85; // из числа 5 сделали
// указатель на байт и
// положили в этот байт 0x85 |
В обоих случаях компилятор HI-TECH выдаёт одинаковый результат.
|
Код:
|
MOVLW 0x85
MOVWF 0x5 |
Ну и всё. Теперь вместо конкретного числа 0х05 можно ставить элемент массива байтов arr[i]. Этот массив сначала заполнили адресами всех портов в нужном количестве и порядке. Потом по индексу массива где-нибудь в цикле можно писать и читать порты вторым способом, через указатель. Уже не вспоминая слова PORTx, а просто пользуя элементы массивы arr[i].
Далее. Обращение к битам портов. Биты объявлены, как переменные типа bit, например, для RA1
|
Код:
|
static volatile bit RA1 @ ((unsigned)&PORTA * 8)+1; |
Специфическая переменная типа bit, к сожалению её адрес нельзя присвоить указателю, нельзя объявить указатель на bit. То есть, как в случае с портом, адреса битов в массив не засунуть.
Поэтому предложен был такой способ. В массиве адресов arr[i] адреса подвинуть влево на 3, освободив 3 младших бита под номер бита в порте от 0 до 7. Имея ввиду, что сдвиг на 3 есть умножение на 8, получаем
|
Код:
|
#define _RA1 (unsigned char)&PORTA*8+1 |
При компиляции _RA1 будет заменено на 41, т.к адрес порта &PORTA = 5 и 5*8+1 = 41. Таким образом определив все возможные биты всех портов от RA0 до RE7 как числа от 40 до 79, заполняем массив нужных нам битов в начале программы.
Затем при обращении к битам через элемент массива, в спец.функции сначала восстанавливаем адрес порта, сдвигая значение элемента массива обратно вправо на 3. Делаем из результата сдвига указатель на байт (второй способ обращения к порту). Потом выделяем 3 младших бита с помощью операции AND 0x07, и сдвигаем единичку 0х01 на полученное число шагов. Попадаем на нужный бит в полученном байте.
Обращение к биту таким образом получается, конечно, гораздо дольше.
Можно сравнить тот же HI-TECH компилятор.
Ассемблер в результате компиляции для установки бита через RA1 занимает 3 строчки
|
Код:
|
// RA1 = 1;
BCF 0x3, 0x5
BCF 0x3, 0x6
BSF 0x5, 0x1 |
а установка через функцию UpdateBit(0,1) - около сотни строк.