Code: Select all
================================
/*
* MOLCD.h
*
* Definitions for interfacing to the LCD.
*
*/
#ifndef MOLDC_h
#define MOLCD_h
#define DEFLCDADR 0x50
void LCDsetadr (int adr); /* Set the address of the LCD to be accessed */
void LCDwrite (int dat);
void LCDstr (char *dat);
int LCDread (void);
void LCDpos (int row, int col);
void LCDcursor (int type, int state);
void LCDhome (void);
void LCDleft (void);
void LCDright (void);
void LCDcls (void);
#define LCDBLOFF 0
#define LCDBLON 0xFF
void LCDbacklight (int state, int minutes);
#define LCDGPOON 0xFF
#define LCDGPOFF 0
void LCDgpo (int state, int chan);
void LCDcontrast (unsigned char val);
#endif /* LCD.h */
=======================================
/*
* Routines to access a Matrix Orbital LK202-25 2x20 LCD.
* They also work for a LK204-25, and probably most MO displays.
* These routines utilize the I2C interface.
*/
#include <string.h>
#include "\JKMicro\H\MOLCD.H"
#include "\JKMicro\H\I2C.H"
#define LCDCOMMAND 0xFE
static int LCD_adr = DEFLCDADR;
void LCDcommand (int cmd, int num, int arg1, int arg2) {
char buf[6];
buf[0] = LCDCOMMAND;
buf[1] = cmd;
buf[2] = arg1;
buf[3] = arg2;
I2Cwrite (LCD_adr, num + 1, buf);
}
/*
* Read the next (if any) character from the keypad.
*/
/* A B C D E F G H I J K L M */
char map[] = {'?','D','#','0','*','?','C','9','8','7','?','B','6',
/* N O P @ R S T U V W X Y Z */
'5','4','?','A','3','2','1','?','?','?','?','?','?'};
int LCDread (void)
{
char c[2];
I2Cread (LCD_adr, 1, c);
if (c[0] == 0) return 0;
return(map [c[0] - 'A']);
}
void LCDwrite (int dat) {
char buf [2];
buf [0] = (char) dat;
I2Cwrite (LCD_adr, 1, buf);
}
void LCDstr (char *dat) {
I2Cwrite (LCD_adr, strlen (dat), dat);
}
void LCDpos (int row, int col) {
LCDcommand (0x47, 3, col, row);
}
void LCDcursor (int type, int state) {
char c;
switch (type*2 + state) {
case 0: c = (0x4B); /* underline off */
case 1: c = (0x4A); /* underline on */
case 2: c = (0x54); /* block off */
case 3: c = (0x53); /* block on */
}
LCDcommand (c, 1, 0, 0);
}
void LCDhome (void) {
LCDcommand (0x48, 1, 0, 0);
}
void LCDleft (void) {
LCDcommand (0x4C, 1, 0, 0);
}
void LCDright (void) {
LCDcommand (0x4D, 1, 0, 0);
}
void LCDcls (void) {
LCDcommand (0x58, 1, 0, 0);
}
void LCDbacklight (int state, int minutes) {
if (state == 0)
LCDcommand (0x46, 1, 0, 0);
else {
LCDcommand (0x42, 2, minutes, 0);
}
}
void LCDgpo (int state, int chan) {
if ((chan >= 1) && (chan <= 6)) {
if (state == 0) LCDcommand (0x57, 2, chan, 0);
else LCDcommand (0x57, 2, chan, 0);
}
}
void LCDcontrast (unsigned char val) {
LCDcommand (0x50, 2, val, 0);
}
========================================
/*
* I2C.H
*
* Prototypes and definitions for I2C.C
*
*/
#ifndef I2C_H
#define I2C_H
#include "\JKMicro\H\ports186.h"
/* standard I2C routines */
int I2Cgetbyte(void);
void I2Cputbyte(int o_byte);
void I2Cnack(void);
void I2Cgiveack(void);
void I2Cinit (void);
void I2Cstart(void);
void I2Cstop(void);
void I2Chighsda(void);
void I2Clowsda(void);
void I2Chighscl(void);
void I2Clowscl(void);
void I2Cread (int adr, int num, char *buf);
void I2Cwrite (int adr, int num, char *buf);
#endif
=====================================
/*
* Routines to drive a standard I2C bus for the JKMicro
* Flashlite 186 Single Board Computer.
*/
#include <stdio.h>
#include "\JKMicro\H\i2c.h"
#include "\JKMicro\H\Ports186.h"
#define SCL PORTA
#define SCLBIT 0x00
#define SDA PORTB
#define SDABIT 0x00
/*
* I2C Routines derived from the pseudo code by V. Himpe,
* and are likewise released into the Public Domain by:
*
* Russell W. Ranshaw
*
* For more information, visit:
* http://www.ping.be/~ping0751/i2cfaq/i2cindex.htm
*
*/
/*
* I2Cinit is to be called immediately after power up.
* This is normally the only I2C routine to be called
* directly by the application.
*/
void I2Cinit (void) {
int n;
I2Chighsda ();
I2Clowscl ();
for (n = 0; n < 3; n++) {
I2Cstop ();
}
}
void I2Cstart (void) {
I2Chighscl ();
I2Chighsda ();
I2Clowsda ();
I2Clowscl ();
I2Chighsda ();
}
void I2Cstop (void) {
I2Clowsda ();
I2Clowscl ();
I2Chighsda ();
}
int I2Cgetbyte(void)
{
int i_byte = 0, n;
SetInputPort (SDA);
for (n=0; n<8; n++)
{
I2Chighscl();
if (GetPortBit (SDA, SDABIT))
{
i_byte = (i_byte << 1) | 0x01; /* msbit first */
}
else
{
i_byte = i_byte << 1;
}
I2Clowscl();
}
I2Chighsda ();
return(i_byte);
}
void I2Cputbyte(int o_byte)
{
int n;
for(n=0; n<8; n++)
{
if(o_byte&0x80)
{
I2Chighsda();
}
else
{
I2Clowsda();
}
I2Chighscl();
I2Clowscl();
o_byte = o_byte << 1;
}
I2Chighsda();
}
void I2Cgiveack(void)
{
I2Clowsda();
I2Chighscl();
I2Clowscl();
I2Chighsda();
}
void I2Cgetack (void) {
int n;
I2Chighsda ();
I2Chighscl ();
SetInputPort (SDA);
/* Wait until Slave pulls SDA low */
/* Note: The pseudocode does not have the for loop.
* It was added to prevent a lock up situation.
*/
for (n = 1; n < 100; n--) {
if (GetPortBit (SDA, SDABIT) == 0)
break;
}
I2Clowscl ();
SetOutputPort (SDA);
}
void I2Chighsda(void)
{
SetOutputPort (SDA);
SetPortBit (SDA, SDABIT);
}
void I2Clowsda(void)
{
SetOutputPort (SDA);
ClearPortBit (SDA, SDABIT);
}
void I2Chighscl(void)
{
SetOutputPort (SCL);
SetPortBit (SCL, SCLBIT);
}
void I2Clowscl(void)
{
SetOutputPort (SCL);
ClearPortBit (SCL, SCLBIT);
}
/*
* Routine to send an address on the I2C bus. To indicate
* adr is a 10-bit address, set the high-order bit (0x8000).
*/
void I2Csendadr (int adr, int rw) {
I2Cstart ();
if ((adr & 0x8000) != 0) {
/* Send two MSBs of the ten bit address */
I2Cputbyte (0xF0 | rw | ((adr > 7) & 0x06));
I2Cgetack ();
I2Cputbyte (adr & 0xFF);
} else {
I2Cputbyte (adr | rw);
}
I2Cgetack ();
}
/* Read num bytes from device adr into buf */
void I2Cread (int adr, int num, char *buf) {
I2Csendadr (adr, 1);
while (num > 0) {
*buf = I2Cgetbyte ();
buf++;
if (--num > 0) I2Cgiveack ();
}
I2Cstop ();
}
/* Write num bytes to device adr from buf */
void I2Cwrite (int adr, int num, char *buf) {
I2Csendadr (adr, 0);
while (num > 0) {
I2Cputbyte (*buf++);
I2Cgiveack ();
num--;
}
I2Cstop ();
}
===============================
The low-level port bit routines have a small delay built in, about a microsecond.