📄 wheeler.4th
字号:
<<< START OF CODE EXAMPLE >>>
\ I2C Demo Code by Steven R. Wheeler
\ Rationale of code:
\ We will use the 8255 on the Tiny as an interface to the I2C bus.
\ The I/O will be as follows:
\ The 8255 will be configured in Mode 0 with
\ Port A as an output port (but is unused),
\ Port B as an output port (SDA for writes), or
\ Port B as an input port (SDA for reads and INT), and
\ Port C as an output port (SCL for reads and writes)
\ SCL (serial clock) will be on the low bit of Port C, because this
\ is convenient. SDA (serial data) will be on the highest-but-one bit
\ of Port B, so that it won't be too hard to write code routines which
\ efficiently move single bits between AH and AL when sending or
\ receiving data. INT will be one bit lower than SDA on Port B. The
\ positions of SDA and INT are constrained because we will be using
\ the keypad connector on the Tiny188 as our connection to the 80196
\ keypad/lcd/tone board, so we want the inputs to have pull-up
\ resistors.
\ We will be talking to two PCF8574 chips on the keypad/lcd/tone board.
\ Each chip is addressed separately, one at address 20h, the other at
\ address 21h. Since the addresses are only 7 bits, and the low order
\ bit indicates read or write, we will actually be sending 40h or 42h
\ to write, and 41h or 43h to read.
\ The PCF8574 at address 20h has the control signals for the LCDs and
\ the tone generator, as well as the key/nokey indication. The PCF8574
\ at address 21h is written with data for the LCD, and provides the
\ keypad data.
\ The control signals are sent in the following bit order:
\
\ +---+---+---+---+---+---+---+---+
\ | + | + | + | + | + | + | + | + |
\ +-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+
\ | | | | | | | +---- R/W* for LCD
\ | | | | | | +-------- LCD 0 enable
\ | | | | | +------------ LCD 1 enable
\ | | | | +---------------- Keypad latch
\ | | | +-------------------- Beep enable (0=on,1=off)
\ | | +------------------------ A0
\ | +---------------------------- A1
\ +-------------------------------- Key available indication
\ A0 serves a dual purpose: it is the command/data register select for
\ the LCDs, and with A1, it selects the frequency of the tone
\ generator.
\ The key available indication is an input. As I read the
\ documentation of the PCF8574, this means that it should always be
\ written with a 1.
HEX
01 CONSTANT R/W* \ 0 = write LCD; 1 = read LCD
02 CONSTANT LCD0 \ 1 = enable LCD0
04 CONSTANT LCD1 \ 1 = enable LCD1
08 CONSTANT KPLATCH* \ 0 = latch keypad
10 CONSTANT BEEP* \ 0 = enable beep
20 CONSTANT RS \ 0 = LCD command; 1 = LCD data
20 CONSTANT A0 \ Same as RS, but also beep freq control
40 CONSTANT A1 \ Beep freq control
80 CONSTANT KeyMask \ Read ... 0 = key available
\ Composite constants for controlling the board
KeyMask A1 OR A0 OR RS OR BEEP* OR R/W* OR CONSTANT Latch-Key
\ LCDx and KPLATCH* low
Latch-Key KPLATCH* OR CONSTANT UnLatch-Key
\ LCDx low
UnLatch-Key
BEEP* NOT AND CONSTANT BEEP3 \ A1,A0 = 11
BEEP3 A0 NOT AND CONSTANT BEEP2 \ A1,A0 = 10
BEEP3 A1 NOT AND CONSTANT BEEP1 \ A1,A0 = 01
BEEP1 A0 NOT AND CONSTANT BEEP0 \ A1,A0 = 00
UnLatch-Key LCD0 OR
R/W* NOT AND CONSTANT LCD0-Data-Out
LCD0-Data-Out
RS NOT AND CONSTANT LCD0-Cmd-Out
UnLatch-Key LCD1 OR
R/W* NOT AND CONSTANT LCD1-Data-Out
LCD1-Data-Out
RS NOT AND Constant LCD1-Cmd-Out
\ 8255 configuration
80 CONSTANT B=Output \ A = out; B = out; C = out
82 CONSTANT B=Input \ A = out; B = in; C = out
\ 8255 port bitmasks for data
40 CONSTANT DataMask \ Bitmask for Data to/from port B
20 CONSTANT IntMask \ INT signal from PCF8574 @ 20h
01 CONSTANT ClockMask \ Clock bit to PCF5874's
01 CONSTANT Read \ OR in to address to read
00 CONSTANT Write \ OR in to address to read
\ I2C "addresses" used on the board
40 CONSTANT Control \ Address of control PCF8574
42 CONSTANT Data \ Address of data PCF8574
\ I/O address of the 8255
E080 CONSTANT CS8255 \ Base address of 8255
DECIMAL
: Set-B-Input ( --) \ This is our normal state of affairs
B=Input CS8255 3 + PC! ;
: Set-B-Output ( --) \ Only when sending
B=Output CS8255 3 + PC! ;
: Clock-High ( --) \ Set the SCL line high
ClockMask CS8255 2+ PC! ;
: Clock-Low ( --) \ Set the SCL line low
00 CS8255 2+ PC! ;
: Toggle-Clock ( --) \ Set SCL high, then low
Clock-High \ First we set it high
Clock-Low ; \ Then we set it low
: Send-Start ( --) \ Send a START condition
00 CS8255 1+ PC! ; \ High-low data transition = START
: Send-Stop ( --) \ Send a STOP condition
DataMask CS8255 1+ PC! ; \ Low-high data transition = STOP
: Send-Next-Bit ( 8b1 -- 8b2) \ Send highest bit of 8b1
DUP 2/ DataMask AND \ Isolate the bit we want
CS8255 1+ PC! \ Place on the data port
Toggle-Clock \ Send the bit
2* ; \ Shift the next bit into position
: Read-Input ( -- 8b1) \ Read the port B input
CS8255 1+ PC@ ;
: Read-Bit ( -- n) \ Returns 0 or 1
Clock-High \ Set the clock bit high
Read-Input \ Read the data (bit 7)
Clock-Low \ Set the clock low again
2* 2* FLIP 1 AND ; \ Move the data to bit 0
: Send-Byte ( 8b1 -- flag) \ Send a byte to the I2C bus
Set-B-Output \ Configure for sending data
8 0 DO Send-Next-Bit \ Send each bit
LOOP DROP \ Remove byte when sent
Read-Bit ;
: Key-Int? ( -- flag) \ TRUE if key status changed
Set-B-Input
CS8255 1+ PC@
IntMask AND 0<>
Set-B-Output ;
: Read-Byte ( -- 8b1)
Set-B-Input
0
8 0 DO 2* Read-Bit OR
LOOP
Set-B-Output Clock-High ;
: Write0 ( byte --)
Control Write OR Send-Start Send-Byte DROP
Send-Byte DROP Clock-High Send-Stop ;
: Write1 ( byte --)
Data Write OR Send-Start Send-Byte DROP
Send-Byte DROP Clock-High Send-Stop ;
: Read0 ( -- byte)
Control Read OR Send-Start Send-Byte DROP Read-Byte Send-Stop ;
: Read1 ( -- byte)
Data Read OR Send-Start Send-Byte DROP Read-Byte Send-Stop ;
: PKey? ( -- flag)
Read0 KeyMask AND 0= ;
: @PKey ( -- n)
-1 Write1 \ Make certain they're inputs
Latch-Key Write0 \ Latch the keypad value
Read1 255 XOR \ Read the keypad value
UnLatch-Key Write0 ; \ Release the keypad latch
: PKey ( -- n)
BEGIN PAUSE PKey? UNTIL
@PKey ;
: Loud ( beepval --)
WRITE0 ;
: Quiet ( --)
UnLatch-Key Write0 ;
: LCD-Write ( byte reg --)
SWAP Write1
DUP Write0
[ LCD0 LCD1 OR NOT ] LITERAL
AND Write0 ;
: LCD0-Command ( byte --)
LCD0-Cmd-Out LCD-Write ;
: LCD0-Data ( byte --)
LCD1-Cmd-Out LCD-Write ;
: LCD1-Command ( byte --)
LCD1-Cmd-Out LCD-Write ;
: LCD1-Data ( byte --)
LCD1-Data-Out LCD-Write ;
: Setup ( --)
Set-B-Output
Clock-High
Send-Stop ;
<<< END OF CODE EXAMPLE >>>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -