📄 lincmpsl.a51
字号:
NAME LINCMPSL ;Lin I睠-Slave
$INCLUDE (Relpc764.inc)
$INCLUDE (TJA1020.inc)
$INCLUDE (LINCMPSL.inc)
;###########################################################################################
;# This routines hold the Lin Mac-layer and LL-Layer. #
;# #
;#Used Hardware: #
;# Timer 0 and Timer 1 #
;# Comparator 1 #
;# UART #
;# #
;###########################################################################################
;Segments for the Lin-Protcol Layer
LIN_DATA SEGMENT DATA
LIN_MAC SEGMENT CODE
LIN_UART_INT SEGMENT CODE
;Segments for the Break detection
S_CMPInt SEGMENT CODE
S_TIMER1_INT SEGMENT CODE
S_TIMERI_INT SEGMENT CODE
S_INIT_BREAK_DETECT SEGMENT CODE
S_BREAK_DETECT_DATA SEGMENT DATA
;Segments for the Time-Out Counter
SGoToSleep SEGMENT CODE
SInitTimeOuts SEGMENT CODE
SSendWakeup SEGMENT CODE
STimer0Isr SEGMENT CODE
SCounterData SEGMENT DATA
;public definitions
;all these symbols will be available in other moduls
PUBLIC InitLinMac, FrameLength, LinID, LinData, LinError, LinState
PUBLIC BreakFlag, LinSynced, LinIDreceived, LinRxData, LinTxData, LinDataRdy, LinFrameOk, LinSleeps, LinWakeitup
PUBLIC ParityError, ValidationError, ChecksumError
PUBLIC SendWakeup
;Data for Lin Protocol Layer
rseg LIN_DATA
_LinLastSent: DS 1 ;last byte sent
_ByteLeft: DS 1 ; number of bytes left to be sent
_LinCRC: DS 1 ; temp CRC-sum
FrameLength: DS 1 ; Lin Frame length, determined from the ID
LinData: DS 8 ; Lindata buffer
LinID: DS 1 ; LinID
_OldDptrL: DS 1 ; backup of the datapointer
_OldDptrH: DS 1
dseg at (_FLAGS_ADR)
LinStateByte: db 1 ;Lin Statusbyte
LinErrorByte: db 1 ;Lin Errorbyte
dseg at (_FLAGS_ADR+2)
_ParityByte: db 1 ;Lin Paritybits
;Data for Time-Out Counter
rseg SCounterData
_cnt_low: DS 1 ;to count a whole timeout, 4 bytes are needed
_cnt_high: DS 1 ;two bytes are already provided by the timer, so we need two additional bytes in RAM
_wakeup_trial: DS 1 ;number of the actual wakeup-trial
;********************************************************************************************************
;********************************************************************************************************
;********************************************************************************************************
;********************************************************************************************************
;Code for the Lin Protocol Layer
;************************************
;Interrupt-Service Routine UART
cseg at 023H
ljmp LinUartInt
rseg LIN_UART_INT
LinUartInt:
CLR ES
PUSH PSW
PUSH ACC
PUSH AR1
;#####################################################################################
;test the Sleep condition
JNB LinSleeps,_MasterTask
JB RI,_sleepRx
_sleepTx: ;transmission while Lin sleeps, only possible if the wakeup-signal should be send or was sent
CLR FE
JB LinWakeitup,_after ; test if this tx is before or after the 0x80-char transmission
_before:
SETB LinWakeitup ; send the wakeup-char
CLR TI
MOV SBUF,#80H
ljmp _normal_return
_after:
CLR TI ; just notify
ljmp _normal_return
_sleepRx:
JNB LinWakeitup,_MasterTask ; notify reception of wakeup character
CLR LinWakeitup
ljmp _normal_return
_MasterTask:
JNB FE,_normalData
;#############################################
;Check on Break
;Framing Error *
;When a framing error occurred, the Lin-protocol statemachine is resettet (wait for break)
;the number of '0's in SBUF is looked up and, basing on this number, the time, which is left for a sync-break,
;is calculated. This value is loaded into the timing-register of timer 1, the timer and the
;comparator are enabled, and the UART disabled.
CLR FE
CLR TR1
PUSH AR0
ANL LinState,#80 ;clear all Flags, except LinSleeps
MOV LinState,#0
MOV LinError,#0
MOV _LinCRC,#0
ANL TMOD,#0FH ;set the Timer1 to counter-mode
ORL TMOD,#10H
;calculate pre-load value for break-detection
MOV R1,#BREAKTIMEH;preload R1 with high-byte of 11bit-times
MOV R0,#BREAKTIMEL;preload R0 with low-byte of 11bit-times
MOV A,SBUF ; store SBUF in accumulator
_loop1: JZ _end_calculate
$IF (TICKSPERBITH>0) ;--> depends on baudrate and osc-frequency, if TICKSPERBITH is greater than '0'
XCH A,R1 ;*only if necessary
SUBB A,#TICKSPERBITH
XCH A,R1
$ENDIF
XCH A,R0
SUBB A,#TICKSPERBITL ;subsctract 1 bit-time from 11-bit-time *
XCH A,R0 ;*
JNC _loop1 ; test overflow *
DEC R1 ; if 'yes', increase high-byte
CLR C
RLC A
ljmp _loop1
_end_calculate:
MOV TH1,R1
MOV TL1,R0
CLR TF1
ANL CMP1,#0FEH ; clear int-Flag
SETB ET1 ;enable Timer 1 Interrupt
SETB EC1 ;enable Comp-Interrupt
SETB TR1 ;start timer
POP AR0
CLR ES ;disable serial int
ljmp _break_return
;#####################################################################################
;Normal Data Transmitted or Received
_normalData:
JNB TI,_RIisset
; test if this node is data transmitting node and the TI flag has been set by the application-program
CLR TI
JNB BreakFlag,_ljmp_normal_return
JNB LinSynced,_ljmp_normal_return
JNB LinIDreceived,_ljmp_normal_return
JB LinFrameOk,_ljmp_normal_return
JB LinTxData,_ljmp_normal_return
JB LinRxData,_ljmp_normal_return
SETB LinTxData; this Bit indicates, that the node is tranmitting data
;send the first data byte
MOV A,#LinData
ADD A,_ByteLeft
MOV R1,A
MOV SBUF,@R1; send the first Databyte
MOV _LinLastSent,@R1
ljmp _normal_return
_ljmp_normal_return:
ljmp _normal_return
;#############################################################
;from this point, RI is set
_RIisset: ;----> Test the current state of the Lin protocol
JB BreakFlag,_testsyncbit
ljmp _reset_return; normal character received without break?!?! that means a protocol-reset
_testsyncbit:
JB LinSynced,_testIDBit
ljmp _check_on_sync
_testIDBit:
JB LinIDreceived,_testdatardy
ljmp _check_on_ID
_testdatardy:
JNB LinDataRdy,_process_data
;#### CRC has been received #################
_process_CRC:
;test if the CRC was transmittet by this node itself (Flag LinTxData)
MOV A,SBUF; CRC in Accumulator
JNB LinTxData,_checkCRC
CJNE A,_LinLastSent,_validationError ;validation
;now check the CRC
_checkCRC:
ADD A,_LinCRC
CJNE A,#0FFH,_CRCError ; sum must be 0xFF
;Lin Frame Ok
SETB LinFrameOk
CLR LinTxData
CLR LinRxData
MOV A,LinID; check on Lin CommandFrame
CJNE A,#3CH,_toLinInt
;Commandframe
MOV A,LinData+7
JNZ _reset_return
SETB ES
CLR RI
POP AR1
POP ACC
POP PSW
ljmp _SettoSleep
;######################################################
_CRCError: SETB ChecksumError
ljmp _toLinError
;##### normal databyte has been received ##############
_process_data:
JB LinTxData,_do_not_set_bit
JB LinRxData,_do_not_set_bit
SETB LinRxData
_do_not_set_bit:
MOV A,#LinData
ADD A,_ByteLeft
MOV R1,A
MOV @R1,SBUF ;receive the data
;calculate CRC
_calcCRC: MOV A,_LinCRC
ADDC A,@R1
JNC _noadd
INC A
_noadd:
MOV _LinCRC,A ;save CRC
;test if this was the last byte
MOV A,_ByteLeft
JNZ _next_is_data
SETB LinDataRdy
_next_is_data:
DEC _ByteLeft
JNB LinTxData,_normal_return; again, test if this node has to transmit the Lin-data
;validate the last data
MOV A,@R1
CJNE A,_LinLastSent,_validationError
JB LinDataRdy,_sendCRC
;send the next databyte
MOV A,#LinData
ADD A,_ByteLeft
MOV R1,A
MOV SBUF,@R1
MOV _LinLastSent,@R1
ljmp _normal_return
_sendCRC: MOV A,#0FFh
CLR C
SUBB A,_LinCRC
MOV _LinLastSent,A
MOV SBUF,A
ljmp _normal_return
;##############################################################################
; here are the return from interrupt functionalities
; they are located in the middle of the ISR to support the +-128-byte jumps
_reset_return:
ANL LinState,#LIN_WAIT_BREAK ;Clear all Flags
CLR TI
_normal_return:
SETB ES
_break_return:
CLR RI
POP AR1
POP ACC
POP PSW
RETI
_validationError:
SETB ValidationError
ljmp _toLinError
_toLinError:
MOV LinState,#LIN_WAIT_BREAK
_toLinInt:
CLR RI
POP AR1
POP ACC
POP PSW
MOV _OldDptrh,DPH
MOV _OldDptrL,DPL
MOV DPTR,#LinServiceRoutine
PUSH DPL
PUSH DPH
MOV DPH,_OldDptrH
MOV DPL,_OldDptrL
SETB ES
reti
;#######################################################################################
;################## process the LinID ##################################################
_check_on_ID:
; evaluate ID
MOV A,SBUF
;CJNE A,_LinLastSent,_validationError ; the masternode always sends the ID ;;outcomment --> this is the slavenode code
MOV LinID,A
ANL LinID,#3FH
RL A
RL A ; ACC = FL,FL,X,X|X,X,P1,P0
; get Frame-Length
MOV FrameLength,#2
RLC A
JNC _addRLC ; ---> one additional RLC has to be done
MOV FrameLength,#4
RLC A
JNC _getParity
MOV FrameLength,#8
ljmp _getParity
_addRLC: RLC A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -