Hello again,

after solving my problems with serial port, I found that PIC (18F46K22) hangs after I send a command 14 times exactly.
I'm using some code I found in the forum to remote control via the NEC infrared protocol a receiver.
It works but when I press quickly 14 times the Volume UP button (to increase volume) the PIC hangs and a reset is needed.

Three questions for anyone who wants to help.
  • I can't increase the Oscillator speed (e.x. το 16 MHz) to get the higher serial port speeds I need, the code works only at 4 MHz.
    I realize that the values of DL1 and DL2 must be icreased, but they don't work for DL1 = 3200 and DL2 = 440 (for 16 MHz), so I'm stuck to 4 MHz
  • The program hangs PIC when I call quickly 14 times the VOLUP subroutine. What is wrong in this subroutine ? I have also implemented a basic repeat function (VOL+ button always pressed which works)
  • How can I enable a feature or a function like WDT to avoid this hang when it occurs ? As you can see in the top of the program I tried to enable the WDT and tried different prescale values but nothing happens. Can you help with that in case I cannot fix the hang ?

Here is the complete program :

Code:
'==================================================================================================
'====================================   CONFIGURE PIC   ===========================================
'==================================================================================================
'                                                     # 18F46K22 #
DEFINE OSC 4
'
DEFINE PULSIN_MAX 10000
'
@ CONFIG PBADEN = OFF                       ' PORTB<5:0> pins are configured as digital I/O on Reset
@ CONFIG LVP = OFF                          ' Single-Supply ICSP disabled
@ CONFIG XINST = OFF                        ' Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
'
'@ CONFIG STVREN = ON                        ' Stack full/underflow will cause Reset
'
'@ CONFIG WDTEN = ON                         ' WDT is always enabled. SWDTEN bit has no effect
'@ CONFIG WDTPS = 512                          ' Watchdog Timer Postscale Select bits
'
'@ CONFIG PWRTEN = ON                        ' Power up timer enabled
'@ CONFIG BOREN = SBORDIS                    ' Brown-out Reset enabled in hardware only (SBOREN is disabled)
'@ CONFIG BORV = 285                         ' VBOR set to 2.85 V nominal
'
@ CONFIG FOSC = INTIO67                      'Internal oscillator block
OSCCON.6 = 1         '####################   111 = 16, 110 = 8
OSCCON.5 = 0         '###### 16 MHz ######   101 =  4, 100 = 2
OSCCON.4 = 1         '####################
OSCTUNE.6 = 0        '##### PLL X 4 ######
'@ CONFIG PLLCFG = ON          'Oscillator multiplied by 4
'#########################################
'#######   Make Ports Digital   ##########
'#########################################
'
ANSELA = $00                                 'SET PORT A ALL DIGITAL
ANSELB = $00                                 'SET PORT B ALL DIGITAL
ANSELC = $00                                 'SET PORT C ALL DIGITAL
ANSELD = $00                                 'SET PORT D ALL DIGITAL
ANSELE = $00                                 'SET PORT E ALL DIGITAL
'
'==================================================================================================
'===================================    INCLUDE FILES    ==========================================
'==================================================================================================
'
'==================================================================================================
'===================================    SET PIC PORTS    ==========================================
'==================================================================================================
'
HCDATA var PORTC.5                               ' Pin 14 74HC595 
HCCLK  var PORTD.4                               ' Pin 11 74HC595  
HCLAT  var PORTC.7                               ' Pin 12 74HC595
CIVP   VAR PORTA.5                               ' TO ICOM REMOTE PORT CI-V
LCDP   VAR PORTB.0                               ' SERIAL LCD PORT (OPTIONAL)
INFRA  VAR PORTD.7                               ' Infrared LED DATA
'LED    VAR PORTC.0                               ' STATUS LED
'
'==================================================================================================
'====================================    SET VARIABLES    =========================================
'==================================================================================================
'
Leader VAR WORD                                  ' will be up to 900 for a 9mS leader pulse
BtnVal VAR BYTE[32]                              ' holds 32 pulse results
DByte1 VAR BYTE                                  ' address byte
DByte2 VAR BYTE                                  ' inverse of address byte
DByte3 VAR BYTE                                  ' command byte
DByte4 VAR BYTE                                  ' inverse of command byte
X      VAR BYTE                                  ' loop count
Y      VAR BYTE                                  ' = DByte3 (command) for subroutines selection
Z      VAR BYTE                                  ' Generic counter FOR-NEXT Loops (digits counter)
RBdata VAR BYTE[6]                               ' Bytes array to store digits for frequency or memory   
f1     VAR BYTE                                  ' Vol, SQL, MSB byte
f2     VAR BYTE                                  ' Vol, SQL, LSB Byte 
f3     VAR BYTE                                  ' BCD to BIN byte store for DEC calculations
f4     VAR BYTE                                  ' BCD to BIN byte store for DEC calculations
pattern   VAR Byte                                ' 74HC595 output pattern

'
'==================================================================================================
'=====================================     SET CONSTANTS    =======================================
'==================================================================================================
'
DL1    CON 800                                   ' > 8.5 ms pulse for NEC Protocol (Start) -  850 @ 4 MHz
DL2    CON 110                                   ' > 1.5 ms pulse for NEC Protocol (read bit 0 or 1) @ 4 MHX
LCDS   CON 16468                                 ' SERIAL LCD SPEED 16468 -> 9600
LINE1  CON 128                                   ' LCD Line 1
LINE2  CON 192                                   ' LCD Line 2
I      CON 254                                   ' LCD general command
CIVS   CON 84                                    ' "188"->4800, "84"->9600, "32"->19200 "813"->1200
CIVA   CON $70                                   ' TRX address
'
'####################################################################################################################################################
'
'
'##################################################################################################
'#################################     PROGRAM STARTS HERE    #####################################
'##################################################################################################
'
START:
'
CLEAR                                       '
pattern = %00000000                         ' LED OFF
gosub OUT_595
PAUSE 200
GOSUB LCDCLS
PAUSE 10
SEROUT2 LCDP,LCDS,["HELLO MALAKA"]
pattern = %11111111                         ' LED ON
gosub OUT_595
pause 500
pattern = %00000000                         ' LED OFF
gosub OUT_595
gosub LCDCLS	                             ' Clear LCD
'
'==================================================================================================
'==============================   MAIN LOOP CHECKS FOR INFRARED COMMAND   =========================
'==================================================================================================
'
MAIN: 
'
PULSIN INFRA,0,Leader                            ' Leader pulse is ~9mS low-going
IF Leader < DL1 THEN Main                        ' Valid start burst check > 8.5 ms

GOSUB READ32                                     ' Read 32 bytes (0-15 for address and 16-31 for command)   

'GOTO MAIN                                       ' ONLY FOR TESTING AND READING VARIOUS NEC REMOTES

GOSUB COMMANDS                                   ' GOTO Check Input Commands
PAUSE 100
GOTO MAIN
'
'==================================================================================================
'===================================   VOLUME UP SUBROUTINE    ====================================
'==================================================================================================
'
VOLUP:                                           ' All variables are set as bytes
'
Z = $01                                          ' For future functions
DO
	IF Leader > DL1 THEN 
		GOSUB VOLUP1                ' Go to increase volume
		ELSE
			pattern = 0
			GOSUB Out_595
        	GOTO MAIN 			
	ENDIF
PULSIN INFRA,0,Leader                    ' Check again for start pulse (autorepeat function) WORKS
LOOP
GOTO VOLUP                                       ' Go back to main routine to check for another button press
'
'==================================================================================================
'================================   VOLUME INCREASE AND BYTE CALCULATIONS   =======================
'==================================================================================================
'
VOLUP1:
'
GOSUB READVD

f4 = f4 + 10                                                ' Increase volume by 10 units

IF f3 < 2 AND f4 >= 99 THEN 
	f4 = 0                                                  ' Make sure result is less than 100
	f3 = f3 + 1                                             ' Increase hundreds by 1
ELSEIF f3 > 1 AND f4 > 54 THEN                              ' If volume > 254 stay to 254 (max)
	f3 = 2
	f4 = 54
ENDIF

f1 = ((f3 / 10) << 4) + (f3 // 10)                          ' Convert bin to BCD
f2 = ((f4 / 10) << 4) + (f4 // 10)                          ' Convert bin to BCD

SEROUT2 CIVP,CIVS,[$FE,$FE,civa,$E0,$14,$01,f1,f2,$FD]      ' NEW VOLUME setting
pause 50
'GOSUB PRINTVAL                                              ' Only for testing and displaying actual volume
     
RETURN
'
'==================================================================================================
'=====================================    RECEIVED COMMANDS    ====================================
'==================================================================================================
'
COMMANDS:
'
Y = DByte3
'
IF Y = 7 OR Y = 3 THEN               ' VOL - (added new NEC remote)
	pattern = 1
	GOSUB Out_595
'	GOSUB VOLDOWN
ENDIF
IF Y = 21 OR Y = 2 THEN              ' VOL + (added new NEC remote)
	pattern = 1
	GOSUB Out_595
	GOSUB VOLUP
ENDIF

RETURN
'
'################################################################################################################################
'########################################################   CLEAR LCD   #########################################################
'################################################################################################################################
'
LCDCLS:
'
SEROUT2 LCDP,LCDS,[254,1]           	' Clear LCD
return
'
'################################################################################################################################
'################################################################################################################################
'################################################################################################################################
'
' -------------------------------------------------------------------------------------------------------------------------------
Out_595:
'
SHIFTOUT HCDATA,HCCLK,1,[pattern]                      ' send pattern to 1st 74HC595
PULSOUT HCLAT, 5                                       ' latch outputs
RETURN
'
'==================================================================================================
'================================   READ 32 Bytes - Address and Command   =========================
'==================================================================================================
'
READ32:
'
FOR X = 0 TO 31                                  ' grab 32 incoming pulses
PULSIN INFRA,1,BtnVal[X]                         ' now measuring high-going pulse widths
NEXT X

FOR X = 0 TO 7                                   ' sort 1st 8 pulses
IF BtnVal[X] > DL2 THEN                          ' > 150 x 10uS = > 1.5mS pulse period
         DByte1.0[X]=1
         ELSE
         DByte1.0[X]=0
ENDIF
NEXT X
 
FOR X = 8 TO 15                                  ' sort 2nd 8 pulses, etc....
IF BtnVal[X] > DL2 THEN
         DByte2.0[X-8]=1
         ELSE
         DByte2.0[X-8]=0
ENDIF
NEXT X
 
FOR X = 16 TO 23
IF BtnVal[X] > DL2 THEN
         DByte3.0[X-16]=1
         ELSE
         DByte3.0[X-16]=0
ENDIF
NEXT X

FOR X = 24 TO 31
IF BtnVal[X] > DL2 THEN
         DByte4.0[X-24]=1
         ELSE
         DByte4.0[X-24]=0
ENDIF
NEXT X

DByte4 = ~ DByte4                                ' Reverse all the 8 bits to compare

IF DByte3 <> DByte4 THEN
	GOSUB LCDCLS
	SEROUT2 LCDP,LCDS, [I,LINE1,"Command ERROR !"]
	pause 500
	GOSUB LCDCLS
	pattern = 0
	GOSUB out_595
	GOTO MAIN
ENDIF

SEROUT2 LCDP,LCDS, [I,LINE1,"A : ",DEC3 DByte1, "-",BIN8 DByte1] ' PRINT ADDRESS
SEROUT2 LCDP,LCDS, [I,LINE2,"C : ",DEC3 DByte3, "-",BIN8 DByte3] ' PRINT COMMAND

RETURN
'
'==================================================================================================
'==================================   Read Volume & SQL Data   ====================================
'==================================================================================================
'
READVD:
'
SEROUT2 CIVP,CIVS,[$FE,$FE,CIVA,$E0,$14,Z,$FD]   ' Send this to the radio to read current SETTING
SERIN2 CIVP,CIVS,[SKIP 6,f1,f2]                  ' Skip first 6 useless bytes and read next 2 bytes
PAUSE 5                                          ' Give sometime to rest
f3 = ((f1 >> 4) * 10) + (f1 & $0f)               ' Convert BCD to binary
f4 = ((f2 >> 4) * 10) + (f2 & $0f)               ' Convert BCD to binary
RETURN                                           ' Go back to set new Volume or Squelch
'
Well, that's all folks...
Thanx in advance
Fanias