Menu

Shift a byte out a port, bit by bit ?

Help
Paul Haug
2017-04-16
2017-04-16
  • Paul Haug

    Paul Haug - 2017-04-16

    I want to shift out the 8 bit A/D conversion value for testing (read the a/d with my logic analyzer) but I can't find shift info. I want to do it with GCB code, not use any .h library.
    Here is my existing code, the a/d read works but with the 8 pin chip I cannot output the full 8 bits in parallel..
    So, serial shift seems a way to do it.
    ;
    ;============================my exsisting code================================
    ;Read A/D temp values of thermistors
    'Pin values for 12F1840
    ;AN0 is pin 7
    ;AN1 IS PIN 6
    ;AN2 IS PIN 5
    ;AN3 IS PIN 3
    #chip 12F1840, 8 'Pic 12F1840
    #config MCLRE = Off, Osc = Int 'Turn off MCLR, select internal osc.
    'WDT and LVP are disabled automatically

    dim advalue1 as byte 'Location to store a/d value
    dim LoopCount as Byte

    Dir PORTA.4 In 'Set the pin 3 used for A/D conversion to an input
    Dir porta.5 out ;Pin 2 for led test light

    'Main routine starts

    for LoopCount = 1 to 3 ;3 fast blink to show it is starting
    set porta.5 on ;led on
    Wait 250 ms
    set porta.5 off ;led off
    Wait 250 ms 'Wait
    next loopcount

    Do

    advalue1 = ReadAD(AN3)
    ; if advalue1 > 127 then
    ; set porta.5 on ;led on
    ; else
    ; set porta.5 off ;led off
    ; end if
    ;Now shift a/d value out porta.5 ?????????????????????????????????????????????
    ;shift rtn will go here
    ;lsb or msb first for test
    ;
    Wait 100 ms
    Loop ;end of do loop

     

    Last edit: Paul Haug 2017-04-16
  • Chris Roper

    Chris Roper - 2017-04-16

    Somthing like this will do it but you may need to introduce a dleay in the loop iff the Bits are too fast:

    For NumBits = 0 to 7
        Rotate advalue1 Right
        If STATUS.C Set PortA.5 ON
        Else Set PortA.5 OFF
        End If
    Next
    

    Cheers
    Chris

     
  • William Roth

    William Roth - 2017-04-16

    It all depends upon what you want to see on your logic analyzer. Do you want the data formatted so that the Logic Analyzer can decode a protocol such as RS232 ? Or do you simply want to take a look and easily be able to see the 1's and 0's ?

    I borrowed this protocol from DHT-11. A "1" is 100 us wide and a "0" is 25 us wide. There is 50 us between bits. This allows you to look at the signal and easily see the 1's and 0's. You will need to modify as needed for your particular chip.

    #chip 18F25K80, 32
    #CONFIG OSC = INTIO2,XINST = OFF, MCLRE = ON
    #Config DEBUG = OFF
    
    
    #option explicit
    
    #define Bit0 ADVal.0
    #define Bit1 ADVal.1
    #define Bit2 ADVal.2
    #define Bit3 ADVal.3
    #define Bit4 ADVal.4
    #define Bit5 ADVal.5
    #define Bit6 ADVal.6
    #define Bit7 ADVal.7
    #define PORTC.1 OUTPORT
    
    DIR OUTPORT OUT
    DIM ADVAL as Byte
    
    
    Do
        AdVal = READAD(An9,True)
        ShiftOUTBits
        Wait 200 ms
    Loop
    
     Sub ShiftOutBits
        If Bit7 = 1 then Pulseout OUTPORT, 100 us
        If Bit7 = 0 then Pulseout OUTPORT, 25 us
        Wait 50 us
    
        If Bit6 = 1 then Pulseout OUTPORT, 100 us
        If Bit6 = 0 then Pulseout OUTPORT, 25 us
        Wait 50 us
    
        If Bit5 = 1 then Pulseout OUTPORT, 100 us
        If Bit5 = 0 then Pulseout  OUTPORT,25 us
        Wait 50 us
    
        If Bit4 = 1 then Pulseout OUTPORT, 100 us
        If Bit4 = 0 then Pulseout OUTPORT, 25 us
        Wait 50 us
    
        If Bit3 = 1 then Pulseout OUTPORT, 100 us
        If Bit3 = 0 then Pulseout OUTPORT, 25 us
        Wait 50 us
    
        If Bit2 = 1 then Pulseout OUTPORT, 100 us
        If Bit2 = 0 then Pulseout OUTPORT, 25 us
        Wait 50 us
    
        If Bit1 = 1 then Pulseout OUTPORT, 100 us
        If Bit1 = 0 then Pulseout OUTPORT, 25 us
        Wait 50 us
    
        If Bit0 = 1 then Pulseout OUTPORT, 100 us
        If Bit0 = 0 then Pulseout OUTPORT, 25 us
        Wait 50 us
     End Sub
    
     
  • William Roth

    William Roth - 2017-04-16

    Here is the same basic code but optimized by using rotate in a repeat loop

    #chip 18F25K80, 32
    #CONFIG OSC = INTIO2,XINST = OFF, MCLRE = ON
    #Config DEBUG = OFF
    #option explicit
    
    #define Bit7 ADVal.7
    #define Outport PORTC.1
    
    DIR OUTPORT OUT
    DIM ADVAL as Byte
    
    Do
        AdVal = READAD(An9,True)
        ShiftOutBits
        Wait 200 ms
    Loop
    
    Sub ShiftOutBits
           Set Status.C OFF
          repeat 8
              If Bit7  = 1 then
                  Pulseout Outport, 100 us
              Else
                 Pulseout Outport, 25 us
            End If
            Rotate ADVal Left
            Wait 50 us
         End Repeat
    End Sub
    
     
  • Paul Haug

    Paul Haug - 2017-04-16

    Really great, thanks guys. Both rotate and individual bit banging, both what I need. Some how I couldn't find right shift/left shift in the code description, so now I know it's rotate.
    .
    On the rotate example above, STATUS.C I asume is the overflow/shiftout bit ? I will try to look it up as I need more clarification on this bit, is it common to all shifts, what does the "C" part stand for ?
    EDIT:################
    Found it now that I know to look for rotate, not shift. Also explains STATUS.C which is the carry bit.
    Dang this GCB is addictive
    END EDIT####################

     

    Last edit: Paul Haug 2017-04-16
  • Paul Haug

    Paul Haug - 2017-04-16

    Found it now that I know to look for rotate, not shift. Also explains STATUS.C which is the carry bit.
    Dang this GCB is addictive.

     

    Last edit: Paul Haug 2017-04-16
  • William Roth

    William Roth - 2017-04-16

    There are Shift functions but the names are somewhat confusing.

    These are FnLSL and FnLSR.

    Example: Databyte = FnLSL(Databyte ,2) '// shift left 2 places
    Example: Databyte = FnLSR( Databyte, 4 ) '// Shift Right 4 places

    Sometimes I "rename" these with a more intuitive/descriptive name using #define

      #define ShiftL FnLSL
    
    
     Databyte = ShiftL(Databyte,2)
    

    *** To read more about FnLSL and FnLSR See Help > Command Referenece > Bitwise

     

    Last edit: William Roth 2017-04-16
    • Chris Roper

      Chris Roper - 2017-04-16

      Trying to find names that are logical but dont conlict with names used in core or hidden functions is a difficult balancing act. In this case FnLSL/FnLSR were chosen becouse LSL/LSR are reserved words (ASM mnemonics) so Fn was added as a prefix to indicate that it was a function that took an argument and returned a result allowing it to replace a variable. I think they have been depreciated, or will be, as Hugh was going to intergrate them into the core compiler. No harm in using them though and they arew actualy a wrapper for the rotate function.

       
      • Anobium

        Anobium - 2017-04-16

        Not depreciated. Still need them.

        If Help or IDE/Helpers need updating we need to restore.

        😀

         
  • Paul Haug

    Paul Haug - 2017-04-16

    Yes, thank you William. I did come across FnLSL and FnLSR but the nanes didn't mean anything so I skipped reading the details. Now I will go back and read. And your renaming scheme is great idea.
    Thanks

     
  • stan cartwright

    stan cartwright - 2017-04-16

    Me to Paul Haug. I saw Fn and thought function so skipped it. You don't need to set c on/off it seems with FnLSR. I found rotate first. Quicker than multiply/divide for bit values..multiply/divide 2,4,8,,128 it seems.

     
    • Chris Roper

      Chris Roper - 2017-04-16

      You are correct, the Carry Flag is ignored in the FnLSL (Logic Shift Left) and FnLSR (Logic Shft Right) the two related functions FnASR (Arithmetic Shift Right) and FnROT are covered by the Rotate function, because they use The Carry Flag, so were not encoded as separate functions.

      I am not sure why you ignored them because they are functions, Functions actually simplify your code, i.e.

          'Set port direction
          Dir PortB Out
      
          'Set initial state of port (LED 4 on)
          PORTB = b'00010000'
      
          PortB = FnLSR(PortB) ' Shilft the LED one Bit to the Right
      

      FnLSL, FnLSR and Rotate can all work on Word values too so you can multiply or divide by a binary number up to 32768.

      Rotate is used where you want the Carry bit to influence the result, Logic Shift Functions are used where you don't want the low order bit rotating into the the high order bit as would happen, with disastrous results, in your division example above.

      Cheers
      Chris

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.