Set clear bits in IO expander using I2C protocol.

Go To Last Post
32 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone!

 

I am making baby steps in programming and I am starting to love it.

Hope to get some help setting and clearing bits.

Somehow I made IO expander (TCA9535-16 bit) working properly but I have no idea how to set/clear bit without disturbing other bits.

I understand general idea of doing it but not using I2C protocol.

Also, I use IO expander in inverted output mode only so to clear entire byte I use 0xFF.

Here is a part of the code to test the outputs:

 

void Exp_Test (uint16_t data) 
 {
     TWI_init_master();
     TWI_start();
     TWI_write_address(0x40);  //device address 
     TWI_write_data(0x06);     //Conf.PORT1
     TWI_write_data (data);       
     TWI_stop();
 }

 

So, I have 2 rows of 8 LED's. By sending 0xFF to the port 1 of IO expander I have 1 on outputs which turns OFF 8 LED's.

 

while(1)
    
        if ((PINC & (1<<1))==0) //Button1
        {
           Exp_Test (0xFF); // 8 bits in PORT1 are set - LED's are OFF
        }        

        else if ((PINC & (1<<2))==0) //Button2 
        {
            Exp_Test (0x00); // 8 bits are clear- LED's are ON
        }
            
    return(0);

 

I need to set /clear bits one at the time.

Any help would be very appreciated.

 

Thanks!

 

This topic has a solution.
Last Edited: Thu. Apr 1, 2021 - 03:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To accomplish your goal, call Exp_Test with a variable instead of a constant.  Use logic or a table of some kind to determine the value of the variable.

 

In consideration of others, please RTFM!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JP, Thank you very much for guidance. 

Little code sample would be helpful....

In the meantime time I will open a book :)

Thanks again!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

adamski73 wrote:
TCA9535

This: https://www.ti.com/product/TCA9535 ?

 

So the Datasheet: https://www.ti.com/lit/ds/symlink/tca9535.pdf

 

jpmargis wrote:
 I have no idea how to set/clear bit without disturbing other bits.

From the datasheet, you can see that it only allows reading or writing complete registers - so you will have to keep a 16-bit variable, manipulate the bits in it as required, then update the complete register in the expander.

 

Note that this has nothing specifically to do with the AVR - it would be the same for any microcontroller.

 

EDIT: Did you see TI's software pack for the chip:  I/O Expander Software and Firmware Package (Rev. A) SLVC564A.ZIP  ?

 

Here's a tutorial on bit manipulation in C:

 

https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101

 

Please see Tip #1 in my signature, below, for how to properly post source code:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Mar 19, 2021 - 08:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

adamski73 wrote:
void Exp_Test (uint16_t data) 
 {
     TWI_init_master();
     TWI_start();

     :

     :
}

You shouldn't need to TWI_init_master(); every single time you write to the device - just do it once at startup

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Sadly you have not told us which AVR or what TWI library it is you are using. But in:

void Exp_Test (uint16_t data) 
 {
     TWI_init_master();
     TWI_start();
     TWI_write_address(0x40);  //device address 
     TWI_write_data(0x06);     //Conf.PORT1
     TWI_write_data (data); 

I rather suspect the API for TWI_write_data() may actually be:

??? TW_write_data(uint8_t data);

If it does just take uint8_t then why is Exp_test being passed a uint16_t ?

 

Anyway reading the datasheet it seems to me:

that is you want to drive 16 output pins what you need is:

 

0x40

0x06

0x00 // conf port 0 set these 8 to output

0x40

0x07

0x00 // conf port 1 set the other 8 to output

0x40

0x02

0xAA // 8 lower bits set to 0xAA pattern

0x40

0x03

0x55 // upper 8 bits to 0x55 pattern

 

Or something along these lines. As it stands you just do:

     TWI_write_address(0x40);  //device address 
     TWI_write_data(0x06);     //Conf.PORT1
     TWI_write_data (data);       

so if "data" is 0xFF you are setting the lower 8 bits to input . When you send data=0x00 you are simply switch the pins to be outputs (but the actual output register for that port presumably remains at a 0x00 default so nothing will likely be seen to happen).

 

As you always send the 0x40 address then a register address and a data byte I would suggest something long the lines of:

void Exp_WriteReg (uint8_t reg, uint8_t data) 
 {
     TWI_start();
     TWI_write_address(0x40);  //device address 
     TWI_write_data(reg);     //Conf.PORT1
     TWI_write_data (data);       
     TWI_stop();
 }

then something like:

enum {
    EXP_INP0 = 0,
    EXP_INP_1,
    EXP_OUT0,
    EXP_OUT1,
    EXP_POL0,
    EXP_POL1,
    EXP_CONF0,
    EXP_CONF1
} exp_command_e;

uint8_t reg0bits = 0xAA;
uint8_t reg1bits = 0x55;

int main(void) {
    TWI_init_master();
    Exp_WriteReg(EXP_CONF0, 0x00); // 0 bits to output
    Exp_WriteReg(EXP_CONF1, 0x00); // 1 bits to output
    while(1) {
        Exp_WriteReg(EXP_OUT0, reg0bits);
        Exp_WriteReg(EXP_OUT1, reg1bits);
    }
}

I have split the holding of the two sets of 8 bits to two variables called reg0bits and reg1bits. You could have a single 16 bit variable:

uint16_t regibits = 0xAA55;

then the output writes would be something like:

    while(1) {
        Exp_WriteReg(EXP_OUT0, regbits & 0xFF);
        Exp_WriteReg(EXP_OUT1, regbits >> 8);
    }

If the variable contains 0xAA55 and now you just want to change one or two of the bits then something like:

regbits &= ~(1 << 15); //Clear top bit in first A
regbits |= (1 << 1); //bottom 5 comes 7

after this 0xAA55 is now 0x2A57. Follow Andy's "101" link in #4 if you don't know why this is.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys,

Thank you so much for the info. I got little constipated with it so I need time to digest it properly :) 

I will do few tests and I will post results.

I wish you all a happy day!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, thank you again for the post. However, by sending 2 bytes together(0xXXXX) the firs one will have to be 0x02 or 0x03 which is one of the output plus lets say 0xAA.

So, if I want to update 16 inputs/outputs, I need to send 4 bytes in total. Am I thinking correctly? 

Well, what about device address? That is another byte....and what about configuration? Do I have to send 4 bytes in total to update one single LED and 8 bytes if I want to update all IO?

I will try to write a test code with 4 buttons to turn ON/OFF 2 LED's. If I will make it work I will poste the code...I know, it sound simple but not for me :) 

I like challenge! Ha! 

By the way I use Atmel Studio 7.0 and Atmega32A for this project....

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Port Expanders tend to have "convenient" modes.

e.g. for updating a single 8-bit port or for updating the whole 16-bit set.

 

Say what you really want to do.

Then we can advise the most efficient way.

 

If you just want to blink a few LEDs or monitor a few switches,  health and efficiency is unimportant.

Just keep it simple.    One universal function.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With that much "what about" looks like you don't even know how I2C protocol works?

I don't know why I'm still doing this hobby

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For getting started with I2C from scratch, see: https://www.avrfreaks.net/commen...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


 

adamski73 wrote:
if I want to update 16 inputs/outputs, I need to send 4 bytes in total. Am I thinking correctly? 

What does the datasheet tell you?

 

You need to study the  TCA9535 datasheet to see how to send stuff to it.

 

EDIT

 

The datasheet shows you how to write both output registers - ie, all 16 output pins:

 

 

EDIT 2

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Mar 23, 2021 - 09:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

adamski73 wrote:

Hi, thank you again for the post. However, by sending 2 bytes together(0xXXXX) the firs one will have to be 0x02 or 0x03 which is one of the output plus lets say 0xAA.

So, if I want to update 16 inputs/outputs, I need to send 4 bytes in total. Am I thinking correctly? 

Well, what about device address? That is another byte....and what about configuration? Do I have to send 4 bytes in total to update one single LED and 8 bytes if I want to update all IO?

I will try to write a test code with 4 buttons to turn ON/OFF 2 LED's. If I will make it work I will poste the code...I know, it sound simple but not for me :) 

I like challenge! Ha! 

I showed you pretty much all you need in #6 (and Andy reiterated some of that in #12). Which bit of that did you not understand?

 

As I showed you each write to the device is basically a 3 byte transfer (if you count the address as one byte):

void Exp_WriteReg (uint8_t reg, uint8_t data) 
 {
     TWI_start();
     TWI_write_address(0x40);  //device address 
     TWI_write_data(reg);     //Conf.PORT1
     TWI_write_data (data);       
     TWI_stop();
 }

If you are only interested in output there's basically 4 registers you need to write - two for direction, two for output state. The pins are in two groups of 8 so one direction and one output register control the state of 8 pins. This isn't really much different to DDRX and PORTx in the AVR itself. I would get familiar with how you do individual pin control with those first, then translate what you learn there to setting the distant pins in the 9535 as it's just a little bit more complex.

 

Do NOT move on to the 9535 stuff until you understand how to change just one bit in a whole byte for a PORTx register (this means knowing what "|= (1 << n)" and "&= ~(1 << n)" are doing as explained in the 101 tutorial in the Tutorial Forum)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
get familiar with how you do individual pin control with those first, then translate what you learn there to setting the distant pins in the 9535 as it's just a little bit more complex.

 

Do NOT move on to the 9535 stuff until you understand how to change just one bit in a whole byte for a PORTx register [in the AVR itself]

Absolutely!

 

It is always best to try to solve just one problem at a time.

 

explained in the 101 tutorial in the Tutorial Forum

This: https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you soo much! You the best!

I got already the idea of data transfer and bit shifts. 

I was little confused but you cleared my mind. 

Now I need to test it and move to another stage which is timers setup.

One step at a time....and I will code like a boss! :D

Thank you again for your support and your time!

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Hello Clawson, Its me again :)

Once configuration for PORT0 and PORT1 is set, in my case 0x06 plus 0x00 and 0x07 plus 0x00 for each register as output, than 2 bytes of data should be sent 

to make any change in each output.

By sending 2 bytes to the expander, the firs one is reserved to let's say PORT1 which is 0x03 and the next byte controls 8 outputs. 

After that stop is sent. To update those 8 outputs always the 0x03 has to be sent plus additional byte. 

I think keeping two variables separate makes the code easier to read (at least for me) 

Now, when the variable becomes updated? Each time I clear/set a bit this variable should change too...

How it should be declared and where exactly? Isn't supposed to be global? 

Is it a good idea to write a function for each output? 

Let's say " void LED1_ON(void)" and "void LED1_OFF(void)? This way the main code would be easier to read/understand.

To operate 16 LED's independently do I have to write 32 functions....Is this the way to go?

Please help me with this variable so I will move forward....

 

Thank you!

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The code below shows better what I am trying to do. 

 

void LED1_ON (void) 
{
    TWI_start();
    TWI_write_address(0x40);         
    TWI_write_data(0x02);    // Port0
    TWI_write_data( ?????? );  // how to set bit
    TWI_stop();
}
void LED1_OFF (void)
{
    TWI_start();
    TWI_write_address(0x40);
    TWI_write_data(0x02);    // Port0
    TWI_write_data( ?????? );  // how to clear bit
    TWI_stop();
}

int main (void) 
{
    TWI_init_master();
    TWI_start();
    TWI_write_address(0x40); // device address
    TWI_write_data(0x06);    // conf. for Port0
    TWI_write_data(0x00);    // conf. as output
    TWI_stop();
    TWI_start();
    TWI_write_address(0x40); 
    TWI_write_data(0x07);    // conf. for Port1
    TWI_write_data(0x00);    // conf. as output
    TWI_stop();
    
    TWI_start();
    TWI_write_address(0x42); // device address
    TWI_write_data(0x06);    // conf. for Port0
    TWI_write_data(0x00);    // conf. as output
    TWI_stop();
    TWI_start();
    TWI_write_address(0x42);
    TWI_write_data(0x07);    // conf. for Port1
    TWI_write_data(0x00);    // conf. as output
    TWI_stop();
    
        
   while(1)
         
        if ((PINC & (1<<1))==0) 
        {  

         _delay_ms(1000);
         LED1_ON();   
         LED4_ON();
         LED10_OFF();
        }    
        else if ((PINC & (1<<2))==0)
        {    

        _delay_ms(1000);
        LED1_OFF();
        }
        else if ((PINC & (1<<3))==0)
        {   

        _delay_ms(1000);
        LED1_ON();
        LED2_ON();
        LED16_OFF();
        LED32_ON();
        }

 

Sorry, i couldn't find a way to past the code properly...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

adamski73 wrote:
Sorry, i couldn't find a way to past the code properly...

Instructions are in my signature, below - see Tip #1 (this was mentioned in post #4)

 

However, if you're on a phone or tablet, the button for the Code Editor may not appear unless you request the  'Desktop' view.

 

For this kind of stuff, a "real" computer is certainly easier, IMO.

 

EDIT

 

and Signatures may also not appear on Mobile devices.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Apr 1, 2021 - 07:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

adamski73 wrote:
    TWI_write_data( ?????? );  // how to set bit
Well once you have addressed the actual port register this is know different than writing to PORTB or PORTD on an AVR without all the added expander\TWI nonsense.

 

I did say:

clawson wrote:

This isn't really much different to DDRX and PORTx in the AVR itself. I would get familiar with how you do individual pin control with those first, then translate what you learn there to setting the distant pins in the 9535 as it's just a little bit more complex.

 

Do NOT move on to the 9535 stuff until you understand how to change just one bit in a whole byte for a PORTx register (this means knowing what "|= (1 << n)" and "&= ~(1 << n)" are doing as explained in the 101 tutorial in the Tutorial Forum)

So how would you set bit 5 in PORTB of some AVR ?

 

That is the same value that you write to the port expander to set it 5 in one of its two 8 bit ports.

 

Of course when you set bit 5 for the AVR port you probably do an implied "read-modify-write". Something like:

PORTB |= (1 << 5);

which as you will know is simply shorthand for:

PORTB = PORTB | (1 << 5);

which effectively means "start by reading what is in the PORT first. then set bit 5 in that, then write it back to the port (that is the read-modify-write). Now I have not checked whether the port expander even lets you read current port status but if it id you would need to do the same - one TWI transaction to read the current 8 bits. then some OR/AND operation to set or clear bits of interest, then another TWI transaction to write this updated value back to the expander. One way round this (to avoid the need to read back) is to keep a cached copy of all 8 bit in a variable. Then when you want to change bits you do the R-M on your cached copy and then a single W to the port expander.

 

But all this added complexity is exactly why I said learn to do this kind of stuff on the AVRs own DDRx/PORTx registers and pins first. When you understand the concepts (like how a bit is cleared or set) then you can take this knowledge to the more complex port expander set up.

 

Walk before you can run !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Now I have not checked whether the port expander even lets you read current port status but if it id you would need to do the same - one TWI transaction to read the current 8 bits. then some OR/AND operation to set or clear bits of interest, then another TWI transaction to write this updated value back to the expander. One way round this (to avoid the need to read back) is to keep a cached copy of all 8 bit in a variable. Then when you want to change bits you do the R-M on your cached copy and then a single W to the port expander.

 

I did not find anything in data sheet about reading the status of current 8 bits. So, how to keep a cached copy of 8 bit in variable? That's what I am looking for. At the start all outputs should be cleared and that's already should be kept in variable which later can be used to R-M and finally W to the port expander. Looks like I will be stuck for a while...:) 

 

Thank you for all your help!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Awneil, thank you for the info!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Example for set output every bit.
.
Edit: remove typo and re-set the c files

Attachment(s): 

I don't know why I'm still doing this hobby

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

MicroGyro, but that is just doing a complete 8 bit write. It still leaves the question of how individual bits might be switched on/off. But the idea of a "cached" copy of the port state which can be changed and then written would work for this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

MicroGyro, but that is just doing a complete 8 bit write.


But the register is 8 bit?
I don't follow.
.
clawson wrote:
It still leaves the question of how individual bits might be switched on/off.

Isn't my example show that? Turn on each bit?
The previous bit set can be leave on or off depends on the value given.
.

clawson wrote:
But the idea of a "cached" copy of the port state which can be changed and then written would work for this.

As input?

I don't know why I'm still doing this hobby

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

adamski73 wrote:
how to keep a cached copy of 8 bit in variable?

 

int main( void )
{
    uint8_t port_0_value = 1;
    uint8_t port_1_value = 2;

    send_to_expander_port_0( port_0_value );
    send_to_expander_port_1( port_1_value );

    // at this point, the two variables retain their values

    // set the top bit in the Port 0 value, leaving all others unaffected
    port_0_value |= 0x80

    // update the port expander
    send_to_expander_port_0( port_0_value );

    // at this point, the variables retain their values
    :
    :
    etc
}

 

Looks like I will be stuck for a while...:) 

Looks like you really need to spend some times on the basics of C programming before complicating the issue with I2C and other such things.

 

This is why it's often recommended to start by learning the language itself on a PC.

 

As already noted,  solve just one problem at a time!

 

Here are some C learning & references materials for you:

 

https://blog.antronics.co.uk/2011/08/08/so-youre-thinking-of-starting-with-c/

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Apr 1, 2021 - 03:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wooohooo! Now everything makes sense. Looks easy to me. Now I have to test it. Thank you sooo much Awneil! I really appreciate it! heartsmiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes! I need to study C intensely! I have jumped to I2C without knowing how to use variable Hahahaha! That's me! laugh

Thanks again!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MicroGyro wrote:

Isn't my example show that? Turn on each bit?

But all you are doing it writing:

 

0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80

 

(I did wonder why the for() limit was 9 not 8 by the way! ;)

 

But say the port currently has 0xAA being output and you want to set bit 6 and clear bit 1, how would you do that?

 

As I outlined above you'd really need do something like:

uint8_t portval;

portval = I2C_read_port(); // read 0xAA currently there
portval |= (1 << 6);       // changes to 0xEA
portval &= ~(1 << 1);       // changes to 0xE8
I2C_write_port(portval);   // write back

However this relies on being able to read the current state in the device and also has the over-head of a read being needed before bits can be changed.

 

As Andy just demonstrated in #25 a way around this is:

uint8_t portval = 0xAA;

portval |= (1 << 6);       // changes to 0xEA
portval &= ~(1 << 1);       // changes to 0xE8
I2C_write_port(portval);   // write back

and similarly for all further on/off changes you just do the bit manipulation on the locally held "portval" then just over-write what is already in the device each time.

 

EDIT putting in the '~' that somehow got over-looked previously!

Last Edited: Thu. Apr 1, 2021 - 06:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I finally got entire concept. Now I have to practice it. I mean master it! :D 

Thank you Clawson for all the info you have provided!

I love you all! heartlaugh

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The "~" is for my testing to invert the all output only, should be erased.
.
The loop is 9 because it'll leave the last bit on if only 8 count.
.
As my example write only because the post #17

I don't know why I'm still doing this hobby

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In binary you count 8 as 0..7 not 0..8 ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ops... My bad

I don't know why I'm still doing this hobby