Jump to content

Recommended Posts

Hey guys I am working on an extremely simple project, but I am beating my head trying to get it to work the way I want. If you look down you will see that I call the delay_s function two times. I did this because on the final version of the software I will have to delay for a few minutes, therefore I will go over the 255 maximum for the delay functions (unless this has changed). What is happening is that my delay is twice what it should be. I have commented out the second delay function call and still with a single function call I am getting twice the time.

 

I am sure there is something simple that I am overlooking but it is driving me nuts.

 

//----------------INITIATE-------------------
void initiate(void)
{
option_reg = 0x00; // bit 7=0 enable pullups
  // bit 6=0 don't care
  // bit 5=0 Fosc/4 = tmr0 clock
  // bit 4=0 don't care
  // bit 3=0 prescaler assigned to tmr0
  // bits 2-0=000 prescale = 1:2 (won't use)		  

cm1con0 &= 0x7F; //turn comparator
cm2con0 &= 0x7F; //features off		  

ansel = 0x00;	//porta bits all set as digital I/O's
wpua = 0x1B;  //enable all pullups on porta
ioca = 0x10;  //interrupt on change enabled for porta bit 4

trisa = 0x3F;	//bit 7-6 = unimplemented
  //bit 5 = spare input #2
  //bit 4 = PushButton input (interrupt on change)
  //bit 3 = MCLR
  //bit 2 = MIN 2 input (seconds to run bit 2)
  //bit 1 = MIN 1 input (seconds to run bit 1)
  //bit 0 = MIN 0 input (seconds to run bit 0)

trisc = 0x20;	//bit 7-6 = unimplemented	
  //bit 5 = spare input #1			
  //bit 4 = spare output #3
  //bit 3 = spare output #2
  //bit 2 = spare output #1
  //bit 1 = active high output
  //bit 0 = active low output	  

portc = 0x01;	//outputs initially off (active high = 0, active low = 1)

intcon |= 0x88;  //turn on global & change on porta interrupts
}

 

//PIC16F610
#include <system.h>
#include "initialization.h"
#pragma CLOCK_FREQ 4000000;
//***********************************************
//USE THIS CONFIGURATION FOR INTERNAL OSCILLATOR
#pragma DATA 0x2007, 0xFC64
/* device configuration block
;bit 15-10 = 111111 -> unimplemented (read as '1')
;bit 9-8 = 00 -> BOR disabled
;bit 7 = 0 -> 4MHz internal clock
;bit 6 = 0 -> program memory code protect disabled
;bit 5 = 1 -> MCLR pin is MCLR function
;bit 4 = 0 -> PWRT enabled
;bit 3 = 0 -> WDT disabled
;bit 2-0 = 100 -> INTOSCIO oscillator
************************************************/
#define vac_on (portc |= 0x02)
#define vac_on2 (portc &= 0xFE)
#define vac_off (portc &= 0xFD)
#define vac_off2 (portc |= 0x01)
#define button_pressed ((porta|0xEF) == 0xEF)
bit start_timer = 0;
unsigned char rotary = 0,
 tick = 0,
 tock = 0;


//------------INTERRUPT HANDLER--------------
//interrupt occurs when RA4 has changed state
//when this interrupt occurs the micro is "woken"
void interrupt(void)
{
intcon &= 0xFE;  //clear interrupt flag
rotary = porta;
start_timer = 1;
}
//----------------------------------------------------------------------
void main()
{
initiate();

while(1)
{
 if(start_timer == 1)
 {
  intcon &= 0x7F; //disable interrupts

  rotary &= 0x07; //only need bits 0-2

  /*
  Rotary Input Run Time (minutes)
  111	0
  110	1
  101	2
  100	3
  011	4
  010	5
  001	0
  000	0
  */

  switch(rotary)
  {
case 0:
 tick = 0;
 tock = 0;
 break;

case 1:
 tick = 0;
 tock = 0;
 break;

case 2:
 tick = 25;//150;
 tock = 25;//150;
 break;

case 3:
 tick = 20;//120;
 tock = 20;//120;
 break;

case 4:
 tick = 15;//90;
 tock = 15;//90;
 break;

case 5:
 tick = 10;//60;
 tock = 10;//60;
 break;

case 6:
 tick = 5;//30;
 tock = 5;//30;
 break;

case 7:
 tick = 0;
 tock = 0;
 break;  
  }

  if(tick > 0)
  {
vac_on;
vac_on2;

delay_s(tick); //activate output for amount of time
	//determined by rotary switch inputs
delay_s(tock); //delay_s function uses char (8-bits)
	//therefore it must be called twice
	//if time is greater than 255secs
vac_off;
vac_off2;
  }

  start_timer = 0; //reset flag
  intcon |= 0x88;  //turn on global & change on porta interrupts  
  sleep(); //go to sleep until interrupt on change occurs
  nop();  //when it awakens it will perform this before going to ISR
 }
}
}

Link to post
Share on other sites

Try removing the semi-colon from the #pragma and see if that makes any difference.

 

#pragma CLOCK_FREQ 4000000

 

The IDE may be using a default if the pragma is not understood.

 

Cheers

 

Reynard

Link to post
Share on other sites

Try removing the semi-colon from the #pragma and see if that makes any difference.

 

#pragma CLOCK_FREQ 4000000

 

The IDE may be using a default if the pragma is not understood.

 

Cheers

 

Reynard

I tried this with no changes. If it will help to point out the problem... the following code works. It accomplishes the same goal but I wanted to use sleep mode and have to find out what in the world is keeping the original code from working correctly.

 

//----------------INITIATE-------------------
void initiate(void)
{
option_reg = 0x00; // bit 7=0 enable pullups
  // bit 6=0 don't care
  // bit 5=0 Fosc/4 = tmr0 clock
  // bit 4=0 don't care
  // bit 3=0 prescaler assigned to tmr0
  // bits 2-0=000 prescale = 1:2 (won't use)		   

cm1con0 &= 0x7F; //turn comparator
cm2con0 &= 0x7F; //features off		   

ansel = 0x00;    //porta bits all set as digital I/O's
wpua = 0x1B;  //enable all pullups on porta
//ioca = 0x10;  //interrupt on change enabled for porta bit 4

trisa = 0x3F;    //bit 7-6 = unimplemented
  //bit 5 = spare input #2
  //bit 4 = PushButton input (interrupt on change)
  //bit 3 = MCLR
  //bit 2 = MIN 2 input (seconds to run bit 2)
  //bit 1 = MIN 1 input (seconds to run bit 1)
  //bit 0 = MIN 0 input (seconds to run bit 0)

trisc = 0x20;    //bit 7-6 = unimplemented	 
  //bit 5 = spare input #1			
  //bit 4 = spare output #3
  //bit 3 = spare output #2
  //bit 2 = spare output #1
  //bit 1 = active high output
  //bit 0 = active low output	  

portc = 0x01;    //outputs initially off (active high = 0, active low = 1)

//intcon |= 0x88;  //turn on global & change on porta interrupts
}

//PIC16F610
#include <system.h>
#include "initialization.h"
#pragma CLOCK_FREQ 4000000;
//***********************************************
//USE THIS CONFIGURATION FOR INTERNAL OSCILLATOR
#pragma DATA 0x2007, 0xFC64
/* device configuration block
;bit 15-10 = 111111 -> unimplemented (read as '1')
;bit 9-8 = 00 -> BOR disabled
;bit 7 = 0 -> 4MHz internal clock
;bit 6 = 1 -> program memory code protect disabled
;bit 5 = 1 -> MCLR pin is MCLR function
;bit 4 = 0 -> PWRT enabled
;bit 3 = 0 -> WDT disabled
;bit 2-0 = 100 -> INTOSCIO oscillator
************************************************/
#define vac_on (portc.0 = 0)
#define vac_on2 (portc.1 = 1)
#define vac_off (portc.0 = 1)
#define vac_off2 (portc.1 = 0)
#define button_pressed (porta.4 == 0)
#define button_not_pressed (porta.4 == 1)
//----------------------------------------------------------------------
void main()
{
initiate();

delay_ms(30);

while(1)
{
 if(button_pressed) //assure button is pressed
 {  
  /*
  Rotary Input Run Time (minutes)
  111	0
  110	1
  101	2
  100	3
  011	4
  010	5
  001	0
  000	0
  */

  if((porta.2==0)&&(porta.1==1)&&(porta.0==0))
  {
 vac_on;
 vac_on2;
 delay_s(50);
 vac_off;
 vac_off2;
  }
  else if((porta.2==0)&&(porta.1==1)&&(porta.0==1))  
  {	
 vac_on;
 vac_on2;
 delay_s(40);
 vac_off;
 vac_off2;
  }
  else if((porta.2==1)&&(porta.1==0)&&(porta.0==0))  
  {	
 vac_on;
 vac_on2;
 delay_s(30);
 vac_off;
 vac_off2;
  }	

  else if((porta.2==1)&&(porta.1==0)&&(porta.0==1))  
  {
 vac_on;
 vac_on2;
 delay_s(20);
 vac_off;
 vac_off2;	
  }

  else if((porta.2==1)&&(porta.1==1)&&(porta.0==0))  
  {
 vac_on;
 vac_on2;
 delay_s(10);
 vac_off;
 vac_off2;  
  }  
 }
}
}

Edited by jwilson
Link to post
Share on other sites

Try reading the port to clear the mismatch condition before clearing the interrupt flag.

 

void interrupt(void)
{
rotary = porta;	 // Clear port mismatch
intcon.RAIF = 0;  //clear interrupt flag
start_timer = 1;
}

 

Cheers

 

Reynard

Link to post
Share on other sites

Reynard, that didn't fix it either. But I did find something that did. Maybe you can shed some light as to exactly why.

 

Simply removing the interrupt disable command solved my problem. Does making GIE=0 effect the delay_s routine?

 

//intcon &= 0x7F; //disable interrupts

Link to post
Share on other sites

I just tried only disabling the RAIF bit and it works also. I can only assume that bringing the GIE = 0 affects the delay_s function. I really would like conformation that I am not insane though. Haha

Link to post
Share on other sites

Using a push button means you will get a double interrupt. Push in and release unless you have some code to ignore one of the states. You may also need to add some debouncing for the button.

 

Global interrupt is something that really should never be disabled unless there is a real need to such as powering down.

Disabling global interrupt flag does not stop interrupts being latched and you could miss something important by doing so.

 

Could you not just poll the push button. Do you have to go to sleep ?

 

The timer functions are software loops and don't rely on interrupts or timers.

 

Consider using one of the PIC timers to control the timeouts. Software timers are blocking functions. Yuk!

 

Cheers

 

Reynard

Link to post
Share on other sites

Thanks for the clarification. I didn't even think about how the pushbutton would call the interrupt twice.

 

I do not have to go to sleep, the second version I posted works great and is less code. I just wanted to know what I was doing wrong and why it wouldn't work.

 

In the past I have always implemented an interrupt using the timer. On the final version of this project I also plan to use a timer. The main reason for my questions were to learn about what I was doing wrong and how to solve them in case it ever presents itself again.

 

Again thanks for the help, you cleared it up for me.

Link to post
Share on other sites

Hi

 

I found a couple of very well explained tutorials on reading and debouncing switches and managing "sleep mode" in here

http://www.gooligum.com.au/tut_baseline_C.html

Mostly basic stuff for me, but I was helping a friend and noticed a lot of those small details that sometimes cost us a serious amount of time.

 

 

Best regards

Jorge

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