Important update: Arm Announces End of Life Timeline for Mbed. This site will be archived in July 2026. Read the full announcement.
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.
Interrupts vs Thread conflict in mbed for STM32?
Topic last updated 20 Jun 2018, by
Yehor Pererva.
0
replies

Hello everyone!
I'm studying mbed for STM32 and have some problem with using interrupts and threads in single program.
**What is going on in code:**\\
3 buttons are used to control states of 3 digital outputs,
Encoder has 2 interrupts : to control PWM (on one pin), second interrupt (encoder button) switches states of all 3 outputs (which are attached to buttons).
The same time I read temperature from 3 temperature sensors (on individual data pins).
PWM forming frequency data and read temperatures are transferred to display.
**Problem**\\
When temperature reading is inside of main() function - everything works amazingly.
But when I'm trying to move all temperature reading to thread outside of the main() function the program compiles, but microcontroller stops (freezes) at the moment when tread starts. After that microcontroller doesn't respond to anything (interrupts do not work).
Is there any conflict if using interrupts and thread in a single program?
Please, help with that.
**Libraries and references**\\
Thread using instructions taken from here: https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/tasks/rtos/
* Enhanced TextLCD by Wim Huiskamp : https://os.mbed.com/users/wim/code/TextLCD/
* DS1820 by Zoltan Hudak : https://developer.mbed.org/users/hudakz/code/DS1820/wiki/Homepage
**Used Hardware**\\
* HD44780 20x4 LCD in 4-bit mode
* 3 x DS18B20 temperature sensors
* BluePill STM32F103C8T6
**Code**\\
<<code title="Code without threads">>
#include "stm32f103c8t6.h"
#include "mbed.h"
#include "TextLCD.h"
#include "DS1820.h"
// ------------------------------------------------------------------------------------------------
class Motor{
public:
void on() { _out = 1; };
void off() { _out = 0; };
void flip(){ _out = !_out;};
bool state() { return _out;};
Motor (PinName button_pin, PinName output_pin) :
// since _out and _interrupt instances are "private" - they have to be initialized with an initializer list!
_out(output_pin), _interrupt(button_pin) {
// now extra actions that has to be done during initializing
off();
_interrupt.fall(callback(this, &Motor::flip));
};
private:
DigitalOut _out;
InterruptIn _interrupt;
};
// ------------------------------------------------------------------------------------------------
DigitalOut led(PC_13);
InterruptIn encoder_A(PA_10); // contact A of encoder
InterruptIn encoder_S(PA_12); // contact Switch of encoder
DigitalIn encoder_B(PA_11); // contact B of encoder
Motor motor_1(PA_15, PB_11); // control button input, output pin
Motor motor_2(PB_3, PB_10);
Motor motor_3(PB_4, PB_1);
PwmOut step(PA_1);
DS1820 ds18b20[3] = {DS1820(PA_2), DS1820(PA_3), DS1820(PA_4)};
float temperatures[3];
// For TextLCD in 4-bit mode:
// TextLCD lcd( p11, p12, p30, p29, p28, p27, TextLCD::LCD20x4 ); // rs, e, d4...d7; RW - wire to GND!
// wire RW to ground!
// place the potentiometer between V0 / VSS / VDD to correct the contrast
// For VDD ~5.0 V: VSS can be wired via 2 x 4K7 resistors (in paralel) to GND
TextLCD lcd(PB_12, PB_13, PB_14, PB_15, PA_8, PA_9, TextLCD::LCD20x4 );
// Just input values ----------------------------------------------------------------------------------------------
float RPM = 10.0; // default value, later shoud be sotred in flash mamory or EEPROM
int SPRmotor = 400; // Steps Per Revolution of motor : defined by motor model
// NEMA 17 : 42BYGHM809 : 400 bipolar
// NEMA 23 : 57BYGH420-2 : 200 bipolar stepper; 2A per phase
int MSM = 16; // 1; 2; 4; 8; 16 : depends on driver
// Big Easy Driver : Allegro A4988 : <2 A per phase : 1, 2, 4, 8, 16
// Easy driver : A3967SLBT : <0.7 A per phase : 1, 2, 4, 8
int pulse_width = 75; // 1...10 microsecond for making step : defined by driver
float period;
volatile bool changed = false; // important to be volatile!!!!, Otherwise the problem with while loop
void update_period(){
period = 60.0/(RPM * SPRmotor * MSM);
};
void print_RPM(){
lcd.locate(0,0);
lcd.printf("%2.1f ", RPM);
lcd.locate(6,0);
lcd.printf("%8.3f ", period*1000000);
lcd.locate(9,1);
lcd.printf("%6.4f", step.read()*100.0);
};
// Functions, attached to interrupts ----------------------------------------------------------------------------------------------
void encoder() {
float lastRPM = RPM;
if (encoder_B == encoder_A) {
RPM = RPM + (float) 0.1;
} else {
RPM = RPM - (float) 0.1;
};
if (RPM < 0.1) {RPM = 0.1;}
if (lastRPM != RPM) {
changed = true;
};
};
void encoder_switch(){
// if at least one motor is on, turn off all
if (motor_1.state() | motor_2.state() | motor_3.state()){
motor_1.off();
motor_2.off();
motor_3.off();
} else {
motor_1.on();
motor_2.on();
motor_3.on();
};
};
// ----------------------------------------------------------------------------------------------
int main() {
led = 0;
// needed for this library, otherwise - places the "_" symbol after last printed symbol
lcd.setCursor(TextLCD::CurOff_BlkOff);
lcd.locate(0,0);
lcd.printf("Inititalizing...");
for (int i = 0; i <3; i++){
lcd.locate(0,i+1);
lcd.printf(" Temp.Probe %d ", i+1);
if (!ds18b20[i].begin()){
lcd.printf("FAIL");
} else {
lcd.printf("PASS");
};
wait(0.1);
};
lcd.cls();
encoder_A.fall(callback(encoder));
encoder_S.fall(callback(encoder_switch));
update_period();
step.period(period);
step.write(0.5);
print_RPM();
while (true){
led = !led;
for (int i = 0; i <3; i++) { ds18b20[i].startConversion();};
led = !led;
if (changed){
changed = false;
update_period();
step.period(period);
step.write(0.5); // for some reason needs to be updates
print_RPM();
};
led = !led;
for (int i = 0; i <3; i++) { temperatures[i] = ds18b20[i].read();};
led = !led;
for (int i = 0; i <3; i++) {
lcd.locate(0+i*5,3);
lcd.printf("%3.1f", temperatures[i]);
};
};
};
<</code>>
<<code title="Code with threads">>
#include "stm32f103c8t6.h"
#include "mbed.h"
#include "TextLCD.h"
#include "DS1820.h"
// ------------------------------------------------------------------------------------------------
class Motor{
public:
void on() { _out = 1; };
void off() { _out = 0; };
void flip(){ _out = !_out;};
bool state() { return _out;};
Motor (PinName button_pin, PinName output_pin) :
// since _out and _interrupt instances are "private" - they have to be initialized with an initializer list!
_out(output_pin), _interrupt(button_pin) {
// now extra actions that has to be done during initializing
off();
_interrupt.fall(callback(this, &Motor::flip));
};
private:
DigitalOut _out;
InterruptIn _interrupt;
};
// ------------------------------------------------------------------------------------------------
DigitalOut led(PC_13);
InterruptIn encoder_A(PA_10); // contact A of encoder
InterruptIn encoder_S(PA_12); // contact Switch of encoder
DigitalIn encoder_B(PA_11); // contact B of encoder
Motor motor_1(PA_15, PB_11); // control button input, output pin
Motor motor_2(PB_3, PB_10);
Motor motor_3(PB_4, PB_1);
PwmOut step(PA_1);
DS1820 ds18b20[3] = {DS1820(PA_2), DS1820(PA_3), DS1820(PA_4)};
float temperatures[3];
Thread temperature_thread;
// For TextLCD in 4-bit mode:
// TextLCD lcd( p11, p12, p30, p29, p28, p27, TextLCD::LCD20x4 ); // rs, e, d4...d7;
// wire RW to ground!
// place the potentiometer between V0 / VSS / VDD to correct the contrast
// For VDD ~5.0 V: VSS can be wired via 2 x 4K7 resistors (in paralel) to GND
TextLCD lcd(PB_12, PB_13, PB_14, PB_15, PA_8, PA_9, TextLCD::LCD20x4 );
// Just input values ----------------------------------------------------------------------------------------------
float RPM = 10.0; // default value, later shoud be sotred in flash mamory or EEPROM
int SPRmotor = 400; // Steps Per Revolution of motor : defined by motor model
// NEMA 17 : 42BYGHM809 : 400 bipolar
// NEMA 23 : 57BYGH420-2 : 200 bipolar stepper; 2A per phase
int MSM = 16; // 1; 2; 4; 8; 16 : depends on driver
// Big Easy Driver : Allegro A4988 : <2 A per phase : 1, 2, 4, 8, 16
// Easy driver : A3967SLBT : <0.7 A per phase : 1, 2, 4, 8
int pulse_width = 75; // 1...10 microsecond for making step : defined by driver
float period;
volatile bool changed = false; // important to be volatile!!!!, Otherwise the problem with while loop
volatile bool measured = false; // important to be volatile!!!!, Otherwise the problem with while loop
void update_period(){
period = 60.0/(RPM * SPRmotor * MSM);
};
void print_RPM(){
lcd.locate(0,0);
lcd.printf("%2.1f ", RPM);
lcd.locate(6,0);
lcd.printf("%8.3f ", period*1000000);
lcd.locate(9,1);
lcd.printf("%6.4f", step.read()*100.0);
};
// Functions, attached to interrupts ----------------------------------------------------------------------------------------------
void encoder() {
float lastRPM = RPM;
if (encoder_B == encoder_A) {
RPM = RPM + (float) 0.1;
} else {
RPM = RPM - (float) 0.1;
};
if (RPM < 0.1) {RPM = 0.1;}
if (lastRPM != RPM) {
changed = true;
};
};
void encoder_switch(){
// if at least one motor is on, turn off all
if (motor_1.state() | motor_2.state() | motor_3.state()){
motor_1.off();
motor_2.off();
motor_3.off();
} else {
motor_1.on();
motor_2.on();
motor_3.on();
};
};
void temperature_monitor(){
led = !led;
for (int i = 0; i <3; i++) { ds18b20[i].startConversion();};
led = !led;
wait(1);
led = !led;
for (int i = 0; i <3; i++) { temperatures[i] = ds18b20[i].read();};
led = !led;
measured = true;
};
// ----------------------------------------------------------------------------------------------
int main() {
led = 0;
// needed for this library, otherwise - places the "_" symbol after last printed symbol
lcd.setCursor(TextLCD::CurOff_BlkOff);
lcd.locate(0,0);
lcd.printf("Inititalizing...");
for (int i = 0; i <3; i++){
lcd.locate(0,i+1);
lcd.printf(" Temp.Probe %d ", i+1);
if (!ds18b20[i].begin()){
lcd.printf("FAIL");
} else {
lcd.printf("PASS");
};
wait(0.1);
};
lcd.cls();
encoder_A.fall(callback(encoder));
encoder_S.fall(callback(encoder_switch));
update_period();
step.period(period);
step.write(0.5);
temperature_thread.start(temperature_monitor);
print_RPM();
while (true){
if (changed){
changed = false;
update_period();
step.period(period);
step.write(0.5); // for some reason needs to be updates
print_RPM();
};
if (measured){
measured = false;
for (int i = 0; i <3; i++) {
lcd.locate(0+i*5,3);
lcd.printf("%3.1f", temperatures[i]);
};
};
};
};
<</code>>
Hello everyone!
I'm studying mbed for STM32 and have some problem with using interrupts and threads in single program.
What is going on in code:
3 buttons are used to control states of 3 digital outputs, Encoder has 2 interrupts : to control PWM (on one pin), second interrupt (encoder button) switches states of all 3 outputs (which are attached to buttons). The same time I read temperature from 3 temperature sensors (on individual data pins). PWM forming frequency data and read temperatures are transferred to display.
Problem
When temperature reading is inside of main() function - everything works amazingly. But when I'm trying to move all temperature reading to thread outside of the main() function the program compiles, but microcontroller stops (freezes) at the moment when tread starts. After that microcontroller doesn't respond to anything (interrupts do not work).
Is there any conflict if using interrupts and thread in a single program?
Please, help with that.
Libraries and references
Thread using instructions taken from here: https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/tasks/rtos/
Used Hardware
Code
Code without threads
Code with threads