PDA

View Full Version : SPI Interface Examples


huffman
03-19-02, 01:15 PM
I'd like to use the 68HC11 SPI bus to configure two NMIY-0020 boards in a master /
slave configuration. Anybody have example code on the SPI bus? Prefer 'C' code if you have
it, but I can sludge through Forth as well.
Thanks!!

nmitech
03-19-02, 01:41 PM
/* HC11 SPI ROUTINES FOR SMALL-C */

/* USE PD5 AS ACTIVE LOW CHIP ENABLE FOR PERIPHERAL DEVICE */
CSLOW()
{
INT MASK_PD5;
MASK_PD5 = PEEKB(REG_BASE+PORTD) & 0x1F;
POKEB(REG_BASE+PORTD,MASK_PD5);
}

/* FORCE PD5 HIGH TO DISABLE PERIPHERAL DEVICE */
CSHIGH()
{
INT SET_PD5;
SET_PD5 = PEEKB(REG_BASE+PORTD) | 0x20;
POKEB(REG_BASE+PORTD,SET_PD5);
}

/* SPI INITIALIZATION */
SPI_INIT()
{
INT JUNK;
POKEB(REG_BASE+PORTD,0x0F); /* TURN ON /CS AS SOON AS DDR INIT */
POKEB(REG_BASE+DDRD,0x38); /* CONFIG I/O FOR PORTD */
POKEB(REG_BASE+SPCR,0x50); /* ENABLE SPI, MASTER */
JUNK = PEEKB(REG_BASE+SPSR); /* CLEAR THE FLAG */
JUNK = PEEKB(REG_BASE+SPDR); /* CLEAN UP JUNK IN BUFFER */
CSHIGH(); /* DEACTIVATE PERIPHERAL DEVICE */
}

/* CHECK FOR SPI ENDING TRANSFER FLAG */
SPIFLAG()
{
WHILE(!(PEEKB(REG_BASE+SPSR) & 0x80));
}

/* GET DATA FROM PERIPHERAL DEVICE */
GET_SPI()
{
INT SPIDATA;
CSLOW(); /* TURN ON PERIPHERAL */
POKEB(REG_BASE+SPDR,0x00); /* WRITE TO INITIATE THE SCK SIGNAL */
SPIFLAG(); /* WAIT TILL DATA FINISH TRANFERRING */
SPIDATA = PEEKB(REG_BASE+SPDR);
CSHIGH(); /* TURN OFF PERIPHERAL */
RETURN SPIDATA;
}


--------------------- FORTH ---------------------------------

( Serial Peripheral Interface Rob Chapman Nov 20, 1999
( When the spi buffer is empty, an interrupt is generated. The servicing
( routine answers the interrupt by writing out the next value from the
( circular buffer. The circular buffer is 256 bytes long. For every two
( bytes the /SS line is pulsed to indicate 16 bits shifted out.
HEX
( SPI vector at FFD8 points to B7C2 jmp xxxx
B028 CONSTANT spcr ( SPI control register
B029 CONSTANT spsr ( SPI status register
B02A CONSTANT spdr ( SPI data register

B008 CONSTANT portd ( port D
B009 CONSTANT ddrd ( data direction register for port D

CREATE spi-buf 1 C, 100 ALLOT ( index; wraparound transmission buffer

CODE SIR-SPI ( servicing interrupt routine for serial peripheral interface
ldxi spi-buf 1+ , ( get base address of buffer
ldabe spi-buf , ( get offset into buffer
bitbi 1 C, ( check lowest bit for previous word sent
bne fwd ( do even ones
ldaai 20 C, ( ss bit
staae portd , ( set ss high - take last data
ldaai 0 C, ( ss bit
staae portd , ( set ss low - active
fwd:
abx ( combine the values to make a pointer
ldaae spsr , ( clear source of interrupt
ldaa 0,x ( get the next byte
staae spdr , ( output next value
ince spi-buf , ( increment pointer
rti ( return from interrupt
END-CODE

: +SPI ( -- ) ( turn on spi
2F portd C! ( ss-hi sclk-lo mosi-hi
38 ddrd C! ( set PD5 /SS PD4 SCLK and PD3 MOSI as outputs
D1 spcr C! ( +int and turn on spi )
0 spdr C! ( prep the system )
ddrd C@ 38 XOR IF ." SPI initialization failed" THEN ;

: -SPI ( -- ) 51 spcr C! ; ( turn off spi

: INIT-SPI ( -- ) -SPI
JMPE B7C2 EEC! ['] SIR-SPI @ B7C3 EE! ( install interrupt jump vector
+SPI ;

CODE-SUB +INT
cli ( enable interrupts
rts ( thread on
END-CODE

CODE-SUB -INT
sei ( disable interrupts
rts ( thread on
END-CODE

-------- Another sample, polling mode -----

( SPI ROUTINES
( -----

: SELECT B008 C@ 1F AND B008 C! ;
: DESELECT B008 C@ 20 OR B008 C! ;

: SPI-INIT
0F B008 C! ( --001111 TURN ON CS AS SOON AS DDR INIT
38 B009 C! ( --OOOIII FOR PORTD
50 B028 C! ( MASTER, SPI ON, SLOW CLOCK
30 B000 C! ( SET CAL MODE, AWAKE
10 B000 C! ( UNSET CAL MODE, AWAKE
B029 C@ DROP ( BOGUS READS TO CLEAR
B02A C@ DROP
DESELECT ;

: SPI@ ( -- n )
0 B02A C! BEGIN B029 C@ 80 AND UNTIL B02A C@ ;

: A/D@ ( -- n )
SELECT
SPI@ >< SPI@ OR
DESELECT ;

: A/D ( -- n ) A/D@ DROP A/D@ ;

-----

huffman
03-19-02, 02:11 PM
Thanks!!! Exactly what I was looking for!
Kevin