PIC C18: Чтение битов из байта

У меня очень элементарный вопрос. Однако, что бы я ни пробовал, я не смог успешно реализовать это.

У меня есть сдвиговый регистр (74LS164), подключенный к PIC18F2550. со следующей аппаратной конфигурацией:

// Data pin
#define SCLCD_DATA          LATBbits.LATB7
#define SCLCD_DATA_TRIS     TRISBbits.TRISB7

// Clock pin
#define SCLCD_CLOCK         LATBbits.LATB6
#define SCLCD_CLOCK_TRIS    TRISBbits.TRISB6

Светодиоды подключены к выходным контактам 74LS164 для просмотра его состояния. У меня есть 8-битная переменная, объявленная как unsigned char. Я хочу отправить биты этой переменной в регистр сдвига. Сдвиговый регистр имеет внутренние триггеры, выходы которых обозначены как Q0-Q7. Первый отправленный бит загружается в Q0, когда вы отправляете второй бит, предыдущий Q0 смещается в Q1, а вновь отправленный бит поступает в Q0, и это продолжается по мере того, как вы отправляете последующие биты. Когда отправка завершена, младший бит переменной должен находиться в Q0 сдвигового регистра, а старший бит — в Q7.

Мой код такой (язык C18):

void SCLCD_SendSerialBits(unsigned char unRegister)
{
    // ucRegister is always passed as 0b10101010 for test
    for (i=0; i<8; i++)
    {
        SCLCD_CLOCK = 0;
        SCLCD_DATA = ((ucRegister & 0b10000000) == 0b10000000) ? 1 : 0;
        ucRegister = ucRegister << 1;
        SCLCD_CLOCK = 1;
    }
}

Приведенный выше код не работает так, как я хочу. Когда я запускаю его, все светодиоды горят, как будто я загрузил 0b11111111 в переменную ucRegister.

Тем не менее, следующий работает очень хорошо:

void SCLCD_SendSerialBits(void)
{
    SCLCD_CLOCK = 0;    SCLCD_DATA = 1;     SCLCD_CLOCK = 1;
    SCLCD_CLOCK = 0;    SCLCD_DATA = 0;     SCLCD_CLOCK = 1;
    SCLCD_CLOCK = 0;    SCLCD_DATA = 1;     SCLCD_CLOCK = 1;
    SCLCD_CLOCK = 0;    SCLCD_DATA = 0;     SCLCD_CLOCK = 1;
    SCLCD_CLOCK = 0;    SCLCD_DATA = 1;     SCLCD_CLOCK = 1;
    SCLCD_CLOCK = 0;    SCLCD_DATA = 0;     SCLCD_CLOCK = 1;
    SCLCD_CLOCK = 0;    SCLCD_DATA = 1;     SCLCD_CLOCK = 1;
    SCLCD_CLOCK = 0;    SCLCD_DATA = 0;     SCLCD_CLOCK = 1;
}

Что не так с моим кодом? Я думаю, что ошибка, скорее всего, будет в строке SCLCD_DATA = ((ucRegister & 0b10000000) == 0b10000000) ? 1 : 0;, но сколько бы я ни смотрел на нее, она выглядит совершенно нормально для меня. Что не так с моим кодом?

Любая помощь будет оценена.


person hkBattousai    schedule 05.02.2012    source источник
comment
Запустите код через симулятор MBLAB, и биты включаются и выключаются, как и ожидалось. Я бы посоветовал вам сделать то же самое, чтобы убедиться, что ваша версия компилятора генерирует инструкцию, которая включит выходные данные, как и ожидалось. Если компилятор генерирует плохой код, я бы обновился до последней версии компилятора. Если симулятор работает нормально, значит, происходит что-то более зловещее. Может дело в сроках? Ваш код, который работает, будет тактировать сдвиговый резистор намного быстрее, чем код, который не работает. Тем не менее, я бы подумал, что более быстрый код потерпит неудачу раньше, чем более медленный.   -  person user957902    schedule 08.02.2012


Ответы (2)


Ваш код выглядит так, как будто он должен работать. Я бы написал это так, чтобы было более читабельно и эффективно (при условии, что в вашей системе есть переключатель ствола):

for (i=7; i>=0; i--)
{
    SCLCD_CLOCK = 0;
    SCLCD_DATA = ((ucRegister >> i) & 1);
    SCLCD_CLOCK = 1;
}

Для систем без переключателя ствола вариант вашего кода

unsigned char ucMask = 0x80;

    for (i=0; i<8; i++)
    {
        SCLCD_CLOCK = 0;
        SCLCD_DATA = (ucRegister & ucMask) ? 1:0;
        ucMask >>= 1;
        SCLCD_CLOCK = 1;
    }

Если мой первый или второй примеры работают, то похоже, что компилятор не обрабатывает константные значения или правильно сравнивает исходный код.

person BitBank    schedule 06.02.2012

Возможно, это просто опечатка, но ваш параметр unRegister, а не ucRegister. Возможно ли, что ucRegister является глобальным значением 0b11111111?

person Martin    schedule 07.02.2012