Jump to content

Problems With Combinin Ioc With Usart, Help Please~~


Recommended Posts

I am trying to implement IOC and USART feature together on PIC16f690. It suppose to work like this: Once the IOC happens, it should go to interrupt routine and light up the led. And then when it goes back to while loop in main, PIC will receive a character using USART (in my code:unsinged char ss=getc()). But it works very weird like this: before any IOC happens, it stays in while loop in main(which is right), but after one interrupt occurs, it stays in the interrupt routine,never goes back to while loop in main. But if I comment out " unsinged char ss=getc() " (the receive code), the IOC works perfectly. So I think it's the reception cause the problem. I just don't understand how come USART could screw up IOC. Can anyone help me?? I will really really appreicate any help!!!

 

Regards,

Baixue

 

 

 

#include <system.h>
#pragma DATA 0x2007, _HS_OSC & _WDT_OFF

// Use portb.4 as IOC port; portb.7 & 5 are USART pins

bool IR_event=false;
unsigned char ss;

void initi_status()
{	   
	baudctl=0x00;//set the baud rate control register
	set_bit(rcsta,7);//set SPEN bit,serial port enabled
	spbrg = 103;//set the baud rate as 2400, brgh=1
	ansel =0x00; // the fllowing two used to turn off analouge modle
	anselh =0x00;

	trisb=0x11; //congigure the RX/TX port

	clear_bit(txsta,6); // 8 bit transmission
	set_bit(txsta,5); // enable the transmission
	clear_bit(txsta,4); // asychronous model
	set_bit(txsta,2); // high speed baud rate

	clear_bit(rcsta,6);// 8 bits reception
	set_bit(rcsta,4);// enable continous receiving once asynchronous is selected


	trisc=0x00;
	portc=0x00;

}

char getc(void)
{

while (pir1.5==0)
{
}// checked if the receiving is done
return rcreg;
}

void main()
{
			initi_status();

trisc=0x00; //configure portc as output
portc=0x00;//initialize portc
trisb=0xff; // configure portb as input, we are going to use portb.6&4 as IOC,save .7& 5 as RX/TX

iocb=0x10; //enable portb. 4 IOC

set_bit(intcon,7);//enable all interrupts
set_bit(intcon,6);//enable all peripheral interrupts
clear_bit(intcon,5);//disable the timer0 interrupt
clear_bit(intcon,4);// disable the RA2/INT exteranl interrupt
set_bit(intcon,3);//enable the interrupt(RABIE)


while(1)
{
				delay_ms(200);
	portc=0x00;

	while(IR_event)
	{
				   delay_ms(300);
				   IR_event=false;
				  [size="6"]ss=getc();[/size] // this reception code screws up the IOC,but how come? why?
	}
}
}


void interrupt()
{   
 IR_event=true;
 portc=0x01;//light up led

 unsigned char rr=portb;//read portb to clear the interrupt
 clear_bit(intcon,0);// clear the interrupt flag(RABIF)	

}

Link to post
Share on other sites

Remember that delay_ms(t) takes only an unsigned char therefore the maximum value is 255 otherwise you will be short changed.

 

Also, use #pragma CLOCK_FREQ 4000000 to tell the compiler your clock frequency so it can calculate the correct delays. You can set the clock rate in the IDE, but it is more complete to use the pragma.

 

Although you only have a single interrupt source, get into the habit of qualifying your interrupt flags:

  if (intcon.RABIF) {
...
 }

 

or if you turn some interrupt on and off within your program:

  if (intcon.RABIE && intcon.RABIF) {
...
 }

 

Cheers

 

Reynard

Link to post
Share on other sites

This time I can see the output from Rs232 so it gives a better view of where the programs stops.

everytime I start to run the program, it works well for the first time it get interrupted, the output shown is like this: start start start start end end start start........... . But when I give it a second interrupt ,it shows like this : start start end end start(it stops here, nothing shows up), when I give it a interrupt again, it only shows : end end. And it continues to show "end end" , never shows "start" again , which means it never goes back to main.

 

So why it alwasy works well for the very first interrupt?(goes to interrupt routine and then go back to main) ,but after that, it is screwed up. My code is here

 

Thank you a lot!

	 
#include <system.h>
#pragma DATA 0x2007, _HS_OSC & _WDT_OFF
#pragma CLOCK_FREQ 4000000


bool IR_event=false;
unsigned char ss;
void initi_status()
{	   
	baudctl=0x00;//set the baud rate control register
	set_bit(rcsta,7);//set SPEN bit,serial port enabled
	spbrg = 207;//set the baud rate as 1200, brgh=1
	ansel =0x00; // the fllowing two used to turn off analouge modle
	anselh =0x00;

	trisb=0x11; //congigure the RX/TX port

	clear_bit(txsta,6); // 8 bit transmission
	set_bit(txsta,5); // enable the transmission
	clear_bit(txsta,4); // asychronous model
	set_bit(txsta,2); // high speed baud rate

	clear_bit(rcsta,6);// 8 bits reception
	set_bit(rcsta,4);// enable continous receiving once asynchronous is selected


	trisc=0x00;
	portc=0x00;

}


void putc(char c) 
{

txreg=c; // put the input into txreg register

while ((txsta&0x02) == 0){

} //check if transmission is done or not

}

void put(char *string)
{   
do
{
	char s = *string;
	if( s == 0 ) // end of string
		break;

	putc( s );	// Send the string refered by pointer		
	string++;
}
while( 1 );
}

char getc(void)
{

while (pir1.5==0)
{
}// checked if the receiving is done
return rcreg;
}

void main()
{
initi_status();

trisc=0x00; //configure portc as output
portc=0x00;//initialize portc
trisb=0xff; // configure portb as input, we are going to use portb.6&4 as IOC,save .7& 5 as RX/TX

iocb=0x10; //enable portb.6 & 4 IOC

set_bit(intcon,7);//enable all interrupts
set_bit(intcon,6);//enable all peripheral interrupts
clear_bit(intcon,5);//disable the timer0 interrupt
clear_bit(intcon,4);// disable the RA2/INT exteranl interrupt
set_bit(intcon,3);//enable the interrupt(RABIE)


ansel =0x00; // the fllowing two used to turn off analouge modle
anselh =0x00;


while(1)
{
							delay_s(1);
		portc=0x00;
	put("start ");


	if(IR_event)
	{

	   	IR_event=false;
		ss=getc();


	}

}
}

void interrupt()
{   
  IR_event=true;

  portc=0x01;
  unsigned char v=portb;//read portb
  clear_bit(intcon,0);// clear the interrupt flag(RABIF)	
  put("end! ");
}

Link to post
Share on other sites

Hi Baixue,

 

The compiler should have warned you that you are calling "put(s)" from different threads. It is OK to do this if you know you have it secure so that put(s) cannot be called simultaneously (not in your case though).

 

Does your IOC switch input have a pull-up resistor on it. If not you could be picking up alot of noise when the switch goes o/c. Use the internal weak pull-ups if you don't.

 

You will also have to consider the possibility of contact bounce from your switch. This can cause multiple IOC interrupts giving double output strings.

 

You may want to consider not using the IOC feature and instead poll the switch, say every 10ms, and incorporate some form of contact bounce elimination method.

 

IOC is nice but has its problems. To quote the manual: "If a change on the I/O pin should occur when the read operation is being executed (start of the Q2 cycle), then the RABIF interrupt flag may not get set."

 

IOC is good if you have some form of portable device that sits in sleep (very low power) mode waiting for someone to press the ON button or keypad to awaken the device for use.

 

Cheers

 

Reynard

Link to post
Share on other sites
To quote the manual: "If a change on the I/O pin should occur when the read operation is being executed (start of the Q2 cycle), then the RABIF interrupt flag may not get set."

 

Hi Reynard,

 

I think the problem must be like the quote says. But I still want to check the USART interrupt feature, maybe~~I accidently enable the USART interrupt somewhere, so it stays in interrupt routine. By the way, I am using a IR sensor as the source of IOC interrupt instead of a switch, so there are not much noise.

 

And also I am wondering if I connect the IR sensor to one of the I/O ports instead of IOC port, and check every 10ms to see if there is a change on the I/O port, that might work, isn't it? Thanks a lot!

 

Cheers,

Baixue

Link to post
Share on other sites

Take note that your "getc()" function is a blocking function. That is, it will not return until it receives a char from the serial port. That is probably why you are not outputting "start" every 1 second. You are waiting for that character to arrive. IOC Interrupts are still active so you are still outputting "ends".

 

The IOC pins are not Schmitt triggers so you need a fairly fast rise and fall time from your IR sensor. A possible cause of double "ends". A bit like contact bounce.

 

Cheers

 

Reynard

Link to post
Share on other sites
  • 2 weeks later...
Take note that your "getc()" function is a blocking function. That is, it will not return until it receives a char from the serial port. That is probably why you are not outputting "start" every 1 second. You are waiting for that character to arrive. IOC Interrupts are still active so you are still outputting "ends".

 

The IOC pins are not Schmitt triggers so you need a fairly fast rise and fall time from your IR sensor. A possible cause of double "ends". A bit like contact bounce.

 

Cheers

 

Reynard

 

 

I've been trying to fix the getc() block function for the past week. But it still doesn't work as I want it to be. So I decide to use two PICs for this, one for IOC,one for USART. Hope it will work this way. Thank you so much for all the help!!!!

 

Cheers,

Baixue

Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...