• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

RS-232 SPI CONTROLLER – part 1

    Blog entry posted in 'Electronics and Other Ramblings...', January 15, 2012.

    This project initiated by the need to control some SPI devices through a PC. A few home-made programs to control some nifty frequency synthesizes were being developed and required an interface to provide communications between the PC and the devices themselves. To accomplish this, two options were looked at: (1) using the parallel port on the PC to directly control the SPI devices, (2) using the serial port on the PC to indirectly control the SPI devices. Option 1 involves bit-banging the parallel port lines to create the SPI interface. Option 2 involves using the serial port to communicate with an intermediate device which translates the serial port communication (RS232) to SPI and vice-versa. Option 1 has been used many times over with great success, but it places strict requirements on the PC-software to toggle the lines appropriately and is quite “boring”. Option 2 potentially makes the PC software less complex and it can use a PIC to act as the interface. Which, of course, made option 2 the more “logical” choice ;).

    The development is not complete yet, so this will be called part 1. This first part introduces the PIC hardware and connections which will be the framework for the project. The following components will be used:
    PIC18F1320
    FTDI - DS_TTL-232R-5V (RS232 –to- TTL cable)

    The schematic is quite simple and shown below. The PIC is able to interface through RS232 with the PC and control an SPI device based on the commands received from the PC. The RS232 control adds the CTS# line to provide handshaking between the PC and the PIC. This is not strictly necessary for applications only controlling the SPI device, but for applications which require to communicate to and from the SPI device, this provides a much easier interface.

    60179

    This initial part of only implements the ability to control the SPI device (for simple control of SPI devices not requiring information to be sent back to the host). Code is presented below. As an example of possible uses, a slightly more elaborate version of this was used to control a DDS and PLL combination from one PC application (one PIC and two SPI devices).

    Code

    Code:
    'languer (©2012)
    'Pin Allocation:
    'PIN# Main_Fn Secondary_Fn
    'RA0 -> not used
    'RA1 -> not used
    'RA2 -> not used
    'RA3 -> not used
    'RA4 -> not used
    'RA5 -> not used
    'RA6 -> OSC
    'RA7 -> OSC
    'RB0 -> CTS# (RS232)
    'RB1 -> TX_RS232 (PC_RX)
    'RB2 -> not used
    'RB3 -> not used
    'RB4 -> RX_RS232 (PC_TX)
    'RB5 -> SPI_CS
    'RB6 -> SPI_SCK PGC (Programming clock)
    'RB7 -> SPI_SDIO PGD (Programming data)
    'Usage Information:
    'RS232 Baud Rate: 19200bps
    'RS232 Handshake: Uses CTS to indicate to PC that MCU is ready to receive next command
    'Version Info:
    'v1
    '->data format: STX,PACKET_LEN,SPI_MODE,DATA
    'where STX is start of character,
    'PACKET_LEN is number of data bytes to expect (maximum packet length: 32_bytes)
    'SPI_MODE is the SPI mode (1 or 2)
    '->SPI modes: 1 or 2
    'SPI Mode 1 for data on rising edge of clock,
    'SPI Mode 2 for data on falling edge of clock
    'CS is active low

    'General Configuration
    'for external 10MHz w PLL (40MHz)
    Define CONFIG1L = 0x00
    Define CONFIG1H = 0x06
    Define CONFIG2L = 0x0a
    Define CONFIG2H = 0x00
    Define CONFIG3L = 0x00
    Define CONFIG3H = 0x80
    Define CONFIG4L = 0x80
    Define CONFIG4H = 0x00
    Define CONFIG5L = 0x03
    Define CONFIG5H = 0xc0
    Define CONFIG6L = 0x03
    Define CONFIG6H = 0xe0
    Define CONFIG7L = 0x03
    Define CONFIG7H = 0x40

    'Oscillator/Clock Configuration
    Define CLOCK_FREQUENCY = 40

    'Debug Option
    Dim debug As Bit
    debug = True
    debug = False

    'HW UART Setup
    Hseropen 19200

    'SPI Definitions
    Symbol spi_cs = RB5
    Symbol spi_sck = RB6
    Symbol spi_sdio = RB7

    'Variable Declarations
    Const trisa1 = %11111111
    Const trisb1 = %00010100

    Symbol pc_tx = RB4 'rs-232 input
    Symbol pc_rx = RB1 'rs-232 output
    Symbol pc_cts_n = RB0 'rs232 cts# handshake signal

    'rs223 interface constants
    Const stx = 0x81 'start-of-packet indicator
    Dim _true As Bit
    Dim _false As Bit

    _true = True
    _false = False

    Dim flag_rxinprogress As Bit
    Dim flag_rxcomplete As Bit
    Dim rxdata As Byte
    Dim rxdata_len As Byte
    Dim rxbuffer(32) As Byte
    Dim rxbuffer_cnt As Byte


    'Main Program
    main:
    Dim data As Byte
    Dim cnt As Byte
    Dim spi_mode As Byte

    If debug = _false Then
    WaitMs 2500
    Endif
    Call init()

    PIR1.RCIF = _false
    INTCON.PEIE = _true 'enable peripheral interrupts
    PIE1.RCIE = _true 'enable RX UART interrupt
    Enable High 'enable general interrupt
    While _true
    If flag_rxcomplete = _true Then
    High pc_cts_n 'mcu busy indication
    spi_mode = rxbuffer(0)
    Call spi_init(spi_mode)
    Low spi_cs
    For cnt = 1 To rxbuffer_cnt
    data = rxbuffer(cnt)
    Call spi_send(spi_mode, data)
    Next cnt
    High spi_cs
    Low spi_sdio
    Low spi_sck
    flag_rxcomplete = _false
    Low pc_cts_n 'mcu idle indication
    Endif
    Wend
    End
    Proc init()
    Dim cnt As Byte
    AllDigital
    TRISA = trisa1
    TRISB = trisb1
    flag_rxinprogress = _false
    flag_rxcomplete = _false
    rxbuffer_cnt = 0
    rxdata_len = 0
    High spi_cs
    Low spi_sdio
    Low spi_sck
    Low pc_cts_n 'mcu idle indication
    End Proc
    Proc spi_init(mode As Byte)
    Select Case mode
    Case 1 'data on rising edge of clock
    High spi_cs
    Low spi_sck
    Low spi_sdio
    WaitUs 10
    Case 2 'data on falling edge of clock
    High spi_cs
    High spi_sck
    Low spi_sdio
    WaitUs 10
    Case Else
    'do nothing
    EndSelect
    End Proc
    Proc spi_send(mode As Byte, data As Byte)
    Dim cnt As Byte
    Select Case mode
    Case 1 'data on rising edge of clock
    For cnt = 0 To 7
    Low spi_sck
    spi_sdio = data.7
    data = ShiftLeft(data, 1)
    High spi_sck
    ASM: nop
    ASM: nop
    ASM: nop
    ASM: nop
    ASM: nop
    ASM: nop
    Next cnt
    Low spi_sck
    Low spi_sdio
    Case 2 'data on falling edge of clock
    For cnt = 0 To 7
    High spi_sck
    spi_sdio = data.7
    data = ShiftLeft(data, 1)
    Low spi_sck
    ASM: nop
    ASM: nop
    ASM: nop
    ASM: nop
    ASM: nop
    ASM: nop
    Next cnt
    High spi_sck
    Low spi_sdio
    Case Else
    'do nothing
    EndSelect
    End Proc

    On High Interrupt
    'Save System
    If PIR1.RCIF = _true Then
    Hserin rxdata
    If flag_rxinprogress = _false Then
    If rxdata = stx Then
    High pc_cts_n 'mcu busy indication
    flag_rxinprogress = _true
    flag_rxcomplete = _false
    rxbuffer_cnt = 0
    rxdata_len = 0
    Else
    'do nothing
    Endif
    Else
    If rxdata_len = 0 Then
    rxdata_len = rxdata
    Else
    rxbuffer(rxbuffer_cnt) = rxdata
    rxbuffer_cnt = rxbuffer_cnt + 1
    If rxdata_len = rxbuffer_cnt Then
    rxbuffer_cnt = rxbuffer_cnt - 1
    flag_rxinprogress = _false
    flag_rxcomplete = _true
    Endif
    Endif
    Endif
    Endif
    PIR1.RCIF = _false
    Resume

    Comments
 

EE World Online Articles

Loading

 
Top