Thread: creating a variable consisting of two other variables side by side

  1. #16
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by dannybeckett View Post
    0xFFFF shifted left 10 times should now read 0x3F the same as 0xFF00 would, or is that wrong? I'm assuming PORTB = temp in your example, unfortunately that didn't work either! all 8 LEDs lit up on PORTB and I dont know why.

    The reason why I text it on the MCU is because unexpected things like this happen so I want to make sure it runs fine on the controller before moving on. It's not so bad writing the code onto the controller anyway, takes max 10 seconds from the compile to chip execution.
    Yeah I did mean temp not test...

    Now comes the problem... why does it light all 8 leds...

    Your way or mine should only light 6 0x3f = 00111111

    Do other combinations work?
    For example if you did PORTB = 1; what happens?

  2. #17
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    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.

  3. #18
    Registered User
    Join Date
    Mar 2011
    Posts
    22
    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...

    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();
    }
    This lights up RB7 only on PORTB as it should.
    Last edited by dannybeckett; 03-08-2011 at 12:02 PM.

  4. #19
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by dannybeckett View Post
    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... try this...
    Code:
    int y = 0x88;                       // 10001000
    for (int x = 0; x < 8; x++)
      { 
         y = y >> 1;
         PORTB = y; 
         Sleep(1000);                // delay 1 second 
          }
    You should see a single led walk across the row...
    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.

  5. #20
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    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.

  6. #21
    Registered User
    Join Date
    Mar 2011
    Posts
    22
    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.

  7. #22
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    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

  8. #23
    Registered User
    Join Date
    Mar 2011
    Posts
    22
    yeah I can use stdint.h, thats awesome. Whats the _t for at the end?

  9. #24
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    I think it's just for "type".

  10. #25
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by dannybeckett View Post
    yeah I can use stdint.h, thats awesome. Whats the _t for at the end?
    It's a naming convention that is sometimes used for typedefs.
    bit∙hub [bit-huhb] n. A source and destination for information.

  11. #26
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by dannybeckett View Post
    yeah I can use stdint.h, thats awesome. Whats the _t for at the end?
    Because the guy who made the library thought it was fancy?

    Actually the guys are right... it means it's a typedef of another variable type.

  12. #27
    Registered User
    Join Date
    Mar 2011
    Posts
    22
    I see, thanks for clearing all this crap up for me =D

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. dark side of global variables
    By MK27 in forum C Programming
    Replies: 18
    Last Post: 12-09-2008, 03:14 AM
  2. A very long list of questions... maybe to long...
    By Ravens'sWrath in forum C Programming
    Replies: 16
    Last Post: 05-16-2007, 05:36 AM
  3. Creating one variable from two
    By Peter_D3T in forum C++ Programming
    Replies: 4
    Last Post: 06-20-2002, 01:39 PM
  4. creating a filename based on a variable
    By Waldo2k2 in forum C++ Programming
    Replies: 3
    Last Post: 05-22-2002, 05:27 PM
  5. Im so lost at . .
    By hermit in forum C Programming
    Replies: 18
    Last Post: 05-15-2002, 01:26 AM