I2C/MCP23017 version

// I2C/MCP23017 version, 2016-09-17

include <stdio.h>

include <stdlib.h>

include <linux/i2c-dev.h>

include <error.h>

include <sys/types.h>

include <sys/stat.h>

include <fcntl.h>

include <unistd.h>

int addr = 0x26; / 23017 chip I2C addr /
char *i2cbus= "/dev/i2c-0";

define D4 1 // 23017 GPB0

define D5 2 // 23017 GPB1

define D6 4 // 23017 GPB2

define D7 8 // 23017 GPB3

define BK_R 16 // 23017 GPB4

define BK_G 32 // 23017 GPB5

define BK_B 64 // 23017 GPB6

define RS 128 // 23017 GPB7

define EN_HI 0xFF // 23017 GPA7

define EN_LO 0x7F // 23017 GPA7

define IODIRA 0x00 // 23017 bit directions for GPIO-A

define IODIRB 0x01 // 23017 bit directions for GPIO-A

define OLATA 0x14 // 23017 output latch: GPIO-A

define OLATB 0x15 // 23017 output latch: GPIO-B

// commands

define LCD_CLEARDISPLAY 0x01

define LCD_RETURNHOME 0x02

define LCD_ENTRYMODESET 0x04

define LCD_DISPLAYCONTROL 0x08

define LCD_CURSORSHIFT 0x10

define LCD_FUNCTIONSET 0x20

define LCD_SETCGRAMADDR 0x40

define LCD_SETDDRAMADDR 0x80

// flags for display entry mode ( | LCD_ENTRYMODESET = 0x04 );

define LCD_ENTRYRIGHT 0x00

define LCD_ENTRYLEFT 0x02

define LCD_ENTRYSHIFTINCREMENT 0x01

define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control ( | DISPLAYCONTROL = 0x08 )

define LCD_DISPLAYON 0x04

define LCD_DISPLAYOFF 0x00

define LCD_CURSORON 0x02

define LCD_CURSOROFF 0x00

define LCD_BLINKON 0x01

define LCD_BLINKOFF 0x00

// flags for display/cursor shift ( | LCD_CURSORSHIFT = 0x10 )

define LCD_DISPLAYMOVE 0x08

define LCD_CURSORMOVE 0x00

define LCD_MOVERIGHT 0x04

define LCD_MOVELEFT 0x00

// flags for function set ( | LCD_FUNCTIONSET = 0x20 )

define LCD_8BITMODE 0x10

define LCD_4BITMODE 0x00

define LCD_2LINE 0x08

define LCD_1LINE 0x00

define LCD_5x10DOTS 0x04

define LCD_5x8DOTS 0x00

int i2c_fd, gpb, bklt=0;
unsigned char displaycontrol=0, displayfunction=0, displaymode=0;

wr_reg(unsigned char reg, unsigned char val) {
unsigned char buf[4];

buf[0]=reg;
buf[1]=val;
if ((write(i2c_fd, buf, 2)) != 2) {
fprintf(stderr,"Error writing 0x%x to reg 0x%x @ addr 0x%x on %sn",val,reg,addr,i2cbus);
exit(1);
}
}

pulse_en () {

    wr_reg(OLATA,EN_HI);
    usleep(2);
    wr_reg(OLATA,EN_LO);
    usleep(1);
    wr_reg(OLATA,EN_HI);
    usleep(2);

}

write1nibble(unsigned char nib) {

    wr_reg(OLATB,(bklt | (nib & 0xF)) );  // RS=high-bit => 0

    usleep(20);

    pulse_en();

    usleep(40);

}

writenibbles(unsigned char value, char mode) {

    unsigned char nib;

    //fprintf(stderr,"sending %X / %d]\n",value, mode);

    /* high nibble first */
    nib = (value >> 4);
    wr_reg(OLATB,(bklt | (nib & 0xF) | (mode ? 0x80 : 0x00)) );

    usleep(20);

    pulse_en();

    usleep(20);

    nib = (value & 0x0f);
    wr_reg(OLATB,(bklt | (nib & 0xF) | (mode ? 0x80 : 0x00)) );

    usleep(20);

    pulse_en();

    usleep(100);

}

message (char *msg) {
int j;

for (j=0; (msg[j]!=0); j++) {
if ((msg[j] == 'n' || msg[j] == 'r'))

    writenibbles(0xC0,0);  /* next line */

else writenibbles(msg[j],1);
}
}

main(int argc, char **argv) {

int i,s;

if (argc < 2) {

   fprintf(stderr,"usage: %s <bkcolor>\n",argv[0]);
   fprintf(stderr,"usage: %s <bkcolor> \"message\"\n",argv[0]);
   fprintf(stderr," -OR-  %s <bkcolor> <charnum1> <param2>...\n",argv[0]);
   exit(1);

}

bklt=((7 ^ atoi(argv[1])) << 4);

if ((i2c_fd = open(i2cbus, O_RDWR)) < 0) {

   fprintf(stderr,"Failed to open i2c port %s\n",i2cbus);
   exit(1);

}
if (ioctl(i2c_fd, I2C_SLAVE, addr) < 0) {

   fprintf(stderr,"Unable to get bus access to talk to addr %x on %s\n",addr,i2cbus);
   exit(1);

}

wr_reg (IODIRA,0x7F); // 0xFF & ~EN;
wr_reg (IODIRB,0x00); // all GPIO-B pins to output

if (argc == 2) {
wr_reg(OLATB,bklt);
exit(0);
}

/ init: enter & exit 8-bit mode to reset possible nibble misalignment... /
write1nibble(0x3);
usleep(5000);
write1nibble(0x3);
usleep(5000);
write1nibble(0x3);
usleep(1000);
write1nibble(0x2);
usleep(1000);

writenibbles(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS,0);
usleep(50);
writenibbles(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF,0); // 0x0C
usleep(50);
writenibbles(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT,0); // 0x06
usleep(50);

writenibbles(LCD_CLEARDISPLAY,0);
usleep(3200);

if (argc > 3) {
s=atoi(argv[2]);
for (i=s;i<(s+16);i++) writenibbles(i,1);
writenibbles(0xC0,0);
for (i=(s+16);i<(s+32);i++) writenibbles(i,1);
}
else
message (argv[2]);
close(i2c_fd);

return 0;
}

标签:none

添加新评论