• AVR Freaks

PLACEHOLDER FOR Code Module Library

Page: 123 > Showing page 1 of 3
Author
DarioG
Allmächtig.
  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline
2007/11/16 08:19:08 (permalink)
5 (1)

PLACEHOLDER FOR Code Module Library

Smile

GENOVA :D :D ! GODO
#1

43 Replies Related Threads

    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Code for sending int/floats as raw binary data (chars) to USART 2007/11/16 08:19:57 (permalink)
    0

    char i,*p;
    float f; // same goes for int or alike

    p=(char *)&f;
    for(i=0; i<sizeof(float); i++) {
    putcUSART(*p++);
    }

    Keep in mind that this value, i.e. the sequence of bytes sent, is "Machine Dependant" (i.e. little endian/big endian sensitive) so the other end of the communication must agree on that.

    GENOVA :D :D ! GODO
    #2
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    USB WAV Player (with schematic and code) 2007/11/16 15:34:41 (permalink)

    GENOVA :D :D ! GODO
    #3
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    FAT16 (Memory Disk Drive File System Library) 2007/11/16 15:36:40 (permalink)
    0
    Hi,
    Microchip released the first version of their Memory Disk Drive File System Library. It's compatible with FAT16.
    You can find the documentation and the source files on Microchip website, application note  AN1045.
    I tested the source and sample files with my older hardware design (compact flash card, with bit-transaction), with success.
    This is exactly what I've been looking and waiting for.....


    Thx to Microchip

    della
    post edited by DarioG - 2007/11/16 15:40:32

    GENOVA :D :D ! GODO
    #4
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    sprintf() using float, for C18 2007/11/16 15:37:28 (permalink)
    0
      
    char buf[8];
    sprintf(buf,"%d.%02u", (int)f , ((int) (((f)-(int)f) * 100)) );

    You can choose how many figures you wish, changing the "02u" and "*100" accordingly, and the "buf" size.


    ADDED by Ren:
    All of the other limitations aside, I tried this method and noticed that it fails to handle negative numbers.  Adding fabs() to the calculation for the decimal part solves that issue, and only added 3 bytes to the program.

      
    sprintf(buf,"%d.%02u", (int) d, (int) fabs(((d - (int) d ) * 100)));

     
     
    ADDED by 1and0 for handling of the -1..0 range (http://www.microchip.com/...7&mpage=1#699128):

    void ftoa(float value, char *string) 
    {
        if (value < 0) {
            *string++ = '-';
            value = -value;
        }
        sprintf(string, (const far rom char *) "%lu.%03u",
                        (long) value,
                        (int) ((value - (long) value) * 1000. + 0.5));
    }

     
    also this one:
    http://support2.microchip....aspx?ID=SQ6UJ9A003PQX
    post edited by DarioG - 2013/01/12 02:42:32

    GENOVA :D :D ! GODO
    #5
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    A Class to do RS232 (Serial Port) Communications in C++ in Windows 2007/11/16 15:38:46 (permalink)
    0
    Attached code (rename it to ".ZIP")

    PS: Usage example:

    //begin
        myComm=new CSerCommObject(comPortString); // such as "COM1:9600,N,8,1
        myComm->Open();


    //use
            if(i=myComm->Send((BYTE *)"test",4)) {
              // do something
              }

            char myBuf[16];
            if(i=myComm->Receive((BYTE*)myBuf,8,2000)) {      // 2secs time allowed forreceive
              // do something
              }




    //end
        myComm->Close();
        delete myComm;


    Attachment (1)

    GENOVA :D :D ! GODO
    #6
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Software I2C routines for PIC18F 2007/11/16 15:42:40 (permalink)
    0

    /**************************************************************
           Start Bit Subroutine
           this routine generates a start bit
           (Low going data line while clock is high)         
    **************************************************************/
    void I2CSTART(void) {

    //    SWStartI2C();
        m_I2CClkBit=0;                    // make sure clock is low
        m_I2CDataBit=1;                    // make sure data is high
        I2CDataTris=0;                    // set data and clock lines for output
        I2CDelay();
        setClockHigh();                    // CLK=1
        I2CDelay();
        m_I2CDataBit=0;                    // data line goes low during high clock for start bit
        I2CDelay();
        m_I2CClkBit=0;                    // start clock train
        I2CDelay();
        }

    /************************************************************
           Stop Bit Subroutine
           This routine generates a stop bit
           (High going data line while clock is high)
    ************************************************************/
    void I2CSTOP(void) {

    //    SWStopI2C();
        m_I2CDataBit=0;                        // make sure data line is low
        m_I2CClkBit=0;                        // make sure clock is low
        I2CDataTris=0;                        // set data/clock lines as outputs
        m_I2CClkBit=1;                        // set clock high
        I2CDelay();
        m_I2CDataBit=1;                        // data goes high while clock high for stop bit
        I2CDelay();
        m_I2CClkBit=0;                        // set clock low again
        I2CDelay();
        I2CDataTris=1;                        // set data line as input
    //    m_I2CClkBit=1;                        // set clock idle

        setClockHigh();                        // CLK=1
        // questa e' un'altra attesa, per i dispos. (tipo PICBELL, PICWDI2C) che il WAIT lo fanno DOPO lo STOP!

    //    m_I2CClkBit=0;
        I2CDelay();

        }

    /*************************************************************
           BITOUT routine takes the bit of data in C and
           transmits it to the serial EE device
    *************************************************************/
    void I2CBITOUT(byte n) {

        I2CDataTris=0;                    // set data,clock as outputs
        if(n)                                        // check for state of data bit to xmit
            m_I2CDataBit=1;                    // output a low bit    
        else
            m_I2CDataBit=0;                    // high? set data line high
        Nop();                                        // dev'esserci un min. ritardo tra il cambio in DATA e la salita di CLK
        Nop();
        m_I2CClkBit=1;                            // set clock line high
        I2CDelay();
        m_I2CClkBit=0;                            // return clock line low
        I2CDelay();
    //    retlw   0
        }
                                                                
    /**************************************************************
           BITIN routine reads one bit of data from the
           serial EE device and stores it in C
    **************************************************************/
    byte I2CBITIN(void) {
        /*overlay*/ byte i;

        I2CDataTris=1;                        // make sdata an input line
        I2CDelay();
        m_I2CClkBit=1;                            // set clock line high
        I2CDelay();                    // just sit here a sec
        i = m_I2CDataBit ? 1 : 0;          // read the data bit
        m_I2CClkBit=0;                        // set clock line low
        return i;
        }

    void setClockHigh(void) {
    // Gestisce WAIT_STATE dello slave (CLK basso)... che puo' succedere SEMPRE!
       
        m_I2CClkBit=1;

        I2CClkTris=1;                        // CLK e' input

        I2CDelay();

        do {
            ClrWdt();
            } while(!m_I2CClkBit);

        I2CClkTris=0;                // CLK e' output

        }

    /****************************************************************
           Transmit Data Subroutine
           This routine takes the byte of data stored in the
           'temp' register and transmits it to the serial EE device.
           It will then send 1 more clock to the serial EE for the
           acknowledge bit.  If the ack bit from the part was low
           then the transmission was sucessful.  If it is high, then
           the device did not send a proper ack bit and the ack
           fail LED will be turned on.
    ****************************************************************/
    #define I2CTXSlaveAddrW() I2CTXByte(0xA0)
    #define I2CTXSlaveAddrR() I2CTXByte(0xA1)


    byte I2CTXByte(byte n) {
        /*overlay*/    static byte I2CData,I2CCnt;

        I2CData=n;

        for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8
            I2CBITOUT(I2CData & 0x80);              // send the bit to serial EE
            I2CData <<= 1;                                            // rotate I2CData/txbuf left, bit in CARRY
            }                                                                        // 8 bits done?
                                                    // no - go again

        // read ack bit
        I2CDataTris=1;
        I2CDelay();
        setClockHigh();                    // aspetto ACK
    //        Per WAIT_STATE dello slave (CLK basso)... NON e' chiaro se PRIMA o DOPO ACK... (PicBell lo fa dopo!)
    //            questo lo controlla SEMPRE!
        I2CDelay();

        // dopo Delay, qua arrivo con W=0 e Z=1
        I2CCnt=m_I2CDataBit;                        // Z=1 se ACK=OK (basso), altrimenti Z=0 e W!=0

        m_I2CClkBit=0;

        if(I2CCnt) {                        // check ack bit
            m_MemCardLedBit=1;                // spegne! set acknowledge fail LED if the device did not pull data low
            return 0;                                // 0=ERR
            }
        return 1;                                // 1=OK
        }
                      
                       
    /****************************************************************
           Receive data routine
           This routine reads one byte of data from the part
           into the 'I2CData' register.
    ****************************************************************/
    byte I2CRXByte(void) {
        static /*overlay*/    byte I2CData,I2CCnt;

    //    SWReadI2C();

    //    I2CData=0;                            // clear input buffer  non serve!
             
        for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8
            I2CData <<= 1;                // rotate I2CData 1 bit left
            I2CData |= I2CBITIN();                            // read a bit
    //        STATUSbits.C = 1;            // la presenza di ASM disabilita l'ottimizzazione, quindi PEGGIORA!
    //        Rlcf(input);            // Rotate the carry into the data byte
            }                                           // 8 bits done?
                                                        // no, do another

        return I2CData;
        }

    /****************************************************************
           Receive data routine
           This routine reads one byte of data from the part
           into the 'I2CData' register.  It then sends a high
           ACK bit to indicate that no more data is to be read
    ****************************************************************/
    byte I2CRX1Byte(void) {
        static /*overlay*/ byte I2CData,I2CCnt;

    //    I2CData=0;                            // clear input buffer  non serve!
             
        for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8
    //        STATUSbits.C = 1;            // la presenza di ASM disabilita l'ottimizzazione, quindi PEGGIORA!
    //        Rlcf(input);            // Rotate the carry into the data byte
            I2CData <<= 1;               // rotate I2CData 1 bit left
            I2CData |= I2CBITIN();                        // read a bit
            }                                      // 8 bits done?
                                                        // no, do another
        // set ack bit = 1
        I2CBITOUT(1);                        // to finish transmission

        return I2CData;
        }

    /**************************************************************
           READ (read routine)
           This routine reads 8 consecutive addresses of the
           serial EE device starting at address 00 in the
           random access mode (non-sequential read). Reading
           the device using the random access mode
           requires that the address pointer be set for every
           byte before the read takes place. The address pointer
           is set by sending a 'write mode' control byte with the
           address of the location to read. 
    ***************************************************************/
    byte I2CReadRandom(byte n) {
        static /*overlay*/ byte I2CData;

    //    bcf     port_a,ackf        ; clear the ack fail LED if on

      I2CSTART();                        // generate start bit
                                                    //
                                                    // now send the write control byte and
                                                    // address to set the pointer
                                                    //
        I2CTXSlaveAddrW();        // get slave address and write mode
    //    movfw   I2CAddr                ; get word address
        I2CTXByte(n);        // and send it
                                                 
                                                 // now read one byte from the part
                                                 
        I2CSTART();                            // generate start bit
        I2CTXSlaveAddrR();            // get slave address and read mode
        I2CData=I2CRX1Byte();        // read 1 byte from serial EE
        I2CSTOP();                            // send stop bit to end transmission

        return I2CData;
        }

    byte I2CReadRandom16(word n) {
        byte I2CData;

    //    bcf     port_a,ackf        ; clear the ack fail LED if on

      I2CSTART();                        // generate start bit
                                                    //
                                                    // now send the write control byte and
                                                    // address to set the pointer
                                                    //
        I2CTXSlaveAddrW();        // get slave address and write mode
                                //    move word address (HIGH)
        I2CTXByte(*(((byte *)&n)+1));                        // and send it       
                                // move word address (LOW)
        I2CTXByte(*((byte *)(&n)));                        // and send it       
                                                 
                                                 // now read one byte from the part
                                                 
        I2CSTART();                            // generate start bit
        I2CTXSlaveAddrR();            // get slave address and read mode
        I2CData=I2CRX1Byte();        // read 1 byte from serial EE
        I2CSTOP();                            // send stop bit to end transmission

        return I2CData;
        }

    /**************************************************************
           READ (sequential read routine)

           This routine reads 8 consecutive addresses of the
           serial EE device starting at address 00 in the
           sequential read mode. Reading in this mode is more
           efficient than the random read mode as the control byte
           and address have to be sent only once at the beginning
           of the sequence.  As many consecutive addresses as
           needed can then be read from the part until a stop bit is
           sent.  In the read mode, the PIC 16C54 must send the acknowledge
           bit after every 8 data bits from the device.  When the
           last byte needed has been read, then the controller will
           send a high acknowledge bit and then a stop bit to halt
           transmission from the device.
    ***************************************************************/
    byte I2CRead8Seq(byte n,byte I2CCntB) {            // entra W=indirizzo part. lettura, FSR punta al buffer
        static /*overlay*/    byte *p;

        //    bcf     port_a,ackf        ; clear the ack fail LED if on
        p=I2CBuffer;                        // bank1, ISP=0!

        I2CSTART();                        // generate start bit
        I2CTXSlaveAddrW();        // send slave address and write mode
                                                        // get word address
        I2CTXByte(n);            // and send it       
        I2CSTART();                        // generate start bit
        I2CTXSlaveAddrR();        // send slave address and read mode

    I2CRead8Seq2:
        *p++=I2CRXByte();                // read 1 byte from device
        if(!--I2CCntB) {                // are all 8 bytes read?
                                                    // no, send low ack and do another
        // yes, send high ack bit
            I2CBITOUT(1);                    // to stop tranxmission
            I2CSTOP();                        // and send a stop bit
            return 8;
            }

        //  send low ack bit
        I2CBITOUT(0);                // to continue transmission
        goto I2CRead8Seq2;        //and read another byte
        }

    /**************************************************************
           READ16 (sequential read routine)

           This routine reads 8 consecutive addresses of the
           serial EE device starting at given 16bit address in the
           sequential read mode. Reading in this mode is more
           efficient than the random read mode as the control byte
           and address have to be sent only once at the beginning
           of the sequence.  As many consecutive addresses as
           needed can then be read from the part until a stop bit is
           sent.  In the read mode, the PIC 16C54 must send the acknowledge
           bit after every 8 data bits from the device.  When the
           last byte needed has been read, then the controller will
           send a high acknowledge bit and then a stop bit to halt
           transmission from the device.
    ***************************************************************/
    byte I2CRead16Seq(word n,byte I2CCntB) {            // entra indirizzo part. lettura, FSR punta al buffer
        static /*overlay*/    byte *p;

    //    bcf     port_a,ackf        ; clear the ack fail LED if on
       
        I2CSTART();                        // generate start bit
        I2CTXSlaveAddrW();        // send slave address and write mode

                                //    move word address (HIGH)
        I2CTXByte(*(((byte *)&n)+1));                        // and send it       
                                // move word address (LOW)
        I2CTXByte(*((byte *)(&n)));                        // and send it       

        I2CSTART();                            // generate start bit
        I2CTXSlaveAddrR();            // send slave address and read mode

        p=I2CBuffer;
       
    I2CRead16Seq2:
        *p++=I2CRXByte();                // read 1 byte from device
        if(!--I2CCntB) {                    // are all n bytes read?
                                                        // no, send low ack and do another
            // yes, send high ack bit
            I2CBITOUT(1);                    // to stop tranxmission
            I2CSTOP();                        // and send a stop bit
            return 16;
            }

      // send low ack bit
        I2CBITOUT(0);              // to continue transmission
        goto I2CRead16Seq2;        // and read another byte
        }

    byte I2CReadRTC(byte I2CCntB) {            // entra num. byte da leggere, buffer
        static /*overlay*/ byte *p;

        //    bcf     port_a,ackf        ; clear the ack fail LED if on
        p=I2CBuffer;                        // bank1, ISP=0!

        I2CSTART();                        // generate start bit
        I2CTXByte(0xD0);            // DS1337C
                                                    // send slave address and read mode
        I2CTXByte(0);                    // send register address
        I2CSTART();                            // generate start bit
        I2CTXByte(0xD1);            // DS1337C

    I2CRead8Seq2:
        *p++=I2CRXByte();                // read 1 byte from device
        if(!--I2CCntB) {                // are all 8 bytes read?
                                                    // no, send low ack and do another
        // yes, send high ack bit
            I2CBITOUT(1);                    // to stop tranxmission
            I2CSTOP();                        // and send a stop bit
            return 1;
            }

        //  send low ack bit
        I2CBITOUT(0);                // to continue transmission
        goto I2CRead8Seq2;        //and read another byte
        }

    /****************************************************************
           Byte Write Routine
           This routine writes the data in "temp" to
           8 consecutive bytes in the serial EE device starting
           at address 00.  This routine waits 10mS after every
           byte to give the device time to do the write.  This
           program repeats forever.
    *****************************************************************/

    void I2CWriteByte(byte n, byte b) {
        static /*overlay*/    byte I2CAddr,I2CCnt;

    //    SWWriteI2C();

    //    clrf    port_a                ; clear all LEDs
        I2CAddr=n;                        // set starting address to W
    //    temp=0x55;                        // set data to write as 55h

        // set number of bytes
        for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8

          I2CSTART();                        // generate start bit
            I2CTXSlaveAddrW();        // send slave address and write mode
            // move word address
            I2CTXByte(I2CAddr);        // and send it       
            I2CTXByte(b);                    // move data byte and transmit it
            I2CSTOP();                        // generate stop bit
       
        //    movlw   10
        //    movwf   loops                    ; set delay time to give
        //    call    WAIT                    ; 10 ms wait after every byte
            I2CWritePagePoll();
       
            I2CAddr++;                        // add 1 to address counter
            }                                            // all 8 bytes written?
                                                        // no, do another byte
        }

    /****************************************************************
           Page Write Routine

           This routine uses page mode to write the data in "temp" to
           8 consecutive bytes in the serial EE device starting
           at address 00. This routine waits 10mS after every
           page to give the device time to do the write.  This
           routine executes forever
    *****************************************************************/

    void I2CWritePage(byte n,byte I2CCntB) {                    // entra W=indirizzo part. lettura, (FSR usato per buffer)
        static /*overlay*/ byte *p;

    //    clrf    port_a                    ; clear all LEDs
        p=I2CBuffer;

        I2CSTART();                            // generate start bit
        I2CTXSlaveAddrW();            // send slave address and write mode

        // move word address
        I2CTXByte(n);                        // and send it       

        do {
            I2CTXByte(*p++);                        // and transmit it
            } while(--I2CCntB);                        // all n bytes written?
                                                                    // no, do another
        I2CSTOP();                            // yes,generate stop bit

    //    movlw   10
    //    movwf   loops                        ; set delay time to give
    //    call    WAIT                        ; 10 ms wait after every byte
        Delay_mS(20);                            // 50mS
        }

    void I2CWriteRTC(byte n,byte I2CCntB) {                    // entra W=indirizzo part. lettura, (FSR usato per buffer)
        static /*overlay*/ byte *p;

    //    clrf    port_a                    ; clear all LEDs
        p=I2CBuffer;

        I2CSTART();                            // generate start bit
                                                    // send slave address and write mode
        I2CTXByte(0xD0);            // DS1337C

                                                        // move register address
        I2CTXByte(n);                        // and send it       

        do {
            I2CTXByte(*p++);                        // and transmit it
            } while(--I2CCntB);                        // all n bytes written?
                                                                    // no, do another
        I2CSTOP();                            // yes,generate stop bit

    //    movlw   10
    //    movwf   loops                        ; set delay time to give
    //    call    WAIT                        ; 10 ms wait after every byte
        }

    /****************************************************************
           Page Write 16 Routine (8 bytes, address a 16 bit)

           This routine uses page mode to write the data in "temp" to
           8 consecutive bytes in the serial EE device starting
           at given address . This routine waits 10mS after every
           page to give the device time to do the write.  This
           routine executes forever
    *****************************************************************/
    #define I2CWritePage16Default() I2CWritePage16((word)&I2CAddr)


    byte I2CWritePage16(word n,byte I2CCntB) {        // entra W=puntat. all'indirizzo part. lettura, (FSR usato per buffer)
        static /*overlay*/    byte *p;

    // clrf    port_a                    ; clear all LEDs

        I2CSTART();                            // generate start bit
        I2CTXSlaveAddrW();            // send slave address and write mode

                                //    move word address (HIGH)
        I2CTXByte(*(((byte *)&n)+1));                        // and send it       
                                // move word address (LOW)
        I2CTXByte(*((byte *)(&n)));                        // and send it       

        p=I2CBuffer;

        do {
            I2CTXByte(*p++);                // and transmit it
            } while(--I2CCntB);                    // move data byte
                                                            // all n bytes written?
                                                            // no, do another
        I2CSTOP();                            // yes,generate stop bit

    //    movlw   10
    //    movwf   loops                        ; set delay time to give
    //    call    WAIT                        ; 10 ms wait after every byte
        Delay_mS(20);                            // 20mS
        return 16;
        }


    byte I2CWritePagePoll(void) {
        byte I2Cpollcnt,i;

        I2Cpollcnt=100;                        // set max number of times to poll as 100
        do {
            I2CSTART();                                // generate start bit
            i=I2CTXSlaveAddrW();                // send slave address and write mode
            if(i)                                        // was the ack bit low?
                goto exitpoll;                // yes, do another byte
            } while(--I2Cpollcnt);         // is poll counter down to zero?
                                                                 // no, poll again.  Otherwise the part is
    //    bsf     port_a,timeout    ; not responding in time so set timeout LED and continue on

    exitpoll:
            ;
        }


    void I2CDelay(void) {            // circa 2,5uSec (400KHz operation)
        /*overlay*/ static byte uSec;            // 1.25 ca.

        uSec=1;
        do {
            ClrWdt();                            // Clear the WDT
            Delay1TCY();            // TARARE!! @48MHz??
            Delay1TCY();
            Delay1TCY();
    //        Delay1TCY();
            } while(--uSec);
        }



    (unfortunately this can't be retrieved from cache...
    will try reposting it.)
    post edited by DarioG - 2007/12/04 01:59:10

    GENOVA :D :D ! GODO
    #7
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Working CONFIG settings for 18F2550/4550 2007/11/17 06:56:55 (permalink)
    0

    #pragma config WDT = OFF, WDTPS = 1024, MCLRE=ON, STVREN=ON, LVP=OFF
    // either watchdog disabled...

    //#pragma config WDT = ON, WDTPS = 1024, MCLRE=ON, STVREN=ON, LVP=OFF
    // ..or watchdog enabled


    #pragma config PLLDIV=2, CPUDIV=OSC1_PLL2, USBDIV=2, FOSC=HSPLL_HS, IESO=OFF, PWRT=OFF, BOR=ON, BORV=2
    // 8MHz Crystal, 48MHz Core, 48MHz SIE engine (USB2, full speed)

    #ifndef __EXTENDED18__
    #pragma config VREGEN=ON, LPT1OSC=OFF, PBADEN=OFF, CCP2MX=ON, XINST=OFF, DEBUG=OFF
    // for Extended Mode...

    #else
    #pragma config VREGEN=ON, LPT1OSC=OFF, PBADEN=OFF, CCP2MX=ON, XINST=ON, DEBUG=OFF
    // ...or normal Mode

    #endif


    ADD: also take a look at
    http://users.edpnet.be/rosseel01/DRO/PIC/18F2455_2550_4455_4550_Usb_Clock.htm
    post edited by DarioG - 2008/11/25 14:16:22

    GENOVA :D :D ! GODO
    #8
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    TEMPLATE for interrupts on 18F parts with C18 2007/11/21 02:58:11 (permalink)
    0

    /** I N T E R R U P T  V E C T O R S *****************************************/

    #pragma code high_vector=0x08
    #define SILICON_REV_A3

    void interrupt_at_high_vector(void) {
      _asm
    #ifdef SILICON_REV_A3
        CALL Foo, 1               // store current value of WREG,BSR, STATUS for a second time
        RETFIE 1                   // FAST
    Foo:
        POP     // clears return address of Foo call
        goto high_isr

    #else
        goto high_isr
    #endif
        _endasm
        }
    #pragma code

    #pragma code low_vector=0x18
    void interrupt_at_low_vector(void) {
      _asm goto low_isr _endasm
        }
    #pragma code

    /** D E C L A R A T I O N S **************************************************/
    /******************************************************************************
     * Function:        void high_isr(void)
     * PreCondition:    None
     * Input:
     * Output:
     * Side Effects:
     * Overview:
     *****************************************************************************/
    #pragma interrupt high_isr     // nosave=section("MATH_DATA"),section(".tmpdata")     // OPTIONAL
    void high_isr(void) {
        if(INTCONbits.TMR0IF) {               // Timer 0..  EXAMPLE
           INTCONbits.TMR0IF=0;                   // clear bitIRQ
          }

        }

    /******************************************************************************
     * Function:        void low_isr(void)
     * PreCondition:    None
     * Input:
     * Output:
     * Side Effects:
     * Overview:
     *****************************************************************************/
    #pragma interruptlow low_isr         //nosave=section("MATH_DATA"),section(".tmpdata")    //OPTIONAL
    void low_isr(void) {


        }
    #pragma code

    GENOVA :D :D ! GODO
    #9
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Several ways to calculate parity 2007/11/24 13:09:06 (permalink)
    0
     
    // calcola la parita': entra W, esce 0 se E e 1 se O
    BOOL GetParita(byte n) {
        static byte p;

    #ifdef DARIO
        p=n >> 1;            // Microchip AN774
        p ^= n;
        n= p >> 2;
        p ^= n;
        n= p >> 4;
        p ^= n;
        return (p & 1);
    #endif

    #ifdef OLDPARITA
        if(n & 0x1)
            p++;
        if(n & 0x2)
            p++;
        if(n & 0x4)
            p++;
        if(n & 0x8)
            p++;
        if(n & 0x10)
            p++;
        if(n & 0x20)
            p++;
        if(n & 0x40)
            p++;
        if(n & 0x80)
            p++;
    #endif

    //From: John Payson
    //comments from Andrew Warren of Fast Forward Engineering

    //8-bit parity
    //This routine will leave the parity of X in X.0
    // while blenderizing most of the rest of X
        p=n;

        _asm
            movlb   p
        swapf   p, 0, 1    //x=     abcdefgh  w =    efghabcd
        xorwf   p, 1, 1    //x=     abcdefgh  w =    efghabcd
            //    xor efghabcd
        rrncf   p, 0, 1     //x=     abcdefgh  w =    -abcdefg
            //    xor efghabcd      xor -efghabc
        xorwf   p, 1, 1     //x=     abcdefgh  w =    -abcdefg
            //    xor efghabcd      xor -efghabc
            //    xor -abcdefg
            //    xor -efghabc

        // at this point, the parity for half the bits
        // (a, b, e, and f) is in bit 2 of X, and the
        // parity for the other half (bits c, d, g, and h)
        // is in bit 0 of X.

        btfsc   p, 2, 1     // if the parity of (a,b,e,f) is 0,
                     // then the parity of (a,b,c,d,e,f,g,h)
                     // is equal to the parity of (c,d,g,h)...
                     // which is already in bit 0, so skip ahead.

        incf    p, 1, 1     // otherwise, the parity of (a,b,e,f) is 1,
            // so the parity of (a,b,c,d,e,f,g,h) is
            // NOT equal to the parity of (c,d,g,h).
            // invert bit 0.

        // at this point, bit 0 contains the parity of
        // (a,b,c,d,e,f,g,h).

        _endasm


    #ifdef RIC
    CheckParity:              
        swapf    X, w    ; John's idea: reducing byte to nibble
        xorwf    X, w
        addlw    41H    ; bit 1 becomes B0^B1 and bit 7 becomes B6^B7
        iorlw    7CH    ; for carry propagation from bit 1 to bit 7
        addlw    2    ; Done! the parity bit is bit 7 of W
        andlw    80H    ; set NZ if odd parity, and leave 00 or 80 in W
        return
    #endif

        #define PARITY(b)   ((((((b)^(((b)<<4)|((b)>>4))) + 0x41) | 0x7C ) +2 ) & 0x80)


      return p & 1;
        }


     
    See also:http://graphics.stanford....hacks.html#ParityNaive
     
    post edited by DarioG - 2013/05/20 03:16:35

    GENOVA :D :D ! GODO
    #10
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Write/Read to/from EEprom in C18 2007/12/04 01:56:05 (permalink)
    0

    // -------------------------------------------------------------------------------------
    void EEscrivi_(SHORTPTR addr,byte n) {

        EEADR = (byte)addr;
        EEDATA=n;

        EECON1bits.EEPGD=0;        // Point to Data Memory
        EECON1bits.CFGS=0;        // Access EEPROM
        EECON1bits.WREN=1;

    //    INTCONbits.GIE = 0;            // disattiva interrupt globali... e USB?
        EECON2=0x55;         // Write 55h
        EECON2=0xAA;         // Write AAh
        EECON1bits.WR=1;                                    // abilita write.
        do {
            ClrWdt();
            } while(EECON1bits.WR);                            // occupato ?

    //    INTCONbits.GIE = 1;            // attiva interrupt globali

        EECON1bits.WREN=0;                                // disabilita write.
      }

    byte EEleggi(SHORTPTR addr) {

        EEADR=(byte)addr;            // Address to read
        EECON1bits.EEPGD=0;        // Point to Data Memory
        EECON1bits.CFGS=0;        // Access EEPROM
        EECON1bits.RD=1;        // EE Read
        return EEDATA;                // W = EEDATA
        }


    SHORTPTR is actually an unsigned char, in this implementation. Typedef'd for future extensions.


    GENOVA :D :D ! GODO
    #11
    corvette321
    Super Member
    • Total Posts : 727
    • Reward points : 0
    • Joined: 2006/10/31 19:17:07
    • Location: Florida
    • Status: offline
    working circular buffer 2007/12/13 09:37:22 (permalink)
    0
    guys here is my finished and tested circular buffa code if anyone wants it!!! feel free to copy it.

    this one is well suited for USART becuase it works with null terminated strings... and returns a null if empty...

    this one handles empty and full also.




    unsigned int head, tail = 0;
    unsigned int length = 127;
    unsigned char buffer_full=0;
    unsigned char buffer_empty=1;
    char rcv_buffa[128];


    //write a byte to receive buffa
    //this process assumes tail is always an empty spot
    //if tail=head then empty , if (tail= head -1) then full
    //
    void write_rcvbuffa(unsigned char blah123)
    {
    //check for a full buffer
    if ((buffer_full) | ((tail+1)==head) | ((tail==length) & (head==0)))
    {
           xbee_rts=1; //inhibit unit from sending more data
           buffer_full=1;
    }
    //if buffer not full
    else
    {
          //write the byte and inc to next empty slot
          rcv_buffa[tail] = blah123;
           if (tail >= length)
          { 
               tail = 0;
           }
           else 
           {
                  tail++; 
           }

           //update flags
           buffer_empty=0;
           if (((tail+1)==head) | ((tail==length) & (head==0)))
          {
                   buffer_full=1;
                   xbee_rts=1; //inhibit more stuff from comming until buffer is not empty 
           }
       }
    }
    //end write a byte to receive buffa

    // read a byte from receive buffer
    unsigned char read_rcvbuffa(void)
    {

    //return a null if buffer is empty, otherwise read 1 from head and increment
    // then returns the value at head.
    // then examines if buffer is empty and sets flag as appropriate for next read (or write)
    if ((buffer_empty) | (head==tail))
    {
          Data1=0x00; //null value
          xbee_rts=0; //good to go
         buffer_empty=1;
    }
    else
    {
          //read 1 from head and inc head
           Data1 = rcv_buffa[head];
          if (head >= length)
         {
                  head = 0;
          }
          else
          {
                 head++;
          }

           //update flags
           buffer_full=0;
           xbee_rts=0;
          if (head==tail)
          {
                 buffer_empty=1;
                 xbee_rts=0; //good to go
          }
      }
    return Data1;
    }
    // end read byte from receive buffa


    lemme know if anyone needs additional info or help with it :)

    this one is tested with xbee pro module as a receive buffer.

    im gonna use it for a transmit one too i think.


    the RTS control stuff can be deleted if your not using it... (or not using an xbee module hahah)
    post edited by corvette321 - 2007/12/13 09:44:51
    #12
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    1-wire Dallas code in Assembler for 16F PICs 2008/01/06 05:54:12 (permalink)
    0

    ; BEGINNING OF CODE

        btfsc PORTB,SPI_232_I            ; se e' basso, c'e' iButton!
        goto noIButton

      movlw TO_ADDR
        movwf DstAddr
      movlw 55                                ; notifica da iButton
      call SetFrame

        movlw 250
        EXTENDED_CALL Delay_uS                    ; aspetto 250uSec

        movlw 0x33                            ; comando READ-ROM
        EXTENDED_CALL DoDallasOut

        bcf PORTB,SPI_232_I            ; DATA=0

        movlw 8                                ; 8 byte...
        movwf temp3
        movlw BuffO6Arg                ; ...a partire da parm1 del pacch. in uscita
        movwf FSR

    _iButton:
        EXTENDED_CALL DoDallasIn
        MY_PAGESEL _iButton
        movwf INDF
        incf FSR,f
        decfsz  temp3,f
        goto  _iButton


    noIButton:
    ; END...


    ; SUPPORT ROUTINES
    DoDallasOut:                    ; entra W= valore;  tSlot=100uS
        movwf temp
        movlw 8
        movwf tempC

        call setDataOutput

    DoDallasOut1:
        bcf  PORTB,SPI_232_I

        movlw 90
        btfsc temp,0
        movlw 10
        call Delay_uS

        bsf  PORTB,SPI_232_I

        rrf temp,f
        movlw 10
        btfsc STATUS,C
        movlw 90
        call Delay_uS

        decfsz tempC,f
        goto  DoDallasOut1

        return


    DoDallasIn:                    ; esce W= valore; tSlot=100uS
        movlw 8
        movwf tempC

    DoDallasIn1:
        call setDataOutput
        movlw 5
        call Delay_uS

        call setDataInput
        movlw 10
        call Delay_uS

        bcf STATUS,C
        btfsc PORTB,SPI_232_I
        bsf STATUS,C
        rrf temp,f

        movlw 85
        call Delay_uS

        decfsz tempC,f
        goto  DoDallasIn1

        movfw temp
        return
    setDataOutput:                       
        bsf STATUS,RP0 ; Bank 1
        bcf TRISB,SPI_232_I            ; DATA e' output
        bcf STATUS,RP0 ; Bank 0
        return

    setDataInput:
        bsf STATUS,RP0 ; Bank 1
        bsf TRISB,SPI_232_I            ; DATA e' input
        bcf STATUS,RP0 ; Bank 0
        return


    GENOVA :D :D ! GODO
    #13
    ren
    Super Member
    • Total Posts : 654
    • Reward points : 0
    • Joined: 2006/04/20 16:17:49
    • Location: So Cali
    • Status: offline
    Writing large arrays (buffers) to FLASH on dsPIC33 processors 2008/01/10 18:36:25 (permalink)
    0
    although there is a brief example of how to use the commands _erase_flash(), _write_flash16() and _write_flash24() that were added in C30 v3.01. This example shows how to write arrays that exceed the page boundary:


    // Flash_Write Test_011008.c
    //
    // A test for demonstrating how to write a large array to FLASH (Program Memory)
    // on the dsPIC33FJ256GP710 processor installed in the Explorer16 development
    // board.  Objective: Define and write an array of 2048 16 bit words to FLASH.

    #include "libpic30.h"
    #include "p33Fxxxx.h"

    // _FLASH_PAGE is a static definition (512 for the dsPIC33).
    // _FLASH_ROW is a static definition (64 for the dsPIC33).
    // Define an array of 2048 words in program memory.
    int FLASH_data[_FLASH_PAGE*4] __attribute__((space(prog),aligned(_FLASH_PAGE*8)));



    int main()
    {
      int data_index;
      int page_index;
      int row_index;
      int Test_data[_FLASH_ROW];
      unsigned long Flash_pointer;

      // initialize some data for this test
      for (data_index = 0; data_index < _FLASH_ROW; )
           {
               Test_data[data_index] = data_index;
               data_index++;
           }

    // Get the address of the predefined variable(s)in program space. 
    _init_prog_address(Flash_pointer, FLASH_data);

    // This outer loop is used to erase each page after the page boundary has been crossed.                                 
    for (page_index = 0; page_index < 4; )
          {
               _erase_flash(Flash_pointer); // erase a page.
     
               // The row level loop.  8 rows per page for the dsPIC33 
               for (row_index = 0; row_index < 8; )
                     {
                            // Write each row here with 64 words of data. 
                            _write_flash16(Flash_pointer, Test_data);
       
                            // increment the values for the test data before writing the next row.
                            // NOTE: This is a post increment so it will increment once more
                            // after the final row is written.
                            for (data_index = 0; data_index < _FLASH_ROW; )
                                  {
                                         Test_data[data_index] += 64;
                                         data_index++;
                                  }
                             asm("nop");  // nops here for breakpoint placement.
                             asm("nop");
                             asm("nop");
                             asm("nop");
        
                             // Increment the Flash_pointer by one row.
                             Flash_pointer += (_FLASH_ROW * 2);
                             // NOTE: No additional addressing action is required when
                             // page boundaries are crossed.  However, the page boundary
                             // must be kept track of since the page erase function is
                             // used prior to the writing of rows on a page.
        
                             // Increment the row index.
                             row_index++;
                     }
                     asm("nop");  // nops here for breakpoint placement.
                     asm("nop");
                     asm("nop");
                     asm("nop");
      
                     // Increment the page index.
                     page_index++;
          }
          asm("nop");  // Place Breakpoint here, then read the part to show data in FLASH.
          asm("nop");
          asm("nop");
          asm("nop");
    }




    post edited by ren - 2008/01/10 18:44:30
    #14
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Using SHT11 on 16F628 in assembler 2008/01/21 16:40:06 (permalink)
    0

    ; init code

        movlw 255                            ; almeno 9 impulsi di clock con DATA=1 per reset SHT11...
        EXTENDED_CALL DoI2CMO
        movlw 255
        EXTENDED_CALL DoI2CMO
    ;  movlw 44   
    ;    EXTENDED_CALL Delay_mS_free
        ; ritardo 11mS non necessario
        MY_PAGESEL main


    ; read

        movlw DELAY_I2C_SLOW
        movwf DelaySPIVal


                                                        ; I2Cstart x SHT11...
        bsf PORTB,SPI_232_I            ; imposto DATA=1 e CLK=0
        EXTENDED_CALL setDataOutput
        ; OCCHIO a manipolare PORTB che e' I/O! (v. anche IRQ)
        EXTENDED_CALL Delay_SPI
        bsf PORTA,SPI_232_O            ; CLK=1
        EXTENDED_CALL Delay_SPI
        bcf PORTB,SPI_232_I            ; DATA=0 ; data line goes low during high clock for start bit
        EXTENDED_CALL Delay_SPI
        bcf PORTA,SPI_232_O            ; CLK=0
        EXTENDED_CALL Delay_SPI
        bsf PORTA,SPI_232_O            ; CLK=1
        EXTENDED_CALL Delay_SPI
        bsf PORTB,SPI_232_I            ; DATA=1
        EXTENDED_CALL Delay_SPI
        bcf PORTA,SPI_232_O            ; CLK=0
        EXTENDED_CALL Delay_SPI


        movlw BuffI8Arg                ; ...a partire da parm3...
        movwf FSR
        EXTENDED_CALL DoI2CMO_INDF                ; mando INDF (address=cmd)
        ; return_code? in parm?
        MY_PAGESEL bytes51

        decf BuffI6Arg,f            ; se ce n'e' un altro...
        bz  byte51_2
        incf FSR,f
        EXTENDED_CALL DoI2CMO_INDF                ; mando INDF
        MY_PAGESEL bytes51

    byte51_2:
                                                    ; questo VUOLE un ritardo tra WR e RD per la conversione (v. data sheet: 55-210mS)
        movfw BuffI8Arg
        xorlw 3
        bz  byte51_4_
        xorlw 3 ^ 5
        bnz  byte51_4
                                                    ; MA SOLO in LETTURA TEMP/HUMID! (NO in impostazioni ecc.)
                                                    ; oppure aspettare che SDI scenda...
    byte51_4_:
        movlw 5
        movwf temp2
    byte51_5:
      movlw 200                            ; 50mS ca.
        EXTENDED_CALL Delay_mS_free
        MY_PAGESEL bytes51
        decfsz temp2,f
        goto byte51_5

    byte51_4:
        movlw 0xff
        movwf parm1
        movwf parm2

        movfw BuffI7Arg                ; se devo ricevere...
        bz    byte51_3                    ; (se no, potrei anche dare ACK semplice... o return_code del WRITE)

        decf BuffI7Arg,w            ; indico se ACK (Buff6=1 -> W=0)
        EXTENDED_CALL DoI2CMI
        MY_PAGESEL bytes51
        movwf parm1
        decf  BuffI7Arg,f
        bz  byte51_3
        decf BuffI7Arg,w            ; indico se ACK (Buff6=1 -> W=0)
        EXTENDED_CALL DoI2CMI
        MY_PAGESEL bytes51
        movwf parm2


    byte51_3:
        EXTENDED_CALL setDataOutput            ; rimetto a posto (mancando I2Cstop qua...)
        bsf PORTB,SPI_232_I            ; DATA=1 ; data goes high while clock high for stop bit
        EXTENDED_CALL Delay_SPI
        MY_PAGESEL bytes51



    ; support routines

    DoI2CMO_INDF:
        movfw INDF

    DoI2CMO:                                ; Master, output (CLK negativo): entra in W il byte


        movwf temp
        movlw 8
        movwf tempC
        call setDataOutput

    DoI2CMO_:
    ;  clrwdt            ; gia' in Delay_uS
        rlf temp,f                            ; MSB first
        btfss STATUS,C
        bcf PORTB,SPI_232_I            ; DATA=0
        btfsc STATUS,C
        bsf PORTB,SPI_232_I            ; DATA=1

        call  Delay_1uS                    ; serve un minimo di ritardo tra il settaggio di DATA e la salita di CLK
        bsf PORTA,SPI_232_O
        call  Delay_SPI
        bcf PORTA,SPI_232_O
        call  Delay_SPI

        decfsz tempC,f
        goto DoI2CMO_

        call setDataInput
        call  Delay_SPI
        call  setClockHigh                ; aspetto ACK
    ;        Per WAIT_STATE dello slave (CLK basso)... NON e' chiaro se PRIMA o DOPO ACK... (PicBell lo fa dopo!)
    ;            questo lo controlla SEMPRE!
        call  Delay_SPI

        ; dopo Delay, qua arrivo con W=0 e Z=1
        btfsc PORTB,SPI_232_I
        addlw -1                                        ; Z=1 se ACK=OK (basso), altrimenti Z=0 e W!=0

        bcf PORTA,SPI_232_O
        return


    DoI2CMI:                                ; Master, input (CLK negativo): esce in W il byte se C=0 o C=1=errore
                                                    ;   entra W=1 se bisogna dare ACK allo slave o 0 se no

        movwf temp2
        movlw 8
        movwf tempC
        call setDataInput

    DoI2CMI_:
    ;  clrwdt            ; gia' in Delay_uS
        call  Delay_SPI
    ;    call  setClockHigh            ; CLK=1    fare? boh?
        bsf PORTA,SPI_232_O
        call  Delay_SPI

    ;    btfss PORTB,SPI_232_I                ; inutile...
        bcf  STATUS,C
        btfsc PORTB,SPI_232_I
        bsf  STATUS,C
        rlf temp,f                            ; MSB first

        bcf PORTA,SPI_232_O

        decfsz tempC,f
        goto DoI2CMI_

        call setDataOutput

        movf  temp2,f                        ; invio ACK come richiesto (Z=1 se stop cioe' ACK=1, Z=0 cioe' ACK=0)
        btfss STATUS,Z
        bcf PORTB,SPI_232_I            ; DATA=0
        btfsc STATUS,Z
        bsf PORTB,SPI_232_I            ; DATA=1

        bsf PORTA,SPI_232_O
        call  Delay_SPI
        bcf PORTA,SPI_232_O
        call Delay_SPI
        movfw temp
        return


    setDataOutput:                       
        bsf STATUS,RP0 ; Bank 1
        bcf TRISB,SPI_232_I            ; DATA e' output
        bcf STATUS,RP0 ; Bank 0
        return



    (to be edited for clarity...)

    GENOVA :D :D ! GODO
    #15
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Basic code for a Stepper Motor on PIC18F2420 2008/02/05 14:00:40 (permalink)
    0
    Referenced here:
    http://forum.microchip.com/post.aspx?m=312998

    http://adpm.homeip.net/files/jeremy_step.zip


    ADD: if anybody finds it useful, plz send 7$ via PayPal Smile
    post edited by DarioG - 2008/11/28 12:29:15

    GENOVA :D :D ! GODO
    #16
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Software PWM to dim Leds, in assembler for 16F628: 2008/04/07 12:08:01 (permalink)
    0
    Software PWM to dim Leds, in assembler for 16F628:

     
            ORG     0x004             ; interrupt vector location
            movwf   w_temp            ; save off current W register contents
            movfw    STATUS                 ; move status register into W register
            movwf    status_temp       ; save off contents of STATUS register

            btfss    INTCON,T0IF                ; Timer 0
            goto  EndISR
                   
    int_TMR0:
            clrf  STATUS                        ; bank 0
            bcf   INTCON,T0IF                ; clear bit IRQ

            movlw TMR0BASE
            movwf TMR0                    ; re-inizializzo TMR0

            movfw Timer64RGB                ; gestisco i livelli PWM R-G-B
            subwf RVal,w
            btfss STATUS,C
            bsf   myPortB,RPWMOBit
            movfw Timer64RGB
            subwf GVal,w
            btfss STATUS,C
            bsf   myPortB,GPWMOBit
            movfw Timer64RGB
            subwf BVal,w
            btfss STATUS,C
            bsf   myPortB,BPWMOBit

            movfw myPortB
            movwf PORTB

            incf  Timer64RGB,f
            btfss Timer64RGB,6                ; se >= 64...
            goto  end_TMR0

            movfw myPortB
            andlw LedOVal | I2CClkVal | TX_RXVal
    ;        movlw LedOVal | I2CClkVal | TX_RXVal
    ;        andwf myPortB,f
            movwf myPortB
            movwf PORTB
            clrf  Timer64RGB

            incf  Timer1,f                        ; il timer a 200Hz

    end_TMR0:


    EndISR:
            movfw   status_temp       ; retrieve copy of STATUS register
            movwf    STATUS                            ; restore pre-isr STATUS register contents
            swapf   w_temp,f
            swapf   w_temp,w          ; restore pre-isr W register contents
            retfie                    ; return from interrupt



    The above handles 3 channels (RGB led) at PORTB: the desired values are placed in RVal, GVal, and BVal, 8bit variables.

    Timer0 must be enabled to generate IRQs @ around 64*desired PWM frequency, i.e. circa 6400 Hz is ok on average.
    post edited by DarioG - 2010/12/27 03:05:53

    GENOVA :D :D ! GODO
    #17
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Software PWM to dim Leds, in C for 18F: 2008/04/07 12:10:23 (permalink)
    0
    Same thing in C, with C18, on a PIC18F such as 4520, 4550, 252, etc:
     
    void high_isr(void) {
        static byte i,j;
    //    static byte Timer64RGB;        messo sopra x ACCESSBANK

        if(INTCONbits.TMR0IF) {                // Timer 0 .. 
            INTCONbits.TMR0IF=0;                    // clear bit IRQ

    //        WriteTimer0(TMR0BASE);                    // reinizializzo TMR0
    // in questo modo evito overhead nell'interrupt... causa chiamata di funzione!
            TMR0L=TMR0BASE;
    //        TMR0H=0;


            Timer64RGB++;

            Timer64RGB &= 0x7f;

            if(Timer64RGB < RGBValue[0][0])
                m_RPWMO1Bit = 1;
            else
                m_RPWMO1Bit = 0;

    //        m_RPWMO1Bit = Timer64RGB < RGBValue[0][0] ? 1 : 0;    e' + veloce come sopra...


            if(Timer64RGB < RGBValue[1][0])
                m_RPWMO2Bit = 1;
            else
                m_RPWMO2Bit = 0;
            if(Timer64RGB < RGBValue[2][0])
                m_RPWMO3Bit = 1;
            else
                m_RPWMO3Bit = 0;
            if(Timer64RGB < RGBValue[3][0])
                m_RPWMO4Bit = 1;
            else
                m_RPWMO4Bit = 0;
            if(Timer64RGB < RGBValue[4][0])
                m_RPWMO5Bit = 1;
            else
                m_RPWMO5Bit = 0;
            if(Timer64RGB < RGBValue[5][0])
                m_RPWMO6Bit = 1;
            else
                m_RPWMO6Bit = 0;
            if(Timer64RGB < RGBValue[6][0])
                m_RPWMO7Bit = 1;
            else
                m_RPWMO7Bit = 0;
            if(Timer64RGB < RGBValue[7][0])
                m_RPWMO8Bit = 1;
            else
                m_RPWMO8Bit = 0;



            Counter++;


    //        m_Led2Bit ^= 1; //check timer


            }        //if timer...


        }



    8 leds are handled in here.
    A similar setup is used to the previous snippet of code.
    post edited by DarioG - 2010/12/27 03:06:32

    GENOVA :D :D ! GODO
    #18
    Xianthax
    Starting Member
    • Total Posts : 48
    • Reward points : 0
    • Joined: 2007/01/10 15:58:25
    • Location: 0
    • Status: offline
    RE: Basic code for a Stepper Motor on PIC18F2420 2008/04/07 13:01:28 (permalink)
    0
    Fast sqrt or inverse sqrt approximation:

    Method and Credit to:
    http://www.mceniry.net/papers/Fast%20Inverse%20Square%20Root.pdf

    Issue at hand is a fast way to do float sqrt(float) or invsqrt to a reasonable accuracy...

    code:

    float fastSqrt(float x)
    {
      union { float f; unsigned long ul;} y;
      y.f = x;
      y.ul = (0xbe6eb50cul - y.ul ) >> 1;
      y.f = 0.5f * y.f * (3.0f - x * y.f * y.f );
      //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f );  //repeat iterations to achieve lower error
      //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f );
      //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f );
      //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f );  //y.f ~= 1.0f/sqrt(x)
      return y.f * x;   // sqrt(x) = x / sqrt(x), return just y.f if you need invsqrt(x)
    }

    runs in about 123us on a pic18 @ 41.66666mhz vs clib sqrt(x) function at about 604us, (mplab sim, 1 newton step).

    error functions can be found in the pdf listed about and newton steps can be added or subtracted as needed for accuracy...1 step yields max relative error <= ~.00175

    i ran through the math far enough to find that doing a new version for sqrt(x) would not be faster to run than calculating 1.0/sqrt(x) and multiplying by x to get sqrt(x) as the newton step would require divisions.

    -x
    #19
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Software USART (only TX) for 16F PICs. 2008/05/21 10:52:14 (permalink)
    0
    Software USART (only TX) for 16F PICs.

     
    ; ---------------------------------------------------------------------
    PutByte232_0:               ; manda uno 0
      clrw                  ; prosegue...

    ; al fondo c'e' un MOVLW/MOVWF per rimettere PORTB a posto (poiche' e' I/O)

    PutByte232:                ; manda un byte
        movwf Data_AREA

        CLRF COUNT232            ;RESET 8 BIT COUNT

    #ifdef TX_BUFFERED
        BCF PORTB,TXComBit         ;LOW RD FOR START BIT
    #else
        BsF PORTB,TXComBit         ;LOW RD FOR START BIT
    #endif

        CALL Delay_Bit

    SendByte1:
        RRF Data_AREA, F       ;SHIFT Data TO CARRY

        BTFSc STATUS,C        ;0 / 1 ?
    #ifdef TX_BUFFERED
        BSF PORTB,TXComBit        ;SEND A 1
    #else
        BcF PORTB,TXComBit        ;SEND A 1
    #endif

        BTFSs STATUS,C        ;1 / 0 ?
    #ifdef TX_BUFFERED
        BCF PORTB,TXComBit           ;SEND A 0
    #else
        BsF PORTB,TXComBit           ;SEND A 0
    #endif

        CALL Delay_Bit
        INCF COUNT232,F
        BTFSS COUNT232,3                    ;COUNT = 8 ?
        GOTO SendByte1

    #ifdef TX_BUFFERED
        BSF PORTB,TXComBit           ;SEND STOP BIT
    #else
        BcF PORTB,TXComBit           ;SEND STOP BIT
    #endif
        CALL Delay_Bit
    #ifdef TX_BUFFERED
        BSF PORTB,TXComBit           ;SEND STOP BIT (un altro...)
        movlw  TXComVal
        movwf PORTB                                  ; IMPORTANTE,xche' PORTB e'in/out (PS/2)
    #else
        BcF PORTB,TXComBit           ;SEND STOP BIT (un altro...)
        movlw  0                                     ; IMPORTANTE,xche' PORTB e' in/out (PS/2)
        movwf PORTB
    #endif
        GOTO Delay_Bit



    Should be self-explaining; the Delay_Bit has to be computed for a bit-time delay, say 104uSec for 9600baud.

    The "TX_BUFFERED" is defined when a MAX232 is used, and undefined otherwise (your case).
    post edited by DarioG - 2010/12/27 03:05:32

    GENOVA :D :D ! GODO
    #20
    Page: 123 > Showing page 1 of 3
    Jump to:
    © 2021 APG vNext Commercial Version 4.5