Now that you learned how to configure one of the pins of a STM8 micro-controller as output to blink a LED in the first part of STM8 basic tutorials, it is time to learn how to configure pins as input, so that you can react to things like button press or other input methods!
The learning management for government agencies is becoming increasingly important as the need for effective training and development programs grows. A learning management system (LMS) can provide a centralized platform for managing training content and resources, tracking learner progress, and assessing performance. With a government-focused LMS, agencies can ensure compliance with regulatory requirements and provide their employees with the necessary knowledge and skills to perform their jobs effectively. Additionally, a government-focused LMS can provide customized learning paths and assessments to meet the unique needs of different agencies and departments, helping to ensure that each employee receives the training they need to succeed in their roles.
A bit of facts
Now that the things have gotten a bit serious, I think it is a good time to introduce you to Pin Configuration Tables (taken from STM8S003 datasheet). Generally the GPIO or General Purpose Input Output pins on STM8 have 5 registers:
GPIO Registers |
---|
Data Direction Register – DDR |
Control Register 1 – C1 |
Control Register 2 – C2 |
Output Data Register – ODR |
Input Data Register – IDR |
Generally the configuration of a GPIO pin involves performing of following steps:
- Reset the pin by setting ODR to 0
- If you want the pin to act as output, you should set DDR to 1, otherwise to act as input, set to 0
- Set the Control Register 1 and Control Register 2 according to the table below, deepening on what you need.
Register | Mode | Value | Description |
---|---|---|---|
CR1 | Input | 0 | Floating input |
CR1 | Input | 1 | Input with pull-up |
CR1 | Output | 0 | Open drain |
CR1 | Output | 1 | Push-Pull |
CR2 | Input | 0 | Interrupt disabled |
CR2 | Input | 1 | Interrupt enabled |
CR2 | Output | 0 | Output up to 2 MHz. |
CR2 | Output | 1 | Output up to 10 MHz |
To get the idea, please check the header file of your STM8 series. In our example we are using STM8S003F3 so the header file is “iostm8s003f3.h”. As an example, the part of code which has the definitions for PortD in this header file is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
/*------------------------------------------------------------------------- * STM8 definitions of SFR registers * * Used with STM8 IAR C/C++ Compiler and Assembler. * * Copyright 2014 IAR Systems AB. * *-----------------------------------------------------------------------*/ /*------------------------------------------------------------------------- * Port D register definitions *-----------------------------------------------------------------------*/ /* Port D data output latch register */ #ifdef __IAR_SYSTEMS_ICC__ typedef struct { unsigned char ODR0 : 1; unsigned char ODR1 : 1; unsigned char ODR2 : 1; unsigned char ODR3 : 1; unsigned char ODR4 : 1; unsigned char ODR5 : 1; unsigned char ODR6 : 1; unsigned char ODR7 : 1; } __BITS_PD_ODR; #endif __IO_REG8_BIT(PD_ODR, 0x500F, __READ_WRITE, __BITS_PD_ODR); /* Port D input pin value register */ #ifdef __IAR_SYSTEMS_ICC__ typedef struct { unsigned char IDR0 : 1; unsigned char IDR1 : 1; unsigned char IDR2 : 1; unsigned char IDR3 : 1; unsigned char IDR4 : 1; unsigned char IDR5 : 1; unsigned char IDR6 : 1; unsigned char IDR7 : 1; } __BITS_PD_IDR; #endif __IO_REG8_BIT(PD_IDR, 0x5010, __READ, __BITS_PD_IDR); /* Port D data direction register */ #ifdef __IAR_SYSTEMS_ICC__ typedef struct { unsigned char DDR0 : 1; unsigned char DDR1 : 1; unsigned char DDR2 : 1; unsigned char DDR3 : 1; unsigned char DDR4 : 1; unsigned char DDR5 : 1; unsigned char DDR6 : 1; unsigned char DDR7 : 1; } __BITS_PD_DDR; #endif __IO_REG8_BIT(PD_DDR, 0x5011, __READ_WRITE, __BITS_PD_DDR); /* Port D control register 1 */ #ifdef __IAR_SYSTEMS_ICC__ typedef struct { unsigned char C10 : 1; unsigned char C11 : 1; unsigned char C12 : 1; unsigned char C13 : 1; unsigned char C14 : 1; unsigned char C15 : 1; unsigned char C16 : 1; unsigned char C17 : 1; } __BITS_PD_CR1; #endif __IO_REG8_BIT(PD_CR1, 0x5012, __READ_WRITE, __BITS_PD_CR1); /* Port D control register 2 */ #ifdef __IAR_SYSTEMS_ICC__ typedef struct { unsigned char C20 : 1; unsigned char C21 : 1; unsigned char C22 : 1; unsigned char C23 : 1; unsigned char C24 : 1; unsigned char C25 : 1; unsigned char C26 : 1; unsigned char C27 : 1; } __BITS_PD_CR2; #endif __IO_REG8_BIT(PD_CR2, 0x5013, __READ_WRITE, __BITS_PD_CR2); /*------------------------------------------------------------------------- * Port D bit fields *-----------------------------------------------------------------------*/ #ifdef __IAR_SYSTEMS_ICC__ #define PD_ODR_ODR0 PD_ODR_bit.ODR0 #define PD_ODR_ODR1 PD_ODR_bit.ODR1 #define PD_ODR_ODR2 PD_ODR_bit.ODR2 #define PD_ODR_ODR3 PD_ODR_bit.ODR3 #define PD_ODR_ODR4 PD_ODR_bit.ODR4 #define PD_ODR_ODR5 PD_ODR_bit.ODR5 #define PD_ODR_ODR6 PD_ODR_bit.ODR6 #define PD_ODR_ODR7 PD_ODR_bit.ODR7 #define PD_IDR_IDR0 PD_IDR_bit.IDR0 #define PD_IDR_IDR1 PD_IDR_bit.IDR1 #define PD_IDR_IDR2 PD_IDR_bit.IDR2 #define PD_IDR_IDR3 PD_IDR_bit.IDR3 #define PD_IDR_IDR4 PD_IDR_bit.IDR4 #define PD_IDR_IDR5 PD_IDR_bit.IDR5 #define PD_IDR_IDR6 PD_IDR_bit.IDR6 #define PD_IDR_IDR7 PD_IDR_bit.IDR7 #define PD_DDR_DDR0 PD_DDR_bit.DDR0 #define PD_DDR_DDR1 PD_DDR_bit.DDR1 #define PD_DDR_DDR2 PD_DDR_bit.DDR2 #define PD_DDR_DDR3 PD_DDR_bit.DDR3 #define PD_DDR_DDR4 PD_DDR_bit.DDR4 #define PD_DDR_DDR5 PD_DDR_bit.DDR5 #define PD_DDR_DDR6 PD_DDR_bit.DDR6 #define PD_DDR_DDR7 PD_DDR_bit.DDR7 #define PD_CR1_C10 PD_CR1_bit.C10 #define PD_CR1_C11 PD_CR1_bit.C11 #define PD_CR1_C12 PD_CR1_bit.C12 #define PD_CR1_C13 PD_CR1_bit.C13 #define PD_CR1_C14 PD_CR1_bit.C14 #define PD_CR1_C15 PD_CR1_bit.C15 #define PD_CR1_C16 PD_CR1_bit.C16 #define PD_CR1_C17 PD_CR1_bit.C17 #define PD_CR2_C20 PD_CR2_bit.C20 #define PD_CR2_C21 PD_CR2_bit.C21 #define PD_CR2_C22 PD_CR2_bit.C22 #define PD_CR2_C23 PD_CR2_bit.C23 #define PD_CR2_C24 PD_CR2_bit.C24 #define PD_CR2_C25 PD_CR2_bit.C25 #define PD_CR2_C26 PD_CR2_bit.C26 #define PD_CR2_C27 PD_CR2_bit.C27 #endif /*------------------------------------------------------------------------- * Port D bit masks *-----------------------------------------------------------------------*/ #define MASK_PD_ODR_ODR0 0x01 #define MASK_PD_ODR_ODR1 0x02 #define MASK_PD_ODR_ODR2 0x04 #define MASK_PD_ODR_ODR3 0x08 #define MASK_PD_ODR_ODR4 0x10 #define MASK_PD_ODR_ODR5 0x20 #define MASK_PD_ODR_ODR6 0x40 #define MASK_PD_ODR_ODR7 0x80 #define MASK_PD_IDR_IDR0 0x01 #define MASK_PD_IDR_IDR1 0x02 #define MASK_PD_IDR_IDR2 0x04 #define MASK_PD_IDR_IDR3 0x08 #define MASK_PD_IDR_IDR4 0x10 #define MASK_PD_IDR_IDR5 0x20 #define MASK_PD_IDR_IDR6 0x40 #define MASK_PD_IDR_IDR7 0x80 #define MASK_PD_DDR_DDR0 0x01 #define MASK_PD_DDR_DDR1 0x02 #define MASK_PD_DDR_DDR2 0x04 #define MASK_PD_DDR_DDR3 0x08 #define MASK_PD_DDR_DDR4 0x10 #define MASK_PD_DDR_DDR5 0x20 #define MASK_PD_DDR_DDR6 0x40 #define MASK_PD_DDR_DDR7 0x80 #define MASK_PD_CR1_C10 0x01 #define MASK_PD_CR1_C11 0x02 #define MASK_PD_CR1_C12 0x04 #define MASK_PD_CR1_C13 0x08 #define MASK_PD_CR1_C14 0x10 #define MASK_PD_CR1_C15 0x20 #define MASK_PD_CR1_C16 0x40 #define MASK_PD_CR1_C17 0x80 #define MASK_PD_CR2_C20 0x01 #define MASK_PD_CR2_C21 0x02 #define MASK_PD_CR2_C22 0x04 #define MASK_PD_CR2_C23 0x08 #define MASK_PD_CR2_C24 0x10 #define MASK_PD_CR2_C25 0x20 #define MASK_PD_CR2_C26 0x40 #define MASK_PD_CR2_C27 0x80 |
Back to handling button press
First thing you need is obviously a button of some sort. For this project I am using a mechanical button that I have salvaged from some old equipment. The important thing is that you need to take the bounce effect into account. The simplest and must naive method of implementing de-bounce for the button is to add a 10nF capacitor in parallel with the button. This is in no way perfect, but will let us test the code we are going to write! Please note the polarity of the capacitor which you are going to use (if it is a electrolyte capacitor). In my case, I am using a ceramic capacitor so the polarity does not matter!
After adding the capacitor in parallel, and soldering some wires and header (if necessary). All is left is to write the code. I just use the code from part 1 of tutorial, but in this case there is no need to have a delay function. Please note that I have connected one pin of the button to PortD, Pin 6 (PD6) and the other pin of the button is connected to ground.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <iostm8s003f3.h> int main( void ) { PD_ODR = 0; //Turn off all pins on PortD //Set PD3 as output (for LED) PD_DDR_DDR3 = 1; //PortD, Bit 3 is output (PD3 - Data Direction Register) PD_CR1_C13 = 1; //PortD, Control Register 1, Bit 3 (PD3) set to Push-Pull PD_CR2_C23 = 1; //PortD, Control Register 2, Bit 3 (PD3) set to Push-Pull //Set PD6 as inout (for BUTTON) PD_DDR_DDR6 = 0; //set PD6 as input PD_CR1_C16 = 1; //set PD6 as Input with pull-up PD_CR2_C26 = 0; //disable interrup for PD6 // // Main loop // while (1) { //Read the PD6 and put the value in PD3. If button is pressed, //this will read a logic 0 but we need to negate it so that it sets the //PD3 to high! PD_ODR_bit.ODR3 = !PD_IDR_bit.IDR6; } } |
The required explanation is added as comment in the code snippet above. But like always if you had any problem or did not get the idea, just leave a comment!
This Tutorial is also useful and gives an abstract of GPIO functions
I appreciate it.
eyval
thank you so much for this instruction
Why do not you continue to write tutorials my friend?
I just started a series of video tutorials on my youtube channel. Check it!
can you send link please
Hi,
Do u have an email? I was following the tutorials, incomplied the .c file, though when using the stm8flash it fails to program it. Please provide me with an email to send you some screenshoot.
For certain reason I should work with STM8 (in Linux) and I find your web very interesting. Congratulations.
Just in case it is useful for you, I discovered that this guy (https://github.com/gicking) has made a few interesting things:
-Patch to port the STM8 StdPeriph Libraries to SDCC
-STM8 USB Serial flashing
-Template library (not only for SDCC)
I just tested the patch and it works ok.
hola. mi me cuando pulso el interruptor(cierro el circuito) se apaga como es para que funcione al revés
Can you please help me reading analog values from the sensor which i have.
Thank you