Using External Interrupt is one of the key feature of any microcontroller. Just like any other microcontroller, STM8s series also provide the external interrupt functionality out of the box. If you are coming with any other 8-bit microcontroller family like the 8051 series you may notice that those microcontrollers provides limited numbers of pins for the external interrupt functionality. Mostly one or two pins, even the famous Arduino Uno board which comes with ATMega328p microcontroller also have only 2 external interrupt pins. But the ST microcontrollers always take cares of users and provide more rich peripherals usage. The STM8s is capable of having the interrupt on any GPIO pin.
In this STM8s external interrupt example we are going to demonstrate the external interrupt functionality but the resultant output code will be very simple. It will toggle the LED whenever the push button is pressed on the external interrupt pin. We are going to use the Cosmic C compiler for writing the code for the STM8s microcontroller. Just like in our previous STM8S LCD interfacing example, as well as the STM8 UART example post. You may view all the examples of STM8 Cosmic C compiler .
The microcontroller number which we are going to use is, as usual the STM8S103F3 microcontroller. You may also use STM8S003F3 which is almost similar with same pinouts. The reason of using this microcontroller is because of its STM8S Blue pill board.
STM8S Interrupt vector Table
Before we would be able to use any interrupts we need to find out the interrupt vector table. To find the interrupt vector table, we have to goto the STM8S103f3p6 micrcontroller’s Datasheet. In this datasheet, if you navigate to the section 7 of interrupt vector mapping, here you need to find out the IRQ number of your required interrupt. We are going to use the PortA for our external mapping. Here we can see it is EXT0 and the IRQ number for this interrupt source is IRQ3. With this information we will go to the STVD IDE for writing the code.
Now if you open the project in STVD IDE, you may see two files. The main.c is the file which we are using in all our previous tutorials. But you may notice that there is one more file named stm8_interrupt_vector.c This is the file which is responsible for this interrupt vector mapping. Double click on this file and open it in the editor. By default it will hold following code
/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices
* Copyright (c) 2007 STMicroelectronics
*/
typedef void @far (*interrupt_handler_t)(void);
struct interrupt_vector {
unsigned char interrupt_instruction;
interrupt_handler_t interrupt_handler;
};
@far @interrupt void NonHandledInterrupt (void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
return;
}
extern void _stext(); /* startup routine */
extern @far @interrupt void EXTI3_IRQHandler (void);
struct interrupt_vector const _vectab[] = {
{0x82, (interrupt_handler_t)_stext}, /* reset */
{0x82, NonHandledInterrupt}, /* trap */
{0x82, NonHandledInterrupt}, /* irq0 */
{0x82, NonHandledInterrupt}, /* irq1 */
{0x82, NonHandledInterrupt}, /* irq2 */
{0x82, NonHandledInterrupt}, /* irq3 */
{0x82, NonHandledInterrupt}, /* irq4 */
{0x82, NonHandledInterrupt}, /* irq5 */
{0x82, (interrupt_handler_t)EXTI3_IRQHandler}, /* irq6 (FOR PRTD EXTERNAL INTERRUPT) */
{0x82, NonHandledInterrupt}, /* irq7 */
{0x82, NonHandledInterrupt}, /* irq8 */
{0x82, NonHandledInterrupt}, /* irq9 */
{0x82, NonHandledInterrupt}, /* irq10 */
{0x82, NonHandledInterrupt}, /* irq11 */
{0x82, NonHandledInterrupt}, /* irq12 */
{0x82, NonHandledInterrupt}, /* irq13 */
{0x82, NonHandledInterrupt}, /* irq14 */
{0x82, NonHandledInterrupt}, /* irq15 */
{0x82, NonHandledInterrupt}, /* irq16 */
{0x82, NonHandledInterrupt}, /* irq17 */
{0x82, NonHandledInterrupt}, /* irq18 */
{0x82, NonHandledInterrupt}, /* irq19 */
{0x82, NonHandledInterrupt}, /* irq20 */
{0x82, NonHandledInterrupt}, /* irq21 */
{0x82, NonHandledInterrupt}, /* irq22 */
{0x82, NonHandledInterrupt}, /* irq23 */
{0x82, NonHandledInterrupt}, /* irq24 */
{0x82, NonHandledInterrupt}, /* irq25 */
{0x82, NonHandledInterrupt}, /* irq26 */
{0x82, NonHandledInterrupt}, /* irq27 */
{0x82, NonHandledInterrupt}, /* irq28 */
{0x82, NonHandledInterrupt}, /* irq29 */
};
Code language: JavaScript (javascript)
All you have to do is to replace the NonHandledInterrupt with your own Interrupt Service Routine pointer in the proper IRQ number. In our case this would be IRQ3.
Final Code
Here is complete working code which blinks onboard LED @PB5 continuously and toggle LED on PD2 whenever it detect RISING EDGE on PD3 . Here we enabled the interrupts from EXTI_CR1 Register.
#include "iostm8s.h"
_Bool LED_BUILTIN @PB_ODR: 5; //TO WRITE OUTPUT
_Bool LED @PD_ODR: 2; //TO WRITE OUTPUT
//---------------------------------
_Bool SW1 @PD_IDR: 3; //TO READ INPUT
//----------------------------------
void delay_ms(unsigned int nCount) {
/* Decrement nCount value */
unsigned int i = 0;
while (nCount != 0) {
for (i = 0; i < 0x3FF; i++);
nCount--;
}
}
main() {
CLK_CKDIVR = 0x00; //CPUDIV=1,HSDIV=1,Int_clock= 16MHz
#asm
sim
#endasm
PB_DDR |= (1 << 5);
PD_DDR |= (1 << 2);
PD_CR1 |= (1 << 2);
PD_DDR &= ~(1 << 3);
PD_CR1 &= ~(1 << 3);
PD_CR2 |= (1 << 3); //ENABLE EXTERNAL INTERRUPT
EXTI_CR1 &= ~(1 << 7); //PORTD FALLING & LOW Level
EXTI_CR1 |= (1 << 6); //PORTD FALLING & LOW Level
#asm
rim
#endasm
while (1) {
unsigned int i = 0;
LED_BUILTIN = ~LED_BUILTIN;
delay_ms(500);
}
}
@far @interrupt void EXTI3_IRQHandler(void) {
if (SW1 == 1) {
LED = ~LED;
}
}
Code language: PHP (php)
One reply on “STM8s External interrupt example”
Thank you so much Sir. I looked at 10 places for interrupt syntax but your tutorial really saved me.