Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
7 years, 2 months ago.
New to mbed trying to use interrupts on pin inputs.
I have a NUCLEO-F411RE. I am looking to interrupt on a few GPIO pins so I can record if they accidentally drop out for milliseconds.
Does anybody know examples of this sort of thing?
2 Answers
7 years, 2 months ago.
Something along the lines of this should do what you want if you want the time the pin is low for. If all you care about is whether they ever go low then you can skip the rising interrupt and timer and just set a flag or increase a count every time it goes low.
This is a very simple implementation, it has a few issues e.g. what if the pin changes while in the process of printing the output, this sort of thing can easily be fixed if it's going to be an issue.
Also I've not tested this code so I make have made some silly mistake somewhere but the basic structure should be good.
Timer lowTimer; InteruptIn pinToMonitor(PC_3); volatile uint32_t measuredTime = 0; // must be volatile or the main loop won't notice that it's changed. void OnPinLow(void) { lowTime.start(); } void OnPinHigh(void) { lowTime.stop(); measuredTime = lowTime; lowTime.reset(); } main () { lowTime.reset(); pinToMonitor.fall(&OnPinLow); pinToMonitor.rise(&OnPinHigh); while (true) { if (measuredTime) { pc.printf("Pin was low for %ul us\r\n",measuredTime ); measuredTime = 0; } } }
Yer this looks good. I am creating an emergency stop message. So if one of a bunch of pins goes down I send a CAN message with what failed.
Sending CAN message should be alot quicker than printf so should be ok ?
posted by 06 Nov 2017The issue is only if the measured time variable starts to change and in an emergency stop situation even that's not a big deal. You don't care what the value is only that something happened.
But it doesn't matter how fast it is, if you don't want an interrupt to change things then disable interrupts, make a copy of the value and then re-enable them.
If you have a group of pins and only care if they change and possibly how many times but not for how long they are low then you can do something like this:
InteruptIn pinToMonitor1(PC_3); InteruptIn pinToMonitor2(PC_4); InteruptIn pinToMonitor4(PC_4); volatile uint8_t pin1Count = 0; // must be volatile or the main loop won't notice that it's changed. volatile uint8_t pin2Count = 0; // must be volatile or the main loop won't notice that it's changed. volatile uint8_t pin3Count = 0; // must be volatile or the main loop won't notice that it's changed. volatile bool error = false; void OnPin1Low(void) { pin1Count++; error = true; } void OnPin2Low(void) { pin2Count++; error = true; } void OnPin3Low(void) { pin3Count++; error = true; } CANMessage errorMessage; main () { // setup the CAN bus (baud rate etc...) // may as well set up the fixed parts of the can message in advance. errorMessage.id=0x200; errorMessage.format=CANStandard; errorMessage.len = 3; pinToMonitor1.fall(&OnPin1Low); pinToMonitor2.fall(&OnPin2Low); pinToMonitor3.fall(&OnPin3Low); while (true) { if (error) { __disable _irq(); // stop the interrupts for now errorMessage.data[0] = pin1Count; // copy the counters to the message data errorMessage.data[1] = pin2Count; errorMessage.data[2] = pin3Count; pin1Count = 0; // reset the counters pin2Count = 0; pin3Count = 0; error = false; // clear the error flag __enable_irq(); // re-enable interrupts, any changes that happened // while disabled will now get processed and will be // counted the next time around the loop.. // send the can message here, it doesn't matter how long it takes because the data is already fixed. } } }
It does not compile? I get:
Error: Identifier "InteruptIn" is undefined in "main.cpp", Line: 6, Col: 2
Error: Identifier "InteruptIn" is undefined in "main.cpp", Line: 7, Col: 2
Error: Identifier "InteruptIn" is undefined in "main.cpp", Line: 8, Col: 2
Error: Identifier "CANMessage" is undefined in "main.cpp", Line: 10, Col: 2
Error: Identifier "CAN" is undefined in "main.cpp", Line: 12, Col: 2
Error: Identifier "p9" is undefined in "main.cpp", Line: 12, Col: 11
Error: Expected a ")" in "main.cpp", Line: 12, Col: 13
Error: Declaration is incompatible with "void error(const char *, ...)" (declared at <a href="#" onmousedown="mbed_doc_goto('/STM32_Button_Interruptextras/mbed_fb8e0ae1cceb/platform/mbed_error.h', '69'); return false;">/extras/mbed_fb8e0ae1cceb/platform/mbed_error.h:69</a>) in "main.cpp", Line: 18, Col: 16
Error: Identifier "CANStandard" is undefined in "main.cpp", Line: 50, Col: 26
Error: Identifier "pinToMonitor3" is undefined in "main.cpp", Line: 55, Col: 6
Error: Identifier "disable" is undefined in "main.cpp", Line: 60, Col: 14
Am I missing some #includes?
I added
include the mbed library with this snippet
CAN can1(p9, p10); if (error) { __disable _irq(); // stop the interrupts for now errorMessage.data[0] = pin1Count; // copy the counters to the message data errorMessage.data[1] = pin2Count; errorMessage.data[2] = pin3Count; pin1Count = 0; // reset the counters pin2Count = 0; pin3Count = 0; error = false; // clear the error flag __enable_irq(); // re-enable interrupts, any changes that happened // while disabled will now get processed and will be // counted the next time around the loop.. } can1.write(errorMessage);// send the can message here, it doesn't matter how long it takes because the data is already fixed. wait(0.5);