en:pfw:spi
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
en:pfw:spi [2023-09-04 18:23] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | en:pfw:spi [2024-08-03 13:47] (current) – [Implementations] willem | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | {{pfw: | ||
+ | ====== SPI protocol, general introduction ====== | ||
+ | |||
+ | ==== The Idea of SPI ==== | ||
+ | |||
+ | SPI is a synchronous serial protocol with three to four lines, it\\ | ||
+ | is used for (LCD) displays, (Flash) memory chips, SD-cards, etc. | ||
+ | |||
+ | < | ||
+ | 1. MOSI | ||
+ | 2. MISO | ||
+ | 3. CLK Clock | ||
+ | 4. CE Chip Enable (also called SS) | ||
+ | </ | ||
+ | |||
+ | This example has the clock signal low at rest, the data is transmitted at\\ | ||
+ | a low to high clock pulse. The data is 8-bits long, the highest bit (MSB) is sent first. Here we have shown one of four modes. They differ in the timings of raising or falling edges of the clock pulses. | ||
+ | |||
+ | {{https:// | ||
+ | |||
+ | It is possible to configure in many variants but this version is common. (The clock rate is arbitrary. If you like you can send bytes just by tipping wires by hand. Ofcourse there is a maximum speed. It depends on the speed of the peripheral hardware (data sheet)) and/or the maximum speed your CPU can handle.\\ | ||
+ | More information about SPI [[https:// | ||
+ | |||
+ | ==== Pseudo code for (bitbang) SPI input & output ==== | ||
+ | |||
+ | < | ||
+ | Function: SPI-ON | ||
+ | Initialise MOSI & SCK as output, MISO as input | ||
+ | </ | ||
+ | |||
+ | ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | < | ||
+ | Function: SPI-I/O ( x -- y ) | ||
+ | 8 loop | ||
+ | write bit-7 level from x to I/O port | ||
+ | shift x left | ||
+ | rising clock pulse on I/O port | ||
+ | read bit-6 level from I/O port | ||
+ | Move bit-6 to bit-0 position | ||
+ | Add bit-0 to y | ||
+ | falling clock pulse on I/O port | ||
+ | Leave only low 8-bits | ||
+ | |||
+ | Function: SPI-OUT | ||
+ | Send byte using SPI-I/O | ||
+ | discard received byte | ||
+ | |||
+ | Function: SPI-IN | ||
+ | Send dummy byte using SPI-I/O | ||
+ | | ||
+ | Function: {SPI ( -- ) | ||
+ | Clear chip enable bit on I/O port | ||
+ | |||
+ | Function: SPI} ( -- ) | ||
+ | Set chip enable bit on I/O port | ||
+ | </ | ||
+ | |||
+ | ==== Generic Forth bitbang example ==== | ||
+ | |||
+ | This example has the SPI interface pins connected like this. | ||
+ | |||
+ | < | ||
+ | MOSI (Data out) = bit-7 | ||
+ | MISO (Data in) = bit-6 | ||
+ | SCK (Clock) | ||
+ | CE (Chip enable) | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | <!-- **Missing words** | ||
+ | ``` | ||
+ | *BIS ( bitmask addr -- ) Set the bits from bitmask at half cell address | ||
+ | *BIC ( bitmask addr -- ) Clear the bits from bitmask at half cell address | ||
+ | BIT* ( bitmask addr -- mask ) Test the bits from bitmask at half cell address | ||
+ | mask = bitmask when the bits were high otherwise zero | ||
+ | ``` | ||
+ | **In minimal Forth** | ||
+ | For a machine with byte wide I/O ports. | ||
+ | --> | ||
+ | </ | ||
+ | **The used addresses are for port-1 of the MSP430G2553: | ||
+ | |||
+ | <code forth> | ||
+ | \ Extra words: TUCK | ||
+ | |||
+ | hex | ||
+ | \ Words with hardware dependencies: | ||
+ | : *BIS ( mask addr -- ) tuck c@ or swap c! ; | ||
+ | : *BIC ( mask addr -- ) >r invert | ||
+ | : BIT* ( mask addr -- b ) c@ and ; | ||
+ | |||
+ | 20 constant P1IN \ Input register of port-1 | ||
+ | 21 constant P1OUT \ Output register of port-1 | ||
+ | 22 constant P1DIR \ Direction register of port-1 | ||
+ | |||
+ | : SPI-ON | ||
+ | B0 P1DIR c! \ P1.4, P1.6 & P1.7 are outputs, P1.5 is input | ||
+ | 20 P1OUT *bic ; \ Start with clock low | ||
+ | |||
+ | : CLOCK-HI | ||
+ | : CLOCK-LOW | ||
+ | |||
+ | : WRITE-BIT ( b -- ) | ||
+ | 80 and if \ Test if bit-7 high? | ||
+ | 80 P1OUT *bis \ Yes, write a high bit | ||
+ | else | ||
+ | 80 P1OUT *bic \ No, write a low bit | ||
+ | then ; | ||
+ | |||
+ | : READ-BIT | ||
+ | 40 P1IN bit* 0= 0= \ Read & convert bit-6 to flag | ||
+ | 1 and or ; \ Convert flag to 1 or 0 & add to b1 | ||
+ | |||
+ | : SPI-I/ | ||
+ | 8 0 do \ Output 8-bits in a loop | ||
+ | dup write-bit | ||
+ | clock-hi | ||
+ | clock-low | ||
+ | loop | ||
+ | FF and ; \ Leave only received byte | ||
+ | |||
+ | : SPI-OUT | ||
+ | : SPI-IN | ||
+ | |||
+ | : {SPI ( -- ) 10 P1OUT *bic ; \ Enable device | ||
+ | : SPI} ( -- ) 10 P1OUT *bis ; \ Disable device | ||
+ | </ | ||
+ | |||
+ | ==== Implementations ==== | ||
+ | |||
+ | Have a look at the sub directories for implementations for different systems. | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||