Menu

DC Motor Encoder Speed control

Help
24 hours ago
4 hours ago
  • Victor Alberto Lengert

    I would be very grateful if someone could help me. I'm trying to compile this code but I can't get it to work.

    Gbasic version : 2025.10.04 (Windows 64 bit) : Build 1523

     
  • Anobium

    Anobium - 16 hours ago

    Hello,

    I am not sure who added this to your code but they gave you good advice. But, not complete.

    // 1. **Syntax**: GCBasic uses a different syntax than MikroC (Basic-like vs C-like)
    // 2. **Bit operations**: Used bitwise operators instead of .F0/.F1 notation
    // 3. **Interrupt handling**: GCBasic uses `oninterrupt` statements
    // 4. **Variable declaration**: Used `dim` instead of type declarations
    // 5. **Constants**: Used `const` instead of `#define`
    // 6. **Delay**: Used `delayms` instead of `Delay_mS()`
    // 7. **Interrupt flags**: Directly access T0IF, GIE, T0IE instead of INTCON structure
    

    However,

    Code Review

    The original GCBASIC port contained critical syntax errors that prevented compilation, including:
    - Invalid endif / wend keywords
    - Deprecated loop structures
    - Incorrect interrupt syntax
    - Bit-shift confusion in quadrature logic


    1. Critical Syntax Errors (Compilation Failures)

    Error Original Code Final Code Fix
    endif endif End If instances to be replaced
    wend wend Loop instance to be removed
    while loop while true … wend Do … Loop Deprecated → use modern syntax
    else after endif Invalid nesting End If before Else Fixed block structure

    These were not warnings — they were hard compiler errors.


    2. Constants

    Aspect Original Final Change
    Syntax const X = Y #DEFINE X Y
    Gain const MOTOR_PROP_GAIN = 10 #DEFINE MOTOR_PROP_GAIN 10 Preprocessor style enforced

    #DEFINE ensures compile-time substitution — no runtime overhead.


    3. Interrupt Handler (Manual Compliance)

    Aspect Original Final Fix
    Declaration oninterrupt Timer0 Sub Interrupt Official syntax
    Closure end oninterrupt End Sub Correct termination

    oninterrupt is not supported — causes linker error.


    4. Delay Function

    Original Final Reason
    delayms 200 Wait 200 ms DelayMS is deprecated

    Wait is official, readable, and future-proof.


    5. Quadrature Encoder Logic

    Line Original Port Final (Approved) Logic
    Condition (enc_new >> 1) (enc_new > 1) Is the shift directive correct?

    6. Bit Access in Main Loop (Readability)

    Original Final
    if (PORTA & 1) then If PORTA.0 Then
    if (PORTA & 2) then If PORTA.1 Then

    Cleaner, safer, and standard GCBASIC style, and a lot faster


    7. Verified Hardware Configuration

    Setting Value Status
    #chip 16F628A, 20 Correct
    Oscillator HS_OSC 20 MHz HS
    PWM Frequency PR2 = 99, T2CON = 0b00000111 20 kHz
    Timer0 Interrupt OPTION_REG = 0b10000000 512-cycle period

    All timing matches Roman Black’s original design.


    Conclusion

    The original port was non-functional due to fundamental syntax violations.

    Through rigorous, line-by-line correction , the code has been compiled into a more robust, correct, and authoritative implementation.

     
  • Anobium

    Anobium - 15 hours ago

    Also, the original source code. You should share this. As the logic in your code provided does not make sense to me. 'if (enc_new > 1) <> (enc_last & 1) then' this makes no sense. It will compile but the outcome is not what you need.

    This surely should be a bitwise inspections. The code may not work as expected.

    Post the C source.

     
  • Anobium

    Anobium - 14 hours ago

    C to GCBASIC Porting Rules

    High-Level Cheat Sheet for PIC16F628A (MikroC → GCBASIC))


    1. Chip & Clock

    MikroC C GCBASIC
    #pragma config FOSC = HS #chip 16F628A, 20
    (any config) #option explicit (recommended)

    Rule: Always start with #chip <model>, <MHz>


    2. Functions

    C GCBASIC
    void main() Use a label Main:
    void interrupt() Sub Interrupt

    Rule: Use Sub and Interrupt
    End with End Sub


    3. Infinite Loop

    C GCBASIC
    while(1) { } DoLoop

    Rule: No condition needed


    4. Variables

    C Type GCBASIC
    unsigned char Dim x As Byte
    unsigned int Dim x As Word
    unsigned long Dim x As Long

    Rule: Match bit width: 8 / 16 / 32


    5. Bit Access

    C GCBASIC
    PORTA.F0 PORTA.0
    var.F3 = 1 var.3 = 1

    Rule: Use dot-number (.0 to .7)


    6. Port I/O

    C GCBASIC
    TRISA = 0b00000011; TRISA = 0b00000011
    (implied by TRIS) Dir PORTA.0 In

    Rule: Always add Dir statements in GCBASIC


    7. Delay

    C GCBASIC
    Delay_ms(200); Wait 200 ms

    Rule: Use ms, us, s — auto-scaled


    8. Logic & Conditions

    C GCBASIC
    if (x != y) If x <> y Then
    else Else
    || Or
    && And

    Rule: <> = not equal


    9. Increment / Decrement

    C GCBASIC
    x++; x++
    x--; x--

    Rule: Same


    10. Constants

    C GCBASIC
    #define MOTOR 100 #Define MOTOR 100
    #define PERIOD 6944444 #Define PERIOD 6944444

    Rule: Use #Define (capital D)
    Type is implied


    11. Comments

    C GCBASIC
    // comment // comment
    /* block */ ' block or //

    Rule: // is fully supported and preferred


    12. PWM & Timer Registers

    C GCBASIC
    PR2 = 99; PR2 = 99
    T2CON = 0b00000111; Same
    CCPR1L = 50; CCPR1L = 50

    Rule: Identical register access


    13. Interrupts

    C GCBASIC
    INTCON = 0b10100000; INTCON = 0b10100000
    INTCON.T0IF = 0; INTCON.T0IF = 0

    Rule: Same bit names and masks


    14. Binary Notation

    C GCBASIC
    PORTA & *b00000011 PORTA And 0b00000011

    Rule: Do not use &b prefix for binary use prefix 0b


    Quick Template

    // C (MikroC)
    void main() {
        TRISA = 0b00000011;
        while(1) {
            if(PORTA.F0) PORTB.F1 = 1;
        }
    }
    

    ```basic
    // GCBASIC

    chip 16F628A, 20

    option explicit

    Dir PORTA.0 In
    Dir PORTB.1 Out

    Main:
    DIR PORTA.0 In
    DIR PORTB.1 Out

    Do
        If PORTA.0 Then PORTB.1 = 1
    Loop
    

    Final Checklist

    • #chip 16F628A, 20
    • All Dir pins set
    • Main loop
    • Sub Interrupt defined
    • INTCON.GIE = 1
    • No return in Sub used End Sub
    • Use Wait, not Delay_ms
    • Use ++ or --
    • Do not use UL for long constants
    • Use // comments


    /******************************************************************************
      DC_motor_xtal.c  - run a DC motor at xtal "clockwork" locked speed
      Started 8 Apr 2013 - Copyright www.RomanBlack.com, allowed for public use,
                           you must mention me as the author and please provide
                           a link to my web page where this system is described;
                           www.RomanBlack.com/onesec/DCmotor_xtal.htm
    
      PIC16F628A - 20MHz HS xtal (see web page for schematic)
      Compiler - MikroC for PIC v8
      PIC pins;
       RA0 = digital ST input, quad encoder A
       RA1 = digital ST input, quad encoder B
       RB3 = CCP1 output, PWM to motor, HI = ON
       RB0 = echo encoder A output
       RB1 = echo encoder A output
    
       PIC configs; MCRLE off, BODEN off, BORES off, WDT off, LVP off, PWRT on
    ******************************************************************************/
    
    #chip 16F628A, 20
    #option Explicit
    
    // This constant sets the motor speed. The value is in nanoSeconds per pulse,
    // as we are using a quadrature encoder there are 4 pulses per encoder slot.
    // My encoder had 36 slots, so that makes 36*4 or 144 pulses per revolution.
    // Example; 1 motor rev per second = 144 pulses /sec.
    // nS per pulse = 1 billion / 144 = 6944444
    // #define  MOTOR_PULSE_PERIOD  1736111    // 4 RPS
    // #define  MOTOR_PULSE_PERIOD  3472222    // 2 RPS
    #define  MOTOR_PULSE_PERIOD  6944444    // 1 RPS
    // #define  MOTOR_PULSE_PERIOD  13888889   // 0.5 RPS
    
    // This constant sets the proportional gain. Basically it sets how much
    // more PWM % is added for each pulse behind that the motor gets.
    // ie; if set to 10, the PWM is increased by 10% for each pulse behind.
    // Values must be within 1-50. Values of 10 or 16 worked well with
    // low motor RPMs, for higher RPMs a smaller value like 2 to 8 can be used.
    #define  MOTOR_PROP_GAIN  10
    
    // global vars
    Dim rpos      As Byte   ' reference position of xtal based freq
    Dim mpos      As Byte   ' actual motor position
    Dim mlag      As Byte   ' amount the motor lags the reference
    Dim enc_new   As Byte   ' holds motor's quadrature encoder data for testing
    Dim enc_last  As Byte   ' previous encoder state
    Dim bres      As Long   ' bresenham accumulator used to make ref frequency
    Dim pins      As Byte   ' temporary var for echoing encoder signals
    
    '=====================================================================
    '  TMR0 INTERRUPT – Closed-loop DC motor speed control
    '  Ported from MikroC void interrupt() function
    '=====================================================================
    
    Sub Interrupt
        // --- Clear TMR0 interrupt flag immediately (max safety)
        INTCON.T0IF = 0
    
        //-- 1. UPDATE ENCODER POSITION ---------------------------
        enc_new = PORTA And 0b00000011          ' read RA0, RA1 only
    
        If enc_new <> enc_last Then
            If enc_new.1 <> enc_last.0 Then
                mpos++                        ' reverse step (original logic)
            Else
                mpos--                        ' forward step
            End If
            enc_last = enc_new
        End If
    
        //-- 2. UPDATE REFERENCE (Bresenham) ----------------------
        ' 512 cycles @ 20 MHz = 512 * 200 ns = 102400 ns per interrupt
        bres = bres + 102400
    
        If bres >= MOTOR_PULSE_PERIOD Then
            bres = bres - MOTOR_PULSE_PERIOD
            rpos++
        End If
    
        //-- 3. PROPORTIONAL CONTROL (PWM) ------------------------
        If mpos < rpos Then                     ' motor lagging
            mlag = rpos - mpos
            If mlag >= (100 / MOTOR_PROP_GAIN) Then
                CCPR1L = 100                    ' full power
            Else
                CCPR1L = mlag * MOTOR_PROP_GAIN ' proportional
            End If
        Else
            CCPR1L = 0                          ' motor ahead → stop
        End If
    
        //-- 4. PREVENT ROLL-OVER (keep error) -------------------
        If rpos > 250 Or mpos > 250 Then
            rpos = rpos - 50
            mpos = mpos - 50
        End If
    End Sub
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    
    //=============================================================================
    //   MAIN
    //=============================================================================
    '=====================================================================
    '  MAIN PROGRAM – GCBASIC port of MikroC main()
    '=====================================================================
    
        //-------------------------------------------------------
        // setup PIC 16F628A
        CMCON = 0b00000111;     // comparators OFF, all pins digital
    
        PORTA = 0b00000000;     //
        TRISA = 0b00000011;     // RA0,RA1 used for digital ST encoder inputs
    
        PORTB = 0b00000000;     //
        TRISB = 0b00000000;     // RB3 is CCP1 PWM out, RB0,RB1 are encoder echo outputs
    
        // set TMR2 to roll every 100 ticks, PWM freq = 5mil/16/100 = 3125 Hz
        T2CON = 0b00000111;     // TMR2 ON, 16:1 prescale
        PR2 = (100-1);          // PWM total period of 100
    
        // set PWM out on CCP1
        CCPR1L = 0;             // PWM range 0-100% = start with PWM of 0%
        CCP1CON = 0b00001100;   // CCP1 on, set to PWM mode
    
        // TMR0 used for interrupt, makes interrupt every 512 insts
        OPTION_REG = 0b10000000;   // PORTB pullups OFF, TMR0 on, 2:1 prescale
    
    
        //-------------------------------------------------------
        // setup before main loop
        Wait 200 ms;    // allow PSU voltages time to stabilise
    
        // setup vars etc, will be used in interrupt
        bres = 0;
        rpos = 0;
        mpos = 0;
    
        // finally start TMR0 roll interrupt
        INTCON = 0b10100000;  // GIE=on, TMR0IE=on
    
        //-------------------------------------------------------
        // main run loop
        Do
            //-------------------------------------------------
            // We don't need to do anything in main loop as the motor speed
            // control is done entirely in the TMR0 interrupt.
    
    
            //-------------------------------------------------
            // For convenience in setting up the encoder trimpots,
            // echo the two encoder pins out two spare PORTB digital outputs!
            pins = 0;
            if (PORTA.0) Then pins.0 = 1;
            if (PORTA.1) Then pins.1 = 1;
            PORTB = pins;    // output those two pins only (PWM output is not affected)
        Loop
    
     

    Last edit: Anobium 8 hours ago
  • Victor Alberto Lengert

    Thanks Anobium, sorry I posted the wrong version of the code. I asked the AI for help, that's why the AI added all that.

     
  • Victor Alberto Lengert

    original MikroC code

    // This constant sets the motor speed. The value is in nanoSeconds per pulse,
    // as we are using a quadrature encoder there are 4 pulses per encoder slot.
    // My encoder had 36 slots, so that makes 36*4 or 144 pulses per revolution.
    // Example; 1 motor rev per second = 144 pulses /sec.
    // nS per pulse = 1 billion / 144 = 6944444
    //#define MOTOR_PULSE_PERIOD 1736111 // 4 RPS
    //#define MOTOR_PULSE_PERIOD 3472222 // 2 RPS

    define MOTOR_PULSE_PERIOD 6944444 // 1 RPS

    //#define MOTOR_PULSE_PERIOD 13888889 // 0.5 RPS

    // This constant sets the proportional gain. Basically it sets how much
    // more PWM % is added for each pulse behind that the motor gets.
    // ie; if set to 10, the PWM is increased by 10% for each pulse behind.
    // Values must be within 1-50. Values of 10 or 16 worked well with
    // low motor RPMs, for higher RPMs a smaller value like 2 to 8 can be used.

    define MOTOR_PROP_GAIN 10

    // global vars
    unsigned char rpos; // reference position of xtal based freq
    unsigned char mpos; // actual motor position
    unsigned char mlag; // amount the motor lags the reference
    unsigned char enc_new; // holds motor's quadrature encoder data for testing
    unsigned char enc_last;
    unsigned long bres; // bresenham accumulator used to make ref frequency
    unsigned char pins; // temporary var for echoing encoder signals

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    void interrupt()
    {
    //-------------------------------------------------------
    // This is TMR0 int, prescaled at 2:1 so we get here every 512 instructions.
    // This int does the entire closed loop speed control;
    // 1. updates encoder to see if motor has moved, records it position
    // 2. updates reference freq generator, records its position
    // 3. compares the two, sets PWM if motor lags behind reference
    // 4. limit both counts, so they never roll, but still retain all error
    //-------------------------------------------------------
    // clear int flag straight away to give max safe time
    INTCON.T0IF = 0;

    // 1. updates encoder to see if motor has moved, records it position
    enc_new = (PORTA & 0b00000011); // get the 2 encoder bits
    if(enc_new != enc_last)
    {
    if(enc_new.F1 != enc_last.F0) mpos++; // record new motor position
    else mpos--;
    enc_last = enc_new;
    }

    // 2. updates reference freq generator, records its position
    bres += 102400; // add nS per interrupt period (512 insts * 200nS)
    if(bres >= MOTOR_PULSE_PERIOD) // if reached a new reference step
    {
    bres -= MOTOR_PULSE_PERIOD;
    rpos++; // record new xtal-locked reference position
    }

    // 3. compares the two, set PWM% if motor lags behind reference
    if(mpos < rpos) // if motor lagging behind
    {
    mlag = (rpos - mpos); // find how far it's lagging behind
    if(mlag >= (100/MOTOR_PROP_GAIN)) CCPR1L = 100; // full power if is too far behind
    else CCPR1L = (mlag * MOTOR_PROP_GAIN); // else adjust PWM if slightly behind
    }
    else // else if motor is fast, cut all power!
    {
    CCPR1L = 0;
    }

    // 4. limit both counts, so they never roll, but still retain all error
    if(rpos>250 || mpos>250)
    {
    rpos -= 50;
    mpos -= 50;
    }

    }
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    //=============================================================================
    // MAIN
    //=============================================================================
    void main()
    {
    //-------------------------------------------------------
    // setup PIC 16F628A
    CMCON = 0b00000111; // comparators OFF, all pins digital

    PORTA = 0b00000000; //
    TRISA = 0b00000011; // RA0,RA1 used for digital ST encoder inputs

    PORTB = 0b00000000; //
    TRISB = 0b00000000; // RB3 is CCP1 PWM out, RB0,RB1 are encoder echo outputs

    // set TMR2 to roll every 100 ticks, PWM freq = 5mil/16/100 = 3125 Hz
    T2CON = 0b00000111; // TMR2 ON, 16:1 prescale
    PR2 = (100-1); // PWM total period of 100

    // set PWM out on CCP1
    CCPR1L = 0; // PWM range 0-100% = start with PWM of 0%
    CCP1CON = 0b00001100; // CCP1 on, set to PWM mode

    // TMR0 used for interrupt, makes interrupt every 512 insts
    OPTION_REG = 0b10000000; // PORTB pullups OFF, TMR0 on, 2:1 prescale

    //-------------------------------------------------------
    // setup before main loop
    Delay_mS(200); // allow PSU voltages time to stabilise

    // setup vars etc, will be used in interrupt
    bres = 0;
    rpos = 0;
    mpos = 0;

    // finally start TMR0 roll interrupt
    INTCON = 0b10100000; // GIE=on, TMR0IE=on

    //-------------------------------------------------------
    // main run loop
    while(1)
    {
    //-------------------------------------------------
    // We don't need to do anything in main loop as the motor speed
    // control is done entirely in the TMR0 interrupt.

    //-------------------------------------------------
    // For convenience in setting up the encoder trimpots,
    // echo the two encoder pins out two spare PORTB digital outputs!
    pins = 0;
    if(PORTA.F0) pins.F0 = 1;
    if(PORTA.F1) pins.F1 = 1;
    PORTB = pins;    // output those two pins only (PWM output is not affected)
    

    }
    }
    //-----------------------------------------------------------------------------

     
  • Anobium

    Anobium - 8 hours ago

    I asked Grok to convert. It gave Grok the rules I wrote. It made one error.

    ' GCBASIC version of the motor speed control code for PIC16F628A
    ' Assumes 20MHz clock
    #chip 16F628A, 20
    
    #option explicit
    
    ' Constants
    #DEFINE MOTOR_PULSE_PERIOD 6944444
    #DEFINE MOTOR_PROP_GAIN 10
    
    ' Variables
    dim rpos as byte        ' reference position
    dim mpos as byte        ' actual motor position
    dim mlag as byte        ' amount the motor lags the reference
    dim enc_new as byte     ' holds motor's quadrature encoder data
    dim enc_last as byte    ' last encoder state
    dim bres as long        ' bresenham accumulator for reference frequency
    dim pins as byte        ' temporary for echoing encoder signals
    
    ' Setup PIC16F628A
    CMCON = 7               ' Disable comparators, all pins digital
    PORTA = 0
    DIR PORTA.0 IN          ' RA0, RA1 for encoder inputs
    DIR PORTA.1 IN
    PORTB = 0
    DIR PORTB OUT           ' All PORTB outputs (RB3 PWM, RB0/RB1 echo)
    
    ' Setup TMR2 for PWM: 3125 Hz, period 100
    T2CON = 0b00000111      ' TMR2 ON, 16:1 prescaler
    PR2 = 99                ' PWM period of 100
    CCPR1L = 0              ' Start with 0% PWM
    CCP1CON = 0b00001100    ' CCP1 PWM mode
    
    ' Setup TMR0 for interrupt every ~102.4 us (512 instructions at 20MHz)
    OPTION_REG = 0b10000000 ' Pullups OFF, TMR0 internal clock, 1:2 prescaler
    InitTimer0 Osc, PRE0_2  ' Internal clock (Fosc/4), prescaler 1:2
    
    ' Initial delay for PSU stabilization
    Wait 200 ms
    
    ' Initialize variables
    bres = 0
    rpos = 0
    mpos = 0
    enc_last = 0
    
    ' Setup and start TMR0 interrupt
    On Interrupt Timer0Overflow Call MotorISR
    
    ' Main loop - echo encoder pins to RB0/RB1
    Do
        pins = 0
        if PORTA.0 = 1 then pins.0 = 1
        if PORTA.1 = 1 then pins.1 = 1
        PORTB = pins          ' Output echo (PWM on RB3 unaffected)
    Loop
    
    ' Interrupt Service Routine for closed-loop speed control
    Sub MotorISR
        TMR0IF = 0             ' Clear interrupt flag
    
        ' 1. Update encoder position
        enc_new = PORTA And 0b00000011
        if enc_new <> enc_last then
            if enc_new.1 <> enc_last.0 then
                mpos = mpos + 1   ' Forward
            else
                mpos = mpos - 1   ' Backward
            end if
            enc_last = enc_new
        end if
    
        ' 2. Update reference frequency generator
        bres = bres + 102400   ' Add ns per interrupt period
        if bres >= MOTOR_PULSE_PERIOD then
            bres = bres - MOTOR_PULSE_PERIOD
            rpos = rpos + 1
        end if
    
        ' 3. Compare positions and adjust PWM if lagging
        if mpos < rpos then
            mlag = rpos - mpos
            if mlag >= (100 / MOTOR_PROP_GAIN) then
                CCPR1L = 100      ' Full power if too far behind
            else
                CCPR1L = mlag * MOTOR_PROP_GAIN  ' Proportional adjustment
            end if
        else
            CCPR1L = 0            ' Cut power if ahead
        end if
    
        ' 4. Limit counts to prevent rollover while retaining error
        if rpos > 250 OR mpos > 250 then
            rpos = rpos - 50
            mpos = mpos - 50
        end if
    End Sub
    
     

    Last edit: Anobium 8 hours ago
  • Victor Alberto Lengert

    Thank you very much ANOBIUM, it compiles well. In the next few days I will try to assemble and test the mechanics to see if it works.
    And what does that error mean?
    OSC: HS, 20Mhz (Clock source is not a primary internal oscillator. Ensure the clock source is correctly setup) Chip: 16F628A

     
  • Anobium

    Anobium - 5 hours ago

    OSC: HS, 20Mhz (Clock source is not a primary internal oscillator. Ensure the clock source is correctly setup) Chip: 16F628A

    GCBASIC Warning Explained


    Message

    > OSC: HS, 20Mhz (Clock source is not a primary internal oscillator. Ensure the clock source is correctly setup) Chip: 16F628A
    

    This is a warning from GCBASIC, not an error.


    What It Means

    Part Explanation
    OSC: HS, 20Mhz Your program is configured to run at 20 MHz using High-Speed Crystal mode.
    Chip: 16F628A Target microcontroller is the PIC16F628A.
    (Clock source is not a primary internal oscillator...) HS mode requires an external crystal — the internal oscillator cannot run at 20 MHz.
    Ensure the clock source is correctly setup You must connect a real 20 MHz crystal and configure the chip correctly.

    Key Point: The PIC16F628A’s internal oscillator maxes at 4 MHz.
    20 MHz requires an external crystal.


    Required Hardware Setup

              +5V
               |
       OSC1 --||-- Crystal (20 MHz) --||-- OSC2
              22pF                 22pF
               |                    |
              GND                  GND
    
    • Crystal: 20 MHz
    • Capacitors: 15–33 pF (22 pF typical)
    • Pins:
    • OSC1 → Pin 15
    • OSC2 → Pin 16

    Required GCBASIC Configuration

    #chip 16F628A, 20
    #config OSC = HS
    

    or

    #chip 16F628A, 20
    #config FOSC = HS
    

    This tells the PIC: "Expect an external high-speed crystal."


    Common Mistakes

    Mistake Result
    No crystal connected PIC won’t start or hangs
    Using 4 MHz crystal Runs 5× too slow
    Forgetting #config OSC = HS Defaults to internal 4 MHz
    Using INTRC with 20 MHz Impossible — internal max 4 MHz

    Summary

    Requirement Status
    20 MHz external crystal Required
    Connected to OSC1/OSC2 Required
    #config OSC = HS Required
     
  • Victor Alberto Lengert

    Thank you for your help and explanation.

     

Log in to post a comment.