2

I have a very elementary question. However, what ever I tried, I couldn't successfully implement this.

I have a shift register (74LS164) connected to PIC18F2550 with the following hardware configuration:

// 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

LEDs are connected to the output pins of 74LS164 to view its status. I have an 8-bit variable declared as unsigned char. I want to send the bits of this variable to the shift register. The shift register has internal flip-flops whose outputs are named as Q0-Q7. The first sent bit loads into Q0, when you send a second bit, previous Q0 shifts to Q1 and the newly sent bit comes to Q0, and this goes so on as you send succeeding bits. When the sending is completed, LSB of the variable is supposed to be on the Q0 of the shift register, and MSB will be on Q7.

My code is like this (Language is 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;
    }
}

The code above doesn't run as I want to. When I run it, all the LEDs light on, as if I had loaded 0b11111111 into the ucRegister variable.

However, the following one works very well:

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;
}

What is wrong with my code? I thing the error is most likely to be on the line SCLCD_DATA = ((ucRegister & 0b10000000) == 0b10000000) ? 1 : 0;, but no matter how much I look at it, it looks perfectly OK to me. What is wrong with my code?

Any help will be appreciated.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
hkBattousai
  • 10,583
  • 18
  • 76
  • 124
  • Ran the code through the MBLAB simulator and the bits turn on and off as expected. I would suggest u do the same to confirm that the your compiler version is generating instruction that will turn the outputs on as expected. If the compiler is generating bad code then I would upgrade to the latest complier relese. If the simulator works ok then somthing more sinister is going on. Could it be timing issues ? Your code that works is going to clock the shift resister much faster than the code that does not work. However, i would think thank the faster code would fail before the slower. – user957902 Feb 07 '12 at 23:55

2 Answers2

2

Your code looks like it should work. I would write it like this to be more readable and efficient (assuming your system has a barrel shifter):

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

For systems without a barrel shifter, a variation of your code

unsigned char ucMask = 0x80;

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

If my first or second examples work, then it sounds like the compiler is not handling the constant values or compares correctly in your original code.

BitBank
  • 8,500
  • 3
  • 28
  • 46
0

Might just be a typo, but your parameter is unRegister not ucRegister. Is it possible that ucRegister is a global which is 0b11111111?

Martin
  • 2,442
  • 14
  • 15