Continue to Site

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.

  • 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.

Multitasking using interrupt

Status
Not open for further replies.
Like I said... The DS1307 reading isn't the problem.... If it was done as a sequential read, it would be less the a milli second...

The problem is the screen update is FAR too slow.... The LED matrices in the example I posted ran 8 8x8's very well using only three micro pins.... The 7Segs could be on two more pins via latched shift registers.. Then only the LED's need serviced..

Dead easy using the interrupts..
 
Well, it is almost trivial. However, more optimization would be necessary if it is battery powered device and demanded minimum battery life. Then this will be a bit of motivation to learn more about interrupts and timers. And a bit different circuit.

Probably another variation of assumed school project...
 
Last edited:
If your coding in C it don't really matter for most compilers they smarter than we are and fix it for us.

Compilers are "smart" as much as people who made it, or how much they allowed it (freeware/payed versions).

Have you tried that actually with MikroC?
 
I wrote a small program that write to a bank of LED matrices ( 8 of them ) + 6 seven segment displays..

As the seven segment displays are latched, the interrupt concentrates purely on the matrix'ed display..

Here is the XC8 code

C:
#include<xc.h>
#include<stdio.h>
#define _XTAL_FREQ 20000000L       // 20 meg crsytal
#pragma config WDTE = OFF, PWRTE = OFF, CP = OFF, BOREN = OFF, DEBUG = OFF, LVP = OFF, CPD = OFF, FOSC = HS           // 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[];
extern const char  anim1[];
unsigned char ledstr[7];
unsigned char buffer[64];          // buffer for screen
unsigned char backbuffer[64];       // Spare screen for drawing on
char pow[8]={128,64,32,16,8,4,2,1};
unsigned char digit[] = {0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x6f};


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==64)      // 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>63 || y>7) return;       // outside drawing limits positive
   tmp = (y << 3) + (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(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<64;addr++)         // Empty display buffer
     backbuffer[addr]= 0;
   }

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

void number(long numb)
   {
   int x, y;
   unsigned char ch;
   long divisor = 100000;
   for(x=0;x<6;x++)
     {
     ch = digit[numb/divisor % 10];
     for(y=0;y<8;y++)
       {
       RC5 = 0;
       if(ch&0x80) RC5 = 1;
       RC6 = 1;
       NOP();
       RC6 = 0;
       ch<<=1;
       }
     divisor/=10;
     }
   RC7 = 1;
   NOP();
   RC7 = 0;

   }
void displaystring(void)         // this routine prints through the screen buffer
   {                   // moving one pixel at a time

     clr();
     sprintf(ledstr,"SUN OCT24");   // Clear the display buffer
     strput(ledstr,0,0);         // adjust the scrolling string
   
     Blit();               // pass to screen buffer
     __delay_ms(800);           // time to view

   }

void main(void)
   {
   int sx,sy;
   long loop = 0;
   int xdir=1, ydir=1;
   ADCON1 = 0x6;             // ALL digital
   T2CON = 0x1e;             // T2 on, 16:1 pre scale
   PR2 = 60;               // 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;
   PORTC = 0;               // Port B as output...
   TRISC = 0;               // Port C as ouput...
   displaystring();
   while(1)
     {
     clr();
     sx += xdir; sy += ydir;   
       
  strput((char *)"]",sx,sy);

     if(sx>60) xdir = -1;
     if(sy>5) ydir = -1;
     if(sx<0) xdir = 1;
     if(sy<0) ydir = 1;
     __delay_ms(60);
     if(loop & 0x080)
        Blit();
     else
       {
       clr();
       sprintf(ledstr,"  %06ld",loop);
       strput(ledstr,0,0);
       Blit();
       }
     number(loop++);
     }
   }   // End main


There is no clock but the main thing is centered around the display aspect..

Here is the schematic...( As I use ISIS, there are no current limiting resistors!!!! Don't forget to fit them!!!)
 

Attachments

  • time.PDF
    127.5 KB · Views: 263
Compilers are "smart" as much as people who made it, or how much they allowed it (freeware/payed versions).

Have you tried that actually with MikroC?
Nope not in awhile but xc8 does and so does hi tech and swordfish but guess what miKro doesn't change it but thats ok means you have to read the doc's with your compiler
 
I wrote a small program that write to a bank of LED matrices ( 8 of them ) + 6 seven segment displays..

As the seven segment displays are latched, the interrupt concentrates purely on the matrix'ed display..

Here is the XC8 code

Ian, which compiler you using after all? This will not compile for sure with latest XC8 compiler (1.34), from several reasons:

1. Config bits must corresponds to specific device, in this case PIC18F45K22. This may not work. I would make it one pragma per bit for clarity.

2. The __delay_ms(60) and similar will not work, as loop is limited to some 3*256*256 cycles, which is about 39ms when use 20Mhz crystal (instruction execution time is 200ns per cycle).

3. The __delay_ms(800) is not correct, as parameter is char only (8 bits).

4. RC7 == 0 and similar is as well not allowed anymore. Correct syntax in XC8 is PORTCbits.RC7 == 0

Furthermore:

1. PORTB=0 is not recommended with PIC18. Instead, LATB=0. When write through the latch register, the value is saved immediately and also written to the port. If that is achieved through the port register, that may not be the case. BTW, free version of XC8 will not correct this automatically - I'm not aware for pro.

2. For OP. It is good practice to add TRISB=0 at beginning . The B port is mostly set by default to output for any PIC, however it is good practice to define and set all used and unused I/O ports at beginning of the code for clarity and latter to avoid some problems in device functioning.
 
Last edited:
We have had this conversation before.... XC8 limitations are on PIC18 only... The chip in the schematic is a pic16F877a.. It was something I did for a certain "Indian gentleman"...

2. For OP. It is good practice to add TRISB=0 at beginning . The B port is mostly set by default to output for any PIC, however it is good practice to define and set all used and unused I/O ports at beginning of the code for clarity and latter to avoid some problems in device functioning.
By default they are input..... But there is a TRISB = 0 statement in the main!!

There is nothing wrong with the code.... It works very well..... The only thing that needs to happen is the serial pins need to be shifted as the OP needs to use I2C....
 
We have had this conversation before.... XC8 limitations are on PIC18 only... The chip in the schematic is a pic16F877a.. It was something I did for a certain "Indian gentleman"...

By default they are input..... But there is a TRISB = 0 statement in the main!!

Sorry, I must overlook both. It is ages and eyes...

OP did mentioned PIC which uses... Well, code may be fine for PIC16 and educational purposes.

In any way, it was not required to use any complication as RTOS for such simple task.
 
Sorry, I must overlook both. It is ages and eyes...

OP did mentioned PIC which uses... Well, code may be fine for PIC16 and educational purposes.

In any way, it was not required to use any complication as RTOS for such simple task.
But in any case! The code needs porting to mikroC so Any C code will do..

RC7 becomes LATCbits.RC7 in XC8 but becomes LATC7_bit in mikroC..
 
Ian Rogers Was there any reason why u decided to use 74LS323 instead of 74HC595 for the matrix? And also pls pardon some of my questions on your code till i finish compiling it in mikroc. You Know its difficult to read someones code and too m doing that in another compiler. Thanks
 
Yes!!! The 74hc 595 is a latching shift register so it is perfect for 7 seg displays as it displays a single byte at a time..

The matrices require a single signal to display a complete byte so the speed of the 74ls323 is what's needed...

I'm off to Amsterdam today for a couple of days so I might not be able to get online... I'm not being ignorant if you do not get any replies...
 
Code:
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>63 || y>7) return;       // outside drawing limits positive
   tmp = (y << 3) + (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
   }

Can anyone explain this line of code for me?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top