Yes, 0xFF00 and 0xFFFF shifted 10 to the right should both equal 0x3F if they're both unsigned. The standard says that right shifting a signed, negative number (in 2's compliment, that's any number with the left-most bit set) is implementation defined. That means that your compiler and my compiler could do different things and both be considered "correct", or conforming to the standard. The best bet is to make sure that you're doing this with unsigned variables and values.
It's a little tough with embedded systems to know exactly why this might be happening, since I don't know what PIC you're using and what your circuit looks like.
Yeah weird isnt it. I'm thinking that the bits it's bringing into int test as it shifts them alongto the right are all 1's?
Putting in things like that light up exactly how you would expect them to. PORTB = 1; // RB0 is lit up. Any direct specification like that works. I can set portb to output contects of 8 bit registers no problem, even 16 bit variables (but the most significant byte is chopped off). The only anomoly I have found is this bit shifting problem.
OK heres some progress...
This lights up RB7 only on PORTB as it should.Code:test() { unsigned int temp; temp = 0x80FF; // an 8 bit number in the upper byte of 16 bits temp = temp >> 8; // only 6 bits remain (0x3F) PORTB = temp; } void main() { initDigitalOut(); test(); }
Last edited by dannybeckett; 03-08-2011 at 12:02 PM.
Ok... try this...
You should see a single led walk across the row...Code:int y = 0x88; // 10001000 for (int x = 0; x < 8; x++) { y = y >> 1; PORTB = y; Sleep(1000); // delay 1 second }
What I'm particularly interested in is if it's going to shift the 1 in bit 4 back over to bit 7... As in perhaps your compiler (for some bizarre reason) is doing circular shifts...
Another test would be to divide 0xFFFF by 1024 and see what happens.
Yeah, sounds like your right shift is sign-extending, which means it takes whatever the leftmost bit is to fill it the spots emptied by the right shift. Try making the appropriate variables unsigned, and suffix your literal values with a U: 0xFFFFU.
A little more to add... I took the above program and shifted the bits incrementally from 8 to 16. As you would expect, the single LED traveled from RB7 to RB0 - then when I shifted it 16 times (expecting no LEDs to be lit) they all came on!
let me try your method tater, ill post back in 5
Ill try what you said anduril as well
OK I've done some relatively thorough testing and here are my results:
Code:#include <htc.h> #define _XTAL_FREQ 8000000 __CONFIG (FOSC_XT & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_OFF); void initDigitalOut() { PORTA = PORTB = PORTC = PORTD = 0; TRISA = TRISB = TRISC = TRISD = 0; ANSEL = ANSELH = 0; } test0() { int temp; int y = 0xFF; // 11111111 PORTB = y; __delay_ms(1000); for (int x = 0; x < 8; x++) { y = y >> 1; PORTB = y; __delay_ms(1000); } } test1() { int y = 0x88; // 10001000 PORTB = y; __delay_ms(1000); for (int x = 0; x < 8; x++) { y = y >> 1; PORTB = y; __delay_ms(1000); } } test2() { int y = 0x8888; // 1000100010001000 PORTB = y; __delay_ms(500); for (int x = 0; x < 16; x++) { y = y >> 1; PORTB = y; __delay_ms(500); } } test3() { int y = 0x7888; // 0111100010001000 PORTB = y; __delay_ms(500); for (int x = 0; x < 16; x++) { y = y >> 1; PORTB = y; __delay_ms(500); } } test4() { unsigned int y = 0x4888U; // 0100100010001000 PORTB = y; __delay_ms(500); for (int x = 0; x < 16; x++) { y = y >> 1; PORTB = y; __delay_ms(500); } } test5() { unsigned int y = 0x8888; // 1000100010001000 PORTB = y; __delay_ms(500); for (int x = 0; x < 16; x++) { y = y >> 1; PORTB = y; __delay_ms(500); } } void main() { initDigitalOut(); // test0(); // Worked fine. // test1(); // This worked fine. Bits shifted along nicely and the last loop outputted a fully-off PORTB. // test2(); // This worked fine until the most significant 1 appeared... It left a trail of 1s behind it! // test3(); // Worked fine. // test4(); // Worked fine. test5(); // Worked as expected. U suffix didn't seem to make a difference, unsigned did though. Tried all combinations of both. }
So there we have it! All is well (after some rejiggering of numbers). Seems that unsigned is what's making the difference here.
Last edited by dannybeckett; 03-08-2011 at 02:14 PM.
Ok... well done, good problem analysis...
So instead of defining variables as int (which is signed) use unsigned int
or if int is 32 bits on that uC, use unsigned short int for 16 bit values.
If your compiler supports the <stdint.n> header you can be very explicit with uint16_t which is a 16 bit unsigned integer.
Last edited by CommonTater; 03-08-2011 at 03:31 PM. Reason: added praise
yeah I can use stdint.h, thats awesome. Whats the _t for at the end?
I think it's just for "type".
I see, thanks for clearing all this crap up for me =D