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