1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

ADXL345 Accelerometer and 18F4550 in Hi-Tech C

Discussion in 'Code Repository' started by ClydeCrashKop, Feb 10, 2014.

  1. ClydeCrashKop

    ClydeCrashKop Active Member

    Joined:
    Apr 28, 2005
    Messages:
    971
    Likes:
    152
    Location:
    Florida
    This program displays the 3 axis output from an ADXL345 Accelerometer and 18F4550 in Hi-Tech C. Specifically the little GY-291 board available cheap on eBay. There are pull-ups on the board to solve the 3 volt problem.
    I got some info from Ngoc Chung Hoang using CCS compiler ADXL345 + Pic 16f877a
    If you ask nice and leave your email, he will send the source code.
    and his Balancing robot

    I use Nigel Goodwin's tutorials in asm... http://www.winpicprog.co.uk/ for an asm library and circuits. Now using HI-TECH C, I use Nigel's tutorials.. re-written in C by Ian Rogers. http://www.electro-tech-online.com/content/467-nigel-goodwin-s-tutorials-c.html as a starting place for C programs and subroutines.
    Thank you Nigel and Ian.
    You are welcome to leave your 18F4550 code in this thread.

    Code (C):

    // ADXL345 Accelerometer and 18F4550 in Hi-Tech C
    // Using the hardware MSSP I2C port on RB0 & RB1 and LCD on port D
     
    /*   Using HI-TECH C for PIC18 MCU Family.
     
      LCD on D  ICSP is on Port B6 and B7.
      The wiring for the LCD using Hitachi HD44780 is at
      http://www.winpicprog.co.uk/pic_tutorial_lcd_board.htm
    */

    //#include <pic18f4550.h>
    #include <pic18.h>
    #include <htc.h>
    #include <stdlib.h>
    #include <stdio.h>
     
    /* Configuration words for a PIC18F4450
    * with a 20 MHz crystal oscillator
    */

    __CONFIG(1,USBPLL&PLLDIV5&CPUDIV4&HSPLL&FCMEN&IESOEN);
    __CONFIG(2,VREGDIS&PWRTEN&BORDIS&BORV42&WDTDIS&WDTPS32K);
    __CONFIG(3,PBDIGITAL&LPT1DIS&MCLREN);
    __CONFIG(4,XINSTDIS&STVRDIS&LVPDIS&ICPORTDIS&DEBUGDIS);
    __CONFIG(5,UNPROTECT);
    __CONFIG(6,UNPROTECT);
    __CONFIG(7,UNPROTECT);
     
     
    char  IDDV =0;
    #define  BW_RATE            44    //0x2C
    #define  POWER_CTL          45    //0x2D
    #define  DATA_FORMAT        49    //0x31
    #define  DATAX0             50    //0x32
    #define  DATAX1             51    //0x33
    #define  DATAY0             52    //0x34
    #define  DATAY1             53    //0x35
    #define  DATAZ0             54    //0x36
    #define  DATAZ1             55    //0x37
    #define  FIFO_CTL           56    //0x38            ADXL1345    1010011   0x53   Device
    #define CHIP_Write    0xA6        // adxl345 address for writing    10100110  0xA6   Write
    #define CHIP_Read    0xA7        // and reading                    10100111  0xA7   Read
     
     
    #define _XTAL_FREQ  20000000        // Xtal speed
     
    #define LCD_PORT PORTD            // constants
    #define LCD_TRIS TRISD            //
    #define LCD_RS     LATD4        // It didn't like RD4?
    #define LCD_RW    LATD6
    #define LCD_E    LATD7
     
     
            // Required prototypes.. each function needs to be declared
            // if called BEFORE definition.
     
    void LCD_init(void), LCD_cmd(unsigned char ch);
    void LCD_goto(char line, char column), LCD_clr(void);
    void LCD_cur(unsigned char ch), pulse_E(void);
    void LCD_char(unsigned char ch), LCD_charD(unsigned char ch);
    void LCD_printC(const char *str), LCD_printR(char *str);
    void delayMs(int x);
     
    // Hardware I2C functions
    void I2CInit(void);
    void I2CStart();
    void I2CStop();
    void I2CRestart();
    void I2CAck();
    void I2CNak();
    void I2CWait();
    void I2CSend(unsigned char dat);
    unsigned char I2CRead(void);
    char E_Write(int addr, unsigned char ch);
    unsigned char E_Read(int addr);
     
     
     
    void ini_adxl345()
    {
    E_Write(FIFO_CTL,0x9f);
    __delay_ms(10);    
    E_Write(DATA_FORMAT,0x09);
    __delay_ms(10);  
    E_Write(BW_RATE,0x0d);
    __delay_ms(10);        
    E_Write(POWER_CTL,0x08);  // activate  
    }
     
    unsigned char LCDbuffer[17];
    char ErrFlags;            // Read error. (I don't use it, but you might!)
       
     
     
    /* our main program loop */
    void main(void)
    {
        CMCON = 0x07;                        // Comparitors off
     
        int index = 0;                        // text variable
        unsigned char ch;
        LCD_TRIS = 0b00000000;            // LCD port as outputs
        LCD_PORT = 0b00000000;            // Clear LCD port
        delayMs(150);                    // let LCD stabilise
        LCD_init();                        // Initalise screen
     
    //    LCD_goto(1,0);    // line 1.
    //    LCD_printC("Hi World");
     
        // Initialize I2C Port
        I2CInit();
        // Initialize ADXL345 Accelerometer
        ini_adxl345();
     
    /*    LCD_goto(1,0);
          int id, pow, bw_rate;
          id= E_Read(IDDV);  // should be 229 for ADXL1345
         __delay_ms(10);
          pow=E_Read(0x2D);  //should be 8 to activate
         __delay_ms(10);
          bw_rate =E_Read(0x2C);  //BW_RATE 0x2C is 13
            sprintf(LCDbuffer,"id=%3d pow=%3d BW_RATE=%3d",id,pow,bw_rate);
            LCD_printR(LCDbuffer);        // use sprintf to format
    */

     
        signed long x,y,z;
        signed long xhi,xlo,yhi,ylo,zhi,zlo;
        signed long Xaccumulate, Yaccumulate, Zaccumulate;
        signed long Xaverage, Yaverage, Zaverage;
        int i;
     
     
      while(1) {
     
        Xaccumulate = Yaccumulate = Zaccumulate = 0;
     
        for (i=0; i<16; i++) {  // Read sequentially 16 times then get an average.
     
     
        ErrFlags = 0;                                    // Clear error
        I2CStart();
        I2CSend(CHIP_Write);
        I2CSend(DATAX0);    // DATAX0 is the first of 6 bytes
        I2CRestart();
        I2CSend(CHIP_Read);                            //
        xlo = I2CRead();                                // read character
        I2CAck();
        xhi = I2CRead();                                // read character
        I2CAck();
        ylo = I2CRead();                                // read character
        I2CAck();
        yhi = I2CRead();                                // read character
        I2CAck();
        zlo = I2CRead();                                // read character
        I2CAck();
        zhi = I2CRead();                                // read character
        I2CNak();
        I2CStop();
     
     
        Xaccumulate += ((xhi<<8) | xlo); //Xaccumulate = Xaccumulate + (xhi*256 + xlo)
        Yaccumulate += ((yhi<<8) | ylo);
        Zaccumulate += ((zhi<<8) | zlo);
     
      }  // for loop
     
    //    x= (xhi<<8) | xlo;
    //    y= (yhi<<8) | ylo;
    //    z= (zhi<<8) | zlo;
     
    // Calculate average accelerometer readings over last 16 samples
     
    /* *** Other methods of dividing gave me results in the +/- thousands ***
    DIV   From Hi-Tech C manual
    Synopsis
    #include <stdlib.h>
    div_t div (int numer, int demon)
    Description
    The div() function computes the quotient and remainder of the numerator divided by the denominator.
    Example
    #include <stdlib.h>
    #include <stdio.h>
    void
    main (void)
    {
    div_t x;
    x = div(12345, 66);
    printf("quotient = %d, remainder = %d\n", x.quot, x.rem);
    }
    See Also
    udiv(), ldiv(), uldiv()
    Return Value
    Returns the quotient and remainder into the div_t structure.
    */

     
    div_t xavg ; // div_t is a structure explained above
    div_t yavg ;
    div_t zavg ;
     
    xavg = div(Xaccumulate, 16);
    yavg = div(Yaccumulate, 16);
    zavg = div(Zaccumulate, 16);
     
    LCD_goto(1,0);
            sprintf(LCDbuffer,"X=%5d",xavg.quot);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(1,9);
            sprintf(LCDbuffer,"Y=%5d",yavg.quot);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(2,4);    
    sprintf(LCDbuffer,"Z=%5d",zavg.quot);
            LCD_printR(LCDbuffer);        // use sprintf to format
    __delay_ms(25);
     
     
     
    /*
    // This reads byte registers one at a time.
       x=(E_Read(DATAX1)*256) | (E_Read(DATAX0));
       y=(E_Read(DATAY1)*256) | (E_Read(DATAY0));
       z=(E_Read(DATAZ1)*256) | (E_Read(DATAZ0));
     
    LCD_goto(1,0);
            sprintf(LCDbuffer,"x=%5d",x);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(1,12);
            sprintf(LCDbuffer,"y=%5d",y);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(2,0);    
    sprintf(LCDbuffer,"z=%5d",z);
            LCD_printR(LCDbuffer);        // use sprintf to format
    */

     
                   }   // while loop
    }  // Main
     
     
     
     
     
    /*
    Function: I2CInit
    Return:
    Arguments:
    Description: Initialize I2C in master mode, Sets the required baudrate
    */

    void I2CInit(void)
    {
        TRISBbits.TRISB0 = 1; /* SDA and SCL as input pin */
         TRISBbits.TRISB1 = 1; /* these pins can be configured either i/p or o/p */
        SSPSTAT |= 0x80; /* Slew rate disabled */
        SSPCON1 = 0x28;//Enable SDA and SCL, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
                    /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
        SSPCON2 = 0x00;      // Reset MSSP Control Register
        SSPADD = 49;      //20000000 / 4= 5000000, 5000000/ 100000= 50 50-1=49
        PIR1bits.SSPIF=0;    // Clear MSSP Interrupt Flag
        PIR2bits.BCLIF=0;
    /* *** For different Frequencies ***
    FOSC     FCY  SSPADD Value  FCLOCK
    40 MHz 10 MHz     63h         100 kHz
    32 MHz     8 MHz    4Fh         100 kHz
    20 MHz     5 MHz    31h, 49d     100 kHz
    16 MHz     4 MHz     27h         100 kHz
    8 MHz     2 MHz     13h, 19d    100 kHz
    4 MHz     1 MHz     09h         100 kHz
    */

    }
     
     
    /*
    Function: I2CStart
    Return:
    Arguments:
    Description: Send a start condition on I2C Bus
    */

    void I2CStart()
    {
        SEN = 1;         /* Start condition enabled */
        while(SEN);      /* automatically cleared by hardware */
                         /* wait for start condition to finish */
    }
     
    /*
    Function: I2CStop
    Return:
    Arguments:
    Description: Send a stop condition on I2C Bus
    */

    void I2CStop()
    {
        PEN = 1;         /* Stop condition enabled */
        while(PEN);      /* Wait for stop condition to finish */
                         /* PEN automatically cleared by hardware */
    }
     
    /*
    Function: I2CRestart
    Return:
    Arguments:
    Description: Sends a repeated start condition on I2C Bus
    */

    void I2CRestart()
    {
        RSEN = 1;        /* Repeated start enabled */
        while(RSEN);     /* wait for condition to finish */
    }
     
    /*
    Function: I2CAck
    Return:
    Arguments:
    Description: Generates acknowledge for a transfer
    */

    void I2CAck()
    {
        ACKDT = 0;       /* Acknowledge data bit, 0 = ACK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
    }
     
    /*
    Function: I2CNck
    Return:
    Arguments:
    Description: Generates Not-acknowledge for a transfer
    */

    void I2CNak()
    {
        ACKDT = 1;       /* Acknowledge data bit, 1 = NAK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
    }
     
    /*
    Function: I2CWait
    Return:
    Arguments:
    Description: wait for transfer to finish
    */

    void I2CWait()
    {
        while ((SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );
        /* wait for any pending transfer */
    }
     
    /*
    Function: I2CSend
    Return:
    Arguments: dat - 8-bit data to be sent on bus
               data can be either address/data byte
    Description: Send 8-bit data on I2C bus
    */

    void I2CSend(unsigned char dat)
    {
        SSPBUF = dat;    /* Move data to SSPBUF */
        while(BF);       /* wait till complete data is sent from buffer */
        I2CWait();       /* wait for any pending transfer */
    }
     
    /*
    Function: I2CRead
    Return:    8-bit data read from I2C bus
    Arguments:
    Description: read 8-bit data from I2C bus
    */

    unsigned char I2CRead(void)
    {
        unsigned char temp;
    /* Reception works if transfer is initiated in read mode */
        RCEN = 1;        /* Enable data reception */
        while(!BF);      /* wait for buffer full */
        temp = SSPBUF;   /* Read serial buffer and store in temp register */
        I2CWait();       /* wait to check any pending transfer */
        return temp;     /* Return the read data from bus */
    }
     
     
    // This is random writing. Write to a specified address
    char E_Write(int addr, unsigned char ch)
        {
        /* Send Start condition */
        I2CStart();
        /* Send ADXL1345 slave address with write operation */
        I2CSend(CHIP_Write);
        /* Send subaddress, we are writing to this location */
        I2CSend(addr);
        /* send I2C data one by one */
        I2CSend(ch);
        /* Send a stop condition - as transfer finishes */
        I2CStop();
        return 1;                                        // All went well
        }
     
    // The function takes an address and Returns a character
    // This is random reading. Read from a specified addess
    unsigned char E_Read(int addr)
        {
        unsigned char byte;
        unsigned char ch;
        ErrFlags = 0;                                    // Clear error
        /* Send Start condition */
        I2CStart();
        /* Send ADXL1345 slave address with write operation */
        I2CSend(CHIP_Write);
        /* this address is actually where we are going to read from */
        I2CSend(addr);
        /* Send a repeated start, after a dummy write to start reading */
        I2CRestart();
        /* send slave address with read bit set */
        I2CSend(CHIP_Read);
     
        ch = I2CRead();                                // read character
        I2CNak();
        I2CStop();
        return ch;
        }
     
     
     
     
    // This may take calculated delay times. Don't use for LCD
    void delayMs(int x)
        {
        while(x--)
            __delay_ms(1);
        }
     
    void LCD_printC(const char * str)    // This passes the start a ROM character array
        {                                // by default the pointer points to data section
        while(*str != 0)                // while the character pointed to isn't 0
            LCD_char(*str++);            // print out the character, then increment
        }                                // the pointer down the array
     
    void LCD_printR(char * str)             // This passes the start of a RAM character array
        {                                // by default the pointer points to data section
        while(*str != 0)                // while the character pointed to isn't 0
            LCD_char(*str++);            // print out the character, then increment
        }
     
    void LCD_init()
        {
        LCD_cmd(0x20);                    // 4 bit
        LCD_cmd(0x28);                    // display shift
        LCD_cmd(0x6);                    // character mode
        LCD_cmd(0xc);                    // display on / off and cursor
        LCD_clr();                        // clear display
        }
     
    void LCD_goto(char line, char column)        // combines line and lineW
        {
        unsigned char data = 0x80;                // default to 1
        if(line == 2)data = 0xc0;                // change to 2
        data += column;                            // add in  column
        LCD_cmd(data);
        }
     
    void LCD_clr()
        {
        LCD_cmd(1);                                // Clr screen
        }
     
    void LCD_cur(char on)
        {
        unsigned char cur = 0xc;                // cursor off
        if(on) cur = 0xd;                        // cursor on
        LCD_cmd(cur);
        }
     
    void LCD_cmd(unsigned char ch)
        {
        LCD_PORT = ch >> 4 & 0xf;            // write high nibble
        LCD_RS = 0;
        pulse_E();
        LCD_PORT = ch & 0xf;                // write low nibble
        LCD_RS = 0;
        pulse_E();
        __delay_ms(5);
        }
     
    void LCD_charD(unsigned char ch)
        {
        ch+=0x30;
        LCD_char(ch);                        // convert to ascii
        }
     
    void LCD_char(unsigned char ch)
        {
        LCD_PORT = ch >> 4 & 0xf;            // High nibble
        LCD_RS = 1;
        pulse_E();
        LCD_PORT = ch & 0xf;                // low nibble
        LCD_RS = 1;
        pulse_E();
        __delay_ms(5);
        }
     
    void pulse_E()
        {
        LCD_E = 1;
        __delay_us(1);
        LCD_E = 0;
        }
     

    Attached Files:

    Last edited: Mar 18, 2014
  2. ClydeCrashKop

    ClydeCrashKop Active Member

    Joined:
    Apr 28, 2005
    Messages:
    971
    Likes:
    152
    Location:
    Florida
    Here it is again for the 16F628A

    Code (C):

    // ADXL345 Accelerometer and 16F628a in Hi-Tech C
    // Using Bit Bang I2C on RA6 & RA7 and LCD on port B
    // This uses up all but 167 bytes of program memory
    // the div_t averaging routine uses 414 bytes
    // The wiring for the LCD using Hitachi HD44780 is at
    // http://www.winpicprog.co.uk/pic_tutorial_lcd_board.htm
     
     
    #include <pic.h>                // pic specific identifiers
    #include <stdlib.h>
    #include <stdio.h>
    #define _XTAL_FREQ  4000000        // Xtal speed
    __CONFIG(0x3D38);                // Config bits
     
    char  IDDV =0;
    #define  BW_RATE            44    //0x2C
    #define  POWER_CTL          45    //0x2D
    #define  DATA_FORMAT        49    //0x31
    #define  DATAX0             50    //0x32
    #define  DATAX1             51    //0x33
    #define  DATAY0             52    //0x34
    #define  DATAY1             53    //0x35
    #define  DATAZ0             54    //0x36
    #define  DATAZ1             55    //0x37
    #define  FIFO_CTL           56    //0x38                        1010011   0x53   Device
    #define CHIP_Write    0xA6        // adxl345 address for writing    10100110  0xA6   Write
    #define CHIP_Read    0xA7        // and reading                    10100111  0xA7   Read
    //#define DEVICE1 (0x53)
     
    #define LCD_PORT    PORTB            //
    #define LCD_TRIS    TRISB
    #define LCD_RS        RB4
    #define LCD_RW        RB6
    #define LCD_E        RB7
     
    #define I2C_PORT    PORTA            // I2C port configuration
    #define I2C_TRIS    TRISA
    #define SDAI        RA7
    #define SCLI        RA6
    #define SDA            TRISA7        // in C  we can control the input / output
    #define SCL            TRISA6        // by one simple command.
     
     
            // Required prototypes
     
    void LCD_init(void), LCD_cmd(unsigned char ch), LCD_busy(void);
    void LCD_printC(const char *str), LCD_printR(char *str);
    void LCD_goto(char line, char column), LCD_clr(void);
    void LCD_cur(unsigned char ch), pulse_E(void), LCD_hex(int value);
    void LCD_char(unsigned char ch), LCD_charD(unsigned char ch);
    void convert(int numb);
     
    unsigned char HEX_Table[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
                                0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
                                0x44, 0x45, 0x46};
    // variables
    unsigned char TenK, Thou, Hund, Tens, Ones;
     
     
    void I2C_Sendnack(void), I2C_ack(void), I2C_Stop(void), clock(void);
    void I2C_Start(void), I2C_Write(unsigned char ch);
    char I2C_nack(), E_Write(int addr, unsigned char ch);
    unsigned char I2C_Read(void);
    unsigned char E_Read(int addr);
     
     
    void ini_adxl345()
    {
    E_Write(FIFO_CTL,0x9f);    
    E_Write(DATA_FORMAT,0x09);
    E_Write(BW_RATE,0x0d);    
    E_Write(POWER_CTL,0x08);  // activate
    }
     
    unsigned char LCDbuffer[17];// a screen buffer big enough for 16 chars + terminator
    char ErrFlags;            // Read error. (I don't use it, but you might!)
       
    // The SDA and SCL pins are ALWAYS set at 0 we use tristated pins to
    // control the control.. while SDA and SCL are inputs the external pullup
    // resistors give a high conditon whilst when SDA or SCL are outputs
    // the control lines are pulled low.
     
     
    void main(void)                            // program entry
        {
        int index = 0;                        // text variable
        OPTION_REG = 0x88;                        // timer pre-scaler
        CMCON = 0x7;                        // Comparitors off
        LCD_TRIS = 0b00000000;                // LCD port as outputs
        I2C_TRIS = 0b11111111;                // I2C port as inputs
        __delay_ms(150);
        RA6 = 0;                // SDC clock
        RA7 = 0;                // SDA Data
        I2C_PORT = 0;
        LCD_init();                            // Initalise screen
        ini_adxl345();                        // Initalise Accelerometer
        __delay_ms(30);                        // Helps Initalise screen
    //    LCD_goto(1,0);
    //    LCD_printC("Writing..");
    /*
        LCD_goto(1,0);
          int id, pow, bw_rate;
          id= E_Read(IDDV);  // should be 229
         __delay_ms(10);
          pow=E_Read(0x2D);  //should be 8 to activate
         __delay_ms(10);
          bw_rate =E_Read(0x2C);  //BW_RATE 0x2C is 13
            sprintf(LCDbuffer,"id=%3d pow=%3d BW_RATE=%3d",id,pow,bw_rate);
            LCD_printR(LCDbuffer);        // use sprintf to format
    */

     
        signed long x,y,z;
        signed long xhi,xlo,yhi,ylo,zhi,zlo;
        signed long Xaccumulate, Yaccumulate, Zaccumulate;
        signed long Xaverage, Yaverage, Zaverage;
        int i;
        while(1)                            // endless Loop
            {
     
        Xaccumulate = Yaccumulate = Zaccumulate = 0;
     
        for (i=0; i<16; i++) {  // Read sequentially 16 times then get an average.
        ErrFlags = 0;                                    // Clear error
        I2C_Start();
        I2C_Write(CHIP_Write);
        if(!I2C_nack()) ErrFlags = 1;                        // Whoops!! problems
     
        I2C_Write((unsigned char) DATAX0 & 0xff);    // DATAX0 is the first of 6 bytes
        if(!I2C_nack()) ErrFlags = 1;                // to read sequentially
        I2C_Start();
        I2C_Write(CHIP_Read);                            //
        if(!I2C_nack()) ErrFlags = 1;
     
        xlo = I2C_Read();                                // read character
        I2C_ack();
        xhi = I2C_Read();                                // read character
        I2C_ack();
        ylo = I2C_Read();                                // read character
        I2C_ack();
        yhi = I2C_Read();                                // read character
        I2C_ack();
        zlo = I2C_Read();                                // read character
        I2C_ack();
        zhi = I2C_Read();                                // read character
        I2C_Sendnack();
        I2C_Stop();
     
        Xaccumulate += ((xhi<<8) | xlo); //Xaccumulate = Xaccumulate + (xhi*256 + xlo)
        Yaccumulate += ((yhi<<8) | ylo);
        Zaccumulate += ((zhi<<8) | zlo);
     
      }  // for loop
     
    //    x= (xhi<<8) | xlo;
    //    y= (yhi<<8) | ylo;
    //    z= (zhi<<8) | zlo;
     
    // Calculate average accelerometer readings over last 16 samples
     
    /* *** Other methods of dividing gave me results in the +/- thousands ***
    DIV   From Hi-Tech C manual
    Synopsis
    #include <stdlib.h>
    div_t div (int numer, int demon)
    Description
    The div() function computes the quotient and remainder of the numerator divided by the denominator.
    Example
    #include <stdlib.h>
    #include <stdio.h>
    void
    main (void)
    {
    div_t x;
    x = div(12345, 66);
    printf("quotient = %d, remainder = %d\n", x.quot, x.rem);
    }
    See Also
    udiv(), ldiv(), uldiv()
    Return Value
    Returns the quotient and remainder into the div_t structure.
    */

     
    div_t xavg ; // div_t is a structure explained above
    div_t yavg ;
    div_t zavg ;
     
    xavg = div(Xaccumulate, 16);
    yavg = div(Yaccumulate, 16);
    zavg = div(Zaccumulate, 16);
     
    LCD_goto(1,0);
            sprintf(LCDbuffer,"X=%5d",xavg.quot);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(1,9);
            sprintf(LCDbuffer,"Y=%5d",yavg.quot);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(2,4);  
    sprintf(LCDbuffer,"Z=%5d",zavg.quot);
            LCD_printR(LCDbuffer);        // use sprintf to format
    //__delay_ms(25);
    __delay_ms(250);  // Just so the numbers don't change too fast.
     
     
    /*
    // This reads byte registers one at a time.
       x=(E_Read(DATAX1)*256) | (E_Read(DATAX0));
       y=(E_Read(DATAY1)*256) | (E_Read(DATAY0));
       z=(E_Read(DATAZ1)*256) | (E_Read(DATAZ0));
     
    LCD_goto(1,0);
            sprintf(LCDbuffer,"x=%5d",x);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(1,12);
            sprintf(LCDbuffer,"y=%5d",y);
            LCD_printR(LCDbuffer);        // use sprintf to format
     
    LCD_goto(2,0);  
    sprintf(LCDbuffer,"z=%5d",z);
            LCD_printR(LCDbuffer);        // use sprintf to format
    */

     
     
            } //while
        } //main(void)
     
    // Write to eeprom this returns a 0 if it fails or a 1 if all gooes well
    // For byte eeproms and RTC devices.. comment out the Hi address byte
    // and the I2C_nack() that follows it in both these functions.
     
    // This is random writing. Write to a specified address
     
    char E_Write(int addr, unsigned char ch)
        {
        I2C_Start();                                    // Send a start condition
        I2C_Write(CHIP_Write);                            // chip write address
        if(!I2C_nack()) return 0;                        // wait for ack
    //    I2C_Write((unsigned char) (addr >> 8 & 0xff));    // Comment out if single byte addess
    //    if(!I2C_nack()) return 0;                        // wait for ack
        I2C_Write((unsigned char) addr & 0xff);            // low address
        if(!I2C_nack()) return 0;                        // wait for ack
        I2C_Write(ch);                                    // Write values to Eeprom
        if(!I2C_nack()) return 0;
        I2C_Stop();                                        // Send a stop.
        return 1;                                        // All went well
        }
     
     
    // The function takes an address and Returns a character
     
    // This is random reading. Read from a specified addess
    unsigned char E_Read(int addr)
        {
        unsigned char byte;
        unsigned char ch;
        ErrFlags = 0;                                    // Clear error
        I2C_Start();
        I2C_Write(CHIP_Write);
        if(!I2C_nack()) return  1;                        // Whoops!! problems
    //    I2C_Write((unsigned char)( addr >> 8 & 0xff));    // Comment out if single byte addess
    //    if(!I2C_nack()) return  1;
        I2C_Write((unsigned char) addr & 0xff);            //
        if(!I2C_nack()) return 1;
        I2C_Start();
        I2C_Write(CHIP_Read);                            //
        if(!I2C_nack()) return  1;
        ch = I2C_Read();                                // read character
        I2C_Sendnack();
        I2C_Stop();
        return ch;
        }
     
    void I2C_Start()        //  start combo
        {
        SDA = 1;
        SCL = 1;
        SDA = 0;            // bring SDA low while SCL is high
        SCL = 0;
        }
     
    void I2C_Stop()            // stop combo
        {
        SCL = 0;
        SDA = 0;
        SCL = 1;
        SDA = 1;            // bring SDA high while SCL is high
        }
     
    unsigned char I2C_Read()
        {
        char index;
        unsigned char byte = 0;                        // initialize in byte
        for(index = 0x80; index > 0 ;index>>=1)        // using index as a mask
            {                                        // cycles through bit 7 to bit 0
            if(SDAI) byte += index;                    // read in the SDA line
            clock();
            }
        return byte;                                // 8 bits in...
        }
     
    void I2C_Write(unsigned char ch)
        {
        char index;
     
        for(index = 0x80; index > 0 ;index>>=1)        // using index as mask
            {
            if(ch & index)                             // bit high or low
                SDA = 1;
            else
                SDA = 0;
            clock();
            }
        }
     
    void I2C_ack()                            // generate an ack
        {
        SDA = 0;
        clock();
        SDA = 1;
        }
     
    void I2C_Sendnack()                        // generate a not ack
        {
        SDA = 1;
        clock();
        }
     
    char I2C_nack()                            // recive a not ack
        {
        unsigned char timeout = 255;
        SDA = 1;
        SCL = 1;
        while(SDAI)                            // wait till SDA goes low
            {
            if(timeout-- == 0) return 0;    // whoops!! no ack recieved
            }
        SCL = 0;
        return 1;
        }
     
    void clock()                            // Might work without the nop
        {
        SCL=1;
        asm("nop");
        SCL=0;
        }
     
    void convert(int numb)                // Takes a interger number
        {                                // and converts to single
        TenK = numb / 10000;            // decimal numbers.
        Thou = (numb % 10000)/ 1000;    //
        Hund = (numb % 1000) / 100;
        Tens = (numb % 100) / 10;
        Ones = numb % 10;
        }
     
    // In C we can use Pointers, Pointers are advanced programming
    // and can tie you in knots. The simplest pointer to use is the
    // array pointer using "rom char" allows the pointer to
    // point to constant character in code section.
     
    void LCD_printC(const char * str)    // This passes the start a ROM character array
        {                                // by default the pointer points to data section
        while(*str != 0)                // while the character pointed to isn't 0
            LCD_char(*str++);            // print out the character, then increment
        }                                // the pointer down the array
     
    void LCD_printR(char * str)             // This passes the start of a RAM character array
        {                                // by default the pointer points to data section
        while(*str != 0)                // while the character pointed to isn't 0
            LCD_char(*str++);            // print out the character, then increment
        }                                // the pointer down the array
     
     
    void LCD_init()
        {
        LCD_cmd(0x20);                    // 4 bit
        LCD_cmd(0x28);                    // display shift
        LCD_cmd(0x6);                    // character mode
        LCD_cmd(0xc);                    // display on / off and cursor
        LCD_clr();                        // clear display
        }
     
    void LCD_hex(int value)
        {
        char data;
        data = value >> 4 & 0xf;
        data = HEX_Table[data];                 // send upper nibble
        LCD_char(data);
        data = value & 0xf;                        // send lower nibble
        data = HEX_Table[data];
        LCD_char(data);
        }
     
    void LCD_goto(char line, char column)        // combines line and lineW
        {
        unsigned char data = 0x80;                // default to 1
        if(line == 2)data = 0xc0;                // change to 2
        data += column;                            // add in  column
        LCD_cmd(data);
        }
     
    void LCD_clr()
        {
        LCD_cmd(1);                                // Clr screen
        }
     
    void LCD_cur(char on)
        {
        unsigned char cur = 0xc;                // cursor off
        if(on) cur = 0xd;                        // cursor on
        LCD_cmd(cur);
        }
     
    void LCD_busy()
        {
        unsigned char BUSY = 0;
        while(1)
            {
            LCD_TRIS = 0x0f;                    // port to read mode
            LCD_RS = 0x0;
            LCD_RW = 0x1;                        // set to read
            LCD_E = 0x1;
            BUSY = LCD_PORT & 0xf;                // high byte comes first
            __delay_us(5);                        // so busy flag is on bit 3
            LCD_E = 0x0;
            LCD_E = 0x1;
            __delay_us(5);                        // dummy read
            LCD_E = 0x0;
            LCD_RW = 0x0;                        // set to write
            LCD_TRIS = 0x00;                    // port to write mode
            if(!(BUSY & 0x8 )) return;            // AND with bit 3
            }
        }
     
    void LCD_cmd(unsigned char ch)
        {
        LCD_PORT = ch >> 4 & 0xf;
        LCD_RS = 0;
        pulse_E();
        LCD_PORT = ch & 0xf;
        LCD_RS = 0;
        pulse_E();
        __delay_ms(5);
        }
     
    void LCD_charD(unsigned char ch)
        {
        ch+=0x30;
        LCD_char(ch);
        }
     
    void LCD_char(unsigned char ch)
        {
        LCD_PORT = ch >> 4 & 0xf;
        LCD_RS = 1;
        pulse_E();
        LCD_PORT = ch & 0xf;
        LCD_RS = 1;
        pulse_E();
        __delay_ms(5);;
        }
     
    void pulse_E()
        {
        LCD_E = 1;
        __delay_us(1);
        LCD_E = 0;
        }
     

    Attached Files:

    Last edited: Mar 18, 2014
  3. ClydeCrashKop

    ClydeCrashKop Active Member

    Joined:
    Apr 28, 2005
    Messages:
    971
    Likes:
    152
    Location:
    Florida
    I just discovered something while setting up another computer for programming PICs.
    HI-TECH C version 9.83 uses OPTION_REG and compacts programs better.
    HI-TECH C version 9.65 uses OPTION and at least on this program uses 110 bytes more memory than the 16F628a has.
    That explains why I have always had to change OPTION to OPTION_REG in Ian's programs.
    Use HI-TECH C version 9.83 or better for this program.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Danielf

    Danielf New Member

    Joined:
    Jan 3, 2017
    Messages:
    5
    Likes:
    0

    Hi, thx for the information..
    I have 2 questions
    1.why u use portb for the i2c, isn't is supposed to be portc? As it written in the data sheet
    2. Did u grounded sd0 pin in the adxl345?
     
    Last edited: Jan 3, 2017
  6. ClydeCrashKop

    ClydeCrashKop Active Member

    Joined:
    Apr 28, 2005
    Messages:
    971
    Likes:
    152
    Location:
    Florida
    In the program:
    ADXL345 0x53 is the alternate Device address
    #define CHIP_Write 0xA6
    #define CHIP_Read 0xA7
    Yes SD0 is grounded with a 4.7 K ohm resistor on this board. 3 Axis Accelerometer, Raspberry Pi, Arduino Compatible Sensor http://www.mpja.com/3-Axis-Accelerometer-Raspberry-Pi-Arduino-Compatible-Sensor/productinfo/31583+MP

    This pinout shows the I2C SCL & SDA on port B
    PIC 18F4550 pinout.jpg
     
  7. Danielf

    Danielf New Member

    Joined:
    Jan 3, 2017
    Messages:
    5
    Likes:
    0
    Hi,
    When I try to initiate adxl345
    The sspbuff loaded with 0xA6
    And the it stuck in endless loop at
    While(BF)
    In my pic 18f452 it's written while(SSPBUF)

    Any idea why?
     
  8. ClydeCrashKop

    ClydeCrashKop Active Member

    Joined:
    Apr 28, 2005
    Messages:
    971
    Likes:
    152
    Location:
    Florida
    I haven’t used an 18F452. I see that the pinout is different and you are right that it uses port C for I2C. Use RC3 on pin 18 for SCL & RC4 on pin 23 for SDA and change them in the program. The configuration is probably different & you will probably have to set up port C instead or port B for I2C.

    When first getting it to work, uncomment this section. id should be 53 Hex or 83 Decimal. If it is, you know that you are communicating.

    /* LCD_goto(1,0);
    int id, pow, bw_rate;
    id= E_Read(IDDV); // should be 53 Hex or 83 Decimal for ADXL345
    __delay_ms(10);
    pow=E_Read(0x2D); //should be 8 to activate
    __delay_ms(10);
    bw_rate =E_Read(0x2C); //BW_RATE 0x2C is 13
    sprintf(LCDbuffer,"id=%3d pow=%3d BW_RATE=%3d",id,pow,bw_rate);
    LCD_printR(LCDbuffer); // use sprintf to format
    */
     
    Last edited: Jan 4, 2017
  9. Danielf

    Danielf New Member

    Joined:
    Jan 3, 2017
    Messages:
    5
    Likes:
    0
    can u also send me the pin sketch ?

    thx a lot !
     
    Last edited: Jan 4, 2017
  10. Danielf

    Danielf New Member

    Joined:
    Jan 3, 2017
    Messages:
    5
    Likes:
    0
    now I run ur comment , id,pow,bwrate=FF
    any idea?

    changed something
    now its ALL 0xE5
     
    Last edited: Jan 4, 2017
  11. Danielf

    Danielf New Member

    Joined:
    Jan 3, 2017
    Messages:
    5
    Likes:
    0
  12. ClydeCrashKop

    ClydeCrashKop Active Member

    Joined:
    Apr 28, 2005
    Messages:
    971
    Likes:
    152
    Location:
    Florida
    The pinout is in the Datasheet, along with info on using I2C on that chip.
    PIC18FXX2 Data Sheet - Microchip
    http://ww1.microchip.com/downloads/en/DeviceDoc/39564c.pdf

    It may not be easy to migrate a program for an 18F4550 to an 18F452. I had to do it entirely different for a 16F628A. (Bitbang) If you can't find the answer in the datasheet, you should start a new thread in the Microcontrollers section where everyone will see it.
     

Share This Page