Pic instruction time counting

Discussion in 'Embedded Systems and Microcontrollers' started by Art, Sep 28, 2014.

  1. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Hi Guys,
    I have pic program I need to code count, and aim for total 25 cycles so that the output of the ports are
    100 kHz roughly 50% duty cycle driven by 10 MHz clock.. The duty cycle and desynchronisation between the two pins are not important because the decade counter outputs are still 50% duty cycle even if their input from the microcontroller isn't.

    Code (Text):
    1.  
    2. cycle:                ' main routine
    3. '
    4. @ nop
    5. @ nop
    6. @ nop
    7. @ nop
    8. @ nop
    9. @ nop
    10. @ nop
    11. @ nop
    12. @ clrwdt            ; clear watchdog timer manually (1)
    13. portb.4 = 1 ' (2)
    14. portb.5 = 1'  (2)
    15. @ nop
    16. @ nop
    17. @ nop
    18. @ nop
    19. @ nop ; (1)
    20. @ nop
    21. portb.4 = 0
    22. portb.5 = 0
    23. '
    24. goto cycle                        ' do it again (2)
    25.  
    It turns out that my scope will count between 99.7xx kHz and 100.20 kHz or so when the pic clocked
    with a rubidium frequency standard, and the scope is only referencing it's own ovenised crystal oscillator.
    There are a few nops I can add or remove from this routine, and still not be sure which version outputs 100kHz.
    There is no evaluation or conditional branching, so the instruction time should be static.
    The compiler does the conversion of the writes to portb bits efficiently, as you would in asm.
    Any help appreciated.



    Cheers, Art.
     
    Last edited: Sep 28, 2014
  2. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    You didn't say which processor you're using, but most (all?) PICs have an instruction cycle time that's 1/4 the oscillator frequency. So if "10MHz clock" means 10MHz oscillator, you have a 2.5MHz instruction rate, and that's a problem--you need 25 instructions to get one cycle of a 100KHz wave, and 25 is an odd number. The best you can do is 12 cycles high and 13 low, but the frequency should be OK.

    Every PIC instructon that doesn't change the program counter takes 1 cycle time, and if the counter is changed, then it's 2 cycles. The only one you've used that takes 2 cycles is the GOTO. So it should be easy enough to figure out a distribution of the program lines to get your 100KHz.
     
  3. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Ok, thanks, if that is the case it would be running fast because I have counted turning port bit on/off as 2 cycles.
    I did take into account to divide the 10 MHz freq by 4, and try to execute 25 cycles of time ready to run the loop again,
    but looks like I'll get it fixed :)
     
  4. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Ok, I measure 100 kHz every time now.
    I used bsf/bcf to switch the port pins to ensure all asm instructions too.
     
  5. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    Just curious why you would not use one of the PWMs (unless your PIC doesn't have one of course ;)) As you've seen, counting clocks can be a hassle and if you ever want to do something else, it can be a bear.

    FWIW, For a typical midrange PIC at 10MHz oscillator 100KHZ 50% calculates out to:
    TMR2 Preacaler = 1
    PR2 = 24 decimal
    CCPRxL = 0Ch
    CCPxCON<5:4>=10 (2 bits)

    Many PICs have multiple PWMs but since yours are running in parallel, could you just drive both counters off of one pin?

    Just my .03
     
  6. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Hi John,
    It's a pic 16F628A, and I believe they do have HWPWM. To be honest I've just never used one, or looked into it.
    I suppose I should have a go...
    Were I to use a button with interrupt to do something, then the HWPM shouldn't be paused while the interrupt executes.
    There is a possibility this chip could also send serial back to the rubidium standard to change it's frequency,
    but I was going to use a separate pic with an Xtal clock for that otherwise the main pic would have it's freq changed from 10 MHz,
    and it's serial would have to be recalculated for 9600 baud when the chip is running at it's new frequency.
    Not a real problem until the new frequency doesn't make it through the filter to drive the pic's clock, and the main pic can no longer run to change it back.

     
  7. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    No worries. Once set up the PWM will run without further intervention. In fact, you'll run into trouble with the software PWM servicing interrupts or even doing other processing.

    Completely doable with the '628A at 10MHz (BRGH=1, SBRG=15 decimal). Use an interrupt-driven receiver (unrelated to any PWM use, just a good idea) to receive the messages. I personally would use an interrupt-driven transmitter as well. When messages are decoded to change the PWM values, store the settings then enable the TIMER 2 interrupt to know when its just rolled over then while its running the next cycle, load the duty / freq registers for smooth changes. Disable TMR2IE until the next change. All of this assumes that you can get the desired freqs/duty cycle out of the normal PWM settings of course.

    If you stay with the brute force cycle count PWM, consider replacing some of the NOPs with code to shadow the output port. Consecutive bcf/bsf on a midrange port can lead to r-m-w problems.

    Good luck.
     
  8. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Well I can wrap my head around all of that except the last part. Would you mind explaining that?
    I will likely continue with the project because it's working and play with this toward the end simply
    because it's more fun to do some other parts of it for now :)

     
  9. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    This is a weird construction feature of PIC processors, which I think few people understand entirely, certainly not me. What happens (maybe someone can correct me if I'm getting it wrong) is that single-bit operations to the port pins (BSF, set a bit, or BCF, clear a bit) are actually executed by a read-modify-write process. What this means is that the first action when you call for a port output bit to change is the entire 8-bit port is read into a hardware register; then the appropriate bit of that register is set or cleared; then the register is written back to the port. What can happen is that the initial read operation may involve reading pins that are set as outputs, and if any of those pins have been pulled high or low by external loads, they are read as having the wrong status, and that status gets written back to the port pin when the read-modify-write completes. So you try to change the output of one port pin, and other pins that you thought you hadn't touched get changed too. It leads to mysterious errors that don't involve anything you can find in your code.

    The easiest way to deal with this PICfall (like a pitfall, you know...) is to have a "shadow" register which you make changes to, and then write the entire register out to the port, which isn't a read-modify-write process. Like this (using C code, but it should be obvious how it would look in assembly):
    Code (Text):
    1.  
    2.     bit_set(porta, 5);                                          // This is legal, but it may get you in trouble
    3.  
    4.     bit_set(porta_shadow, 5);
    5.     porta = porta_shadow;                              // Takes longer, but it's guaranteed to do what you think it does
    6.  
    The price of safety, unfortunately, is that the dangerous procedure only takes 1 instruction, whereas being safe takes 3, and it requires a memory location. Engineering often involves compomises.
     
  10. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Ok, thanks, that's no problem to take care of, but I had not heard of that before.

    Did I say fun? I meant hair raising experience with anxiety.
    These resistors are for LED bargraph decade displays.

    [​IMG]
     
    Last edited: Oct 4, 2014
  11. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    Look up PIC read modify write and you'll find lots of references, with better explanations than I can give.
     
  12. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Here's a bit more progress... The decade counter is supposed to take frequency input once it's got 3 more faster 4017 chips in front of it,
    but for now it just takes input from one of the faster frequencies available on the gate timer board.

     
  13. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Hello again Guys,
    Since the main chip in the project (16F877A) has HPWM, I could ditch the first chip and just divide that for the gate timer.
    Should I assume the resolution is only as accurate as the input osc where the hpwm frequency is evenly divisible by fosc/4 ?
    ie.. a 1 kHz PWM from a 10 MHz osc is absolutely accurate at 50% duty cycle?

    I want to generate the lowest frequency divisible by 10 that is absolutely accurate so that I can further divide it down to 1 Hz with as few decade counters as possible.
     
  14. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    Are you serious? You dont need resistors for them (while it is upto you to use sockets and large amounts of tin).

    You can drive them with 74hc595 they have 150 Ohms built in, or with 16F PICs for instance 16F59 they also have a current limit built-in which works well for LEDs.

    And you can multiplex them too, 6 phases work quite well while with 8, you loose too much brightness.
     
  15. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    How does that help connect decade bargraphs to decade counters with less soldering?
    The idea is to run the cascaded decade counters for a gate time, and alternately disable the counters so the display can be read,
    then reset and start again.
    The real time clock display section is multiplexed.
     
    Last edited: Nov 9, 2014
  16. Art

    Thread Starter Distinguished Member

    Sep 10, 2007
    785
    61
    Hi Guys, well another update...
    The home stretch! :D


    [​IMG]

    [​IMG]
     
Loading...