element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      • Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Embedded and Microcontrollers
  • Technologies
  • More
Embedded and Microcontrollers
Embedded Forum Running a pic18F45K20 at full speed
  • Blog
  • Forum
  • Documents
  • Quiz
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Embedded and Microcontrollers to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 16 replies
  • Subscribers 474 subscribers
  • Views 1328 views
  • Users 0 members are here
  • i2c
  • pic18f45k20
  • ds1803
  • pics
Related

Running a pic18F45K20 at full speed

JohnDSiviter
JohnDSiviter over 15 years ago

Can anyone help with this simple problem, I want to achieve full speed 64MHz, at the moment I am getting 16MHz external, when I run a simple while loop (while(1){PORTD=0xFF;PORTD=0x00;}, I get a 4MHz squarewave, also I am having problems getting I2C working communicating with a DS1803E-010DS1803E-010 digital potentiometer:

 


#pragma config FOSC = INTIO7, FCMEN = OFF, IESO = OFF                       // CONFIG1H
#pragma config PWRT = ON, BOREN = OFF, BORV = 30                            // CONFIG2L
#pragma config WDTEN = OFF, WDTPS = 32768                                   // CONFIG2H
#pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC     // CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF                          // CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF                   // CONFIG5L
#pragma config CPB = OFF, CPD = OFF                                         // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF               // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF                           // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF           // CONFIG7L
#pragma config EBTRB = OFF                                                  // CONFIG7H

/** I N C L U D E S **************************************************/
#include "p18f45k20.h"
#include "07 ADC.h"  // header file
#include "delays.h"
#include "spi.h"
#include "i2c.h"

//#include "math.h"
//#include "08 Interrupts.h"  // header file ****throws error

/** Prototypes**/
void main(void);
unsigned char I2C_SendByte(char myVolume);//char myByte)
unsigned char IncrementGrey(unsigned char Value); unsigned char DecrementGrey(unsigned char Value);
unsigned char WriteI2C1(  unsigned char data_out );
unsigned char ReadI2C1(  unsigned char data_out );
/** V A R I A B L E S *************************************************/
#pragma udata   // declare statically allocated uinitialized variables

/** D E C L A R A T I O N S *******************************************/
#pragma code    // declare executable instructions

/*******Global Variables******************/

/**********************************/
void main(void)
{
unsigned char count=1;
signed   char Direction_Up=-1;
unsigned char volume=0x00;
unsigned char PA=0x00;
unsigned char NAPA=0x00;
unsigned char greyCode=0x00;
unsigned char temp;
unsigned char PORTx;
/******************************************************************/
WDTCONbits.SWDTEN = 0; // Disable Watchdog
OSCTUNEbits.PLLEN    = 1; // Enable PLL //PLL enabled for INTOSC (4 MHz and 8 MHz only)

// IDLEN IRCF2 IRCF1 IRCF0 OSTS(1) IOFS SCS1 SCS0

OSCCONbits.IDLEN     = 0;    // Not enable pherimetral during sleep()
OSCCONbits.SCS1      = 1;    // Internal oscillator selected
OSCCONbits.SCS0      = 0;    //

OSCCONbits.IRCF2     = 1;    // 16 Mhz selected, 110=8Mhz
OSCCONbits.IRCF1     = 1;
OSCCONbits.IRCF0     = 1;

while(OSCCONbits.OSTS == 0){}       //Oscillator Start-up Time-out Status bit
while(OSCCONbits.IOFS == 0){}       //INTOSC Frequency Stable bit       
/******************************************************************/
    // Init I/O
    TRISC = TRISD = 0x00;      // PORTD bits 7:0 are all outputs (0)
    TRISB = 0xFF;  // PORTB (Encoder) are all inputs (1)
// TRISAbits.TRISA0 = 1;  // TRISA0 input

INTCON2bits.RBPU = 0;  // enable PORTB internal pullups
INTCON = 0b11100000;
INTCONbits.GIEL = 1;
INTCON2bits.INTEDG1 = 0;
INTCON3bits.INT1IP = 0;
INTCON3bits.INT1IE = 1;
INTCON3bits.INT1IF = 0;
//INTCON.PLLEN = 1;
RCONbits.IPEN = 1;

WPUBbits.WPUB0 = 1;   // enable pull up on RB0
    TRISBbits.TRISB0 = 1;       // PORTB bit 0 (connected to switch) is input (1)

PA=NAPA=PORTD=0;
volume=0xFF;PORTD=0xFF;
while(1)
{

PA=NAPA;
/* remove this after test */
while (!Switch_Pin1)
{
  Delay1KTCYx(50); //delay for switch debouncing - triggers lagging edge
  if (Switch_Pin1) {Delay1KTCYx(50);NAPA = IncrementGrey(NAPA);} //Increments PA on key release
}
/**************************/
// NAPA=PORTB;
if (PA!=NAPA)
{
  switch(NAPA)
  {

     case 0x00:
        switch (PA) //check last state
        {
         case 0x02:Direction_Up=1; break;
         case 0x01:Direction_Up=0; break;
         default:  Direction_Up=-1;break;
        }
      break;

      case 0x01:
        switch (PA)
        {
         case 0x00:Direction_Up=1; break;//TEMP STOP CODE break;
         case 0x03:Direction_Up=0; break;
         default:  Direction_Up=-1;break;
        }
      break;

     case 0x03:
        switch (PA)
        {
         case 0x01:Direction_Up=1; break;
         case 0x02:Direction_Up=0; break;
         default:  Direction_Up=-1;break;
        }
      break;
         
      case 0x02:
        switch (PA)
        {
         case 0x03: Direction_Up=1; break;   
         case 0x00: Direction_Up=0; break;
         default:   Direction_Up=-1;break;
        }
      default:break;
    
  }
}

switch (Direction_Up)
{
  case 1: volume++;PORTx = I2C_SendByte(volume);PORTD = volume;break;
    default: break;
  case 0: volume--;PORTx = I2C_SendByte(volume);PORTD = volume;break;
}

Direction_Up=-1;
} //while end

}


unsigned char I2C_SendByte(char myVolume)//char myByte)
{
unsigned char SPI_result=-1;
 
//• MSSP Control Register 1 (SSPCON1)
//• MSSP Control Register 2 (SSPCON2)
//• MSSP STATUS register (SSPSTAT)
//• Serial Receive/Transmit Buffer Register
//(SSPBUF)
//• MSSP Shift Register (SSPSR) – Not directly
//accessible
//• MSSP Address Register (SSPADD)
SSPSTAT = 0x80;//Disable SMBus & Slew Rate Control
SSPCON1 = 0x28; //Enable MSSP Master, SSPCON1=MASTER;
   // SPPADD must go after SSPCON1=MASTER; // ADD<7:0> = 1/Fi2c * FOSC-1 = 1/400,000 * 16,000 - 1 = 39 = 0010,0111b = 0x27
SSPCON2 = 0x00; //Clear Control Bits
//SSPADD = 0x18; //Should be 0x18 for 100kHz
SSPADD=0x27;//SCL pin clock period = ((ADD<7:0> + 1) *4)/FOSC
DDRCbits.RC3 = 1; //Configure SCL as Input
DDRCbits.RC4 = 1; //Configure SDA as Input
   //StartI2C();
   //OpenI2C(MASTER, SLEW_ON);
     SPI_result =WriteI2C(0b10100000);// 0101,address
     Delay1KTCYx(500);
  SPI_result =WriteI2C(myVolume);
  //Delay1KTCYx(500);
  return ReadI2C();
}

 

unsigned char IncrementGrey(unsigned char Value)
{
switch (Value)
{
   case 0x00:Value=0x01;break;
   case 0x01:Value=0x03;break;
   case 0x03:Value=0x02;break;
   case 0x02:Value=0x00;break;
   default:break;
}
return Value;
}
unsigned char DecrementGrey(unsigned char Value)
{
switch (Value)
{
   case 0x00:Value=0x02;break;
   case 0x01:Value=0x00;break;
   case 0x03:Value=0x01;break;
   case 0x02:Value=0x03;break;
   default:break;
}
return Value;
}

  • Sign in to reply
  • Cancel
Parents
  • Former Member
    Former Member over 15 years ago

    I'm new here, thought I would chime in..

    You will NOT see the full 64MHz (or even 16MHz) on a scope, if you're just looking at a pin output.

     

    Assuming your uC is running at the full 64MHz (16MHz with 4X PLL and NO cpu division, aka CPU_DIV = 1), the instruction clock speed is actually 64MHz/4 = 16MHz, since the PIC18F architecture uses a "1 instruction per 4 clock cycle" division.

     

    Then, your while loop is adding further overhead to your square wave output, because you are executing two instructions plus an additional comparison instruction or two per iteration of the while loop. That kills the frequency you would see on the output, and thus it is not representative of the true operating speed of the PIC. For a better (although still not ideal) test, simply copy the instructions "PORTD=0xFF;PORTD=0x00;" many many times in your main loop (or in a while(1) loop) and now try viewing the output on a scope. You should see a 16MHz/2 = 8MHz square wave, with an occasional hiccup (where the while loop ends/restarts). If you don't see around 8MHz something else is wrong, and if you're using the internal oscillator it almost HAS to be the software configuration of the oscillator bits or PLL. Hope that helps!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • JohnDSiviter
    JohnDSiviter over 15 years ago in reply to Former Member

    Thanks Brennathi, that is the answer that wins for me, makes perfect sense, hope I get the 8MHz squarewave when I try later image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • MicrochipRTCfr
    MicrochipRTCfr over 15 years ago in reply to JohnDSiviter

    John

     

    The best way to check the processor speed by toggling a port is to use a timer interrupt.

    If you write code in C it will generate several assembly instructions and therefore you'll never toggle the port at the fastest speed. This is only possible in assembler.

    Another VERY IMPORTANT point : for all ports bits that you use in output mode use LATx instead of PORTx.  e.g : LATD = 0xFF instead of PORTD = 0xFF.

     

    If you use TIMER1 to generate interrupts with the prescaler set to 1/8 and writing (65536-20000) into PR1 you will generate an interrupt every Fosc/4  / 8 / 20000 = 10ms which will be easy to look at with a scope (or counting every 50 interrupts) with give a 1s blinking LED.

    Note : assume Fosc = 64MHz

     

    regards

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Former Member
    Former Member over 15 years ago in reply to MicrochipRTCfr

    But if you use an interrupt doesn't the PIC first have to jump to the interrupt vector, then jump to the service routine and THEN toggle the output pin? It seems like there would be just as much overhead that way. Or is there a way to directly toggle a pin the instant an interrupt is triggered?

     

    The way I said will still work, even though it's not the most elegant solution. The C18 compiler will optimize the port toggle instructions so that they each only take one assembly instruction. You could also just directly toggle the port in assembly if you're paranoid about the compiler.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • JohnDSiviter
    JohnDSiviter over 15 years ago in reply to MicrochipRTCfr

    Thanks, can I mix assembler and C code together in the same project, how do I call assembler codes from my C program?.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • firatkocak
    firatkocak over 15 years ago in reply to JohnDSiviter

    Hi,

     

    Yes, you can mix. I don't know which compiler do you use. But in MikroC it is done as simple as below,

     

    asm bcf PORTB , 3

     

    Firat

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • firatkocak
    firatkocak over 15 years ago in reply to JohnDSiviter

    Hi,

     

    Yes, you can mix. I don't know which compiler do you use. But in MikroC it is done as simple as below,

     

    asm bcf PORTB , 3

     

    Firat

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Children
  • Former Member
    Former Member over 15 years ago in reply to firatkocak

    If you're using the C18 compiler, inline assembly is done like this

     

    _asm
    /* User assembly code */
    MOVLW 10 // Move decimal 10 to count
    MOVWF count, 0
    /* Loop until count is 0 */
    start:
    DECFSZ count, 1, 0
    GOTO done
    BRA start
    done:
    _endasm

    _asm  /* User assembly code */ _endasm

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • JohnDSiviter
    JohnDSiviter over 15 years ago in reply to Former Member

    Thanks all, and thanks Brennanthi I will try that later.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • JohnDSiviter
    JohnDSiviter over 15 years ago in reply to JohnDSiviter

    My latest code (good for anyone learning the PIC18F45K20), I have also copied the descriptions for the status registers in there, the code is purposely bulky by switching invividual bits in the status register, but I like it that way when learning these PICs:

     


    /** C O N F I G U R A T I O N   B I T S ******************************/

    #pragma config FOSC = INTIO7, FCMEN = OFF, IESO = OFF                       // CONFIG1H, FSOC=HSPLL, INTIO67
    #pragma config PWRT = ON, BOREN = OFF, BORV = 30                            // CONFIG2L
    #pragma config WDTEN = OFF, WDTPS = 1                                       // CONFIG2H
    #pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = OFF, CCP2MX = PORTC     // CONFIG3H
    #pragma config STVREN = ON, LVP = OFF, XINST = OFF                          // CONFIG4L
    #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF                   // CONFIG5L
    #pragma config CPB = OFF, CPD = OFF                                         // CONFIG5H
    #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF               // CONFIG6L
    #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF                           // CONFIG6H
    #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF           // CONFIG7L
    #pragma config EBTRB = OFF                                                  // CONFIG7H

    /** I N C L U D E S **************************************************/
    #include "p18f45k20.h"
    #include "myLibrary.h"  // header file
    #include "delays.h"
    #include "i2c.h"
    #include "spi.h"

    //#include "math.h"

    /** Prototypes*********************************************************/
    void          main(void);
    void        I2C_DS1803_SendByte(char myVolume);//char myByte)
    unsigned char I2C_DS1803_RecieveByte(signed char myVolume);//char myByte);
    unsigned char IncrementGrey(unsigned char Value); unsigned char DecrementGrey(unsigned char Value);
    unsigned char EEPROM_Read(unsigned char address);void EEPROM_Write(unsigned char address, unsigned char databyte);
    unsigned char myI2CWriteByte(unsigned char myByte);
    signed char returnVolumeFromGrey(unsigned char PresentState, unsigned char NextState, signed char myvolume);
    unsigned char ifSwitchIncNAPA(unsigned char SwitchPin, unsigned char NAPA);
    /** Interupt Prototypes ***********************************************/
    void interrupt_at_high_vector(void);
    void high_isr(void);

    /** V A R I A B L E S *************************************************/
    #pragma udata   // declare statically allocated uinitialized variables

    /** Interrupts ********************************************************/
    #pragma code high_vector=0x08
    void interrupt_at_high_vector(void)
    {
      _asm GOTO high_isr _endasm
    }

    #pragma code /* return to the default code section */

    #pragma interrupt high_isr
    void high_isr(void)
    {
    // This is where we keep the service routine, remember to set the config
        LATC = 1; //RC0 HIGH
        INTCONbits.TMR0IF = 0; //CLEAR TMR0 INT FLAG
    }
    //#pragma stack 0x300 0xff // set 64 byte stack at 0x300, needed by sdcc
    /***********************************************************************/
    void main(void)
    {
    // User Variables
    signed   char volume=0xFF;
    unsigned char PA=0x00;
    unsigned char NAPA=0x00;
    unsigned char temp;
    unsigned char PORTx;
    unsigned char save_me = 'x';
        unsigned char from_eeprom;
        // User Init I/O
        TRISD = 0x00;                      // PORTD bits 7:0 are all outputs (0)
        TRISB = 0xFF;                     // PORTB (Encoder) are all inputs (1)
    TRISC = 0xFF;
    DDRCbits.RC3 = 1;                  //Configure SCL as Output
    DDRCbits.RC4 = 1;                  //Configure SDA as Output
        /********************************************************************************** CPU Clocking ********************************************/
       
    //OSCCON***************** IDLEN IRCF2 IRCF1 IRCF0 OSTS(1) IOFS SCS1 SCS0
    OSCCONbits.IDLEN     = 0;    // Not enable pherimetral during sleep()
    OSCCONbits.IRCF2     = 1;    // 111=16 Mhz selected, 110=8Mhz
    OSCCONbits.IRCF1     = 1;
    OSCCONbits.IRCF0     = 1;
    OSCCONbits.SCS0      = 0; //  // Internal oscillator selected Internal 1X: Secondary 01:Primary:00
    OSCCONbits.SCS1      = 0;
    //Clock Status bits:
    while(OSCCONbits.OSTS == 0){}       //Oscillator Start-up Time-out Status bit
    while(OSCCONbits.IOFS == 0){}       //INTOSC Frequency Stable bit  
    WDTCONbits.SWDTEN    = 0;           // Disable Watchdog

     

    // OSCTUNE*************** INTSRC — — TUN4 TUN3 TUN2 TUN1 TUN0
    OSCTUNEbits.TUN0  = 1;
    OSCTUNEbits.TUN1  = 1;
    OSCTUNEbits.TUN2  = 1;
    OSCTUNEbits.TUN3  = 1;
    OSCTUNEbits.TUN4  = 0;
    /*
    bit 4-0 TUN4:TUN0: Frequency Tuning bits
      01111 = Maximum frequency
      • •
      • •
      00001
      00000 = Center frequency. Oscillator module is running at the calibrated frequency.
      11111
      • •
      • •
      10000 = Minimum frequency */

    OSCTUNEbits.PLLEN = 1;              // Enable PLL //PLL enabled for INTOSC (4 MHz and 8 MHz only)
    OSCTUNEbits.INTSRC= 1;              // PLL for 31khz option when selected
      //(SCS)System clock select bits:
     
       //
    //scs: 00 = Primary clock (determined by CONFIG1H[FOSC<3:0>]).
        /********************************************************************************** Interrupt Control ***************************************/   
    // INTCON  **************** GIE/GIEH PEIE/GIEL TMR0IE INT0IE RBIE TMR0IF INT0IF RBIF
    INTCONbits.GIE      = 0;    // Global Interrupt Enable bit:        1 = Enables all unmasked interrupts, 0 = Disables all interrupts
    INTCONbits.GIEL     = 0;     // PEIE/GIEL: Peripheral Interrupt Enable bit: When IPEN = 0:,   1 = Enables all unmasked peripheral interrupts, 0 = Disables all peripheral interrupts
    INTCONbits.TMR0IE   = 0;       // TMR0IE: TMR0 Overflow Interrupt Enable bit
    INTCONbits.INT0IE   = 0;       // INT0IE: INT0 External Interrupt Enable bit
    INTCONbits.RBIE     = 0;     // RBIE: RB Port Change Interrupt Enable bit
    INTCONbits.TMR0IF   = 0;       // TMR0IF: TMR0 Overflow Interrupt Flag bit
    INTCONbits.INT0IF   = 0;       // INT0IF: INT0 External Interrupt Flag bit
    INTCONbits.RBIF     = 0;       // RBIF: RB Port Change Interrupt Flag bit

     

    // INTCON2 **************** RBPU INTEDG0 INTEDG1 INTEDG2 — TMR0IP — RBIP 
    INTCON2bits.RBPU     = 1;    // RBPU: 'PORTB Pull-up Enable bit
    INTCON2bits.INTEDG0  = 0;      // INTEDG0: External Interrupt 0 Edge Select bit, 1 = Interrupt on rising edge, 0 = Interrupt on falling edge   
    INTCON2bits.INTEDG1  = 0;      // INTEDG1: External Interrupt 1 Edge Select bit, 1 = Interrupt on rising edge, 0 = Interrupt on falling edge
    INTCON2bits.INTEDG2  = 0;      // INTEDG2: External Interrupt 2 Edge Select bit, 1 = Interrupt on rising edge, 0 = Interrupt on falling edge
    INTCON2bits.TMR0IP   = 0;      // TMR0IP: TMR0 Overflow Interrupt Priority bit , 1 = High priority           , 0 = Low priority
    INTCON2bits.RBIP     = 0;      // RBIP: RB Port Change Interrupt Priority bit  , 1 = High priority           , 0 = Low priority

     

    // INTCON3 **************** INT2IP INT1IP — INT2IE INT1IE — INT2IF INT1IF
    INTCON3bits.INT2IP  = 0;       // INT2IP: INT2 External Interrupt Priority bit , 1 = High priority           , 0 = Low priority
    INTCON3bits.INT1IP  = 0;       // INT1IP: INT1 External Interrupt Priority bit , 1 = High priority           , 0 = Low priority
      //bit 5 unimplemented Read as '0'
    INTCON3bits.INT2IE  = 0;       // INT2IE: INT2 External Interrupt Enable bit   , 1 = Enables the INT2 external interrupt
    INTCON3bits.INT1IE  = 0;       // INT1IE: INT1 External Interrupt Enable bit   , 1 = Enables the INT1 external interrupt
    INTCON3bits.INT2IF  = 0;       // INT2IF: INT2 External Interrupt Flag bit     , 1 = The INT2 external interrupt occurred (must be cleared in software)
    INTCON3bits.INT1IF  = 0;       // INT1 External Interrupt Flag bit             , 1 = The INT1 external interrupt occurred (must be cleared in software)
    RCONbits.IPEN = 1;

    WPUBbits.WPUB0 = 1;           // enable pull up on RB0
    /********************************************************************************** MSSP Control ***************************************/   
    /***************I2C Setup*********************************************/
    //SSPCON - Control Register, SSPSTAT - Status Register,
    //*********************SSPCON1............ WCOL SSPOV SSPEN CKP SSPM3 SSPM2 SSPM1 SSPM0
    SSPCON1bits.WCOL    = 0;    //*      // WCOL: Write Collision Detect bit (Transmit mode only), 1 = The SSPBUF register is written while it is still transmitting the previous word (must be cleared in software)
    SSPCON1bits.SSPOV   = 0;             // SSPOV: Receive Overflow Indicator bit, only for spi slave mode
    SSPCON1bits.SSPEN   = 1;    //*      // 1 = SSPEN; Enables the serial port and configures the SDA and SCL pins as the serial port pins
    SSPCON1bits.CKP     = 0;    //*      // Write Collision Detect bit = OFF
    SSPCON1bits.SSPM3   = 1;             // 1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
    SSPCON1bits.SSPM2   = 0;             //
    SSPCON1bits.SSPM1   = 0;             //
    SSPCON1bits.SSPM0   = 0;             //
    /*
    bit 3-0 SSPM3:SSPM0: Synchronous Serial Port Mode Select bits
    1111 = I2C Slave mode, 10-bit address with Start and Stop bit interrupts enabled
    1110 = I2C Slave mode, 7-bit address with Start and Stop bit interrupts enabled
    1011 = I2C Firmware Controlled Master mode (Slave Idle)
    1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
    0111 = I2C Slave mode, 10-bit address
    0110 = I2C Slave mode, 7-bit address
    */
        // SPPADD must go after SSPCON1=MASTER; // ADD<7:0> = 1/Fi2c * FOSC-1 = 1/400,000 * 16,000 - 1 = 39 = 0010,0111b = 0x27
    // SSPCON2 = 0x00; //Clear Control Bits, GCEN ACKSTAT ACKDT ACKEN(1) RCEN(1) PEN(1) RSEN(1) SEN(1)

     

    SSPCON2bits.SEN    = 1;     // *        // Start Condition Enabled/Stretch Enabled bit(1) *try toggling
    SSPCON2bits.PEN    = 1;     // *        // Stop Condition Enable bit (Master mode only)(1) ****
    SSPCON2bits.RCEN   = 0;     // *        // Receive Enable bit (Master mode only)(1)
    SSPCON2bits.ACKEN  = 0;     // *        // Acknowledge Sequence Enable bit (Master Receive mode only)(1) #####
    SSPCON2bits.ACKDT  = 0;     // *        // Acknowledge Data bit (Master Receive mode only) #####
    SSPCON2bits.ACKSTAT= 0;     // *        // Acknowledge Status bit (Master Transmit mode only) %%%%%
    SSPCON2bits.GCEN   = 0;                 // General Call Enable bit (Slave mode only), 0 = General call address disabled
    //SSPADD = 0x18; //Should be 0x18 for 100kHz

     

    //*********************SSPSTAT............ SMP CKE D/A P S R/W UA BF
    SSPSTATbits.SMP    = 0;               // SMP: Slew Rate Control bit, 1 = Slew rate control disabled for Standard Speed mode (100 kHz and 1 MHz), 0 = Slew rate control enabled for High-Speed mode (400 kHz)
    SSPSTATbits.CKE    = 0;      // CKE: SMBus Select bit, 1 = Enable SMBus specific inputs, 0 = Disable SMBus specific inputs
    SSPSTATbits.D      = 0;      // D/A: Data/Address bit, for slave mode, 1 = Indicates that the last byte received or transmitted was data, 0 = address
    SSPSTATbits.P      = 0;      // P: Stop bit, 1 = Indicates that a Stop bit has been detected last
    SSPSTATbits.S      = 0;      // S: Start bit, 1 = Indicates that a Start bit has been detected last
    SSPSTATbits.R      = 0;      // R/`W: Read/Write bit Information (I2C mode only),slave (1=read, 0=write), master (1=transmit in progress, 0=transmit not in progress).
    SSPSTATbits.UA     = 0;      // UA: Update Address bit (10-bit Slave mode only), 1 = Indicates that the user needs to update the address in the SSPADD register, 0 = Address does not need to be updated
    SSPSTATbits.BF     = 0;      // BF: Buffer Full Status bit, 'In Transmit mode'(1 = Receive complete, SSPBUF is full, 0 = Receive not complete, SSPBUF is empty), 'In Receive mode:'(1 = Data transmit in progress (does not include the 'ACK and Stop bits), SSPBUF is full,0 = Data transmit complete (does not include the 'ACK and Stop bits), SSPBUF is empty).

     

    SSPADD=0x27;                          //SCL pin clock period = ((ADD<7:0> + 1) *4)/FOSC

     

    //********************** ANSEL............. ANS7(1) ANS6(1) ANS5(1) ANS4 ANS3 ANS2 ANS1 ANS0

     

    /*********************************************************************/
    PA=NAPA=PORTD=0;
    volume=0x30;PORTD=0x00;
        /********************************   MAIN LOOP   ****************************************************************************************/
    while(1)
    {
      PA=NAPA; /* remove this after test */
      //NAPA   = ifSwitchIncNAPA      (Switch_Pin1, NAPA  );
      while (!Switch_Pin1)
      {
       Delay1KTCYx(50); //delay for switch debouncing - triggers lagging edge
       if (Switch_Pin1) {NAPA = IncrementGrey(NAPA);} //Increments PA on key release
       I2C_DS1803_SendByte(volume);
      }
      volume = returnVolumeFromGrey (PA, NAPA   , volume);
            Delay1KTCYx(50);PORTD=volume;
     
     
    }
    //EEPROM_Write(0x7000, 12354);
    //PORTD = EEPROM_Read(0x7000);
    }
        /********************************   MAIN LOOP   ****************************************************************************************/
       
       
    /******************************** FUNCTIONS ************************************************************************************************/
    void I2C_DS1803_SendByte(signed char myVolume)//char myByte)
    {
            TRISC = 0x00; //turn on tri-state register and
                          //make all output pins
            //PORTC = 0x00; //make all output pins LOW

            OpenI2C( MASTER, SLEW_OFF);
            SSPADD = 0x27;//0x33;
      StartI2C();                     // Sends start bits
          WriteI2C(0b01010000);       // Address
          WriteI2C(0b10101111);       // Command: write to both potentiometers
       WriteI2C(0b00110101);  // Value
      IdleI2C ();
    }
    unsigned char I2C_DS1803_RecieveByte(signed char myVolume)//char myByte)
    {
    unsigned char R1, R2;
            TRISC = 0x00; //turn on tri-state register and
                          //make all output pins
            PORTC = 0x00; //make all output pins LOW

            OpenI2C( MASTER, SLEW_OFF);
            SSPADD = 0x3F;
        AckI2C();IdleI2C ();
    StartI2C();                         // Sends start bits
    AckI2C();IdleI2C ();
    WriteI2C(0b01010000);               // Address
    AckI2C();IdleI2C ();
    R1 = ReadI2C();
    AckI2C();IdleI2C ();
    R2 = ReadI2C();
    AckI2C();IdleI2C ();
        Delay1KTCYx(500);
    return R1;                   // Value
    }


    unsigned char IncrementGrey(unsigned char Value)
    {
    switch (Value)
    {
       case 0x00:Value=0x01;break;
       case 0x01:Value=0x03;break;
       case 0x03:Value=0x02;break;
       case 0x02:Value=0x00;break;
       default:break;
    }
    return Value;
    }
    unsigned char DecrementGrey(unsigned char Value)
    {
    switch (Value)
    {
       case 0x00:Value=0x02;break;
       case 0x01:Value=0x00;break;
       case 0x03:Value=0x01;break;
       case 0x02:Value=0x03;break;
       default:break;
    }
    return Value;
    }

     

    unsigned char EEPROM_Read(unsigned char address)
    { // reads and returns the EEPROM byte value at the address given
    // given in "address".
    EECON1bits.EEPGD = 0;// Set toaccessEEPROMmemory
    EECON1bits.CFGS= 0;// Do notaccessConfigregisters
    EEADR = address;//Load EEADRwith address of location to write.
    // execute the read
    EECON1bits.RD = 1;//Set the RDbit to execute the EEPROM read
    //The value read is ready the next instruction cycle in EEDATA. No wait is
    //needed.
    return EEDATA;
    }


    void EEPROM_Write(unsigned char address, unsigned char databyte)
    { // writes the "databyte" value to EEPROM at the address given
    // location in "address".
    EECON1bits.EEPGD = 0; // Set to access EEPROM memory
    EECON1bits.CFGS = 0; // Do not access Config registers
    EEDATA = databyte; // Load EEDATA with byte to be written
    EEADR = address; // Load EEADR with address of location to write.
    EECON1bits.WREN = 1; // Enable writing
    INTCONbits.GIE = 0; // Disable interrupts
    EECON2 = 0x55; // Begin Write sequence
    EECON2 = 0xAA;
    EECON1bits.WR = 1; // Set WR bit to begin EEPROM write
    INTCONbits.GIE = 1; // re-enable interrupts
    while (EECON1bits.WR == 1)
    { // wait for write to complete.
    };
    EECON1bits.WREN = 0;
    }


    signed char returnVolumeFromGrey(unsigned char PA, unsigned char NAPA, signed char myvolume)
    {
      if (PA!=NAPA)
      {
       switch(NAPA)
       {
          case 0x00:
            switch (PA) //check last state
            {
             case 0x02:myvolume++; break;
             case 0x01:myvolume--; break;
            }
           break;

           case 0x01:
            switch (PA)
            {
             case 0x00:myvolume++; break;
             case 0x03:myvolume--; break;
            }
           break;

          case 0x03:
            switch (PA)
            {
             case 0x01:myvolume++; break;
             case 0x02:myvolume--; break;
            }
           break;
             
           case 0x02:
            switch (PA)
            {
             case 0x03: myvolume++; break;   
             case 0x00: myvolume--; break;
            }
           default:break;
       }

      }
    return myvolume;
    } 
    unsigned char ifSwitchIncNAPA(unsigned char SwitchPin, unsigned char NAPA)
    {
      while (!Switch_Pin1)
      {
       Delay1KTCYx(50); //delay for switch debouncing - triggers lagging edge
       if (Switch_Pin1) {NAPA = IncrementGrey(NAPA);} //Increments PA on key release
      }
    }

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • JohnDSiviter
    JohnDSiviter over 15 years ago in reply to JohnDSiviter

    I started designing the PCB, I like NI's Electronic workbench 3D representation, all fits on a 4cm x 4cm board (needs a few connectors on there and a few op-amps): image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • JohnDSiviter
    JohnDSiviter over 15 years ago in reply to JohnDSiviter

    Ignore above, in my MCU discovery I have decided the 18F is too lowly a beast and have migrated onto the dsPIC33, wooed by its DSP charms and simplicity.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Former Member
    Former Member over 15 years ago in reply to JohnDSiviter

    I figured that was going to be the case but I didn't want to lead you in a different direction.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube