redelz 发表于 2024-3-18 16:38:32

STC单片机SPI实现PLC功能扩展单元联接总线

用STC单片机SPI实现PLC功能扩展单元联接总线
1,PLC梯形图指令主要是解决算法结构和数据的读写和操作方式。为了实现用有限的梯形图指令实现无限的功能扩展,必须特殊功能放置到功能扩展单元。PLC主机与功能扩展单元的总线连接必须有软件协议栈支撑,必须实现透明实时传输,队列传输,事件触发传输这三种数据传输方式。透明实时传输就是我们熟知基本I/O方式。队列传输要保证一段数据传输的先后次序及数据完整性。事件传输就是每次数据传输有一次完整的应答握手。
2,总线采用32字节加2字节CRC效验固定数据块长度传输方式,也就是不管那种传输方式每次同步双向传输34个字节。因为PLC的可靠性不能允许错误数据,所以必须每次传输进行数据完整性效验。
3,SPI是STC单片机效率和速率非常高的数据传输接口,所以主机采用查询等待方式(关闭中断),也就是必须等待34字节数据双向传输完成,这样就可以与PLC整体输入输出扫描实现数据同步,避开复杂的时序同步算法。
4,由于SPI接口的输入输出同步传输属性,无法给从机等待时间。所以从机采用双缓冲中断传输机制。这样只需一个信号切换量需要数据保护就可以完成从机的快速中断响应。当然双缓冲就使得数据序列,读写完整性保护算法比较复杂。

代码比较复杂,给大家展示部分代码。供参考

;主机部分代码节选
EXB0                    equ   p4.7
EXB1                    equ   p5.4
;
SPISS0                   equ           P1.2            ;SPI slave select, connect to slave' SS(P1.3) pin
SPISS1                   equ           P1.6            ;SPI slave select, connect to slave' SS(P1.4) pin
;------------
CheckExt0:                      ;check if Extand 0 is valid
                              ;resault put to Extand0Valid
      setb    EXB0
      mov   c,EXB0
      jnc   chckex0
      clr   Extand0Valid    ;extand modula 0 is not valid
      ret
chckex0:setb    Extand0Valid    ;extand modula 0 is valid
      ret
;-----------------------------------------------------------------------
CheckExt1:                      ;check if Extand 0 is valid
                              ;resault put to Extand0Valid
;        clr        SPISS1
      setb    EXB1
      mov   c,EXB1
      jnc   chckex1
      clr   Extand1Valid    ;extand modula 0 is not valid
      ret
chckex1:setb    Extand1Valid    ;extand modula 0 is valid
      ret
;----------------------------------------------------------------------------------------------------
INIT_SPI:                               ;Initial SPI to access data
;        clr   SPISS1
        setb    SPISS1                ;for STW15W4K
      MOV   SPDAT,#0                ;initial SPI data
      MOV   SPSTAT,#(SPIF OR WCOL)   ;clear SPI status
                                        ;SPDHH   EQU   000H            ;SPR1=0, SPR0=0, CPU_CLK/4
                                        ;SPDH    EQU   001H            ;SPR0 CPU_CLK/8
                                        ;SPDL    EQU   002H            ;SPR1 CPU_CLK/16
                                        ;SPDLL   EQU   003H            ;SPR1=1, SPR0=1, CPU_CLK/32
      MOV   SPCTL,#(SSIG OR SPEN OR MSTR OR SPDLL)                        ;master mode with CPU_CLK/32
      anl   IE2,#DISPI            ;disable interrupt
;      orl   IE2,#ESPI       ;enable SPI interrupt
      RET
;--------------------------------------------------------------------------------------------------
ExtCheckByte:                        ;check ifSPI frame is OK?
                                ;RETURN A ==0 frame OK
                                ;       ELSE frame error
        mov   r2,#SPI_TABLE_SIZE
        mov   r0,#Spi_In_Table
        lcall        CheckCRC
        ret
;从机部分代码
;-----------------------------------------------------------------
;** SPI Access routine
;-------------------------------------------------------------------
;//#define MASTER                  //define:master undefine:slave
SPIF            EQU   080H            ;SPSTAT.7
WCOL            EQU   040H            ;SPSTAT.6
SSIG            EQU   080H            ;SPCTL.7
SPEN            EQU   040H            ;SPCTL.6
DORD            EQU   020H            ;SPCTL.5
MSTR            EQU   010H            ;SPCTL.4
CPOL            EQU   008H            ;SPCTL.3
CPHA            EQU   004H            ;SPCTL.2
SPDHH         EQU   000H            ;CPU_CLK/4
SPDH            EQU   001H            ;CPU_CLK/16
SPDL            EQU   002H            ;CPU_CLK/64
SPDLL         EQU   003H            ;CPU_CLK/128
;
SPI_P4                EQU        20h                ;SPI bits selector to P4
SPI_S0                equ        04H
SPI_S1                equ        08h                ;SPI select
                                        ;SPI_S1:SPI_S0
                                        ;00        P1.2SS   P1.3MOSIP1.4MISO   P1.5SCLK
                                        ;01        P2.4SS   P2.3MOSIP2.2MISO   P2.1SCLK
                                        ;10        P5.4SS   P4.0MOSIP4.1MISO   P4.3SCLK
                                        ;11        Invalid
ADRJ                EQU        04h                ;10 bits ready mask
;
;EADC_SPI      equ   IE.5
ESPI            equ   02h             ;IE2.1
;
ENEXT                equ        p4.4
PSSS0                equ        p4.0
;
;P4SW                equ        0BBh                ;port4 switch setting bits
;
;START                 0FFh
;END                07Eh
;Change char         05Fh
; 0FFh change it as 05Fh, 05Dh
; 07Eh change it as 05Fh, 05Eh
; 07Fh change it as 05Fh, 05Fh
EX_CHANGE_START                equ        0FEh
EX_CHANGE_END                equ        7Eh
EX_CHANGE_CG                equ        5Fh
EX_CHANGE_CS                equ        5Dh
EX_CHANGE_CE                equ        5Eh
;
INIT_SPI:                               ;Initial SPI to access data
;        clr        ENEXT
        anl        AUXR1,#(NOT(SPI_S0))
        orl        AUXR1,#SPI_S1                ;SPI_S1:SPI_S0=10        P5.4SS   P4.0MOSIP4.1MISO   P4.3SCLK
      MOV   SPDAT,#02h                ;initial SPI data
      MOV   SPSTAT,#(SPIF OR WCOL)    ;clear SPI status
      MOV   SPCTL,#(SPEN)         ; OR SSIG)   ; OR MSTR)        ;SSIG)                ;slave mode for ext
        orl        IE2,#ESPI
        ;
;        clr        ENEXT                        ;enable MISO
        ;
        clr        SpiDataReady
        clr        SpiInCharChanged        ;if change char sent to and secong char is in
        clr        SpiOutCharChanged        ;if change char sent to and secong char is out
        clr        SpiInFrameEnd
        clr        SpiOutFrameEnd
        clr        SpiTraslated
        setb        PSSS0Check                                ;PSSS0 not setting
        ;
        mov        a,#EX_CHANGE_END
        mov        r0,#Spi_In_End_Ch1
        movx        @r0,a
        mov        r0,#Spi_In_End_Ch2
        movx        @r0,a
        ;
      RET
;------------------------------------------------------------------------
SpiEnableCheck:                                ;check PSSS0 wait it to low an enable SPI
        jnb        PSSS0Check,spienb3        ;PSSS0
        mov        c,PSSS0                        ;get pin signal
        jc        spienb2
        nop
        nop
        mov        c,PSSS0                        ;get pin signal
        jc        spienb2
        clr        PSSS0Check
        orl   SPCTL,#(SPEN OR SSIG)        ;MSTR)        ;SSIG)                ;slave mode for ext
        orl        IE2,#ESPI
        setb        c
        ret
spienb3:mov        c,PSSS0                        ;get pin signal
        jnc        spienb2
        nop
        nop
        mov        c,PSSS0                        ;get pin signal
        jnc        spienb2
        setb        PSSS0Check
        anl   SPCTL,#((NOT(SPEN OR SSIG) AND 0FFh))        ;MSTR)        ;SSIG)                ;slave mode for ext
        anl        IE2,#(NOT(ESPI))
spienb2:clr        c
        ret
;------------------------------------------------------------------------
SPI_SWAP:                               ;exchange data from SPI
                                        ;INPUT: A= byte data to translate
                                        ;OUTPUT:A= byte data read from master
      MOV   SPDAT,A                        ;trigger SPI send
spiswp1:
      MOV   A,SPSTAT
      JNB   ACC.7,spiswp1                ;wait send complete
      MOV   SPSTAT,#(SPIF OR WCOL)   ;clear SPI status
      MOV   A,SPDAT                        ;return received SPI data
      RET
;-----------------------------------------------------------------------------------------------


页: [1]
查看完整版本: STC单片机SPI实现PLC功能扩展单元联接总线