Code:
'*********** Process received command **************************************
ProcessCmdAdj:
' varResult = myArray[0]*100 + myArray[1]*10 + myArray[2]
HSEROUT ["Cmd: ", CmdVal, _ ' send Command, Length of Adjustment & Adjustment value and CR/LF
", LenAdj: ", LenAdjVal, " [", DEC LenAdjVal, "]", _
", Adj: ", myArray[0], myArray[1], myArray[2], 13, 10]
' ", Adj: ", AdjVal, " [", DEC AdjVal,"]", 13, 10]
state = 0 ' indicate CMD & ADJ has been processed
cmdVal = 0
LenAdjVal = 0
AdjVal = 0
For i = 0 to (ArrayLength - 1) ' clear out array
myArray[i] = 0
NEXT i
RETURN
I can't figure out how to take the 3 characters stored in myArray and convert it to a numerical 255 value that I can then use to set PWM duty cycle. As you can see from the commented-out line above, I tried multiplying the first 2 characters by 100 & 10, but that just gives garbled results. I know the ISR is building the array properly because the above HSEROUT shows me the correct characters in each item of myArray[].
Code:
' :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
' Based on Darrel Taylor's example
' http://www.picbasic.co.uk/forum/showthread.php?t=9932&p=65066#post65066
' :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
' MPASM, LabX-1 , PBP3, Using PIC 16F877A @ 4mHz, 9600 Baud,
' USART and MAX232 to MCS Serial Communicator on PC
' ***************************************************************
' >>>>>>>>>>>>>>>>> Slave IC ID: 0 <<<<<<<<<<<<<<<<<<<<<<<
' ***************************************************************
ThisChipID CON "0"
DEFINE OSC 4
DEFINE HSER_RCSTA 90h ' enable serial port,
DEFINE HSER_TXSTA 24h ' enable transmit,
DEFINE HSER_BAUD 9600 ' set baudrate to 9600
DEFINE HSER_CLOERR 1 ' automatic clear overrun error
TRISD = %00000000 ' D to outputs for the LEDs
TRISC = %10000000 ' PORTC.7 is the RX input, PORTC.6 is the TX output
ADCON1 = %00001111 ' Set up ADCON1 register no matter what yr doing!!!
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
;-- Place a copy of these variables in your Main program -------------------
;-- The compiler will tell you which lines to un-comment --
;-- Do Not un-comment these lines --
;---------------------------------------------------------------------------
;wsave VAR BYTE $20 SYSTEM ' location for W if in bank0
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
' if using $70, comment wsave1-3
' --- IF any of these three lines cause an error ?? ------------------------
' Comment them out to fix the problem ----
' -- Which variables are needed, depends on the Chip you are using --
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
' --------------------------------------------------------------------------
' ***************************************************************
' ASM Interrupt Definitions
' ***************************************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, ReloadTMR1, ASM, no ; MUST be first
INT_Handler TMR1_INT, _T1handler, PBP, yes
INT_Handler RX_INT, _GetBytes, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
' Variable definition
':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ERROR_LED VAR PORTD.1 ' rename the LED's
LATE_LED VAR PORTD.2
HEART_LED VAR PORTD.0
PORTD = 0
LEDonDELAY CON 4
TxEndChar CON "~"
SyncByte CON "S"
i VAR BYTE
SerialData VAR BYTE
CmdVal VAR BYTE
LenAdjVal VAR BYTE
AdjVal VAR BYTE
ERRORtime VAR BYTE
LATEtime VAR BYTE
HEARTtime VAR BYTE
state VAR BYTE
SyncRcvd VAR state.0 ' sync byte received
ForMe VAR state.1 ' packet is for this device
CmdRcvd VAR state.2 ' command has been received
LenAdjRcvd VAR state.3 ' decimal length of adjustment value to follow
AdjRcvd VAR state.4 ' adjustment factor has been received
MsgRcvd VAR state.5 ' compelte message received
ERROR VAR state.6 ' sync received out of order
LATE VAR state.7 ' command received before last one was processed
state = 0 ' Initialize default values
i = 0
cmdVal = 0
LenAdjVal = 0
AdjVal = 0
serialdata = 0
ArrayLength CON 3
myArray VAR BYTE[ArrayLength]
varResult VAR BYTE
' Example of received command from master chip:
' ============================================
' SyncByte, Chip Id, Cmd Id, Length of modifier, <modifier>, TxEndChar
'HSEROUT ["S", "0", "A", "3", "155", "~"]
;--- Change these to match the desired interrupt frequency -------------------
;--- See http://DarrelTaylor.com/DT_INTS-14/TimerTemplate.html for more Info.
@Freq = 10 ; Frequency of Interrupts in Hz
@Prescaler = 2 ; Timers Prescaler setting
T1CON = $10 ; $30 = Prescaler 1:8, TMR1 OFF
; $00=1:1, $10=1:2, $20=1:4, $30=1:8 -- Must match @Prescaler value
' Enable interrupts
@ INT_ENABLE RX_INT ; enable USART RX_INT interrupts
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
GOSUB StartTimer ; Start Timer 1
Main:
IF MsgRcvd THEN GOSUB ProcessCmdAdj ' Process incomming data
IF ERROR THEN ' if there's been an Error
HIGH ERROR_LED ' Turn ON ERROR LED
ERROR = 0 ' reset the error flag
ERRORtime = LEDonDELAY ' start countdown till LED-OFF
HSEROUT ["Error",13,10]
; HSEROUT ["SyncRcvd: ", DEC SyncRcvd,", SyncIndx: ",DEC SyncIndx, _
; ", ForMe: ", DEC ForMe,", CmdRcvd: ",DEC CmdRcvd, _
; ", AdjRcvd: ",DEC AdjRcvd,", Cmd: ",CmdVal, ", Adj: ",DEC AdjVal,13,10]
ENDIF
IF LATE THEN ' if command took too long
HIGH LATE_LED ' Turn ON LATE LED
LATE = 0 ' reset the LATE flag
LATEtime = LEDonDELAY ' start countdown till LED-OFF
HSEROUT ["Late",13,10]
ENDIF
GOTO Main
'*********** Process received command **************************************
ProcessCmdAdj:
' varResult = myArray[0]*100 + myArray[1]*10 + myArray[2]
HSEROUT ["Cmd: ", CmdVal, _ ' send Command, Length of Adjustment & Adjustment value and CR/LF
", LenAdj: ", LenAdjVal, " [", DEC LenAdjVal, "]", _
", Adj: ", myArray[0], myArray[1], myArray[2], 13, 10]
' ", Adj: ", AdjVal, " [", DEC AdjVal,"]", 13, 10]
state = 0 ' indicate CMD & ADJ has been processed
cmdVal = 0
LenAdjVal = 0
AdjVal = 0
For i = 0 to (ArrayLength - 1) ' clear out array
myArray[i] = 0
NEXT i
RETURN
' ***************************************************************
' [TMR1_INT - interrupt handler]
' ***************************************************************
T1handler:
IF ERRORtime > 0 THEN ' if the Error LED is ON
ERRORtime = ERRORtime - 1 ' decrement the count
IF ERRORtime = 0 THEN ' when it reaches 0
LOW ERROR_LED ' turn the Error LED OFF
ENDIF
ENDIF
IF LATEtime > 0 THEN ' if the LATE LED is ON
LATEtime = LATEtime - 1 ' decrement the count
IF LATEtime = 0 THEN ' when it reaches 0
LOW LATE_LED ' turn the LATE LED OFF
ENDIF
ENDIF
HEARTtime = HEARTtime + 1 ' Toggle heartbeat ~.5sec
IF HEARTtime = 7 THEN
HEARTtime = 0
TOGGLE HEART_LED
ENDIF
@ INT_RETURN
' ***************************************************************
' [RX_INT - interrupt handler]
' ***************************************************************
GetBytes:
' TODO: Update code to handle AdjVal > 1 character (an array?)
HSERIN [Serialdata] ' Get the serial data (guaranteed here to have at
IF Serialdata = SyncByte THEN
IF SyncRcvd THEN ' if it's a Sync byte,
state = 0 ' last command was corrupted; reset 'state'
ERROR = 1 ' and indicate error
ENDIF
SyncRcvd = 1 ' indicate Sync was rcvd
ELSE
IF SyncRcvd THEN
IF !ForMe THEN ' if we haven't rcvd the ID
IF Serialdata = ThisChipID THEN 'and this byte matches the ID
ForMe = 1 ' indicate ID rcvd
ELSE
state = 0 ' Not meant for this chip, reset and wait for next msg
ENDIF
ELSEIF !CmdRcvd THEN
CmdVal = SerialData
CmdRcvd = 1
ELSEIF !LenAdjRcvd THEN
LenAdjVal = SerialData
LenAdjRcvd = 1
i = 0
ELSEIF !AdjRcvd THEN
AdjVal = SerialData
myArray[i] = AdjVal
i = i + 1
If i = ArrayLength THEN
AdjRcvd = 1
ENDIF
ELSEIF !MsgRcvd THEN
If SerialData = TxEndChar THEN
MsgRcvd = 1
ENDIF
ENDIF
ENDIF
ENDIF
@ INT_RETURN
;---[TMR1 reload - interrupt handler]-----------------------------------------
ASM ; Calculate Timer Reload Constant
ReloadInst = 8 ; # of Intructions used to reload timer
if ((Prescaler == 1)||(Prescaler == 2)||(Prescaler == 4)||(Prescaler == 8))
MaxCount = 65536 + (ReloadInst / Prescaler)
TimerReload = MaxCount - (OSC*1000000/4/Prescaler/Freq)
if ((TimerReload < 0) || (TimerReload > (65535-ReloadInst)))
error Invalid Timer Values - check "OSC", "Freq" and "Prescaler"
endif
else
error Invalid Prescaler
endif
ENDASM
@Timer1 = TMR1L ; map timer registers to a word variable
Timer1 VAR WORD EXT
TimerReload CON EXT ; Get the External Constant
TMR1ON VAR T1CON.0 ; Alias the Timers ON/OFF bit
;---Reload Timer1------
ASM
ReloadTMR1
MOVE?CT 0, T1CON, TMR1ON ; 1 stop timer
MOVLW LOW(TimerReload) ; 1 Add TimerReload to the
ADDWF TMR1L,F ; 1 value in Timer1
BTFSC STATUS,C ; 1/2
INCF TMR1H,F ; 1
MOVLW HIGH(TimerReload) ; 1
ADDWF TMR1H,F ; 1
MOVE?CT 1, T1CON, TMR1ON ; 1 start timer
INT_RETURN
ENDASM
;---Start/Stop controls -----
StartTimer:
Timer1 = TimerReload ; Load Timer
TMR1ON = 1 ; start timer
RETURN
StopTimer:
TMR1ON = 0 ; stop timer
RETURN
Bookmarks