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.

UART Disables external interrupt

Status
Not open for further replies.

SneaKSz

Member
Hello all,

Ive got a pic wich has a connection with the laptop and keypad ( external interrupt INT1) . Both can send numbers to the pic and the pick will show it on the LCD.

When I press some buttons on the keypad(external interrupt) they appear on the LCD , when I send chars to the PIC it shows them op the LCD.

The problem that I"m facing is that : I press the keypad , the value is shown in the LCD but when I send a char now , it will also be shown in the LCD , but now the PIC does NOT
recognize the keypad's external interrupt. It's like the UART disabled the external interrupt .

The pic ( before sending data ) recognizes if ( INTCON3bits.INT1IF==1 ) , but after having an interrupt ( going to an interrupt routine) from the uart , it stops recognizing if ( INTCON3bits.INT1IF==1) when I press a button on the keypad.

Ive been searching for ' fast context saving ' and saved PCLATCH , w , STATUS ... . But it has no affect, I"ve also switched the priority levels.


Someone has experienced this before?

kind regards
 

edman222

Member
A silly question but... Did you reset the external keypad interrupt after you acknowledged it? ( the port change on interrupt bits)

I don't think a PIC auto clears such things as keypad/button/logic changes on an (RB?) port. You have to re enable that as well as any global interrupts/priority after you use it/disabled it. ( although this is not always true for data bus related things, but we are talking about a keypad) What device are you using??
 

SneaKSz

Member
Hi ,

Yes , after that I calculated the button that is pressed , I do INTCON3bits.INT1IF==0 and test again if INT1IF go's high.

Thanks
 

edman222

Member
What PIC are you using? Also does the UART stay active after you send it something, like sending data twice through the UART? ( meaning does the mcu freeze? or does it keep running like normal but with keypad issues?)

Will think about this some more...
 

SneaKSz

Member
Hi,

Yea after the keypad freezes , I still can send data trough the uart and it will be displayed on the screen. When I press a button of the keypad then , the interrupt will go high , but it will never go back low.

It's like the UART disables the external interrupt when coming back from the interrupt handler.
 

ericgibbs

Well-Known Member
Most Helpful Member
Hi,

Yea after the keypad freezes , I still can send data trough the uart and it will be displayed on the screen. When I press a button of the keypad then , the interrupt will go high , but it will never go back low.

It's like the UART disables the external interrupt when coming back from the interrupt handler.

hi,
Can you post your full program listing.??
 

SneaKSz

Member
Hello,

Here is it
Code:
#include <p18f14k50.h> 
//#include <usart.h>
# include <string.h>
#include <stdio.h>
#include <delays.h>

	#pragma config    CPUDIV = NOCLKDIV
	#pragma config    USBDIV = OFF  
	#pragma config    FOSC = HS
	#pragma config    PLLEN = OFF 
	#pragma config    FCMEN = OFF
	#pragma config    IESO = OFF 
	#pragma config    PWRTEN = ON
	#pragma config    BOREN = ON
	#pragma config    BORV = 30
	#pragma config    WDTEN = OFF
	#pragma config    WDTPS = 1
	#pragma config    MCLRE = ON
	#pragma config    HFOFST = ON 
	#pragma config    STVREN = ON 
	#pragma config    LVP = OFF
	#pragma config    BBSIZ = OFF 
	#pragma config    XINST = OFF
	#pragma config    CP0 = ON 
	#pragma config    CPB = ON 
	#pragma config    CPD = ON 
	#pragma config    WRT1= ON 
	#pragma config    WRTB = ON 
	#pragma config    WRTC = ON 
	#pragma config    WRTD = ON 
	#pragma config    EBTRB = ON

  #define SCL TRISBbits.TRISB6 // SCL line
  #define SDA TRISBbits.TRISB4 // SDA line 

#define IODIR       0x00
#define IPOL        0x01
#define GPINTEN     0x02
#define DEFVAL      0x03
#define INTCON      0x04
#define IOCON       0x05
#define GPPU        0x06
#define INTF        0x07
#define INTCAP      0x08
#define GPIO        0x09
#define OLAT        0x0A



// methoden
void init(); 
void SendStart();
void SendStop();
void SendRestart();
void SendByte(unsigned char  address ,unsigned char  cmdb,unsigned char data );
char ReadByte(unsigned char  address ,unsigned char  cmdb,unsigned char readaddress );
void ACKSTAT();
void I2CFAIL();
void SSPFlag();
void Nack();


// LCD

void SendByteControl();
void SendByteControl2();
void initLCD();
void clearLCD();
void writeLCD(unsigned char x);
void StartLCD(unsigned char place);
void clearLCD2();
void StartLCD2(unsigned char place);
void writeData();
void writeData2();


void Strans(unsigned char data);

int i=0;
unsigned char result[];
unsigned char keypad; 
unsigned char lcdchar;
unsigned char received[];
unsigned int c;
unsigned char dummy;
void InterruptHandlerHigh (void);

// High priority interrupt vector

#pragma code InterruptVectorHigh = 0x08 // comp mode default vector
void InterruptVectorHigh (void)
{
  _asm
    goto InterruptHandlerHigh //jump to interrupt routine
  _endasm
}


//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerHigh

	void InterruptHandlerHigh ()
	{

// received[1]= RCREG;
//c=c+1 ==>>>>>>>>>>>>> werkt NIET C wordt = RCREG , raar
		if(PIR1bits.RCIF)
		{

		switch( c )
			     {
			case 0 : // address
				received[0]=RCREG;
				if ( received[0]==0x38) received[0]=0x08;
				c++;
				break;
			case 1 : // first value
				received[1]=RCREG;
				c++;
				break;
			case 2: 	// second value		
				received[2]=RCREG;
				c=0;
		//		LATCbits.LATC0=1;
			//		while(1){			
		//					SendStart(); // send S
		//					SendByte(received[0]); // Address
		//					SendByte(received[1]); // send address (Address Byte)
		//					SendByte(received[2]); // send address (Address Byte)
		//					SendStop();// send P (stop)	
				//			Delay10KTCYx(100);//10ms		
				//			Delay10KTCYx(100);//10ms	
				//			Delay10KTCYx(100);//10ms
					// LCD aansturing

					break;
			}

			if(!(RCSTAbits.OERR|RCSTAbits.FERR))
			{
					Strans('#');//start
					Strans('T');
					Strans('E');
					Strans('S');
					Strans('T');
					Strans('&');//end
			}

			else  
			{
	
				if (RCSTAbits.OERR) 
					{
					unsigned char h;
				     //Overrun Error
				    RCSTAbits.CREN = 0; //Reset error
				    h = RCREG; //Flush buffer
				    RCSTAbits.CREN = 1;
					LATCbits.LATC1=0;
						Strans('E');
						Strans('R');
						Strans('R');
						Strans('O');
						Strans('R');
			
				    }
				if (RCSTAbits.FERR) 
					{
				     //Frame Error
					unsigned char j ;
				     j = RCREG; //Reset error
					LATCbits.LATC0=0;
						Strans('E');
						Strans('R');
						Strans('R');
						Strans('O');
						Strans('R');
				    }
			 }

		dummy = RCREG;
		dummy=dummy+128;

		clearLCD();
		StartLCD(0x00);// start ROW 0 
		SendStart();
		writeData();					
		// first row ABC
		writeLCD(dummy);
		SendStop();
		}// end if RCIF

	}
void main(void){
	init();// setup
	initLCD();
	Delay10TCYx(3);// wait 333ms startup GPIO	

     SendByte(0x40,IODIR,0xF0); //WriteAddress iodir , high nibble is input      
     Delay10TCYx(1);  
     SendByte(0x40,GPIO,0xF0); // toggle the outputs  
     Delay10TCYx(1);  
     SendByte(0x40,IOCON,0b00110010);  // active high  
     Delay10TCYx(1);  
     SendByte(0x40,INTCON,0xF0); // compare to def val  
     Delay10TCYx(1);  
     SendByte(0x40,IPOL,0x00); // same pol   
     Delay10TCYx(1);  
     SendByte(0x40,DEFVAL,0xF0);// def val to compare  
     Delay10TCYx(1);  
     SendByte(0x40,GPINTEN,0xF0); // enable input pin for inter on change  
while(1){

		LATCbits.LATC1=1;
	//	test= ReadByte(0x40,INTCAP,0x41);  
	//	test= ReadByte(0x40,GPIO,0x41); 
 
		if(INTCONbits.INT0IF==1)
			{				
		  			result[0]= ReadByte(0x40,INTCAP,0x41);  
//			     	if (result[0]==0XE0){
//					LATCbits.LATC0=1; // SET HIGH
//			}
	// flip
			     SendByte(0x40,GPPU,0x0F); // enable input pin for inter on change 
			     Delay10TCYx(1);   
			     SendByte(0x40,IODIR,0x0F); //WriteAddress iodir , high nibble is input      
			     Delay10TCYx(1);  
			     SendByte(0x40,GPIO,0x0F); // toggle the outputs  
			     Delay10TCYx(1);   
			     SendByte(0x40,INTCON,0x0F); // compare to def val  
			     Delay10TCYx(1);  
			     SendByte(0x40,IPOL,0x00); // same pol   
			     Delay10TCYx(1);  
			     SendByte(0x40,DEFVAL,0x0F);// def val to compare  
			     Delay10TCYx(1);  
			     SendByte(0x40,GPINTEN,0x0F); // enable input pin for inter on change  

	       while ( PORTCbits.RC1==1)// while INT input is high
				{

				 result[1]=ReadByte(0x40,GPIO,0x41);  // read this register because this contains the actual value of the IO pins 
// the INTCAP contains the value of the IO when an interrupt happens
					while ( PORTCbits.RC0==1){
					unsigned dum ;
				    Delay10TCYx(1); 		
					dum =ReadByte(0x40,GPIO,0x41);
					}
		     	}
			LATCbits.LATC1=0;
// the INTCAP contains the value of the IO when an interrupt happens
			INTCONbits.INT0IF=0;
			result[2]=result[0]|result[1];
		//		if ( result[2]==0xED)	LATCbits.LATC0=1; // SET HIGH
// get the number	
			     switch( result[2] )
			     {
			//first row
			        case 0xEE : keypad='1'; lcdchar=0xB1;
			                   break;
			        case 0xED  :keypad='2';lcdchar=0xB2;
				           break;
					case 0xEB  :keypad='3';lcdchar=0xB3;
				           break;
			        case 0xE7 : keypad='F';lcdchar=0xC6;
				           break;
			//second row
					case 0xDE:  keypad='4'; lcdchar=0xB4;
				           break;
					case 0xDD:  keypad='5'; lcdchar=0xB5;
				           break;
					case 0xDB:  keypad='6'; lcdchar=0xB6;
				           break;
					case 0xD7:  keypad='E';lcdchar=0xC5;
				           break;
			//3rd row
					case 0xBE:  keypad='7'; lcdchar=0xB7;
				           break;
					case 0xBD:  keypad='8'; lcdchar=0xB8;
				           break;
					case 0xBB:  keypad='9'; lcdchar=0xB9;
				           break;
					case 0xB7:  keypad='D'; lcdchar=0xC4;
				           break;
			
			//4th row
					case 0x7E:  keypad='A';lcdchar=0xC1; 
				           break;
					case 0x7D:  keypad='0'; lcdchar=0xB0;
				           break;
					case 0x7B:  keypad='B';lcdchar=0xC2;
				           break;
					case 0x77:  keypad='C'; ;lcdchar=0xC3;
				           break;
					default  : keypad=0;  lcdchar=0xC3;
			                   break;
				}

// write char :


			StartLCD(0x00);// start ROW 0 
			SendStart();
			writeData();
		
		// first row ABC
			writeLCD(lcdchar);
			SendStop();
			Strans(keypad);

		 }	// end if

     SendByte(0x40,IODIR,0xF0); //WriteAddress iodir , high nibble is input      
     Delay10TCYx(1);  
     SendByte(0x40,GPIO,0xF0); // toggle the outputs  
     Delay10TCYx(1);  
     SendByte(0x40,IOCON,0b00110010);  // active high  
     Delay10TCYx(1);  
     SendByte(0x40,INTCON,0xF0); // compare to def val  
     Delay10TCYx(1);  
     SendByte(0x40,IPOL,0x00); // same pol   
     Delay10TCYx(1);  
     SendByte(0x40,DEFVAL,0xF0);// def val to compare  
     Delay10TCYx(1);  
     SendByte(0x40,GPINTEN,0xF0); // enable input pin for inter on change  

			
	}// end while		
}// end main

	void init(){
	ADCON1=0x07;//Configure A/D
	TRISCbits.TRISC0=1; //  INT0
	TRISCbits.TRISC1=0; // INT1 PIN
	
	INTCONbits.INT0IE=1;
//	INTCON3bits.INT1IP=1;// high prio
	INTCONbits.INT0IF=0;
	INTCON2bits.INTEDG0=1;// risiing edge.

	ANSELbits.ANS4=0; // digital IO RC0
	ANSELbits.ANS5=0; // digital IO RC1
	CM1CON0bits.C1ON=0;// Disable compare
	CM2CON0bits.C2ON=0;// Disable compare

	SDA=1; // input
	SCL=1;// input
	// MSSP registers 
	SSPCON1=0b00101000; // I²C master mode , SSPEN enable
	SSPSTAT=0b10000000; // Slew Rate control (SMP) 100kHz
	// baud rate 100.000kHz-> 19kHz
	SSPADD = 19; 

// serial

	TRISBbits.TRISB7=0;//TX
	TRISBbits.TRISB5=1;///RX
	ANSELHbits.ANS11=0; // RB5 digital IO
	TXSTA=0x20;// enable transmit 
	SPBRG=19; // 9600 bps
	RCSTA=0x90;//enable receive + serial port.
	TXSTAbits.TXEN=1;
	PIR1bits.RCIF=0;
    TXSTAbits.SYNC;
    RCSTAbits.SPEN;
    RCSTAbits.CREN;

	PIE1bits.RCIE=1;
	PIR1bits.RCIF=0;
	INTCONbits.GIE=1;
	INTCONbits.PEIE=1;

	c=0;
}

void writeData(){
	writeLCD(0x76);
	writeLCD(0x40); // code for sending data

}
void writeData2(){
	writeLCD(0x74);
	writeLCD(0x40); // code for sending data

}
void initLCD(){
	Delay10KTCYx(200);// wait 666ms startup  lcd
	SendByteControl(); // command
	SendByteControl2(); // command
	clearLCD();// clear row 1 and 2
	clearLCD2();
}
void StartLCD(unsigned char place ){ // 
// LCD1 
	SendStart();
	writeLCD(0x76);// i2c slave Address 
	writeLCD(0x00);// Control byte for Instruction 
	writeLCD(0x80 |place );// DDRAM Address set to place  
	SendStop();
//LCD2


}
void writeLCD( unsigned char x){

	SSPBUF= x;// i2c data
	SSPFlag();
}

void clearLCD(){

	StartLCD(0x00);

	SendStart();
	writeLCD(0x76);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();

	StartLCD(0x40);

	SendStart();
	writeLCD(0x76);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();
	
}
void StartLCD2(unsigned char place ){ // 
// LCD1 
	SendStart();
	writeLCD(0x74);// i2c slave Address 
	writeLCD(0x00);// Control byte for Instruction 
	writeLCD(0x80 |place );// DDRAM Address set to place  
	SendStop();
//LCD2


}

void clearLCD2(){

	StartLCD2(0x00);

	SendStart();
	writeLCD(0x74);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();

	StartLCD2(0x40);

	SendStart();
	writeLCD(0x74);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();
	
}


void SendByteControl(){
SendStart();
//	SendByteControl(0x76,0x00,0x34,0x0E, 0x06); // command
SSPBUF= 0x76;
SSPFlag();
SSPBUF= 0x00;
SSPFlag();
SSPBUF= 0x34;
SSPFlag();
SSPBUF= 0x0E;
SSPFlag();
SSPBUF= 0x06;
SSPFlag();
SSPBUF= 0x35;// extended
SSPFlag();
SSPBUF= 0x04;
SSPFlag();
SSPBUF= 0x10;
SSPFlag();
SSPBUF= 0x42;
SSPFlag();
SSPBUF= 0x9F;
SSPFlag();
SSPBUF= 0x34;//Regular
SSPFlag();
SSPBUF= 0x80;
SSPFlag();
SSPBUF= 0x02;
SSPFlag();
SSPBUF= 0x01;
SSPFlag();

SendStop();

}

void SendByteControl2(){
SendStart();
//	SendByteControl(0x76,0x00,0x34,0x0E, 0x06); // command
SSPBUF= 0x74;
SSPFlag();
SSPBUF= 0x00;
SSPFlag();
SSPBUF= 0x34;
SSPFlag();
SSPBUF= 0x0E;
SSPFlag();
SSPBUF= 0x06;
SSPFlag();
SSPBUF= 0x35;// extended
SSPFlag();
SSPBUF= 0x04;
SSPFlag();
SSPBUF= 0x10;
SSPFlag();
SSPBUF= 0x42;
SSPFlag();
SSPBUF= 0x9F;
SSPFlag();
SSPBUF= 0x34;//Regular
SSPFlag();
SSPBUF= 0x80;
SSPFlag();
SSPBUF= 0x02;
SSPFlag();
SSPBUF= 0x01;
SSPFlag();

SendStop();

}

void Strans(unsigned char W){
while(PIR1bits.TXIF==0); // wait until the last bit is gone
TXREG=W;

}
// The SSPIF flag is checked to ensure the byte has been sent.
void SendStart(){
SSPCON2bits.SEN=1;
SSPFlag();
}

void SendStop(){
SSPCON2bits.PEN=1; // P activeren
SSPFlag();
}
void SendRestart(){

SSPCON2bits.RSEN=1;
SSPFlag();
}
void SendByte(unsigned char  address ,unsigned char  cmdb,unsigned char data ){

SendStart();
SSPBUF= address;
SSPFlag();
SSPBUF= cmdb;
SSPFlag();
SSPBUF= data;
SSPFlag();
SendStop();
}

char ReadByte(unsigned char  address ,unsigned char  cmdb,unsigned char readaddress ){

char data;
SendStart();
SSPBUF= address;
SSPFlag();
SSPBUF= cmdb;
SSPFlag();
SendRestart();

SSPBUF=readaddress;
SSPFlag();
SSPCON2bits.RCEN=1;
SSPFlag();


Nack();
SendStop();

data=SSPBUF;
Delay10TCYx(1);


return data;

}
void I2CFAIL(){
SSPCON2bits.PEN=1;
LATCbits.LATC0=0; 
}

void ACKSTAT(){
	if ( SSPCON2bits.ACKSTAT==1){ // check ackstat
	I2CFAIL(); // STOP
	
	}
}

void Nack(){

SSPCON2bits.ACKDT=1;	
SSPCON2bits.ACKEN=1;
}
void SSPFlag() {
while(PIR1bits.SSPIF==0); // wait until sent
PIR1bits.SSPIF=0; // set low
}

Thanks
 
Last edited:

binzer

Member
Not an expert, just getting back started with this.

The int's get disabled once triggered, and get enabled once the int routine finishes.

I only see one Int handler, do both the keypad and usart use same one?

Also, the interrupt routine should be kept as short as possible, or you will miss some interrupts.
 
Last edited:

SneaKSz

Member
Hi ,

yes indeed , I only have 1 interrupt for the UART and the external interrupt , I use polling.

When the external interrupt occurs , I also set the flag back low : INTCONbits.INT0IF=0;

I thought the interrupts get disabled when interrupt the interrupt vector and set back active again when leaving the interrupt vector. So it shouldnt modify the state of the external interrupt.

I think I'll use a method to handle the interrupts.


Ive pimped the code a little bit , 2 interrupts each with their own handler


Code:
#include <p18f14k50.h> 
//#include <usart.h>
# include <string.h>
#include <stdio.h>
#include <delays.h>

	#pragma config    CPUDIV = NOCLKDIV
	#pragma config    USBDIV = OFF  
	#pragma config    FOSC = HS
	#pragma config    PLLEN = OFF 
	#pragma config    FCMEN = OFF
	#pragma config    IESO = OFF 
	#pragma config    PWRTEN = ON
	#pragma config    BOREN = ON
	#pragma config    BORV = 30
	#pragma config    WDTEN = OFF
	#pragma config    WDTPS = 1
	#pragma config    MCLRE = ON
	#pragma config    HFOFST = ON 
	#pragma config    STVREN = ON 
	#pragma config    LVP = OFF
	#pragma config    BBSIZ = OFF 
	#pragma config    XINST = OFF
	#pragma config    CP0 = ON 
	#pragma config    CPB = ON 
	#pragma config    CPD = ON 
	#pragma config    WRT1= ON 
	#pragma config    WRTB = ON 
	#pragma config    WRTC = ON 
	#pragma config    WRTD = ON 
	#pragma config    EBTRB = ON

  #define SCL TRISBbits.TRISB6 // SCL line
  #define SDA TRISBbits.TRISB4 // SDA line 

#define IODIR       0x00
#define IPOL        0x01
#define GPINTEN     0x02
#define DEFVAL      0x03
#define INTCON      0x04
#define IOCON       0x05
#define GPPU        0x06
#define INTF        0x07
#define INTCAP      0x08
#define GPIO        0x09
#define OLAT        0x0A



// methoden
void init(); 
void SendStart();
void SendStop();
void SendRestart();
void SendByte(unsigned char  address ,unsigned char  cmdb,unsigned char data );
char ReadByte(unsigned char  address ,unsigned char  cmdb,unsigned char readaddress );
void ACKSTAT();
void I2CFAIL();
void SSPFlag();
void Nack();


// LCD

void SendByteControl();
void SendByteControl2();
void initLCD();
void clearLCD();
void writeLCD(unsigned char x);
void StartLCD(unsigned char place);
void clearLCD2();
void StartLCD2(unsigned char place);
void writeData();
void writeData2();


void Strans(unsigned char data);


void UARTHandler();
void KeypadHandler();

int i=0;
unsigned char result[];
unsigned char keypad; 
unsigned char lcdchar;
unsigned char received[];
unsigned int c;
unsigned char dummy;
void InterruptHandlerHigh (void);

// High priority interrupt vector

#pragma code InterruptVectorHigh = 0x08 // comp mode default vector
void InterruptVectorHigh (void)
{
  _asm
    goto InterruptHandlerHigh //jump to interrupt routine
  _endasm
}


//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerHigh

	void InterruptHandlerHigh ()
	{


				if(INTCONbits.INT0IF==1)
					{				
					KeypadHandler();
				 }	// end if

// received[1]= RCREG;
//c=c+1 ==>>>>>>>>>>>>> werkt NIET C wordt = RCREG , raar
		if(PIR1bits.RCIF)
		{
	UARTHandler();
		}// end if RCIF

	}
void main(void){
	init();// setup
	initLCD();
	Delay10TCYx(3);// wait 333ms startup GPIO	

     SendByte(0x40,IODIR,0xF0); //WriteAddress iodir , high nibble is input      
     Delay10TCYx(1);  
     SendByte(0x40,GPIO,0xF0); // toggle the outputs  
     Delay10TCYx(1);  
     SendByte(0x40,IOCON,0b00110010);  // active high  
     Delay10TCYx(1);  
     SendByte(0x40,INTCON,0xF0); // compare to def val  
     Delay10TCYx(1);  
     SendByte(0x40,IPOL,0x00); // same pol   
     Delay10TCYx(1);  
     SendByte(0x40,DEFVAL,0xF0);// def val to compare  
     Delay10TCYx(1);  
     SendByte(0x40,GPINTEN,0xF0); // enable input pin for inter on change  

while(1){
// wait
	}// end while		
}// end main

	void init(){
	ADCON1=0x07;//Configure A/D
	TRISCbits.TRISC0=1; //  INT0
	TRISCbits.TRISC1=0; // INT1 PIN
	
	INTCONbits.INT0IE=1;
//	INTCON3bits.INT1IP=1;// high prio
	INTCONbits.INT0IF=0;
	INTCON2bits.INTEDG0=1;// risiing edge.

	ANSELbits.ANS4=0; // digital IO RC0
	ANSELbits.ANS5=0; // digital IO RC1
	CM1CON0bits.C1ON=0;// Disable compare
	CM2CON0bits.C2ON=0;// Disable compare

	SDA=1; // input
	SCL=1;// input
	// MSSP registers 
	SSPCON1=0b00101000; // I²C master mode , SSPEN enable
	SSPSTAT=0b10000000; // Slew Rate control (SMP) 100kHz
	// baud rate 100.000kHz-> 19kHz
	SSPADD = 19; 

// serial

	TRISBbits.TRISB7=0;//TX
	TRISBbits.TRISB5=1;///RX
	ANSELHbits.ANS11=0; // RB5 digital IO
	TXSTA=0x20;// enable transmit 
	SPBRG=19; // 9600 bps
	RCSTA=0x90;//enable receive + serial port.
	TXSTAbits.TXEN=1;
	PIR1bits.RCIF=0;
    TXSTAbits.SYNC;
    RCSTAbits.SPEN;
    RCSTAbits.CREN;

	PIE1bits.RCIE=1;
	PIR1bits.RCIF=0;
	INTCONbits.GIE=1;
	INTCONbits.PEIE=1;

	c=0;
}
void UARTHandler(){
		switch( c )
			     {
			case 0 : // address
				received[0]=RCREG;
				if ( received[0]==0x38) received[0]=0x08;
				c++;
				break;
			case 1 : // first value
				received[1]=RCREG;
				c++;
				break;
			case 2: 	// second value		
				received[2]=RCREG;
				c=0;

					break;
			}

			if(!(RCSTAbits.OERR|RCSTAbits.FERR))
			{
					Strans('#');//start
					Strans('T');
					Strans('E');
					Strans('S');
					Strans('T');
					Strans('&');//end
			}

			else  
			{
	
				if (RCSTAbits.OERR) 
					{
					unsigned char h;
				     //Overrun Error
				    RCSTAbits.CREN = 0; //Reset error
				    h = RCREG; //Flush buffer
				    RCSTAbits.CREN = 1;
					LATCbits.LATC1=0;
						Strans('E');
						Strans('R');
						Strans('R');
						Strans('O');
						Strans('R');
			
				    }
				if (RCSTAbits.FERR) 
					{
				     //Frame Error
					unsigned char j ;
				     j = RCREG; //Reset error
					LATCbits.LATC0=0;
						Strans('E');
						Strans('R');
						Strans('R');
						Strans('O');
						Strans('R');
				    }
			 }

		dummy = RCREG;
		dummy=dummy+128;// adaption to LCD from ascii

		clearLCD();
		StartLCD(0x00);// start ROW 0 
		SendStart();
		writeData();					
		// first row ABC
		writeLCD(dummy);
		SendStop();

}




void KeypadHandler(){


				  		 result[0]= ReadByte(0x40,INTCAP,0x41);  
			// flip
					     SendByte(0x40,GPPU,0x0F); // enable input pin for inter on change 
					     Delay10TCYx(1);   
					     SendByte(0x40,IODIR,0x0F); //WriteAddress iodir , high nibble is input      
					     Delay10TCYx(1);  
					     SendByte(0x40,GPIO,0x0F); // toggle the outputs  
					     Delay10TCYx(1);   
					     SendByte(0x40,INTCON,0x0F); // compare to def val  
					     Delay10TCYx(1);  
					     SendByte(0x40,IPOL,0x00); // same pol   
					     Delay10TCYx(1);  
					     SendByte(0x40,DEFVAL,0x0F);// def val to compare  
					     Delay10TCYx(1);  
					     SendByte(0x40,GPINTEN,0x0F); // enable input pin for inter on change  
		
			       while ( PORTCbits.RC0==1)// while INT input is high
						{
						 result[1]=ReadByte(0x40,GPIO,0x41);  // read this register because this contains the actual value of the IO pins 
		// the INTCAP contains the value of the IO when an interrupt happens
							while ( PORTCbits.RC0==1){
							unsigned dum ;
						    Delay10TCYx(1); 		
							dum =ReadByte(0x40,GPIO,0x41);
							}
				     	}
		// the INTCAP contains the value of the IO when an interrupt happens
					INTCONbits.INT0IF=0;
					result[2]=result[0]|result[1];
				//		if ( result[2]==0xED)	LATCbits.LATC0=1; // SET HIGH
		// get the number	
					     switch( result[2] )
					     {
					//first row
					        case 0xEE : keypad='1'; lcdchar=0xB1;
					                   break;
					        case 0xED  :keypad='2';lcdchar=0xB2;
						           break;
							case 0xEB  :keypad='3';lcdchar=0xB3;
						           break;
					        case 0xE7 : keypad='F';lcdchar=0xC6;
						           break;
					//second row
							case 0xDE:  keypad='4'; lcdchar=0xB4;
						           break;
							case 0xDD:  keypad='5'; lcdchar=0xB5;
						           break;
							case 0xDB:  keypad='6'; lcdchar=0xB6;
						           break;
							case 0xD7:  keypad='E';lcdchar=0xC5;
						           break;
					//3rd row
							case 0xBE:  keypad='7'; lcdchar=0xB7;
						           break;
							case 0xBD:  keypad='8'; lcdchar=0xB8;
						           break;
							case 0xBB:  keypad='9'; lcdchar=0xB9;
						           break;
							case 0xB7:  keypad='D'; lcdchar=0xC4;
						           break;
					
					//4th row
							case 0x7E:  keypad='A';lcdchar=0xC1; 
						           break;
							case 0x7D:  keypad='0'; lcdchar=0xB0;
						           break;
							case 0x7B:  keypad='B';lcdchar=0xC2;
						           break;
							case 0x77:  keypad='C'; ;lcdchar=0xC3;
						           break;
							default  : keypad=0;  lcdchar=0xC3;
					                   break;
						}
		
		// write char :
		
		
					StartLCD(0x00);// start ROW 0 
					SendStart();
					writeData();
				
				// first row ABC
					writeLCD(lcdchar);
					SendStop();
					Strans(keypad);
		// set back
		     SendByte(0x40,IODIR,0xF0); //WriteAddress iodir , high nibble is input      
		     Delay10TCYx(1);  
		     SendByte(0x40,GPIO,0xF0); // toggle the outputs  
		     Delay10TCYx(1);  
		     SendByte(0x40,IOCON,0b00110010);  // active high  
		     Delay10TCYx(1);  
		     SendByte(0x40,INTCON,0xF0); // compare to def val  
		     Delay10TCYx(1);  
		     SendByte(0x40,IPOL,0x00); // same pol   
		     Delay10TCYx(1);  
		     SendByte(0x40,DEFVAL,0xF0);// def val to compare  
		     Delay10TCYx(1);  
		     SendByte(0x40,GPINTEN,0xF0); // enable input pin for inter on change  
		
		


}
void writeData(){
	writeLCD(0x76);
	writeLCD(0x40); // code for sending data

}
void writeData2(){
	writeLCD(0x74);
	writeLCD(0x40); // code for sending data

}
void initLCD(){
	Delay10KTCYx(200);// wait 666ms startup  lcd
	SendByteControl(); // command
	SendByteControl2(); // command
	clearLCD();// clear row 1 and 2
	clearLCD2();
}
void StartLCD(unsigned char place ){ // 
// LCD1 
	SendStart();
	writeLCD(0x76);// i2c slave Address 
	writeLCD(0x00);// Control byte for Instruction 
	writeLCD(0x80 |place );// DDRAM Address set to place  
	SendStop();
//LCD2


}
void writeLCD( unsigned char x){

	SSPBUF= x;// i2c data
	SSPFlag();
}

void clearLCD(){

	StartLCD(0x00);

	SendStart();
	writeLCD(0x76);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();

	StartLCD(0x40);

	SendStart();
	writeLCD(0x76);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();
	
}
void StartLCD2(unsigned char place ){ // 
// LCD1 
	SendStart();
	writeLCD(0x74);// i2c slave Address 
	writeLCD(0x00);// Control byte for Instruction 
	writeLCD(0x80 |place );// DDRAM Address set to place  
	SendStop();
//LCD2


}

void clearLCD2(){

	StartLCD2(0x00);

	SendStart();
	writeLCD(0x74);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();

	StartLCD2(0x40);

	SendStart();
	writeLCD(0x74);
	writeLCD(0x40);// Control byte for Data 
// first ROW
	for ( i=0 ; i<=15;i++){
	writeLCD(0xA0);// Control byte for Data 
	}
	SendStop();
	
}


void SendByteControl(){
SendStart();
//	SendByteControl(0x76,0x00,0x34,0x0E, 0x06); // command
SSPBUF= 0x76;
SSPFlag();
SSPBUF= 0x00;
SSPFlag();
SSPBUF= 0x34;
SSPFlag();
SSPBUF= 0x0E;
SSPFlag();
SSPBUF= 0x06;
SSPFlag();
SSPBUF= 0x35;// extended
SSPFlag();
SSPBUF= 0x04;
SSPFlag();
SSPBUF= 0x10;
SSPFlag();
SSPBUF= 0x42;
SSPFlag();
SSPBUF= 0x9F;
SSPFlag();
SSPBUF= 0x34;//Regular
SSPFlag();
SSPBUF= 0x80;
SSPFlag();
SSPBUF= 0x02;
SSPFlag();
SSPBUF= 0x01;
SSPFlag();

SendStop();

}

void SendByteControl2(){
SendStart();
//	SendByteControl(0x76,0x00,0x34,0x0E, 0x06); // command
SSPBUF= 0x74;
SSPFlag();
SSPBUF= 0x00;
SSPFlag();
SSPBUF= 0x34;
SSPFlag();
SSPBUF= 0x0E;
SSPFlag();
SSPBUF= 0x06;
SSPFlag();
SSPBUF= 0x35;// extended
SSPFlag();
SSPBUF= 0x04;
SSPFlag();
SSPBUF= 0x10;
SSPFlag();
SSPBUF= 0x42;
SSPFlag();
SSPBUF= 0x9F;
SSPFlag();
SSPBUF= 0x34;//Regular
SSPFlag();
SSPBUF= 0x80;
SSPFlag();
SSPBUF= 0x02;
SSPFlag();
SSPBUF= 0x01;
SSPFlag();

SendStop();

}

void Strans(unsigned char W){
while(PIR1bits.TXIF==0); // wait until the last bit is gone
TXREG=W;

}
// The SSPIF flag is checked to ensure the byte has been sent.
void SendStart(){
SSPCON2bits.SEN=1;
SSPFlag();
}

void SendStop(){
SSPCON2bits.PEN=1; // P activeren
SSPFlag();
}
void SendRestart(){

SSPCON2bits.RSEN=1;
SSPFlag();
}
void SendByte(unsigned char  address ,unsigned char  cmdb,unsigned char data ){

SendStart();
SSPBUF= address;
SSPFlag();
SSPBUF= cmdb;
SSPFlag();
SSPBUF= data;
SSPFlag();
SendStop();
}

char ReadByte(unsigned char  address ,unsigned char  cmdb,unsigned char readaddress ){

char data;
SendStart();
SSPBUF= address;
SSPFlag();
SSPBUF= cmdb;
SSPFlag();
SendRestart();

SSPBUF=readaddress;
SSPFlag();
SSPCON2bits.RCEN=1;
SSPFlag();


Nack();
SendStop();

data=SSPBUF;
Delay10TCYx(1);


return data;

}
void I2CFAIL(){
SSPCON2bits.PEN=1;
LATCbits.LATC0=0; 
}

void ACKSTAT(){
	if ( SSPCON2bits.ACKSTAT==1){ // check ackstat
	I2CFAIL(); // STOP
	
	}
}

void Nack(){

SSPCON2bits.ACKDT=1;	
SSPCON2bits.ACKEN=1;
}
void SSPFlag() {
while(PIR1bits.SSPIF==0); // wait until sent
PIR1bits.SSPIF=0; // set low
}
Thx
 
Last edited:
Status
Not open for further replies.

EE World Online Articles

Loading
Top