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.

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

Status
Not open for further replies.
Please explain the procedure you are applying in post #97 the logic behind it!!

You can't use the same code as in the tutorials, You'll need to modify it for columns instead of rows.... Essentially its easier to scroll columns than it is rows..

Why it is easier???
 
Oh come on.....

[ 10101010 ] --> [10101010] Is harder as you need to check the digit falling out of one and ensure its in the new when shifting. It takes 8 x 2 x 8 operations to complete..

[0] --> [0]
[1] --> [1]
[0] --> [0]
[1] --> [1]
[0] --> [0]
[1] --> [1]
[0] --> [0]
[1] --> [1] ... Is just moving one byte at a time take 8 operations to complete..
 
OK, then the use of 74164 will be only to shift like 4017....
i found two problem while going through this method :
1. While scanning columns the data on LED display shakes i mean ghosting images.
2. the font we are using when saved in buffer are of vertical sort we want in horizontal..
 
1) this is what I have been talking about.... This is the scan rate that you need to maintain... Also you need to switch OFF the previous column and then light the new column.. It makes it a bit sharper...

2) The font is the same font used in the KS0107 GLCD ...Here's the one I use..

Code:
// font.h
//
//  5x7 
// 
const char  font5x8[] = {
0x00, 0x00, 0x00, 0x00, 0x00,// (space)
0x00, 0x00, 0x5F, 0x00, 0x00,// !
0x00, 0x07, 0x00, 0x07, 0x00,// "
0x14, 0x7F, 0x14, 0x7F, 0x14,// #
0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
0x23, 0x13, 0x08, 0x64, 0x62,// %
0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x1C, 0x22, 0x41, 0x00,// (
0x00, 0x41, 0x22, 0x1C, 0x00,// )
0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x50, 0x30, 0x00, 0x00,// ,
0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x30, 0x30, 0x00, 0x00,// .
0x20, 0x10, 0x08, 0x04, 0x02,// /
0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41,// <
0x14, 0x14, 0x14, 0x14, 0x14,// =
0x41, 0x22, 0x14, 0x08, 0x00,// >
0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x32, 0x49, 0x79, 0x41, 0x3E,// @
0x7E, 0x11, 0x11, 0x11, 0x7E,// A
0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x7F, 0x09, 0x09, 0x01, 0x01,// F
0x3E, 0x41, 0x41, 0x51, 0x32,// G
0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x7F, 0x02, 0x04, 0x02, 0x7F,// M
0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x46, 0x49, 0x49, 0x49, 0x31,// S
0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x7F, 0x20, 0x18, 0x20, 0x7F,// W
0x63, 0x14, 0x08, 0x14, 0x63,// X
0x03, 0x04, 0x78, 0x04, 0x03,// Y
0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41,// [
0x02, 0x04, 0x08, 0x10, 0x20,// "\"
0x41, 0x41, 0x7F, 0x00, 0x00,// ]
0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x01, 0x02, 0x04, 0x00,// `
0x20, 0x54, 0x54, 0x54, 0x78,// a
0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x38, 0x44, 0x44, 0x44, 0x20,// c
0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x38, 0x54, 0x54, 0x54, 0x18,// e
0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x08, 0x14, 0x54, 0x54, 0x3C,// g
0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x20, 0x40, 0x44, 0x3D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44,// k
0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x38, 0x44, 0x44, 0x44, 0x38,// o
0x7C, 0x14, 0x14, 0x14, 0x08,// p
0x08, 0x14, 0x14, 0x18, 0x7C,// q
0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x48, 0x54, 0x54, 0x54, 0x20,// s
0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x44, 0x28, 0x10, 0x28, 0x44,// x
0x0C, 0x50, 0x50, 0x50, 0x3C,// y
0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x00, 0x08, 0x36, 0x41, 0x00,// {
0x00, 0x00, 0x7F, 0x00, 0x00,// |
0x00, 0x41, 0x36, 0x08, 0x00,// }
0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
};
 
1) this is what I have been talking about.... This is the scan rate that you need to maintain... Also you need to switch OFF the previous column and then light the new column.. It makes it a bit sharper...

How to maintain scan rate, pls give code hint???
and then what is the use of 74164??
 
Here is my setup

Capture.png


Here is my code to do this

Code:
#include<pic.h>
#define _XTAL_FREQ 20000000L
__CONFIG(0x3F18);

char displayPointer=0;
extern const char  font[];

unsigned char buffer[26]; // buffer for screen

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
		RC3 = 1;
		__delay_us(20);				// Clock the shift registers
		RC3 = 0;
		RC4 = 0;
		PORTB = buffer[displayPointer];	 // Move buffer line by line		
		if(++displayPointer==24) 		//  24 LED columns
			displayPointer = 0;			// back to first..
		}
	TMR2IF = 0;
	}

void display(const char* str)
	{
	int addr;
	char x, y;
	while(*str != 0)					// while there is still characters
		{
		addr = (int) *str++ - 0x20;		// get character
		addr *=5;
		for(y=0;y<5;y++)				// 5x8 font so 5 columns
			{
			buffer[25] = font[addr++];  // put it in buffer	
			for(x=0;x<26;x++)
				{
				buffer[x] = buffer[x+1];	// shift all the columns <--
				__delay_ms(5);				// so you can see it
				}
			}
		buffer[25] = 0;						// This is the scpace between 
		for(x=0;x<26;x++)					// the characters.. Or they will be too close
			{
			buffer[x] = buffer[x+1];		//	shift the space in
			__delay_ms(5);
			}							// NOTE!!! your array is 28 not 24 like mine
		}	
	}


void main(void)
	{
	ADCON1 = 0x6;
	T2CON = 0x1e;	
	PR2 = 129;							// timer preload value
	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...
	while(1)
		{
		display("HELLO WORLD!!!    ");   // Here's the message
		}
	}	// End main

This does work Each data column is loaded just off screen then scrolled into view..
 
Last edited:
Hi again,
which pic are you using and if we are not using A/D then why ADCON1 = 0x6; ??
In ISR:-
1. T2CON = 0x1e; -------->it mean 1:4 Postscale 1 = Timer2 is on 1x = Prescaler is 16, right??? then what the use of it here??
2. PR2=129; -----------> Set the PWM period by writing to the PR2 register.
3.TMR2IE = 1;---------------> TMR1IE: TMR1 Overflow Interrupt Enable bit
4. if(TMR2IF)------------> TMR2IF: TMR2 to PR2 Match Interrupt Flag bit
1 = TMR2 to PR2 match occurred (must be cleared in software)
0 = No TMR2 to PR2 match occurred


One thing more i am not getting it is. the program start executing from main to display then where ISR is called???
RC4/SDI/SDA and RC3/SCK/SCL are you using these SDI/SDA also or just simple ??
 
Last edited:
You really have little experience in programming... I apologize, I assumed you at least knew how micro architecture worked.. I thought you used to program in assembly.

A)... The same chip as you... PIC16F877A

B).. ADCON1 = 0x6: // This makes PORTA digital I always use it if I don't need the ADC

C).. I had to play around with PR2, T2 pre and post scalers to get the timing as I wanted..

D).. PR2 is a preloaded figure, its not just used for PWM...

FINALLY.... The whole point of interrupts is they are called when required...If you notice I set the Timer2 to interrupt when it overflows...

This means that every 1.4mS a column is lit... My example has 24 columns.. Therefore we have 33mS per scan , You will be able to change the buffer to 29 and scan to 28 without there being much difference...

I picked SDA and SCL because I just did....
 
RESULT:-
https://www.youtube.com/watch?v=DVRJwHjG3Xs&feature=youtu.be

Code:
#include<pic.h>
__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_XT);
#define _XTAL_FREQ 4000000
#define DAD PORTB
#define RST RD7
#define CLK RD4
#define DATA RD5


 
char displayPointer=0;
extern const char  font[];
 
unsigned char buffer[32]; // buffer for screen
 
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..
			DATA = 1;				// Data = 1 on the first clock
		CLK = 1;
		__delay_us(20);				// Clock the shift registers
		CLK = 0;
     	DATA = 0;
		PORTB = buffer[displayPointer];	 // Move budffer line by line		
		if(++displayPointer==31) 		//  24 LED columns
			displayPointer = 0;			// back to first..
		}
	TMR2IF = 0;
	}
 
void display(const char* str)
	{
	int addr;
	char x, y;
	while(*str != 0)					// while there is still characters
		{
		addr = (int) *str++ - 0x20;		// get character
	//	DAD=addr;
 addr *=5;
//DAD=addr;
		for(y=0;y<5;y++)				// 5x8 font so 5 columns
			{
			buffer[31] = font[addr++];  // put it in buffer	
		
 	for(x=0;x<32;x++)
				{
				buffer[x] = buffer[x+1];	// shift all the columns <--
				//DAD=buffer[x];
__delay_ms(2);				// so you can see it
				}
			}
		buffer[31] = 0;						// This is the scpace between 
		for(x=0;x<32;x++)					// the characters.. Or they will be too close
			{
			buffer[x] = buffer[x+1];		//	shift the space in
			__delay_ms(30);
			}							// NOTE!!! your array is 28 not 24 like mine
		}	
	}
 
 
void main(void)
	{
	ADCON1 = 0x6;
	T2CON = 0x1e;	
	PR2 = 129;							// timer preload value
	TMR2IE = 1;							// enable timer 2 interrupt
	PEIE = 1;							// enable peripheral interrupt
	GIE = 1;							// enableglobal interrupt
	TRISB = 0;							// Port B as output...
	TRISD = 0;	
RST=1;						// Port C as ouput...
	while(1)
		{
		display("HELLO WORLD!!!    ");   // Here's the message
		}
	}	// End main
 
No! I could have used any pins.... I'm using timer2 to get the results I wanted...

You couldn't really use he MSSP module for this.... Especially with the shift registers I picked...

When using a clocking data method it just seems right to use these two pins... Its forward thinking really...
 
I am really not getting you, what are you trying to say....
anyway why the text is mirror images and flickering so much i am using 4mhz crystal that's why?? and RD5 and RD4 pin for clk and data to 74164
 
Here is my setup

View attachment 70975


Here is my code to do this

Code:
#include<pic.h>
#define _XTAL_FREQ 20000000L
__CONFIG(0x3F18);

char displayPointer=0;
extern const char  font[];

unsigned char buffer[26]; // buffer for screen

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
		RC3 = 1;
		__delay_us(20);				// Clock the shift registers
		RC3 = 0;
		RC4 = 0;
		PORTB = buffer[displayPointer];	 // Move buffer line by line		
		if(++displayPointer==24) 		//  24 LED columns
			displayPointer = 0;			// back to first..
		}
	TMR2IF = 0;
	}

void display(const char* str)
	{
	int addr;
	char x, y;
	while(*str != 0)					// while there is still characters
		{
		addr = (int) *str++ - 0x20;		// get character
		addr *=5;
		for(y=0;y<5;y++)				// 5x8 font so 5 columns
			{
			buffer[25] = font[addr++];  // put it in buffer	
			for(x=0;x<26;x++)
				{
				buffer[x] = buffer[x+1];	// shift all the columns <--
				__delay_ms(5);				// so you can see it
				}
			}
		buffer[25] = 0;						// This is the scpace between 
		for(x=0;x<26;x++)					// the characters.. Or they will be too close
			{
			buffer[x] = buffer[x+1];		//	shift the space in
			__delay_ms(5);
			}							// NOTE!!! your array is 28 not 24 like mine
		}	
	}


void main(void)
	{
	ADCON1 = 0x6;
	T2CON = 0x1e;	
	PR2 = 129;							// timer preload value
	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...
	while(1)
		{
		display("HELLO WORLD!!!    ");   // Here's the message
		}
	}	// End main

This does work Each data column is loaded just off screen then scrolled into view..


not working with 20mhz crystal (12pf capacitor) the serial data & clk was giving pulse but portb is zero at all time don't know why???
 
Play with the setting of PR2.... Also the small delay after each buffer shift... I used these settings on ISIS... With real LEDs you may need a faster scan... take PR2 down to 90 or 80, the brightness of the LEDs will suffer though

Nice video....
 
Nice video....

thanks


take PR2 down to 90 or 80, the brightness of the LEDs will suffer though

I am still confused with the code logic anyway what is the use of PR here??
i am using 32 column now and confused with you are using sometimes 24 26 buffer like that why??
 
PR2 determine the LED ON time, at the moment its 1.4mS... As I said if you make this smaller, the LEDs are going to be duller... Compromise situation...


I only need a 25 byte buffer for a 24 column display... So you can draw the columns off screen..
 
Hi,

Now i am using two different led per 74164 output both anode are tie up to 74164 directly and the cathode to BC547 via PORTB...
the base R is 3.3K and I am using a series resistance of ~150/220ohms connected to gnd common of BJT. the problem is that some row light very little don't know why??
the single Red of other display was working fine....
 

Attachments

  • ab.jpg
    ab.jpg
    159.3 KB · Views: 160
  • ac.jpg
    ac.jpg
    178.4 KB · Views: 160
Status
Not open for further replies.

Latest threads

Back
Top