MCP23016

by lnino on Tue Feb 26, 2013 2:07 pm

Hi at all.

I am working on my MCP23016 to get a button input working.

At now I am able to say if a pin is Output or Input.
I can also set them to High or Low.
In case of that I can turn on a LED. (see my code)

But I want to wire a button on f.i. GP1.1 and I want to be able to check if this button is either pressed or not.

I already set GP1.1 to Input, but I don't know how to check the button status. Pressed or not.

Did someone realised this or can help me?

I use the fleury i2cmaster library for this. (http://homepage.hispeed.ch/peterfleury/ ... tware.html)

Thanks for the help.
Attachments
ioexpander.c
(719 Bytes) Downloaded 43 times
lnino
 
Posts: 4
Joined: Mon Dec 17, 2012 10:22 am

Re: MCP23016

by adafruit_support_mike on Tue Feb 26, 2013 6:28 pm

The chip Adafruit sells is the MCP23017, which is slightly different from the MCP23016. They're both 16-channel I2C expanders, but some of the options are different.

If you do have the '17, Adafruit has a library made especially for that chip: https://github.com/adafruit/Adafruit-MC ... no-Library

If you're using the '16, or just prefer to stick with the Fleury code, the MCP23016 datasheet (http://ww1.microchip.com/downloads/en/D ... 20090C.pdf) tells you how to read the chip's registers in section 1.9.3 (page 15). It looks like the master sends a 'read' command (a zero bit on the end of the address byte) then a byte that identifies the register it wants to read. The list of 'command bytes' is Table 1-3 (page 4), and according to that, you send the byte '0' to get GP0 and the byte '1' to get GP1.
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.
User avatar
adafruit_support_mike
 
Posts: 7068
Joined: Thu Feb 11, 2010 1:51 pm

Re: MCP23016

by lnino on Wed Feb 27, 2013 5:29 am

Thanks for your reply and the explanation.

I made some evaluation boards fitting for MCP23016 therefore I would really like to go ahead with this IC.
But when I've done with it I will definately try another project with the MCP23017. The 17' is much faster. :-)

At the moment I will go forward with the fleury library.

I thought the adafruit library for MCP23017 and the wire library is only for arduino.

I am using a breadboard with ATmega168 and do code in ANSI C.

But now to the center of my question.

I tried to understand the section you highlighted in the manual, but was not able to write a code.
I think I could not interprete it the right way.

Maybe you can give me a code example according to the MCP23016, the fleury lib and my present code.

Thanks for your help.
lnino
 
Posts: 4
Joined: Mon Dec 17, 2012 10:22 am

Re: MCP23016

by adafruit_support_mike on Wed Feb 27, 2013 11:27 pm

lnino wrote:I thought the adafruit library for MCP23017 and the wire library is only for arduino.

Not really. The Arduino library is basically a set of utility routines for ATmega168 programming, mostly written in C. I think the Wire library is written in C++ for the sake of modularity, but aside from that, it's just a set of wrappers around I2C operations.

lnino wrote:Maybe you can give me a code example according to the MCP23016, the fleury lib and my present code.

I didn't know the Fleury library existed until yesterday, but it would probably look something like this:

Code: Select all
#define MCP23016    0x40
#define GP0         (unsigned char) 0
#define GP1         (unsigned char) 1

#   send the address:
i2c_start_wait( MCP23016 + I2C_WRITE );
i2c_write( GP1 );
i2c_stop();

#   read the data:
i2c_start_wait( MCP23016 + I2C_READ );
unsigned char gp1 = i2c_read_ack();
unsigned char gp2 = i2c_read_nak();


I was mistaken about the read process. You start by issuing a WRITE command and the address, then create the stop condition before sending any data. Then you issue a READ command and collect the data that's in the registers.
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.
User avatar
adafruit_support_mike
 
Posts: 7068
Joined: Thu Feb 11, 2010 1:51 pm

Re: MCP23016

by lnino on Fri Mar 08, 2013 10:32 am

Thanks for your reply.

Hmm, I am not sure If I understood this right.

Regarding to my code would it look like this? (At the moment I am not at my evaluatin board to test it)

Original Code:

Code: Select all
int main(void)
   
   {   
   i2c_init();                             // initialize I2C library
   
   SendData(0x06,0x00);               // Sets all Ports on GP0(0x06) to Output
   SendData(0x07,0xFF);               // Sets all Ports on GP1(0x07) to Input

       while(1)
       {
         Senddata(0x00,0x04);             //Sets GP0.2 to High, Rest to Low --> LED turns on  (0x00=GP0)
       }
   }
   
void SendData(uint8_t command, uint8_t port)
{
   i2c_start_wait(0x40);         // set device address and write mode
   i2c_write(command);
   i2c_write(port);
   i2c_stop();
}


Additional Function:

Code: Select all
void ReadData()
{
      i2c_start_wait(0x40 + ??);
      i2c_write(0x07);             //GP1
      i2c_stop();

      i2c_start_wait(0x40 + ??);
      unsigned char gp1 = i2c_read_ack();
      unsigned char gp2 = i2c_read_nak();
}


I used a question mark where I don't know which value I should use.
Did I get that right? Or this completely wrong?

And how do I check If the button is pressed?

Code: Select all
If (??? == ???)
{
   // Button is pressed - LED lights up
}
lnino
 
Posts: 4
Joined: Mon Dec 17, 2012 10:22 am

Re: MCP23016

by lnino on Sun Mar 10, 2013 6:50 am

I studied the datasheet and some sample codes.

Now I think I understood.

Because I am right now not at my evaluation board, this is an untested code:

Might this work?

Code: Select all
#define F_CPU 14745600
#include <stdio.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <util/delay.h>

#include "../libnerdkits/i2cmaster.h"

#define MCP23016   0x40

voaltile uint8_t inputregister;

void SendData(uint8_t, uint8_t);
uint8_t ReadData(uint8_t);

int main(void)
   
   {   
    i2c_init();                             // initialize I2C library
   
   SendData(0x06,0x00);               // Sets all Ports on GP0 to Output
   SendData(0x07,0xFF);               // Sets all Ports on GP1 to Input
 
       while(1)
       {
           inputregister = ReadData(0x06);                 // Reads Input on GP1
      
          if(inputregister == 0b00000010 ) // When Button GP1.1 is pressed
           {
                    // Do something         
           }

          elseif(inputregister == 0b00000100 ) // When Button GP1.2 is pressed
           {
                     // Do something         
           }

          elseif(inputregister == 0b00001000 ) // When Button GP1.3 is pressed
           {
                      // Do something         
           }
       }
   }   

uint8_t ReadData(uint8_t command)
{
  uint8_t  data;

  i2c_start_wait(MCP23016 | 0x00);      // Write
  i2c_write(command);               // GP0 or GP1
  i2c_stop();
            
  i2c_rep_start(MCP23016 | 0x01);      // Read
  data = i2c_readNak();
  i2c_stop();

  return data;
}

void SendData(uint8_t command, uint8_t port)
{
   i2c_start_wait(MCP23016);         // set device address and write mode
   i2c_write(command);
   i2c_write(port);
   i2c_stop();
}
lnino
 
Posts: 4
Joined: Mon Dec 17, 2012 10:22 am

Re: MCP23016

by adafruit_support_mike on Sun Mar 10, 2013 8:21 pm

That looks like the right sequence. The real test will be on the board though.
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.
User avatar
adafruit_support_mike
 
Posts: 7068
Joined: Thu Feb 11, 2010 1:51 pm

Re: MCP23016

by soerena on Wed Jun 26, 2013 4:55 am

MCP23016
by lnino » 26 Feb 2013 19:07

Hi at all.

I am working on my MCP23016 to get a button input working.

At now I am able to say if a pin is Output or Input.
I can also set them to High or Low.
In case of that I can turn on a LED. (see my code)

But I want to wire a button on f.i. GP1.1 and I want to be able to check if this button is either pressed or not.

I already set GP1.1 to Input, but I don't know how to check the button status. Pressed or not.

Did someone realised this or can help me?

I use the fleury i2cmaster library for this. (http://homepage.hispeed.ch/peterfleury/ ... tware.html)

Thanks for the help.



Hi, I'm using 3 10pf caps in parallel (instead of 1 33pf) on the clock pin 9 to GND. I was wondering if you have any idea if this would work? Obviously I can't get it working, but I don't know if it has anything to do with the cap value.

Søren
soerena
 
Posts: 51
Joined: Fri Nov 16, 2012 6:00 am

Re: MCP23016

by Zener on Wed Jun 26, 2013 8:11 pm

That would make 30pF which should be close enough to 33pF.
Zener
 
Posts: 2381
Joined: Sat Feb 21, 2009 1:38 am