- Preparació del maquinari
- Descripció dels pinouts GPIO a STM8S103F
- Descripció del pinout i consells per a la selecció GPM STM8S103F
- Programació de STM8S per a entrada i sortida GPIO mitjançant SPL
- Càrrega i prova del programa
Per als microcontroladors, un programa de parpelleig LED equival al programa "hola world". Al nostre tutorial anterior, vam aprendre a començar amb la placa de desenvolupament STM8S103F3 i a configurar l’IDE i el compilador per programar els nostres controladors STM8S. També hem après a utilitzar les biblioteques perifèriques estàndard i a compilar i penjar el codi al nostre microcontrolador. Amb tots els conceptes bàsics coberts, comencem a escriure codi. En aquest tutorial, aprendrem a realitzar funcions generals de GPIO als controladors STM8S. La placa ja té un LED integrat connectat al pin 5 del port B, aprendrem a parpellejar aquest LED i també afegirem un LED extern i el controlarem amb un polsador. Si sou completament nou, és molt recomanable llegir el tutorial anterior abans de continuar.
Preparació del maquinari
Abans de capbussar-nos al programa, deixeu preparades les connexions de maquinari. Com es va esmentar abans, farem servir dos LEDs aquí, un és un LED integrat que parpellejarà continuament i l’altre és un LED extern que es commutarà amb un polsador. La idea és aprendre totes les funcionalitats GPIO en una configuració senzilla. El LED incorporat ja està connectat a PB5 (pin5 de PORTB), de manera que acabo de connectar un LED a PA3 i un polsador a PA2, com podeu veure al diagrama següent.

Però, de tots els pins de sortida disponibles al nostre controlat, per què he seleccionat PA3 per a sortida i PA2 per a entrada? Les preguntes són vàlides i ho explicaré més endavant en aquest article. A continuació es mostra la configuració del maquinari d’aquest tutorial. Com podeu veure, també he connectat el meu programador ST-link a pins de programació que no només programaran la nostra placa, sinó que també actuaran com a font d’energia.

Descripció dels pinouts GPIO a STM8S103F
Ara tornem a la pregunta, per què PA2 per a l'entrada i per què PA3 per a sortida? Per entendre-ho, donem una ullada més detallada al pinout del microcontrolador que es mostra a continuació.

Segons el diagrama pinout, tenim quatre ports al nostre microcontrolador, és a dir, PORT A, B, C i D denotats per PA, PB, PC i PD respectivament. Cada pin GPIO també té una altra funcionalitat especial. Per exemple, el PB5 (pin 5 de PORT B) no només pot funcionar com a pin GPIO, sinó també com a pin SDA per a la comunicació I2C i com a pin de sortida Timer 1. Per tant, si fem servir aquest pin per a propòsits GPIO senzills, com ara connectar un LED, no podrem utilitzar I2C i el LED alhora. Malauradament, el LED incorporat està connectat a aquest pin, de manera que no tenim molta opció aquí i, en aquest programa, no utilitzarem I2C, de manera que no suposa un gran problema.
Descripció del pinout i consells per a la selecció GPM STM8S103F
En veritat, no estaria de més utilitzar PA1 un pin d'entrada i només funcionaria. Però deliberadament ho vaig plantejar per oferir-me l'oportunitat de mostrar-vos algunes trampes habituals en què podríeu caure quan seleccioneu pins GPIO en un microcontrolador nou. El millor per evitar les trampes és llegir els detalls del pin i la descripció del pin proporcionats al full de dades STM8S103F3P6. Per a la descripció dels pins del microcontrolador STM8S103F3P6, esmentats al full de dades, es mostren a continuació les imatges.

Els pins d'entrada del nostre microcontrolador poden ser flotants o pull-up febles i els pins de sortida poden ser Open Drain o Push-pull. La diferència entre els pins de sortida Open Drain i Push-Pull ja és discutida, per tant no entrarem en detalls. Per simplificar-ho, un pin de sortida Open Drain pot fer que la sortida sigui tan baixa com no alta, mentre que un pin de sortida push-pull pot fer que la sortida sigui tan alta com alta.
A part de la taula anterior, també podeu observar que un pin de sortida pot ser de sortida ràpida (10 Mhz) o de sortida lenta (2 MHz). Això determina la velocitat GPIO; si voleu canviar els vostres pins GPIO entre alt i baix molt ràpidament, podem triar la sortida ràpida.

Alguns pins GPIO del nostre controlador admeten True Open Drain (T) i High Sink Current (HS) com s’esmenta a la imatge anterior. Una diferència considerable entre el drenatge obert i el drenatge obert real és que la sortida connectada al drenatge obert no es pot treure més que la tensió de funcionament del microcontrolador (Vdd), mentre que un veritable pin de sortida de drenatge obert es pot treure més alt que Vdd. Els pins amb capacitat elevada d’aigüera vol dir que pot enfonsar-se més corrent. La font i el corrent d’enfonsament de qualsevol pin GPIO HS és de 20 mA, mentre que la línia elèctrica pot consumir fins a 100 mA.
Fent una ullada més de prop a la imatge anterior, notareu que gairebé tots els pins GPIO són de tipus High Sink Current (HS), excepte PB4 i PB5, que són True Open Drain Type (T). Això vol dir que aquests passadors no es poden fer alts, no podran proporcionar 3,3 V fins i tot quan es posin alts. És per això que el led integrat està connectat a un 3.3V i es connecta a terra a través de PB5 en lloc d’alimentar-lo directament des del pin GPIO.

Consulteu la pàgina 28 del full de dades per obtenir la descripció detallada dels pins. Com s'esmenta a la imatge anterior, PA1 es configura automàticament com a pull-up feble i no es recomana utilitzar-lo com a pin de sortida. De totes maneres es pot utilitzar com a pin d'entrada junt amb un polsador, però vaig decidir utilitzar PA2 només per intentar habilitar l'extracció del programa. Aquestes són només algunes coses bàsiques que seran útils quan escrivim programes molt més complicats. De moment, està bé si moltes coses et rebotessin del cap, hi entrarem en la capa en altres tutorials.
Programació de STM8S per a entrada i sortida GPIO mitjançant SPL
Creeu un espai de treball i un projecte nou tal com hem comentat al nostre primer tutorial. Podeu afegir tots els fitxers de capçalera i origen o només afegir els fitxers gpio, config i stm8s. Obriu el fitxer main.c i comenceu a escriure el vostre programa.

Assegureu-vos que heu inclòs els fitxers de capçalera tal com es mostra a la imatge superior. Obriu el fitxer main.c i inicieu el codi. El codi main.c complet es pot trobar a la part inferior d’aquesta pàgina i també podreu descarregar el fitxer del projecte des d’aquí. L’explicació del codi és la següent, també podeu consultar el manual de l’usuari SPL o el vídeo enllaçat a la part inferior d’aquesta pàgina si esteu confós sobre la part de codificació.
Desinicialització del port requerit
Comencem el nostre programa desinicialitzant els ports necessaris. Com ja hem comentat anteriorment, cada pin GPIO tindrà moltes altres funcions associades, a part de funcionar com una entrada i una sortida normals. Si aquests pins s'han utilitzat prèviament per a algunes altres aplicacions, s'hauria de desinicialitzar abans de fer-los servir. No és obligatori, però, és una bona pràctica. Les dues línies de codi següents s’utilitzen per desinicialitzar el port A i el port B. Simplement utilitzeu la sintaxi GPIO_DeInit (GPIOx); i mencioneu el nom del port en lloc de x.
GPIO_DeInit (GPIOA); // prepareu el port A perquè funcioni GPIO_DeInit (GPIOB); // prepara el Port B per treballar
Declaració GPIO d’entrada i sortida
A continuació, hem de declarar quins pins s'utilitzaran com a entrada i quins com a sortida. En el nostre cas, s’utilitzarà el pin PA2 com a entrada, també declararem aquest pin amb Pull-up intern per tal de no haver-ne d’utilitzar externament. La sintaxi és GPIO_Init (GPIOx, GPIO_PIN_y, GPIO_PIN_MODE_z); . On x és el nom del port, y és el número de PIN i z és el mode Pin GPIO.
// Declareu PA2 com a pin d'entrada pull up GPIO_Init (GPIOA, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);
A continuació, hem de declarar els pins PA3 i PB5 com a sortida. De nou són possibles molts tipus de declaracions de sortida, però utilitzarem "GPIO_MODE_OUT_PP_LOW_SLOW", cosa que significa que la declararem com a pin de sortida de tipus push-pull a velocitat lenta. I, per defecte, el valor serà baix. La sintaxi serà la mateixa.
GPIO_Init (GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW); // Declareu PB5 com a pin de sortida push pull GPIO_Init (GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);
La següent instantània del manual de l'usuari SPL esmenta tots els modes GPIO possibles (z).

Bucle while infinit
Després de la declaració del pin, hem de crear un bucle infinit dins del qual seguirem parpellejant el LED per sempre i supervisarem l’estat del botó per canviar el LED. El bucle infinit es pot crear amb un temps (1) o amb un per a (;;) . Aquí he utilitzat while (1).
mentre (1) {}
Comprovació de l’estat del pin d’entrada
Hem de comprovar l’estat del pin d’entrada, la sintaxi per fer-ho és GPIO_ReadInputPin (GPIOx, GPIO_PIN_y); on x és el nom del port i y és el número de PIN. Si el pin és alt, obtindrem '1' i, si el pin és baix, obtindrem un '0'. Hem acostumat a dins d’un bucle if per comprovar si el pin és alt o baix.
if (GPIO_ReadInputPin (GPIOA, GPIO_PIN_2)) // si es prem el botó
Fer un pin GPIO alt o baix
Per fer un pin GPIO alt o baix, podem utilitzar GPIO_WriteHigh (GPIOx, GPIO_PIN_y); i GPIO_WriteLow (GPIOx, GPIO_PIN_y); respectivament. Aquí hem fet que el LED s’encengui si es prem el botó i s’apagui si no es prem el botó.
if (GPIO_ReadInputPin (GPIOA, GPIO_PIN_2)) // si es prem el botó GPIO_WriteLow (GPIOA, GPIO_PIN_3); // LED ON encès GPIO_WriteHigh (GPIOA, GPIO_PIN_3); // LED apagat
Commutació d'un pin GPIO
Per canviar un pin GPIO, tenim GPIO_WriteReverse (GPIOx, GPIO_PIN_y); trucant a aquesta funció canviarà l'estat del pin de sortida. Si el passador és alt, es canviarà a baix i, si és baix, es canviarà a alt. Estem utilitzant aquesta funció per parpellejar el LED integrat al PB5.
GPIO_WriteReverse (GPIOB, GPIO_PIN_5);
Funció de retard
A diferència d'Arduino, el compilador còsmic no té una funció de retard predefinida. Per tant, n’hem de crear un per nosaltres mateixos. La meva funció de retard es dóna a continuació. El valor del retard es rebrà a la variable ms i utilitzarem dos per a bucle per mantenir o executar el programa. Igual que _asm ("nop") és una instrucció de muntatge que no significa cap operació. Això significa que el controlador entrarà en bucle al bucle for sense realitzar cap operació, creant així un retard.
retard buit (int ms) // Definició de la funció {int i = 0; int j = 0; for (i = 0; i <= ms; i ++) {for (j = 0; j <120; j ++) // Nop = Fosc / 4 _asm ("nop"); // No realitzeu cap operació // Codi de muntatge}}
Càrrega i prova del programa
Ara que el nostre programa està a punt, el podem carregar i provar. Un cop carregat, el meu maquinari funcionava com s’esperava. El LED vermell integrat parpellejava cada 500 mil·lisegons i el LED verd extern s’encenia cada vegada que premia l’interruptor.

El funcionament complet es pot trobar al vídeo enllaçat a continuació. Quan hàgiu arribat a aquest punt, podeu provar de connectar l'interruptor i el LED a diferents pins i tornar a escriure el codi per entendre el concepte. També podeu jugar amb el temps de retard per comprovar si heu entès els conceptes amb claredat.
Si teniu cap pregunta, deixeu-les a la secció de comentaris a continuació i, per a altres qüestions tècniques, podeu utilitzar els nostres fòrums. Gràcies per seguir-ho, ens veiem al següent tutorial.
