• AVR Freaks

Helpful ReplyHot!Simulating Inputs

Author
deadlyBuzz
New Member
  • Total Posts : 2
  • Reward points : 0
  • Joined: 2019/08/12 14:16:13
  • Location: 0
  • Status: offline
2019/08/24 12:04:53 (permalink)
0

Simulating Inputs

Hello
I am looking to build a circuit to drive a stepper motor.
The circuit is based on the Curiosity Nano board DM164144 using the PIC16F18846
I am using Pins C0 and C1 as inputs from my Encoder A and B to update a count, up or down based on .
When the count is not "0", the motor unit will start iterating through the output pin patterns to drive the stepper motor forwards or backwards.
All simple enough right?
Well, I'm trying to simulate the circuit on MPLabX (V5.25) but cannot get the interrupts or portC to read values correctly.When I enable WPU on pins C0 and C1 - they default to "1" and wont change to trigger the inetrrupt and when I disable the WPU, they stay at "0"
I've tried researching this and the one thing about relying on a forum is that the solutions are spread across multiple questions and versions across years and nowhere can I find a simple answer.
How do I simulate the portC changing to fire the interrupt (Change the value of PortC in Watch?)
 
My Code is as follows:
Main:
This is simple enough, checking the counter and if it has been adjusted by the interrupt monitoring the encoder, will iterate through the relevant pattern:
/**
  Generated Main Source File

  Company:
    Microchip Technology Inc.

  File Name:
    main.c

  Summary:
    This is the main file generated using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  Description:
    This header file provides implementations for driver APIs for all modules selected in the GUI.
    Generation Information :
        Product Revision : PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.77
        Device : PIC16F18446
        Driver Version : 2.00
*/

/*
    (c) 2018 Microchip Technology Inc. and its subsidiaries.
    
    Subject to your compliance with these terms, you may use Microchip software and any
    derivatives exclusively with Microchip products. It is your responsibility to comply with third party
    license terms applicable to your use of third party software (including open source software) that
    may accompany Microchip software.
    
    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
    IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
    FOR A PARTICULAR PURPOSE.
    
    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
    HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
    THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
    CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
    OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
    SOFTWARE.
*/

#include "mcc_generated_files/mcc.h"

/*
                         Main application
 */
void main(void)
{
    // initialize the device
    SYSTEM_Initialize();
    int8_t pulseCount = 0;
    int stepperVal = (PORTC&0xF0)>>4; // read in the value of the stepper output by default
    uint8_t outVal = 0; // variable to assign to output value.

    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:

    // <<<< We must enable the following interrupts
    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();

    while (1)
    {
        // Add your application code
        stepperVal = (PORTC&0xF0)>>4; // read in the value of the stepper output by default
        
        if(pulseCount>0){
            switch(stepperVal){
                case 0x01:
                    outVal = 0x03;
                    break;
                case 0x03:
                    outVal = 0x02;
                    break;
                case 0x02:
                    outVal = 0x06;
                    break;
                case 0x06:
                    outVal = 0x04;
                    break;
                case 0x04:
                    outVal = 0x0B;
                    break;
                case 0x0B:
                    outVal = 0x08;
                    break;
                case 0x08:
                    outVal = 0x09;
                    break;
                case 0x09:
                    outVal = 0x01;
                    pulseCount--;
                    break;
                default:
                    outVal = 0x01;
                    break;
            }
        }
        if(pulseCount<0){
            switch(stepperVal){
                case 0x01:
                    outVal = 0x09;
                    break;
                case 0x09:
                    outVal = 0x08;
                    break;
                case 0x08:
                    outVal = 0x0B;
                    break;
                case 0x0B:
                    outVal = 0x04;
                    break;
                case 0x04:
                    outVal = 0x06;
                    break;
                case 0x06:
                    outVal = 0x02;
                    break;
                case 0x02:
                    outVal = 0x03;
                    break;
                case 0x03:
                    outVal = 0x01;
                    break;
                default:
                    outVal = 0x01;
                    pulseCount++;
                    break;
            }
        }
        __delay_ms(200); // Small delay before re-evaluating the counter ==> Speed
        STP_A_LAT = (outVal&0x01)>0;
        STP_B_LAT = (outVal&0x02)>0;
        STP_C_LAT = (outVal&0x04)>0;
        STP_D_LAT = (outVal&0x08)>0;
        
    }
}
/**
 End of File
*/

 
Interrupt manager Minus the header - Default from MCC
#include "interrupt_manager.h"
#include "mcc.h" // <<<< Included to give scope to the pulse count

void __interrupt() INTERRUPT_InterruptManager (void)
{
    // interrupt handler
    if(PIE0bits.IOCIE == 1 && PIR0bits.IOCIF == 1)
    {
        PIN_MANAGER_IOC();
    }
    else
    {
        //Unhandled Interrupt
    }
}
/**
 End of File
*/

 
pin_manager.C where the interrupt ISR and configs are set:
#include "pin_manager.h"
#include "mcc.h"




void (*IOCCF0_InterruptHandler)(void);


void PIN_MANAGER_Initialize(void)
{
    /**
    LATx registers
    */
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;

    /**
    TRISx registers
    */
    TRISA = 0x3F;
    TRISB = 0xF0;
    TRISC = 0x0F;

    /**
    ANSELx registers
    */
    ANSELC = 0x0C;
    ANSELB = 0xF0;
    ANSELA = 0x37;

    /**
    WPUx registers
    */
    WPUB = 0x00;
    WPUA = 0x00;
    WPUC = 0x00;

    /**
    ODx registers
    */
    ODCONA = 0x00;
    ODCONB = 0x00;
    ODCONC = 0x00;

    /**
    SLRCONx registers
    */
    SLRCONA = 0x37;
    SLRCONB = 0xF0;
    SLRCONC = 0xFF;

    /**
    INLVLx registers
    */
    INLVLA = 0x3F;
    INLVLB = 0xF0;
    INLVLC = 0xFF;


    /**
    IOCx registers
    */
    //interrupt on change for group IOCCF - flag
    IOCCFbits.IOCCF0 = 0;
    //interrupt on change for group IOCCN - negative
    IOCCNbits.IOCCN0 = 0;
    //interrupt on change for group IOCCP - positive
    IOCCPbits.IOCCP0 = 1;



    // register default IOC callback functions at runtime; use these methods to register a custom function
    IOCCF0_SetInterruptHandler(IOCCF0_DefaultInterruptHandler);
   
    // Enable IOCI interrupt
    PIE0bits.IOCIE = 1;
    
}
  
void PIN_MANAGER_IOC(void)
{
 // interrupt on change for pin IOCCF0
    if(IOCCFbits.IOCCF0 == 1)
    {
        IOCCF0_ISR();
    }
}

/**
   IOCCF0 Interrupt Service Routine
 * Interrupt on change Flag
*/
void IOCCF0_ISR(void) {

    // Add custom IOCCF0 code <<<< This is where I have added the update to the pulseCount,
    if(ENC_A_PORT&&ENC_B_PORT)
        pulseCount++;

    if(ENC_A_PORT&&!ENC_B_PORT)
        pulseCount--;

    // Call the interrupt handler for the callback registered at runtime
    if(IOCCF0_InterruptHandler)
    {
        IOCCF0_InterruptHandler();
    }
    IOCCFbits.IOCCF0 = 0;
}

/**
  Allows selecting an interrupt handler for IOCCF0 at application runtime
*/
void IOCCF0_SetInterruptHandler(void (* InterruptHandler)(void)){
    IOCCF0_InterruptHandler = InterruptHandler;
}

/**
  Default interrupt handler for IOCCF0
*/
void IOCCF0_DefaultInterruptHandler(void){
    // add your IOCCF0 interrupt custom code
    // or set custom function using IOCCF0_SetInterruptHandler()
}

/**
 End of File
*/

 
MCC.C:
#include "mcc.h"


void SYSTEM_Initialize(void)
{
    PMD_Initialize();
    PIN_MANAGER_Initialize();
    OSCILLATOR_Initialize();
}

void OSCILLATOR_Initialize(void)
{
    // NOSC HFINTOSC; NDIV 4;
    OSCCON1 = 0x62;
    // CSWHOLD may proceed; SOSCPWR Low power;
    OSCCON3 = 0x00;
    // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled;
    OSCEN = 0x00;
    // HFFRQ 4_MHz;
    OSCFRQ = 0x02;
    // HFTUN 0;
    OSCTUNE = 0x00;
}

void PMD_Initialize(void)
{
    // CLKRMD CLKR enabled; SYSCMD SYSCLK enabled; FVRMD FVR enabled; IOCMD IOC enabled; NVMMD NVM enabled;
    PMD0 = 0x00;
    // TMR0MD TMR0 enabled; TMR1MD TMR1 enabled; TMR4MD TMR4 enabled; TMR5MD TMR5 enabled; TMR2MD TMR2 enabled; TMR3MD TMR3 enabled; TMR6MD TMR6 enabled;
    PMD1 = 0x00;
    // NCO1MD NCO1 enabled;
    PMD2 = 0x00;
    // ZCDMD ZCD enabled; CMP1MD CMP1 enabled; ADCMD ADC enabled; CMP2MD CMP2 enabled; DAC1MD DAC1 enabled;
    PMD3 = 0x00;
    // CCP2MD CCP2 enabled; CCP1MD CCP1 enabled; CCP4MD CCP4 enabled; CCP3MD CCP3 enabled; PWM6MD PWM6 enabled; PWM7MD PWM7 enabled;
    PMD4 = 0x00;
    // CWG2MD CWG2 enabled; CWG1MD CWG1 enabled;
    PMD5 = 0x00;
    // U1MD EUSART1 enabled; MSSP1MD MSSP1 enabled; MSSP2MD MSSP2 enabled;
    PMD6 = 0x00;
    // CLC3MD CLC3 enabled; CLC4MD CLC4 enabled; DSM1MD DSM enabled; SMT1MD SMT1 enabled; CLC1MD CLC1 enabled; CLC2MD CLC2 enabled;
    PMD7 = 0x00;
}


/**
 End of File
*/

 
and finally - an extract from PinManager.H showing what variables have what names...
// get/set ENC_A aliases
#define ENC_A_TRIS TRISCbits.TRISC0
#define ENC_A_LAT LATCbits.LATC0
#define ENC_A_PORT PORTCbits.RC0
#define ENC_A_WPU WPUCbits.WPUC0
#define ENC_A_OD ODCONCbits.ODCC0
#define ENC_A_ANS ANSELCbits.ANSC0
#define ENC_A_SetHigh() do { LATCbits.LATC0 = 1; } while(0)
#define ENC_A_SetLow() do { LATCbits.LATC0 = 0; } while(0)
#define ENC_A_Toggle() do { LATCbits.LATC0 = ~LATCbits.LATC0; } while(0)
#define ENC_A_GetValue() PORTCbits.RC0
#define ENC_A_SetDigitalInput() do { TRISCbits.TRISC0 = 1; } while(0)
#define ENC_A_SetDigitalOutput() do { TRISCbits.TRISC0 = 0; } while(0)
#define ENC_A_SetPullup() do { WPUCbits.WPUC0 = 1; } while(0)
#define ENC_A_ResetPullup() do { WPUCbits.WPUC0 = 0; } while(0)
#define ENC_A_SetPushPull() do { ODCONCbits.ODCC0 = 0; } while(0)
#define ENC_A_SetOpenDrain() do { ODCONCbits.ODCC0 = 1; } while(0)
#define ENC_A_SetAnalogMode() do { ANSELCbits.ANSC0 = 1; } while(0)
#define ENC_A_SetDigitalMode() do { ANSELCbits.ANSC0 = 0; } while(0)

// get/set ENC_B aliases
#define ENC_B_TRIS TRISCbits.TRISC1
#define ENC_B_LAT LATCbits.LATC1
#define ENC_B_PORT PORTCbits.RC1
#define ENC_B_WPU WPUCbits.WPUC1
#define ENC_B_OD ODCONCbits.ODCC1
#define ENC_B_ANS ANSELCbits.ANSC1
#define ENC_B_SetHigh() do { LATCbits.LATC1 = 1; } while(0)
#define ENC_B_SetLow() do { LATCbits.LATC1 = 0; } while(0)
#define ENC_B_Toggle() do { LATCbits.LATC1 = ~LATCbits.LATC1; } while(0)
#define ENC_B_GetValue() PORTCbits.RC1
#define ENC_B_SetDigitalInput() do { TRISCbits.TRISC1 = 1; } while(0)
#define ENC_B_SetDigitalOutput() do { TRISCbits.TRISC1 = 0; } while(0)
#define ENC_B_SetPullup() do { WPUCbits.WPUC1 = 1; } while(0)
#define ENC_B_ResetPullup() do { WPUCbits.WPUC1 = 0; } while(0)
#define ENC_B_SetPushPull() do { ODCONCbits.ODCC1 = 0; } while(0)
#define ENC_B_SetOpenDrain() do { ODCONCbits.ODCC1 = 1; } while(0)
#define ENC_B_SetAnalogMode() do { ANSELCbits.ANSC1 = 1; } while(0)
#define ENC_B_SetDigitalMode() do { ANSELCbits.ANSC1 = 0; } while(0)

// get/set STP_A aliases
#define STP_A_TRIS TRISCbits.TRISC4
#define STP_A_LAT LATCbits.LATC4
#define STP_A_PORT PORTCbits.RC4
#define STP_A_WPU WPUCbits.WPUC4
#define STP_A_OD ODCONCbits.ODCC4
#define STP_A_ANS ANSELCbits.ANSC4
#define STP_A_SetHigh() do { LATCbits.LATC4 = 1; } while(0)
#define STP_A_SetLow() do { LATCbits.LATC4 = 0; } while(0)
#define STP_A_Toggle() do { LATCbits.LATC4 = ~LATCbits.LATC4; } while(0)
#define STP_A_GetValue() PORTCbits.RC4
#define STP_A_SetDigitalInput() do { TRISCbits.TRISC4 = 1; } while(0)
#define STP_A_SetDigitalOutput() do { TRISCbits.TRISC4 = 0; } while(0)
#define STP_A_SetPullup() do { WPUCbits.WPUC4 = 1; } while(0)
#define STP_A_ResetPullup() do { WPUCbits.WPUC4 = 0; } while(0)
#define STP_A_SetPushPull() do { ODCONCbits.ODCC4 = 0; } while(0)
#define STP_A_SetOpenDrain() do { ODCONCbits.ODCC4 = 1; } while(0)
#define STP_A_SetAnalogMode() do { ANSELCbits.ANSC4 = 1; } while(0)
#define STP_A_SetDigitalMode() do { ANSELCbits.ANSC4 = 0; } while(0)

// get/set STP_B aliases
#define STP_B_TRIS TRISCbits.TRISC5
#define STP_B_LAT LATCbits.LATC5
#define STP_B_PORT PORTCbits.RC5
#define STP_B_WPU WPUCbits.WPUC5
#define STP_B_OD ODCONCbits.ODCC5
#define STP_B_ANS ANSELCbits.ANSC5
#define STP_B_SetHigh() do { LATCbits.LATC5 = 1; } while(0)
#define STP_B_SetLow() do { LATCbits.LATC5 = 0; } while(0)
#define STP_B_Toggle() do { LATCbits.LATC5 = ~LATCbits.LATC5; } while(0)
#define STP_B_GetValue() PORTCbits.RC5
#define STP_B_SetDigitalInput() do { TRISCbits.TRISC5 = 1; } while(0)
#define STP_B_SetDigitalOutput() do { TRISCbits.TRISC5 = 0; } while(0)
#define STP_B_SetPullup() do { WPUCbits.WPUC5 = 1; } while(0)
#define STP_B_ResetPullup() do { WPUCbits.WPUC5 = 0; } while(0)
#define STP_B_SetPushPull() do { ODCONCbits.ODCC5 = 0; } while(0)
#define STP_B_SetOpenDrain() do { ODCONCbits.ODCC5 = 1; } while(0)
#define STP_B_SetAnalogMode() do { ANSELCbits.ANSC5 = 1; } while(0)
#define STP_B_SetDigitalMode() do { ANSELCbits.ANSC5 = 0; } while(0)

// get/set STP_C aliases
#define STP_C_TRIS TRISCbits.TRISC6
#define STP_C_LAT LATCbits.LATC6
#define STP_C_PORT PORTCbits.RC6
#define STP_C_WPU WPUCbits.WPUC6
#define STP_C_OD ODCONCbits.ODCC6
#define STP_C_ANS ANSELCbits.ANSC6
#define STP_C_SetHigh() do { LATCbits.LATC6 = 1; } while(0)
#define STP_C_SetLow() do { LATCbits.LATC6 = 0; } while(0)
#define STP_C_Toggle() do { LATCbits.LATC6 = ~LATCbits.LATC6; } while(0)
#define STP_C_GetValue() PORTCbits.RC6
#define STP_C_SetDigitalInput() do { TRISCbits.TRISC6 = 1; } while(0)
#define STP_C_SetDigitalOutput() do { TRISCbits.TRISC6 = 0; } while(0)
#define STP_C_SetPullup() do { WPUCbits.WPUC6 = 1; } while(0)
#define STP_C_ResetPullup() do { WPUCbits.WPUC6 = 0; } while(0)
#define STP_C_SetPushPull() do { ODCONCbits.ODCC6 = 0; } while(0)
#define STP_C_SetOpenDrain() do { ODCONCbits.ODCC6 = 1; } while(0)
#define STP_C_SetAnalogMode() do { ANSELCbits.ANSC6 = 1; } while(0)
#define STP_C_SetDigitalMode() do { ANSELCbits.ANSC6 = 0; } while(0)

// get/set STP_D aliases
#define STP_D_TRIS TRISCbits.TRISC7
#define STP_D_LAT LATCbits.LATC7
#define STP_D_PORT PORTCbits.RC7
#define STP_D_WPU WPUCbits.WPUC7
#define STP_D_OD ODCONCbits.ODCC7
#define STP_D_ANS ANSELCbits.ANSC7
#define STP_D_SetHigh() do { LATCbits.LATC7 = 1; } while(0)
#define STP_D_SetLow() do { LATCbits.LATC7 = 0; } while(0)
#define STP_D_Toggle() do { LATCbits.LATC7 = ~LATCbits.LATC7; } while(0)
#define STP_D_GetValue() PORTCbits.RC7
#define STP_D_SetDigitalInput() do { TRISCbits.TRISC7 = 1; } while(0)
#define STP_D_SetDigitalOutput() do { TRISCbits.TRISC7 = 0; } while(0)
#define STP_D_SetPullup() do { WPUCbits.WPUC7 = 1; } while(0)
#define STP_D_ResetPullup() do { WPUCbits.WPUC7 = 0; } while(0)
#define STP_D_SetPushPull() do { ODCONCbits.ODCC7 = 0; } while(0)
#define STP_D_SetOpenDrain() do { ODCONCbits.ODCC7 = 1; } while(0)
#define STP_D_SetAnalogMode() do { ANSELCbits.ANSC7 = 1; } while(0)
#define STP_D_SetDigitalMode() do { ANSELCbits.ANSC7 = 0; } while(0)

 
Any help is appreciated.Its probably something small but its years since I had to look at this stuff and all the information I can find online seems to be a needle in a haystack - too much information and unanswered questions left and right.
 
Thanks Folks
 
Regads
Alan
#1
GeorgePauley
Moderator
  • Total Posts : 1185
  • Reward points : 0
  • Joined: 2009/12/01 13:59:30
  • Location: Chandler AZ
  • Status: offline
Re: Simulating Inputs 2019/08/26 09:48:57 (permalink) ☄ Helpfulby deadlyBuzz 2019/08/28 10:04:32
0
I think you meant PIC16F18446, not PIC16F18846.

It's a little unclear to me:  Are you in fact using the MPLAB X Simulator?  If so, you want to investigate the simulator's injection language:  SCL.  You can find documentation on SCL in the docs sub folder of your MPLAB X installation directory.
#2
deadlyBuzz
New Member
  • Total Posts : 2
  • Reward points : 0
  • Joined: 2019/08/12 14:16:13
  • Location: 0
  • Status: offline
Re: Simulating Inputs 2019/08/28 10:07:16 (permalink)
0
Thanks @GeorgePauley, I wasnt aware of SCL before this, I;ll have a look.
Apologies for the delay getting back to you, I found my issue regarding the simulator - it was on the Stimulous window.  I was used to using netbeans and just changing the values through the watch window but I found the stimulous window in the manual and started experimenting.
Quite a handy tool the simulator - if only the debugger was so easy but at least I have somewhere to start :-)
 
#3
GeorgePauley
Moderator
  • Total Posts : 1185
  • Reward points : 0
  • Joined: 2009/12/01 13:59:30
  • Location: Chandler AZ
  • Status: offline
Re: Simulating Inputs 2019/08/28 11:24:44 (permalink)
+1 (1)
Stimulus is a GUI front-end for the SCL language.  If stimulus meets your needs then definitely go for it as a quick and easy solution.  Just be aware that stimulus provides a tiny fraction of the capabilities of the SCL injection language.
#4
Jump to:
© 2019 APG vNext Commercial Version 4.5