SAMD20 External interrupts

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
I am using a SAMD20 to pick up the edges of a square wave created by a linear encoder.  Using the ASF External Interrupt method this is working in as far as the interrupt is being detected: I have put a blink signal in the interrupt function to check.         I am aiming to
 increment or decrement  a counter depending on the state of another square wave in quadrature.

 

void extint_detection_callback(edge)
{
	if (port_pin_get_input_level(PIN_PA11) == 1) {(edge)++;	} 
	else if (port_pin_get_input_level(PIN_PA11) == 0) { (edge)--;	}
	
	blink();
	
}

I have also got a display function working correctly in the main function.  My difficulty is getting some communication between the two.  Clearly the edges of the square wave are unpredictable and vary in speed whereas the display loop can be regular.

 

while (true) {
		
	
		MeterToDisplay(edge);
		
		delay_s(0.1);
	
	
	        }

I have tried all sorts of methods to create a counter variable which is accessible to both functions.  I have put the interrupt function with other external interrupt functions in its own library and this may be part of the problem but even when I put the detection function in the same file as main there is still no communication.  

 

The counter variable I have made global by declaring before the main function.  I have also set up pointers, because I gather the only way of getting a variable to hold its value outside a function is to use pointers as arguments.   Whenever I use the pointer as parameter the detection function seems to hang.  I have tried to overcome the problem by making the counter volatile.  

 

volatile int edge;
int *PntEdge = &edge;

If anybody has some wisdom on the subject of using variables across a program where it is not simply a question of a function calling another function, I would appreciate it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Making edge as a volatile global variable works.

 

But  port_pin_get_input_level() returns a bool, not an int.

 

Note that  you should not call port_pin_get_input_level() twice (value of the port may change between the 2 calls)

 

Does something like that work:

void extint_detection_callback(edge)
{
	if (port_pin_get_input_level(PIN_PA11)) {(edge)++;	} 
	else { (edge)--;	}
	
	blink();
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for this.  I am realizing that there are further points where my logic is falling down not to mention my poor knowledge of pointers, but I am making progress.  I aim to use a UART to show me what the numbers are doing at each point, but I am waiting for a PCB to turn up so I can get 3v data from the SAMD onto the PC RS232 port.

 

I have written a little function which will maintain the information between the external interrupt callback function and the display function.

void keep_count(int c, int * d) 


{
	static int total;
	total + c;
	*d =  total;
}

The interrupt callback function will feed in c depending on the quadrature result.  The display function will pull out d ( total ) from it when it calls it.

The callback function now looks like:

void extint_detection_callback(void)
{
	int quadr_res, dist ;
	if (port_pin_get_input_level(PIN_PA11)) { quadr_res = 1 ;	}
	else { quadr_res = -1 ;	}
	keep_count(quadr_res, &dist);    
	blink();
	
}