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

How to use Interrupt in PIC16F877A in C..??

Discussion in 'Microcontrollers' started by koolguy, Jan 14, 2013.

  1. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    I have been playing.... I have created a 8x32 LED array with row scanning... I have still used interrupts but I am scanning exactly the same way as the T6963C controller scans the LCD. I can change pixel by pixel and draw animations

    http://www.youtube.com/watch?v=6UmvOTKGY7Q&feature=youtu.be

    It looks laggy but that isn't how it is I can't produce decent video's.

    This way you can draw to the screen just as we do for the larger screen..

    Here is the code..

    Code (text):

    #include<pic.h>
    #define _XTAL_FREQ 20000000L            // 20 meg crsytal
    __CONFIG(0x3F52);                       // HS on,  WDT off, BOR on, PWRTon..

    char displayPointer=0;                  // for interrupt use...
    extern const char  fnt[];               // Font in external C file
    extern const char  anim[];
    unsigned char buffer[32];               // buffer for screen
    unsigned char backbuffer[32];           // Spare screen for drawing on
    char pow[8]={128,64,32,16,8,4,2,1};

    void interrupt ISR()                    // This just swaps the buffer to the display
        {
        if(TMR2IF)                          // Make sure its the timer interrupt.
            {
            PORTB = 0;                      // Clear old data first
            if(displayPointer == 0 )        // 1st frame..
                RC4 = 1;                    // Data = 1 on the first clock only
            RC3 = 1;
            __delay_us(20);                 // Clock the shift registers
            RC3 = 0;
            RC4 = 0;                        // Make sure data stays low for the rest of the cycles
            PORTB = buffer[displayPointer]; // Move buffer row by row( 4 row sections per row )    
            if(++displayPointer==32)        // 32 LED row sections in total
                displayPointer = 0;         // Back to first row..
            }
        TMR2IF = 0;                         // Clear timer 2 interrupt flag
        }

    void pixel(signed char x,signed char y,int cond)
        {
        int tmp;
        char pix,msk;
        if(x<0 || y<0) return;          // outside drawing limits negative
        if(x>31 || y>7) return;         // outside drawing limits positive
        tmp = (y << 2) + (x>>3);        // Linear position
        pix = x%8;                      // pixel required
        pix = pow[ pix];
        msk = backbuffer[tmp];          // get exsisting data
        if(cond == 2)
            pix ^= msk;                 // XOR data to screen
        if (cond == 1)
            {
            pix = ~pix;
            pix &= msk;                 // AND data to screen
            }
        if(cond == 0)
            pix |= msk;                 // OR data to screen
        backbuffer[tmp] = pix;          // apply changes
        }

    void charput(char ch, signed char x,signed char y)
        {
        signed char x1, y1;            
        const char* addr2;              // pointer to character
        char disp;
        ch -= 0x20;                     // characters starts a 0 not 0x20
        addr2 = &fnt[0];                // start of font array
        addr2 = addr2 + ((int)ch * 8);  // start place in font array
        for( y1=0;y1<8;y1++)            // eight rows
            {
            disp = *addr2;
            for (x1 = 0; x1<8; x1++)    // eight pixels
                {          
                if(disp & pow[x1])
                    pixel(x+x1,y+y1,0); // OR the pixel to the display buffer
                }
            addr2++;
            }  
        }

    void strput(const char* ch, signed char x,signed char y)
        {
        int addr;
       
        while (*ch )
            {
            charput(*ch++,x,y);         // write a string to the display buffer
            x+=7;
            }      
        }

    void clr()
        {
        int addr;
        for(addr=0;addr<32;addr++)              // Empty display buffer
            backbuffer[addr]= 0;
        }

    void Blit()
        {
        int addr=0;
        GIE = 0;
        for(addr=0;addr < 32;addr ++)
            {
            buffer[addr] = backbuffer[addr];    // put all data from display buffer
            }                                   // to screen buffer
        GIE = 1;
        }

    void animation(void)
        {
        char x,y;
        const char* frame;                      // pointer to frames
        for(x=0;x<14;x++)                       // 14 frames in animation
            {
            clr();                              // clears the display buffer
            frame = &anim[0];                   // start of frames
            frame += x*32;                      // each frame is 32 bytes long
            for(y=0;y<32;y++)
                backbuffer[y] = *frame++;       // Cycle through the animation
            Blit();                             // pass to screen buffer
            __delay_ms(200);                    // time to view
            }
        }

    void displaystring(void)                // this routine prints through the screen buffer
        {                                   // moving one pixel at a time
        signed char x=32,y=0;               // I made these signed so I could print
        for(y = 0;y  < 96 ;y++)             // to nowhere so I could produce the scrolling effect
            {
            clr();                          // Clear the display buffer
            strput("HELLO WORLD!!",x--,0);  // adjust the scrolling string
            Blit();                         // pass to screen buffer
            __delay_ms(100);                // time to view
            }
        }

    void main(void)
        {
        int s;
        ADCON1 = 0x6;                       // ALL digital
        T2CON = 0x1e;                       // T2 on, 16:1 pre scale
        PR2 = 109;                          // timer preload value ( equates to 1.4mS with 20mhz crystal)
        TMR2IE = 1;                         // enable timer 2 interrupt
        PEIE = 1;                           // enable peripheral interrupt
        GIE = 1;                            // enableglobal interrupt
        TRISB = 0;                          // Port B as output...
        TRISC = 0;                          // Port C as ouput...
        animation();
        displaystring();
        while(1)
            {
            clr();
            if(s==0) strput("LOL",0,0);             // Here's the message
            if(s==1) strput(" LOL",0,0);
            if(++s == 2) s=0;
            __delay_ms(500);
            Blit();
            }
        }   // End main
     
    Thre are two external files ... The animation and the font... The font is slightly different as the screen writes are for row orientation..
     
    Last edited: Mar 17, 2013
  2. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Thanks for the help...
    are using using another external animation file where is it??
    and why are you using different font? pls give it...
     
  3. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    The font for row scanning is different to the one for column scanning... I'll attach the anim tonight... Also I have made the old bouncing ball demo.. looks good!!

    I'll post both files later..
     
  4. dave

    Dave New Member

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


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK

    Ok the animation file.... I have remarked so you can see how it works

    The ball in the bouncing ball is the "°" symbol but its easier to define "]" as that character as the "°" symbol isn't on the keyboard..
     

    Attached Files:

  6. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    The code on display is doing nothing why???
    I have programed the chip but the led is showing random/damage effect not taht what u have send, why??
    i have connected the Rc4 and 3 and RSt to Vcc
     
  7. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    Each matrix must be the right way round.... I haven't got the circuit to hand but A,B,C etc are at the bottom and 123 etc at the top

    YOU MUST change the properties of each matrix in ISIS to "NOT INVERT"

    Are you using the same shift registers that I'm using?
     
  8. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    One other thing.... I didn't mention the order of the shift registers...

    The scan is row by row... When I say row I mean complete row all four matrices..


    scan.PNG

    This way I can use the memory as linear... Perfect for drawing..
     
  9. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Hi,

    I am using my old display that i was using before i have tied RST to Vcc. 74hc164
    if you are using row scanning then why are using scanning column by ISR ....and how are you feeding serial data??
    I have more question first i want to clear this!!
     
  10. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    I'm not!! I'm using row scanning.. The ISR doesn't need to change as there are as many rows as columns...

    If you are using your old display you would need to change the way you write your data to the buffer..

    I scan a full row... You scan a full matrix..

    There is no serial data... I feed all 8 led's in a single row from portb

    All I do is ground the leds row by row...

    I have been following your progress on AAC.. If you want to use animation... This is definitely the best option...

    Remember your title of this thread How to use interrupt in pic16f877a in c??

    I am trying to get you to use interrupts...
     
  11. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    I am still confused a image can help...what are you trying to do?
     
  12. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    you also said this, are you using unions please explain little bit more about your code..
     
  13. Ragens

    Ragens Member

    Joined:
    Jan 31, 2013
    Messages:
    75
    Likes:
    0
    what use of interrupt exactly? i think i read someone post that interrupt we cant detect as it occur very fast...
     
  14. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    I WAS going to use a union... But I though if we did a basic scanning system (Row scanning was your idea ) You could animate the screen FAR FAR easier than you have been doing..

    Let me explain.


    Once you are scanning the complete display, just the same as your computer scans its monitor, From left to right from top to bottom... Most imaging software creates their images this way..... All you need to do is paste the image into a buffer... You need this for speed as virtually no image processing is needed..

    I have implemented a technique called "clipping"... Any pixel outside the drawing surface isn't drawn... This way you could have a larger picture than the display and scroll up, down, left or right just by changing the initial x,y value.... You can create frames in "Paint" and use that "FastLCD" program to create your binary images... Then you can blit your backbuffer to the displaybuffer in milliseconds... creating any animation you want.... If you create a string ie... "Hello world!!!"... This has 14 characters 14x8 pixels or 114 pixels long.. If you print the string to the buffer... ( clear the buffer first )
    Code (text):

    for(i=32;i> -96;i--)
       {
       clr();
       strput(str,i,0);
       blit();
       __delay_ms(100);
       }
     
    The first character STARTS at 32,0... "Off screen" so none of the rest of the string is printed..

    When "i" becomes negative, all the pixels negative are "Off screen" so they are not printed, all the pixels positive will..
    That routine above will print the string, in full, across the display but only the pixels that fall in between 0 and 31 will be seen!!!
     
  15. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    You should really start your own thread if you need to ask something....

    The idea of interrupts is mainly for convenience... Lets say you have a keypad connected to PORTB... You can poll the keypad all day long if you need to, but if you need to be getting on with some process and polling the keypad is taking some valuable ticks... You need to use the interrupt to read in PORTB and assign the key input to a variable that you can use in you main program...

    Or if you have data coming in on the serial port to fast for you to handle... For example your main super loop takes 200mS to complete and your data is coming in at a rate of 199mS between packets... You know if you poll the serial port your going to miss one or two packets... Then you need to read the uart "on the fly" so you DON'T miss anything.

    As I sad before... Once you get your head around using interrupts, you'll wonder why you didn't use them all the time...
     
  16. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Code (text):
    for(i=32;i> -96;i--)
       {
       clr();
       strput(str,i,0);
       blit();
       __delay_ms(100);
       }
    Still not so clear especially your deep logic behind this??
    why -ve I loop and
    Code (text):
    strput(str,i,0);
       blit();
    logic you are using is going over my head......
     
  17. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    Take a look at my scroll logic... This is a snapshot of x at 32 then at 8 and lastly at -16

    The four matrices are highlighted...

    scroll logic.png


    The string "HELLO!" is first printed at 32,0 so nothing appears as every pixel is outside the display area ( clipped).

    The string is then printed at 31,30,29.... and you will only see the partial string...

    As you can see at position "8" the letters "HEL" are visible.... And eventually at -16 you can see "LLO!" ... Quite simple really.
     
  18. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    OK, x indicate the number where the display is starting.....
    anyway i was searching strput is this C command?? but i can't find this in Google also the use of it?
    and you full code is also using :

    Code (text):
    void pixel(signed char x,signed char y,int cond)
        {
        int tmp;
        char pix,msk;
        if(x<0 || y<0) return;          // outside drawing limits negative
        if(x>31 || y>7) return;         // outside drawing limits positive
        tmp = (y << 2) + (x>>3);        // Linear position
        pix = x%8;                      // pixel required
        pix = pow[ pix];
        msk = backbuffer[tmp];          // get exsisting data
        if(cond == 2)
            pix ^= msk;                 // XOR data to screen
        if (cond == 1)
            {
            pix = ~pix;
            pix &= msk;                 // AND data to screen
            }
        if(cond == 0)
            pix |= msk;                 // OR data to screen
        backbuffer[tmp] = pix;          // apply changes
        }
     
    what is linear here?? and cond =0/1/2 mean??
    I am confused with full code that why going through it one by one!!
     
  19. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK
    Its MY routine... two functions under the pixel routine....

    The pixel routine lights an individual LED

    The LED matrices make up a small screen of 32x8 pixels ( think of pixels as small dots... Each LED is a dot..)

    The pixel routine determines the position of the LED you wish to light ... READ THE REMARKS...

    pix (LED we want to change) ^= msk( LED status now);

    This takes the status of LED's in a single row and XOR's the new LED value.. ( if its not the same invert it)

    pix (LED we want to change) = ~msk( LED status now);
    pix (LED we want to change) &= msk( LED status now);

    This takes the status of the LED's.. Complemets them and AND's the new value ( turns it off)

    pix (LED we want to change) |= msk( LED status now);

    This just turns the new LED on...
     
  20. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Code (text):
    void interrupt ISR()                    // This just swaps the buffer to the display
        {
        if(TMR2IF)                          // Make sure its the timer interrupt.
            {
            PORTB = 0;                      // Clear old data first
            if(displayPointer == 0 )        // 1st frame..
                RC4 = 1;                    // Data = 1 on the first clock only
            RC3 = 1;
            __delay_us(20);                 // Clock the shift registers
            RC3 = 0;
            RC4 = 0;                        // Make sure data stays low for the rest of the cycles
            PORTB = buffer[displayPointer]; // [B]Move buffer row by row( 4 row sections per row )[/B]     
            if(++displayPointer==32)        // 32 LED row sections in total
                displayPointer = 0;         // Back to first row..
            }
        TMR2IF = 0;                         // Clear timer 2 interrupt flag
        }
    what do you mean by this????
    the code is same as you have done this before in column scanning scrolling....
     
  21. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,141
    Likes:
    907
    Location:
    Rochdale UK

    Aha!! You are very observant!!... Look at the shift register outputs.... Each one accesses the rows in turn.

    The first output ( Q0 ) is connected to matrix row 1
    The second ( Q1 ) is connected to matrix 2 row 1
    The third ( Q2 ) .... third matrix row 1
    Then ( Q3 ) ... forth matrix row 1

    BUT THEN!!

    (Q4 ) is connected to the first matrix row 2
    ...
    .. so on....

    The changes needed were in the hardware...
     

Share This Page