Index
- BMSBattery S series
- BMSBattery S06S
- S06ST (torque sensor version)
- S06S-BL (Bluetooth version)
- PWM signals
- Phase B current signal
- Throttle
- BMSBattery S06SC
- BMSBattery S12S
- BMSBattery bottle battery controller
- LCD control panel
- Kunteng mobile app
- Bluetooh
- How to open the controller and solder the programming header
- Hardware mods
- Other controllers
- BMSBattery S06P
- Kunteng 18 mosfets motor controller
- Lishui motor controllers
- JinHui motor controllers
- GreenEBikeKit
- Torque speed
- Motor control scheme of S06S controller
- BLDC 6 steps
- PWM schemes
- So, Which PWM Technique is Best? (Part 1)
- So, Which PWM Technique is Best? (Part 2)
- So, Which PWM Technique is Best? (Part 3)
- So, Which PWM Technique is Best? (Part 4)
- So, Which PWM Technique is Best? (Part 5)
- So, Which PWM Technique is Best? (Part 6)
- So, Which PWM Technique is Best? (Part 7)
- PWM control and Dead Time Insertion
- Low inductance motors
- Throttle Control Modes
- Phase angle FOC
- PWM frequency VS motor eRPM
- Sinusoidal Control of BLDCM with Hall Sensors Based
- Self-Learn Hall Sensor Calibration Mode
- STM8S105 Alternatives
- PID algorithm - negative output values
- Regeneration
- FOC
Datasheets and application notes
- STM8S105C6T6
- Endless-sphere.com forum messages
- 2017.04.25 - Initial forum message
- 2017.05.08 - First flash and debug on a dev board
- 2017.05.18 - First code flashing and running
- 2017.05.20 - more new information
- 2017.08.23 - SxxP versus SxxS versus LSW-675
- 2017.09.01 - Trying to figure out an algorithm to automatically adjust ui8_position_correction_value
- 2017.09.02 - How to do FOC on the BMSBattery S06S/Kunteng STM8 motor controllers
- 2017.09.03 - more ideas about zero crossing for FOC
- 2017.09.05 - measuring IQ current and manually adjusting position_correction_value
- 2017.09.15 - our OpenSource firmware efficiency compared to Lishui 12 FET FOC
- 2017.09.19 - measuring motor current
- 2017.10.23 - FOC and no FOC comparison
- 2018.01.10 - How to measure FOC_READ_ID_CURRENT_ANGLE_ADJUST
- 2018.02.20 - Reading motor phase current from the DC link current (shunt)
Interrupts
http://blog.mark-stevens.co.uk/2012/09/interrupts-on-the-stm8s/Interrupts on the STM8S
A while ago I wrote about using interrupts on the STM8S (see External Interrupts on the STM8S and hinted there that I would come back to the topic and here we are. In this article we will cover the following:
• List of interrupts available and the interrupt table
• Writing your own Interrupt Service Routine (ISR)
• Setting/Changing interrupt priorities
It is probably a good time to remind you that the STM8S Reference Manual (document number RM0016), available from ST’s web site is handy, to keep available for reference. This post is really meant for the application developer who wants to know which interrupts are available and how to use them.
Interrupt Table
The STM8S holds a list of interrupt vectors in a table in memory. As a programmer you are able to add your own ISRs to your application. These are really just conventional methods with a slightly different entry and exit mechanism. You don’t have to worry about how this mechanism works as you can make the compiler do all of the work for you. We shall see how later. The compiler is also be good enough to ensure that the table of interrupt vectors is also updated to point to your code as part of the application start up.
The following table lists the interrupts which are available on the STM8S103F3 microcontroller:
click me | click me | click me |
---|---|---|
Vector Number | Abbreviation | Description |
1 (0x01) | TRAP | TRAP |
2 (0x02) | TLI | Top Level Interrupt |
3 (0x03) | AWU | Auto Wake Up |
4 (0x04) | CLK | Clock |
5 (0x05) | EXTI_PORTA | External Interrupts for Port A (Pins 2 through 6 inclusive) |
6 (0x06) | EXTI_PORTB | External Interrupts for Port B(All pins) |
7 (0x07) | EXTI_PORTC | External Interrupts for Port C(All pins) |
8 (0x08) | EXTI_PORTD | External Interrupts for Port D (Pins 0 through 6 inclusive) |
9 (0x09) | N/A | Not used |
10 (0x0a) | N/A | Not used |
11 (0x0b) | N/A | Not used |
12 (0x0c) | SPI | SPI |
13 (0x0d) | TIM1_UPD_OVF_TRG_BRK | Timer 1 Update/Overflow/Trigger/Break |
14 (0x0e) | TIM1_CAP_COM | Timer 1 Capture/Compare |
15 (0x0f) | TIM2_UPD_OVF_BRK | Timer 2 Update/Overflow/Break |
16 (0x10) | TIM2_CAP_COM | Timer 2 Capture/Compare |
17 (0x11) | TIM3_UPD_OVF_BRK | Timer 5 Update/Overflow/Break |
18 (0x12) | TIM3_CAP_COM | Timer 3 Capture/Compare |
19 (0x13) | UART_RX | UART Rx |
20 (0x14) | UART_TX | UART Tx |
21 (0x15) | I2C | I2C |
22 (0x16) | UART2_RX | UART 2 Rx |
23 (0x17) | UART2_TX | UART 2 Tx |
24 (0x18) | ADC1 | ADC1 |
25 (0x19) | TIM4_UPD_OVF | Timer 1 Update/Overflow |
26 (0x1a) | EEPROM_EEC | EEPROM EEC |
One thing to remember is that while the interrupt vector numbers remain unchanged the availability of the interrupt vectors will change depending upon the chip you are using. For instance, vector 10 is not used here but on the STM8S208 this is available to process one of the CAN interrupts. The simplest way to find out if an interrupt is available is to look at the header file for your chip. So let’s
So how do you know which interrupts are available for your microcontroller?
The first thing to note is that the vector numbers for interrupts 1-9 are usually the same as these features are available on most of the controllers. Note that whilst interrupt 9 is not available on my chip it is the EXTI_PORTE vector. I have not been able to locate any standard definitions (i.e. #define’s etc) for these interrupt vectors in any of the header files supplied with the compiler.
For the rest of the vectors we will have to start to look through the header files for the microcontroller. Opening up <iostm8s103f3.h> and going to the very end of the file we find a section with the comment Interrupt vector numbers. There should be one or more definitions for each of the features which allow the use of interrupts and which are available on the microcontroller.
One of the things to note about the list of available interrupts is that there are more than one #define statements for each feature. Consider the following extract:
view sourceprint?01./*-------------------------------------------------------------------------02.* Interrupt vector numbers03.*-----------------------------------------------------------------------*/04.#define SPI_TXE_vector 0x0C05.#define SPI_RXNE_vector 0x0C06.#define SPI_WKUP_vector 0x0C07.#define SPI_MODF_vector 0x0C08.#define SPI_CRCERR_vector 0x0C09.#define SPI_OVR_vector 0x0C10.#define TIM1_CAPCOM_TIF_vector 0x0D11.#define TIM1_CAPCOM_BIF_vector 0x0D12.#define TIM1_OVR_UIF_vector 0x0D
If we look at the SPI definitions we can see that all of the vectors map to the same interrupt number. This is because there is only one ISR for this (SPI) feature. So the important point to take away is that your ISR must work out which condition it is working with.
Consider the example from the earlier post External Interrupts on the STM8S. This used the following ISR:
view sourceprint?1.#pragma vector = 82.__interrupt void EXTI_PORTD_IRQHandler(void)3.{4.PD_ODR_ODR3 = !PD_ODR_ODR3; // Toggle Port D, pin 3.5.}
This method performed the same action every time this ISR was called. Now this did not matter for the example as we only had one switch attached to Port D. If we had another switch and LED attached to the same port then we would have had to work out which switch had been pressed in order to work out which action to take. Whilst this is simple in the case of switches the same principle applies to other features like SPI. In the case of SPI, the application should interrogate the status registers in order to work out why the ISR has been called.
Writing your own Interrupt Service Routine (ISR)
Writing your own ISR is really no different from writing any other method in C. There are a few extra rules which need to be followed but the majority of the techniques are the same. So let us return to the external interrupt code example:
view sourceprint?1.#pragma vector = 82.__interrupt void EXTI_PORTD_IRQHandler(void)3.{4.PD_ODR_ODR3 = !PD_ODR_ODR3; // Toggle Port D, pin 3.5.}
The first thing you notice is the addition of the #pragma vector = 8 statement. This tells the compiler which interrupt vector we are going to be writing. In this case it is vector 8 which is the EXTI_PORTD interrupt vector (see the table above). You can also use the values found in the header file for you microcontroller. So you could write the following:
view sourceprint?1.#pragma vector = SPI_TXE_vector
instead of:
view sourceprint?1.#pragma vector = 0x0c
If you are using the same method for multiple vectors then you can provide the list of vector numbers as a comma separated list thus:
view sourceprint?1.#pragma vector = SPI_TXE_vector, TIM1_OVR_UIF_vector
The next thing to notice is the __interrupt decoration which has been applied to the method. This tells the compiler that the method is to be used as an ISR. Knowing this, the compiler will ensure that the preamble and exit from the method are set up correctly as these are different from those of any other method which you might call.
Something which is not obvious from the above code is the fact the an ISR cannot take any parameters nor can it return a value. Hence the method definition takes a void parameter list and returns void.
You should also note that it is possible to write an interrupt method (i.e. decorate a method with __interrupt) without providing a #pragma vector statement. In this case the compiler will not generate an entry in the interrupt vector table.
You should also consider how fast the ISR needs to be. In this case, a single button press, we do not need any real efficiency as the microcontroller is not really doing anything overly complex. This may not be the case in non-trivial applications. In which case you will need to analyse your system to determine how fast the ISR needs to be. You also need to take into account the fact that one ISR may be interrupted by a higher priority ISR.
Setting/Changing interrupt priorities
Interrupts can be assigned a software priority from 0 to 3. This allows the interrupts to be nested ensuring that the most important interrupts receive attention over less important interrupts.
Interrupt priority is given by the following:
click me | click me |
---|---|
Priority | Bit Value |
0 | 10 |
1 | 01 |
2 | 00 |
3 | 11 |
Where the priority increases from the top of the table towards the bottom.
By default, all of the interrupts are assigned the same software priority, 3. This effectively means that the priority is disabled and all interrupts are treated as equal by the software. When the software priority is disabled or when two or more interrupts have the same priority then the interrupts are queued for processing
The software interrupt priority for the interrupt vectors (and hence your ISR) is stored in a group of registers. Each register (ITC_SPR1 through ITC_SPR8) holds the priority for four interrupt vectors. At reset all of these priorities are reset to 11 – software priority disabled. The register mapping is given by the following table:
click me | click me | click me | click me | click me |
---|---|---|---|---|
Register | Bits 7:6 | Bits 5:4 | Bits 3:2 | Bits 1:0 |
ITC_SPR1 | VECT3SPR | VECT2SPR | VECT1SPR | VECT0SPR |
ITC_SPR2 | VECT7SPR | VECT6SPR | VECT5SPR | VECT4SPR |
ITC_SPR3 | VECT11SPR | VECT10SPR | VECT9SPR | VECT8SPR |
ITC_SPR4 | VECT15SPR | VECT14SPR | VECT13SPR | VECT12SPR |
ITC_SPR5 | VECT19SPR | VECT18SPR | VECT17SPR | VECT16SPR |
ITC_SPR6 | VECT23SPR | VECT22SPR | VECT21SPR | VECT20SPR |
ITC_SPR7 | VECT27SPR | VECT26SPR | VECT25SPR | VECT24SPR |
ITC_SPR8 | – | – | VECT29SPR | VECT28SPR |
Changing the priority is a simple matter of identifying the vector and changing the appropriate register (ITC_SPR1_VECT1SPR for vector 1, ITC_SPR1_VECT2SPR for vector 2 etc.).
Conclusion
Much of the information we have covered here is adequate for the average user intending to develop a module for the Netduino GO!. For more advanced topics such as what happens in low power modes, how interrupts are handled, nested interrupt handling etc. then you should refer to Chapter 6 in RM0016.