News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

Had to replace SHOut command

Started by shantanu@india, Jun 29, 2025, 04:20 PM

Previous topic - Next topic

shantanu@india

Hi,
I didn't have time to delve deep into it so I simply replaced the SHOut with a for loop. The PIC was hanging for some reason with the SHOut.

I have attached my program for others to analyze. The commnted out SHOut lies in the "control_relay" subroutine
Regards
Shantanu

Frizie

#1
I can not open the .rar file.
Please send .zip file.
Ohm sweet Ohm | www.picbasic.nl

Pepe

#2
If the program doesn't work in Proteus, it's because the timer interrupt is disabled after shout is called, but I think it's not a problem with Proteus; I am attaching a working program.

'28.6.25...BOREN disabled to eliminate initial chattering(power on jitter?? why??)
'27.6.25 The relays are driven through a shift register
'Hysteresis of 0.5 degC added to avoid relay chattering
'Control relays according to temperature setpoints
'20.5.25 Programming & storing the setpoints added.
'19.5.25 Testing the pushbuttons
'18.5.25 Reading temperature from DS18B20 connected to  PORTA.1
'17.5.25 Testing the hardware
;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings

Device = 18F24K22

Config_Start
  FOSC = INTIO67    ;Internal oscillator block
  PLLCFG = OFF    ;Oscillator used directly
  PRICLKEN = On    ;Primary clock enabled
  FCMEN = OFF    ;Fail-Safe Clock Monitor disabled
  IESO = OFF    ;Oscillator Switchover mode disabled
  PWRTEN = On    ;Power up timer enabled
  BOREN = On    ;Brown-out Reset enabled and controlled by software (SBOREN is enabled)
  BORV = 190    ;VBOR set to 1.90 V nominal
  WDTEN = On    ;WDT is always enabled. SWDTEN bit has no effect
  WDTPS = 32768    ;1:32768
  CCP2MX = PORTC1    ;CCP2 input/output is multiplexed with RC1
  PBADEN = OFF    ;PORTB<5:0> pins are configured as digital I/O on Reset
  CCP3MX = PORTB5    ;P3A/CCP3 input/output is multiplexed with RB5
  HFOFST = On    ;HFINTOSC output and ready status are not delayed by the oscillator stable status
  T3CMX = PORTC0    ;T3CKI is on RC0
  P2BMX = PORTB5    ;P2B is on RB5
  MCLRE = INTMCLR    ;RE3 input pin enabled; MCLR disabled
  STVREN = On    ;Stack full/underflow will cause Reset
  LVP = OFF    ;Single-Supply ICSP disabled
  XINST = OFF    ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
  Debug = OFF    ;Disabled
  Cp0 = On    ;Block 0 (000800-001FFFh) code-protected
  CP1 = On    ;Block 1 (002000-003FFFh) code-protected
  CPB = On    ;Boot block (000000-0007FFh) code-protected
  CPD = OFF    ;Data EEPROM not code-protected
  WRT0 = On    ;Block 0 (000800-001FFFh) write-protected
  WRT1 = On    ;Block 1 (002000-003FFFh) write-protected
  WRTC = On    ;Configuration registers (300000-3000FFh) write-protected
  WRTB = On    ;Boot Block (000000-0007FFh) write-protected
  WRTD = OFF    ;Data EEPROM not write-protected
  EBTR0 = On    ;Block 0 (000800-001FFFh) protected from table reads executed in other blocks
  EBTR1 = On    ;Block 1 (002000-003FFFh) protected from table reads executed in other blocks
  EBTRB = On    ;Boot Block (000000-0007FFh) protected from table reads executed in other blocks
Config_End

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------
        Declare Xtal= 16
        Declare Stack_Size 40
        Declare Reminders 0
        Declare Warnings 0
        Declare Watchdog On
        Declare Optimiser_Level = 3                ' Full optimisation
        Declare Dead_Code_Remove = On            ' Remove redundant ASM mnemonics
        Declare Create_Coff On
        Declare LCD_DTPin PORTB.4 'using 4 wire interface
        Declare LCD_ENPin PORTB.3  ' used to assing En line of the pin
        Declare LCD_RSPin PORTB.2 'used to assing RS line attachment
        Declare LCD_Lines 2 
       
        Declare SHOW_SYSTEM_VARIABLES = True

'*************************************************************************************
Symbol buff_start "%"      'start character...32 characters follow this
Symbol buff_stop  "#"      'stop character...1+ 32 characters precede this
Symbol DigIn  PORTA.0      'digital input
Symbol sensor PORTA.1      'sensor input 
Symbol prog_pb  PORTA.2
Symbol inr_pb  PORTA.3
Symbol dcr_pb  PORTA.4
Symbol enter_pb PORTA.5
'Symbol Dout1  LATC.4
'Symbol Dout2  LATB.0
'Symbol Dout3  LATC.3
'Symbol Dout4  LATC.2
'Symbol Dout5  LATC.1
'Symbol Dout6  LATC.0
'Symbol Dout7  LATA.6
'Symbol Dout8  LATA.7
Symbol StrobePin  LATA.7
Symbol DataPin    LATC.0
Symbol ClockPin  LATA.6
Symbol dir    LATC.5      'directionD 
Symbol led    LATB.1      'led
Symbol Hys    5

'************************************************************************************
Set1Save  EData Word  300    'default value of temerature set 1
Set2Save  EData Word  310    'default value of temerature set 2
Set3Save  EData Word  320    'default value of temerature set 3
Set4Save  EData Word  330    'default value of temerature set 4
Set5Save  EData Word  340    'default value of temerature set 5
Set6Save  EData Word  350    'default value of temerature set 6
Set7Save  EData Word  360    'default value of temerature set 7
Set8Save  EData Word  370    'default value of temerature set 8
'*************************************************************************************
Dim timer1        As TMR1L.Word
Dim timer1_count  As Word
Dim timer1_count2 As Word
Dim lcd_init      As Word
Dim display_timer As Word
Dim inbyte        As Byte
Dim rxbuffer[32]  As Byte
Dim buff_ptr      As Byte
Dim buff_full    As Bit
Dim lcdinit      As Byte
Dim  BPF          As Byte System
Dim refresh_flag  As Bit
Dim sec_pulse    As Bit
Dim sec          As Word
Dim blink        As Bit 
Dim jump_val      As Word

Dim wTemperature  As Word ' Holds the temperature value
Dim Temperature  As Word

Dim keypresstimer As Word
Dim enter_stat    As Bit
Dim count_val    As Word
Dim prog_lev      As Byte
Dim relay_state  As Byte

Dim Set1    As Word
Dim Set2    As Word
Dim Set3    As Word
Dim Set4    As Word
Dim Set5    As Word
Dim Set6    As Word
Dim Set7    As Word
Dim Set8    As Word

Dim Flag1    As Bit
Dim Flag2    As Bit
Dim Flag3    As Bit
Dim Flag4    As Bit
Dim Flag5    As Bit
Dim Flag6    As Bit
Dim Flag7    As Bit
Dim Flag8    As Bit

Dim index    As Byte
Dim BitVal  As Byte
'**************************************************
GoTo main
'*************************************************
On_Hardware_Interrupt GoTo interrupt_program

interrupt_program:

    Context Save

  'TMR1 interrupt  @ 100 msec

    If PIR1.0 =1 Then                               
        Clear PIR1.0
        timer1=15535
        Inc timer1_count
        Inc timer1_count2
        If timer1_count>=4 Then
            Set refresh_flag       
            timer1_count=0           
        EndIf
        If timer1_count2>=10 Then
            Set sec_pulse           
            timer1_count2=0
        EndIf     
        If sec_pulse=1 Then      '@ 1 sec
          sec_pulse=0
          Inc sec
          blink=blink^1      'toggle blink
          led = led^1         
        EndIf
    EndIf
  Context Restore
'*****************************************************
main:   
  OSCCON=%01110010            '16 MHz clock
  EECON1=0
  Clear
  Cls 
  DelayMS 200
  PORTA=0
  PORTB=0
  PORTC=0
  PORTE=0
  LATA=0
  LATB=0
  LATC=0
  ANSELA=0
  ANSELB=0
  ANSELC=0
  WPUB.0=1
  TRISA=%00111111
  TRISB=0
  TRISC=%11000000 
  jump_val=1 
  led=0
  dir=0                    'default in receive mode
  SHOut DataPin,ClockPin, LsbFirst,[relay_state\8]    'all outputs initialized to zero   
  High StrobePin
  Nop
  Low StrobePin
  Set1=ERead Set1Save
  Set2=ERead Set2Save
  Set3=ERead Set3Save
  Set4=ERead Set4Save
  Set5=ERead Set5Save
  Set6=ERead Set6Save
  Set7=ERead Set7Save
  Set8=ERead Set8Save
  timer1=15535              'load timer1 with the preload value
  T1CON=%00110011          'start timer1 with 16-bit read , Fosc/4  clock(0.25us) , 1:8 prescale / 100 msec interrupt rate
  PIE1=%00100001        'unmask USART receive & TMR1 interrupt
  INTCON=%11000000      'Peripheral interrupts enabled
 
  Print At 1,1,"Ultratech"
  While 1=1
    Clrwdt   
    If refresh_flag=1 Then
        refresh_flag=0
        GoSub display_init              'reinitialize display after 60 secs 
        GoSub kscan
        GoSub save_setpoint       
        GoSub read_temperature          '
        GoSub control_relay                       
        GoSub display_update          '   
    EndIf   
  Wend

'*************************************************************************************
'reinitialize the LCD after 60 seconds
display_init:
If sec=60 Then                                 
  lcd_init=0
  Clear BPF.1                                          ' reinitialize LCD after 60 secs
  sec=0                                   
EndIf 
Return
'*******************************************************************************
read_temperature:
    wTemperature = DS18B20_Read()                          ' Read the temperature from the DS18B20 device
    If wTemperature <> 32767 Then                          ' Was the temperature read?
      Temperature=wTemperature
    EndIf
    Return
'*******************************************************************************
control_relay:
   
    If Temperature>= Set1 And Flag1=0 Then
        relay_state=relay_state|%00000001
        Flag1=1
    ElseIf Temperature<Set1 And Flag1=0 Then
        relay_state=relay_state&%11111110
    ElseIf Temperature>= Set1 And Flag1=1 Then
        relay_state=relay_state|%11111110
    ElseIf Temperature < (Set1-hys) And Flag1=1 Then
        relay_state=relay_state&%00000001
        Flag1=0   
    EndIf
    If Temperature>= Set2 And Flag2=0 Then
        relay_state=relay_state|%00000010
        Flag2=1
    ElseIf Temperature<Set2 And Flag2=0 Then
        relay_state=relay_state&%11111101
    ElseIf Temperature>= Set2 And Flag2=1 Then
        relay_state=relay_state|%00000010
    ElseIf Temperature < (Set2-hys) And Flag2=1 Then
        relay_state=relay_state&%11111101
        Flag2=0   
    EndIf
    If Temperature>= Set3 And Flag3=0 Then
        relay_state=relay_state|%00000100
        Flag3=1
    ElseIf Temperature<Set3 And Flag3=0 Then
        relay_state=relay_state&%11111011
    ElseIf Temperature>= Set3 And Flag3=1 Then
        relay_state=relay_state|%00000100
    ElseIf Temperature < (Set3-hys) And Flag3=1 Then
        relay_state=relay_state&%11111011
        Flag3=0   
    EndIf
    If Temperature>= Set4 And Flag4=0 Then
        relay_state=relay_state|%00001000
        Flag4=1
    ElseIf Temperature<Set4 And Flag4=0 Then
        relay_state=relay_state&%11110111
    ElseIf Temperature>= Set4 And Flag4=1 Then
        relay_state=relay_state|%00001000
    ElseIf Temperature < (Set4-hys) And Flag4=1 Then
        relay_state=relay_state&%11110111
        Flag4=0   
    EndIf
    If Temperature>= Set5 And Flag5=0 Then
        relay_state=relay_state|%00010000
        Flag5=1
    ElseIf Temperature<Set5 And Flag5=0 Then
        relay_state=relay_state&%11101111
    ElseIf Temperature>= Set5 And Flag5=1 Then
        relay_state=relay_state|%00010000
    ElseIf Temperature < (Set5-hys) And Flag5=1 Then
        relay_state=relay_state&%11101111
        Flag5=0   
    EndIf
    If Temperature>= Set6 And Flag6=0 Then
        relay_state=relay_state|%00100000
        Flag6=1
    ElseIf Temperature<Set6 And Flag6=0 Then
        relay_state=relay_state&%11011111
    ElseIf Temperature>= Set6 And Flag6=1 Then
        relay_state=relay_state|%00100000
    ElseIf Temperature < (Set6-hys) And Flag6=1 Then
        relay_state=relay_state&%11011111
        Flag6=0   
    EndIf
    If Temperature>= Set7 And Flag7=0 Then
        relay_state=relay_state|%01000000
        Flag7=1
    ElseIf Temperature<Set7 And Flag7=0 Then
        relay_state=relay_state&%10111111
    ElseIf Temperature>= Set7 And Flag7=1 Then
        relay_state=relay_state|%01000000
    ElseIf Temperature < (Set7-hys) And Flag7=1 Then
        relay_state=relay_state&%10111111
        Flag7=0   
    EndIf
    If Temperature>= Set8 And Flag8=0 Then
        relay_state=relay_state|%10000000
        Flag8=1
    ElseIf Temperature<Set8 And Flag8=0 Then
        relay_state=relay_state&%01111111
    ElseIf Temperature>= Set8 And Flag8=1 Then
        relay_state=relay_state|%10000000
    ElseIf Temperature < (Set8-hys) And Flag8=1 Then
        relay_state=relay_state&%01111111
        Flag8=0   
    EndIf
   
    INTCON.7=0
    SHOut DataPin,ClockPin, MsbFirst,[relay_state]
           
    High StrobePin
    Nop
    Low StrobePin
    INTCON.7=1
   
    PIE1.0 = 1 'added

'    LoadBit relay_state,0,Dout1
'    LoadBit relay_state,1,Dout2
'    LoadBit relay_state,2,Dout3
'    LoadBit relay_state,3,Dout4
'    LoadBit relay_state,4,Dout5
'    LoadBit relay_state,5,Dout6
'    LoadBit relay_state,6,Dout7
'    LoadBit relay_state,7,Dout8

   
    Return
'********************************************************************************
display_update:     
    Print At 1,1," ", Dec2 Temperature / 10, ".", Dec Temperature//10,$DF, "C ", Bin8 relay_state
    If prog_lev=0 Then       
        Print At 2,1,"S1 ", Dec2 Set1 / 10, ".", Dec Set1//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    ElseIf prog_lev=1 Then       
        Print At 2,1,"S2 ", Dec2 Set2 / 10, ".", Dec Set2//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    ElseIf prog_lev=2 Then       
        Print At 2,1,"S3 ", Dec2 Set3 / 10, ".", Dec Set3//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    ElseIf prog_lev=3 Then       
        Print At 2,1,"S4 ", Dec2 Set4 / 10, ".", Dec Set4//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    ElseIf prog_lev=4 Then       
        Print At 2,1,"S5 ", Dec2 Set5 / 10, ".", Dec Set5//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    ElseIf prog_lev=5 Then       
        Print At 2,1,"S6 ", Dec2 Set6 / 10, ".", Dec Set6//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    ElseIf prog_lev=6 Then     
        Print At 2,1,"S7 ", Dec2 Set7 / 10, ".", Dec Set7//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    ElseIf prog_lev=7 Then       
        Print At 2,1,"S8 ", Dec2 Set8 / 10, ".", Dec Set8//10,$DF, "C ",Dec2 count_val / 10, ".", Dec count_val//10,$DF, "C"
    EndIf   
    Return
'*******************************************************************************
save_setpoint:
    If enter_stat=1 Then
        If prog_lev=0 Then
            Set1=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set1Save,[Set1]
            SetBit INTCON,7
            prog_lev=1
        ElseIf prog_lev=1 Then
            Set2=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set2Save,[Set2]
            SetBit INTCON,7
            prog_lev=2
        ElseIf prog_lev=2 Then
            Set3=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set3Save,[Set3]
            SetBit INTCON,7
            prog_lev=3
        ElseIf prog_lev=3 Then
            Set4=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set4Save,[Set4]
            SetBit INTCON,7
            prog_lev=4
        ElseIf prog_lev=4 Then
            Set5=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set5Save,[Set5]
            SetBit INTCON,7
            prog_lev=5
        ElseIf prog_lev=5 Then
            Set6=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set6Save,[Set6]
            SetBit INTCON,7
            prog_lev=6
        ElseIf prog_lev=6 Then
            Set7=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set7Save,[Set7]
            SetBit INTCON,7
            prog_lev=7
        ElseIf prog_lev=7 Then
            Set8=count_val            '& saving in EEPROM
            ClearBit INTCON,7
            EWrite Set8Save,[Set8]
            SetBit INTCON,7
            prog_lev=0
        EndIf
  EndIf
    Return
'********************************************************************************
' Read a DS18B20 device with its default 12-bit resolution
' Input    : None
' Output    : Returns the integer temperature value x10, in Celsius
'          : If the device cannot be read, the value returned is 32767
' Notes    : Uses integer calculations, so the temperature returned will need to be divided
'            for the whole and fraction numbers to be displayed
'          : Because the CRC value is not being used from the DS18B20 device,
'            there is no need to read all 9 data bytes from it
'
Proc DS18B20_Read(), SWord
    Dim bTimeOut As Result.Byte0  = $FF                    ' A timeout for the conversion wait loop
    OWrite sensor, 1, [$CC, $44]                            ' Start a temperature conversion
'
' Wait until the conversion is complete
'
    Repeat                                                  ' Create a loop
        If ORead sensor, 4 = 1 Then ReadTemp                ' Exit the loop if the conversion is complete
        DelayMS 10                                          ' A small delay within the loop
        Dec bTimeOut                                        ' Decrement the timeout counter
    Until STATUSbits_Z = 1                                  ' Finish the loop when it reaches zero
    Result = 32767                                          ' Return 32767 because the loop completed
    ExitProc                                                ' Exit the procedure prematurely because it timed out
ReadTemp:
    OWrite sensor, 1, [$CC, $BE]                            ' Set to read the temperature
    ORead sensor, 0, [Result.Byte0, Result.Byte1]          ' Read the temperature data only from the DS18B20 device
    Result = Result * 10                                    ' Multiply the raw temperature value by 10
    Result = Result / 16                                    ' Convert to Celsius
EndProc
'************************************************************************************* 
kscan:

  If inr_pb=1 Or dcr_pb=1 Then
      Inc keypresstimer
  Else
      Clear keypresstimer
  EndIf

  If keypresstimer>=10 Then
      jump_val=10     
  Else
      jump_val=1
  EndIf

                                  'first scan the prog/run button
  If prog_pb=1 Then
    If prog_lev<7 Then
      Inc prog_lev
    ElseIf prog_lev=7 Then
      prog_lev=0
    EndIf
  EndIf


                                    'then scan the enter button
  If enter_pb=1 Then
      enter_stat=1

  Else
      enter_stat=0
  EndIf

  If inr_pb=1 Then
      count_val=count_val+jump_val     
  EndIf

  If dcr_pb=1 Then

      If count_val-jump_val>=0 Then
          count_val=count_val-jump_val       
      EndIf

  EndIf
 

  Return

shantanu@india

Hi Pepe,
Thanks.
Unfortunately I don't have Proteus to simulate but I presume it is working OK in simulation.
In the actual hardware the led stops blinking & the pushbuttons stop responding with SHOut.
Regards
Shantanu

Pepe

Can you try the program I attached?

Pepe

#5
In the shout function, this disables the timer1 interrupt, which is why the LED and the keyboard do not work, because no interrupts are generated.

    Movf GEN,W
    Addlw 18
    Movwf FSR0L
    Comf GENH,W
    Andwf INDF0,F

 

it's the same as doing PIE1.0 = 0

I don't know why Les does it in shout.

If it is removed as shown in the code below, then it works correctly. I hope 'Les' can verify if I am correct.

__shout_8_
    movlw 8
__shout_
    movwf PP3
    setf FSR0H
    movff GEN2,FSR0L
    movf GEN2H,W
    btfsc GPR,2
    rcall __set_pin_high__
    btfss GPR,2
    rcall __pull_pin_low__
    setf FSR1H
    movff GEN2,FSR1L
                          '  movf GEN,W
                          '  addlw 18
                          '  movwf FSR0L
                          '  comf GENH,W
                          '  andwf INDF0,F
    movf PP3,W
    bz __shout_exit__
    btfsc GPR,0
    rcall __reversebits__16_
    movff GEN,FSR0L
__shout_loop__
    rrcf PP0H,F
    rrcf PP0,F
    movf INDF0,W
    iorwf GENH,W
    btfss STATUS,0
    xorwf GENH,W
    movwf INDF0
    rcall __shiftX_toggle_clock__
    decfsz PP3,F
    bra __shout_loop__
__shout_exit__
    return

shantanu@india

Thanks a million Pepe for detecting the fallacy.
I shall definitely try it out.
Maybe Les can have a look at the backend code generated by SHOut when he is free.
Regards
Shantanu

shantanu@india

Your code is working perfectly. :)
Thanks Pepe.
Regards
Shantanu