1. my note for pascalio with MCP23017 - 16 bit I/O expanding board.
2023.11.20 15:58
My note for pascalio/test/mcp23017_plain/project2.lpr file
{ Testing Unit i2c_dev with MCP23017 GPIO extender
Copyright (C) 2013 Simon Ameis, <simon.ameis@web.de>
This source is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This code is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
A copy of the GNU General Public License is available on the World Wide Web
at <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing
to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
}
{
This demo program shows how to use unit i2c_dev to access a simple device
like the MCP23017.
It assumes:
- MCP23017 is connected to I2C Port 1
- The device address is set to $20 by connecting all thre address pins to GND
- All A ports will be configured as input (connect to GND or +3V3)
- All B ports will be configured as output (connect them to a LED)
How to connect:
+---------+
(blink) LED<-| 1 28|->3V3 (read)
/| 2 27|->GND (read)
/ | 3 26|\
/ | 4 M 25| \
(blink) < | 5 C 24| \ whatever you want
\ | 6 P 23| / (will be read)
\ | 7 2 22| /
\| 8 3 21|/
3V3<-| 9 0 20|
GND<-|10 1 19|
|11 7 18|
SCL<-|12 17|->GND
SDA<-|13 16|->GND
|14 15|->GND
+---------+
}
program project2;
uses
i2c_dev, BaseUnix; // i2c_dev.pas unit is part of pascalio
const
// I2C bus to which the device is connected. /dev/i2c-# can be changed by hardware setting.
BUS_NAME = '/dev/i2c-1';
// mcp23017 device's default adress (as set by address pins)
ADDR = $20;
var
fileh: cint; // device handle
rval: LongInt; // variable used for reading from PortA $12
i: Integer; // dummy counter
begin
// open device file
fileh := FpOpen(BUS_NAME, O_RDWR); // same as FpOpen('/dev/i2c-1', O_RDWR); O_RDWR = read/write
if fileh < 0 then // if handle is not properly connected = FAILED
begin
writeln('Opening file ', BUS_NAME ,' failed: ',fileh); // screen display failed message
halt(1); // Quit.
end
else
WriteLn('Opening file ', BUS_NAME,' succeeded: ', fileh); // screen display success message
// set device address
if (FpIOCtl(fileh, I2C_SLAVE, Pointer(ADDR)) < 0) then // Assign address on handle failed
begin // pointing $20 address of '/dev/i2c-1'
writeln('Opening slave ', ADDR, ' failed.'); // screen display failed message
halt(1); // Quit.
end else
writeln('Opening slave ', ADDR, ' succeeded'); // screen display success message
// set Input/Output modes
rval := i2c_smbus_write_byte_data(fileh, $00, $FF);// GPIOA = INPUT, set portA's 8 pins input
rval := i2c_smbus_write_byte_data(fileh, $01, $00);// GPIOB = Output, set portB's 8 pins output
// gets input values from GPIOA, address $12 is used for accessing portA
rval := i2c_smbus_read_byte_data(fileh, $12); // read High/Low status from port A
writeln('Input Values A: ', rval); // screen display of port A (8 pins)
// blink GPIOB
for i := 0 to 5 do
begin // address $13 is used for accessing portB
i2c_smbus_write_byte_data(fileh, $13, $FF); // on = set all pins high on portB
FpSleep(1); // Sleep 1 second. Its unit is seconds. Use Sleep command for millisecond.
i2c_smbus_write_byte_data(fileh, $13, $00); // off = set all pins low on portB
fpsleep(1); // Sleep 1 second. Its unit is seconds. Use Sleep command for millisecond.
end;
// close file handle!
fpclose(fileh);
end.
// ================================================================= //
// ===== My Better Display of Binary Value ==================================== //
// ================================================================= //
// add strutils on uses clauses for inttobin(rval, 8);
// uses i2c_dev, BaseUnix, strutils;
// Connect one of the pin of PortA with one of the pin of PortB : to see value changes
// After each fpSleep(1), add following code
// rval := i2c_smbus_read_byte_data(fileh, $12);
// writeln('Input Values A: ', inttobin(rval, 8));
// This will produce status of 8 of PortA pins in binary format.
program MyTest01;
uses
i2c_dev, BaseUnix, strutils; // i2c_dev unit is part of pascalio.
// struitls is needed for inttobin(ival, 8) display
const
// I2C bus to which the device is connected. /dev/i2c-# can be changed by hardware setting.
BUS_NAME = '/dev/i2c-1';
// mcp23017 device's default adress (as set by address pins)
ADDR = $20;
var
handle_mcp23017 : cint; // device handle
readingVal : LongInt; // variable used for reading from PortA $12 or PortB $13
i: integer; // dummy counter
begin
// First, assign the handle to the device
handle_mcp23017 := FpOpen(BUS_NAME, O_RDWR); // FpOpen('/dev/i2c-1', O_RDWR); readable & writeable
if handle_mcp23017 < 0 then // if handle is not properly connected = FAILED
begin
writeln('Opening file ', BUS_NAME ,' failed: ', handle_mcp23017); // screen display failed message
halt(1); // Quit.
end;
WriteLn('Opening file ', BUS_NAME,' succeeded: ', handle_mcp23017); // screen display success message
// set device address : pointing $20 address of '/dev/i2c-1'
if (FpIOCtl(handle_mcp23017, I2C_SLAVE, Pointer(ADDR)) < 0) then // if Assign address on handle failed
begin
writeln('Opening slave ', ADDR, ' failed.'); // screen display failed message
halt(1); // Quit.
end;
writeln('Opening slave ', ADDR, ' succeeded'); // screen display success message
// set Input/Output modes
readingVal := i2c_smbus_write_byte_data(handle_mcp23017, $00, $FF);// GPIOA = INPUT, set portA's 8 pins input
// GPIOA = $00, Last $FF = %11111111 = all pins are for input,
readingVal := i2c_smbus_write_byte_data(handle_mcp23017, $01, $00);// GPIOB = Output, set portB's 8 pins
// GPIOB = $01, Last $00 = %00000000 = all pins are for output
// Now you can read from PortA since its all 8 pins are set for INPUT
readingVal := i2c_smbus_read_byte_data(handle_mcp23017, $12); // read High/Low status from port A which is $12
writeln('Input Values A: ', inttobin(readingVal, 8)); // Display result in binary format on screen
// blink GPIOB
for i := 0 to 5 do
begin // address $13 is used for accessing portB
i2c_smbus_write_byte_data(handle_mcp23017, $13, $FF); // on = set all pins high on portB
readingVal := i2c_smbus_read_byte_data(handle_mcp23017, $12); // read High/Low status from port A which is $12
writeln('Input Values A: ', inttobin(readingVal, 8)); // Display result in binary format on screen
FpSleep(1); // Sleep 1 second. Its unit is seconds. Use Sleep command for millisecond.
i2c_smbus_write_byte_data(handle_mcp23017, $13, $00); // off = set all pins low on portB
readingVal := i2c_smbus_read_byte_data(handle_mcp23017, $12); // read High/Low status from port A which is $12
writeln('Input Values A: ', inttobin(readingVal, 8)); // Display result in binary format on screen
FpSleep(1); // Sleep 1 second. Its unit is seconds. Use Sleep command for millisecond.
end;
// close file handle!
fpclose(handle_mcp23017);
end.
Multimedia video is in attached.