Menu

Changing the frequency of a PIC inside a program.

mkstevo
2019-10-04
2019-10-05
  • mkstevo

    mkstevo - 2019-10-04

    Is there a way of changing the oscillator frequency 'on the fly'?

    Thanks to Chris Roper, the white noise source is running well. The 'noise' generated sounds rather different at different ocsillator frequencies and I thought it might be useful to be able to change this using a button to select the different oscillator frequencies.

    Is this possible with GCB, or is the #Chip compiler directive the only way of setting the frequency?

     
  • Anobium

    Anobium - 2019-10-04

    Yes, you can. With ease but... you will impact the delay timing and other timing calcs.

    So, set the chip frequency as normal. Then, when you change simply proportionally change the delays. Remember, the USART would change also - so, just recalc and be aware of the proportional change.

    How?
    I would create a program with the different frequencie(s). Compile. Open the ASM. Lift the top piece of INITSYS and paste into your main program as a new Sub.

    ;Source: system.h (99)
    INITSYS
    ;asm showdebug OSCCON type is 105 'Bit(SPLLEN) Or Bit(IRCF3) And NoBit(INTSRC) and ifdef Bit(IRCF3)
    ;osccon type is 105
    ;OSCCON = OSCCON AND b'10000111'
    ;OSCCON = OSCCON OR b'01100000'
    ;Set IRCF3 On
      banksel OSCCON
      bsf OSCCON,IRCF3
    ;Set IRCF2 On
      bsf OSCCON,IRCF2
    ;Set IRCF1 Off
      bcf OSCCON,IRCF1
    ;Set IRCF0 Off
      bcf OSCCON,IRCF0
    ;Set SPLLEN Off
      bcf OSCCON,SPLLEN
    ;Ensure all ports are set for digital I/O and, turn off A/D
    

    So, the code you needs for this is the Great Cow BASIC code.

    This code is for ,2

    Set IRCF3 On
    Set IRCF2 On
    Set IRCF1 Off
    Set IRCF0 Off
    Set SPLLEN Off
    

    Then, I create new code with ,8. If you look carefully Set IRCF1 On

    Set IRCF3 On
    Set IRCF2 On
    Set IRCF1 On
    Set IRCF0 Off
    Set SPLLEN Off
    

    Now create all that you need. Take the code from INITSYS and stop at the line ;Ensure all ports are set for digital I/O and, turn off A/D

     
  • mkstevo

    mkstevo - 2019-10-04

    Thanks.
    As I'm not using any timing or other bits and pieces, I shouldn't need to do much else.

     
  • mkstevo

    mkstevo - 2019-10-04

    Here is my code for adjusting the frequency.
    A button on PortA.3 is tested for being pressed for a period of time which then increments the frequency. The button must be released for a period of time before the next change can be made.

    #Chip 12F1840, 32
    
    'Inspired by the Practical Electronics White Noise project, September 2019
    'White Noise source
    'Using a 31 bit shift register random generator XOR Q31 and Q28
    
    'Most of this work was done by Chris Roper
    'of the GCB forum for which I am most grateful.
    
    #Define Button  PortA.3
    Dir Button      In
    
    #Define Pressed 0
    
    Dim Noise       As Long  ' Create a 32bit shift register
    Let Noise     = Random   ' Seed the LSFR
    Dim PressTime   As Word
    Dim ReleaseTime As Word
    Dim TimeOut     As Word
    
    Dim LastFreq    As Byte
    Dim Freq        As Byte
    
    Dim LS          As Bit
    'This allows us to the port on, or off. Without it the port goes
    'momentarily low in each cycle, even if it is intended to stay high
    
    'You end up with this:
    
    '____|‾|‾|‾|____|‾|‾|____
    
    'Instead of this:
    
    '____|‾‾‾‾‾|____|‾‾‾|____
    
    Let PressTime   = 0
    Let ReleaseTime = 0
    Let LastFrq     = 0 '0 + 1 = 1 = 2MHz
    Let Freq        = Frq2
    
    
    #Define  Frq01  5
    #Define  Frq05  7
    #Define  Frq1   11
    #Define  Frq2   12
    #Define  Frq4   13
    #Define  Frq8   14
    #Define  Frq16  15
    #Define  Frq32  30
    
    Wait 100 mS
    ChangeFrequency
    
    Do
    
      If Button=Pressed Then
        If PressTime > TimeOut Then
          If ReleaseTime = 0 Then
            ChangeFrequency
            Let ReleaseTime = PressTime
          End If
        Else
          Let PressTime = PressTime + 1
        End If
      Else
        If ReleaseTime > 0 Then
          Let ReleaseTime = ReleaseTime - 1
          If ReleaseTime > TimeOut Then
            Let ReleaseTime = TimeOut
          End If
        End If
        If ReleaseTime = 0 Then
          Let PressTime   = 0
        End If
      End If
    
      LSFR
    
    Loop
    
    Sub ChangeFrequency
    
      Let LastFreq = LastFreq + 1
      If LastFreq > 8 Then 
        Let LastFreq = 1
      End If
    
    
      Select Case LastFreq
        Case 1
          Let Freq = Frq2
          Let TimeOut = 400
        Case 2
          Let Freq = Frq4
          Let TimeOut = 800
        Case 3
          Let Freq = Frq8
          Let TimeOut = 1600
        Case 4
          Let Freq = Frq16
          Let TimeOut = 3200
        Case 5
          Let Freq = Frq32
          Let TimeOut = 6400
        Case 6
          Let Freq = Frq01
          Let TimeOut = 25
        Case 7
          Let Freq = Frq05
          Let TimeOut = 50
        Case 8
          Let Freq = Frq1
          Let TimeOut = 200
      End Select
    
      If Freq.0 = 1 Then
        Set IRCF0 On
      Else
        Set IRCF0 Off
      End If
    
      If Freq.1 = 1 Then
        Set IRCF1 On
      Else
        Set IRCF1 Off
      End If
    
      If Freq.2 = 1 Then
        Set IRCF2 On
      Else
        Set IRCF2 Off
      End If
    
      If Freq.3 = 1 Then
        Set IRCF3 On
      Else
        Set IRCF3 Off
      End If
    
      If Freq.4 = 1 Then
        Set SPLLEN On
      Else
        Set SPLLEN Off
      End If
    
    End Sub
    
    Sub LSFR
    'This line causes an error:
    'Error: GCASM: Symbol 3.0 has not been defined
      'Let C = Noise.28 XOR Noise.31 ' Test and set Carry flag
    
    'Replaced with this If...Then
      If Noise.27 <> Noise.30 Then
        Let C = 1
      Else
        Let C = 0
      End If
    
      Rotate Noise Left             ' Rotate all 32 bits
      If Noise.31 <> LS Then
        Let LS = Noise.31
        Let PortA.2 = LS            ' Output bit 31
      End If
    End Sub
    
     
  • Chris Roper

    Chris Roper - 2019-10-04

    You shouldn't be running the Processor at 32MHz.
    You are hearing a strange pitch because you are running 4 times faster than the original code was designed for.
    The ASM in the article and the GCBASIC version both expect a Clock frequency of 8MHz.
    Change your Chip definition to:

    #Chip 12F1840,8
    

    and I think you will find that your pitch issues are reduced if not eliminated with no need to have a Clock adjust button.

     
  • mkstevo

    mkstevo - 2019-10-05

    This is intended to go into a unit that will connect to headphones (with appropriate attenuation) to create "noise" to mask external sounds (snoring!) that prevent me from sleeping. The actual frequency of the "noise" isn't important to me, but the effectiveness of it helping me to sleep is. I wanted the option of changing the pitch (if noise has any pitch at all) to give me a few things to try.

    If anything, the very low frequencies seemed to have most potential. I was using the lowest (125kHz) when debugging as I tried to decode why the XOR wasn't working, eventually shifting all zeros into the register.

     
  • mkstevo

    mkstevo - 2019-10-05

    The orignal device from P.E. was a 12F617 (I originally mistakenly said it was a 12F675). The source code comments suggest it was running at 2MHz?

    ; 2 to the power of 31 -1 results = 2,147,483,647
    ; clock is 2MHz so 13 cycles is 153.8451kHz generating max frequency of 76.923kHz
    ; minimum frequency is 76.923kHz/ 2,147,483,647 = 35.83uHz
    ; sequence repeats after 13us x 2,147,483,647 = 27,917,280s or 7.75hours

     
  • Chris Roper

    Chris Roper - 2019-10-05

    The PIC has a 4 phase Clock so that the Fetch, Execute, Store and Branch portions of the instruction execution can overlap. If you read any of the Datasheets you will see mention of FSC/4 which is Front Side Clock or Clock Speed divided by 4. For that reason the Clock frequency of the PIC is divided by 4 to get that actual instruction Cycle time.In this case an 8Mhz Clock speed would result in a 2MHz Instruction cycle time hence 2Mhz being used to calculate the bandwidth in the article.

     

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.