Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 5330

C/C++ • Can't get MCP23017 Inputs working consistently with C

$
0
0
Thanks for taking the time to read, it is a long read but I tried to document thoroughly. Also, is this the best forum to post this in or is there a better one for this subject? I've gone through all the old forums and data sheets and am close but still missing something. Everything works well with outputs (both command line and program). The inputs are where I'm having the issues.

First off, I do have IOCON set correctly I think (0x60) and it sequences through each bank but I can't figure out how to directly know which bank is what. A second problem just started happening and I'm not sure what I did to start it. The program starts by reading some other register (getting a 0xFA), not sure which one but once I do a command line read from another terminal window, it syncs up and sequences between the banks. But again, I'm not sure how I know which bank is each read.

Command line calls

sudo i2cdetect -y 1
This is what I get (running 3 chips)

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 21 22 -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --                        

Set to inputs.
sudo i2cset -y 1 0x20 0x00 0xff

This is what I get which is correct. Once I do this, the program gets the correct data for banks A & B.
sudo i2cget -y 1 0x20 0x12
0xf0

Here is a sample of the output from the program. I did a command line read of 0x12 from the other terminal at line 14 in the output and it started reading the correct banks. 0xF0 is Bank A and 0xFE is Bank B. If I do a command line read of 0x13, the banks are reversed in the output.

One thing I don't understand is the difference between the command line read and the program read, Since it is I2C, the chip shouldn't know the difference.

MCP0 FA FA 12
MCP0 FA FA 13
MCP0 FA FA 14
MCP0 FE F0 15
MCP0 FE F0 16
MCP0 FE F0 17
MCP0 FE F0 18

I simplified the code and here it is.

Code:

#include "mcp23017.h"#define MCP0_ADDR 0x20#define MCP1_ADDR 0x21//#define MCP2_ADDR 0x22#define IODIRA 0x00#define IODIRB 0x01#define IPOLA  0x02#define IPOLB  0x03#define IOCON  0x0A#define GPPUA  0x0C#define GPPUB  0x0D#define GPIOA  0x12#define GPIOB  0x13#define OLATA  0x14#define OLATB  0x15#define INPUT 0xFF#define OUTPUT0x00#define PULLUP 0xFA#define ALLOFF 0xFF#define MCP_WRITE 0static const char *device = "/dev/i2c-1";uint8_t buffer0[2]; uint8_t buffer1[2]; //uint8_t buffer2[2]; int mcp0;int mcp1;//int mcp2;uint32_t ulCounter = 0;int mcp_init(void) {   // Initialize 1st MCP23017 with 0x20 address:   mcp0 = open(device, O_RDWR);   ioctl(mcp0, I2C_SLAVE, MCP0_ADDR);   // Initialize 2nd MCP23017 with 0x21 address:   mcp1 = open(device, O_RDWR);   ioctl(mcp1, I2C_SLAVE, MCP1_ADDR);#if MCP_WRITE   // Initialize 3rd MCP23017 with 0x22 address:   mcp2 = open(device, O_RDWR);   ioctl(mcp2, I2C_SLAVE, MCP2_ADDR);#endif   // IOCON Chip 0x20   buffer0[0] = IOCON;   buffer0[1] = 0x60;          // Bank 0, Seq disabled   write(mcp0, buffer0, 2);   // IOCON Chip 0x21   buffer1[0] = IOCON;   buffer1[1] = 0x60;          // Bank 0, Seq disabled   write(mcp1, buffer1, 2);   #if MCP_WRITE   // IOCON Chip 0x22   buffer2[0] = IOCON;   buffer2[1] = 0x60;          // Bank 0, Seq disabled   write(mcp2, buffer2, 2);#endif      // Direction Chip 0x20   buffer0[0] = IODIRA;   buffer0[1] = INPUT;   write(mcp0, buffer0, 2);    // set IODIRA to all inputs   buffer0[0] = IODIRB;   buffer0[1] = INPUT;   write(mcp0, buffer0, 2);    // set IODIRB to all inputs      // Direction Chip 0x21   buffer1[0] = IODIRA;   buffer1[1] = INPUT;   write(mcp1, buffer1, 2);    // set IODIRA to all inputs   buffer1[0] = IODIRB;   buffer1[1] = INPUT;   write(mcp1, buffer1, 2);    // set IODIRB to all inputs#if MCP_WRITE   // Direction Chip 0x22   buffer2[0] = IODIRA;   buffer2[1] = OUTPUT;   write(mcp2, buffer2, 2);    // set IODIRA to all outputs   buffer2[0] = IODIRB;   buffer2[1] = OUTPUT;   write(mcp2, buffer2, 2);    // set IODIRB to all outputs#endif   // Pullups Chip 0x20   buffer0[0] = GPPUA;   buffer0[1] = PULLUP;   write(mcp0, buffer0, 2);    // set IODIRA to all inputs   buffer0[0] = GPPUB;   buffer0[1] = PULLUP;   write(mcp0, buffer0, 2);    // set IODIRB to all inputs      // Pullups Chip 0x21   buffer1[0] = GPPUA;   buffer1[1] = PULLUP;   write(mcp1, buffer1, 2);    // set IODIRA to all inputs   buffer1[0] = GPPUB;   buffer1[1] = PULLUP;   write(mcp1, buffer1, 2);    // set IODIRB to all inputs   #if MCP_WRITE   // State Chip 0x22   buffer2[0] = GPIOA;   buffer2[1] = ALLOFF;   write(mcp2, buffer2, 2);    // set GPIOA to all off      buffer2[0] = GPIOB;   buffer2[1] = ALLOFF;   write(mcp2, buffer2, 2);    // set GPIOB to all off#endif}int main(void) {   // Initialize the chips:   mcp_init();   printf("init\n");   sleep(1);   while(1)   {      buffer0[0] = GPIOA;      buffer0[1] = 0xAA;      printf("MCP0 ");      if (read(mcp0, buffer0, 2) == 2)      {         printf("%02X %02X ", buffer0[0], buffer0[1]);      }      else      {         buffer0[0] = 0x00;         buffer0[1] = 0x00;         printf("failed ");      }      printf("%d\n", ulCounter++);      sleep(1);   }  return 0 ;}

Statistics: Posted by gjm27n — Sun Jan 19, 2025 4:25 pm — Replies 0 — Views 32



Viewing all articles
Browse latest Browse all 5330

Trending Articles