STM32F407(STM32F4-DISCOVERY) – Nem szabványos megközelítés – Szabványos könyvtár 1. rész. Az STM32F10x SPL konfigurálása makródefiníciókkal

Eddig a pontig a szabványos kernelkönyvtárat, a CMSIS-t használtuk. Ahhoz, hogy egy portot a kívánt üzemmódra állíthassunk, meg kellett keresnünk az adott funkcióért felelős regisztert, és egy nagy dokumentumban meg kellett keresnünk a folyamattal kapcsolatos egyéb információkat. A dolgok még fájdalmasabbak és rutinosabbak lesznek, amikor elkezdünk dolgozni egy időzítővel vagy ADC-vel. A regiszterek száma sokkal nagyobb, mint az I/O portoké. Kézi beállítás sok időt vesz igénybe és növeli a hibázás esélyét. Ezért sokan szívesebben dolgoznak a szabványos perifériakönyvtárral - StdPeriph. Mit ad? Egyszerű – az absztrakció szintje növekszik, nem kell belemenni a dokumentációba, és többnyire a regiszterekre gondolni. Ebben a könyvtárban az MK periféria összes működési módja és paramétere struktúrák formájában van leírva. Most egy periféria konfigurálásához csak az eszköz inicializálási funkcióját kell meghívnia kitöltött szerkezettel.

Az alábbi képen az absztrakciós szintek sematikus ábrázolása látható.

A CMSIS-sel dolgoztunk (ami a "legközelebb" van a maghoz), hogy megmutassuk, hogyan működik a mikrokontroller. A következő lépés a standard könyvtár, amelyet most megtanulunk használni. Ezután következnek az eszközillesztők. *.c \ *.h fájlokként értendők, amelyek kényelmes szoftveres felületet biztosítanak bármely eszköz vezérléséhez. Például ezen a tanfolyamon a max7219 chiphez és az esp8266 WiFi modulhoz biztosítunk illesztőprogramokat.

Egy szabványos projekt a következő fájlokat tartalmazza:


Először is természetesen ezek azok a CMSIS fájlok, amelyek lehetővé teszik, hogy a szabványos könyvtár működjön együtt a kernellel, már beszéltünk róluk. Másodszor, a szabványos könyvtári fájlok. Harmadszor pedig a felhasználói fájlok.

A könyvtári fájlok megtalálhatók a cél MK-nak szentelt oldalon (nálunk ez stm32f10x4), a szekcióban Tervezési források(a CooCox IDE-ben ezek a fájlok a fejlesztői környezet tárolójából töltődnek le). Minden periféria két fájlnak felel meg - fejléc (*.h) és forráskód(*.c). Részletes leírás megtalálható a támogatási fájlban, amely a honlapon található könyvtár archívumában található.

  • stm32f10x_conf.h - könyvtár konfigurációs fájl. A felhasználó csatlakoztathatja vagy leválaszthatja a modulokat.
  • stm32f10x_ppp.h – periféria fejlécfájlja. A ppp helyett lehet gpio vagy adc.
  • stm32f10x_ppp.c - C nyelven írt periféria-illesztőprogram.
  • stm32f10x_it.h - fejlécfájl, amely tartalmazza az összes lehetséges megszakításkezelőt (prototípusukat).
  • Az stm32f10x_it.c egy sablon-forráskód fájl, amely megszakítási szolgáltatási rutint (ISR) tartalmaz a Cortex M3 kivételes helyzeteihez. A felhasználó saját ISR-t adhat hozzá a használt perifériákhoz.

A szabványos könyvtár és a perifériák elnevezési függvényeket és jelöléseket alkalmaznak.

  • A PPP a perifériák, például az ADC rövidítése.
  • Rendszer-, fejléc- és forráskódfájlok – kezdje az stm32f10x_ karakterekkel.
  • Az egy fájlban használt állandók abban a fájlban vannak meghatározva. Az egynél több fájlban használt konstansok a fejlécfájlokban vannak meghatározva. A perifériakönyvtár minden állandója leggyakrabban NAGYBETŰVEL van írva.
  • A regisztereket konstansként kezeli, és NAGYBETŰ betűknek is nevezik.
  • A perifériaspecifikus függvénynevek tartalmaznak egy mozaikszót is, például USART_SendData() .
  • Az egyes perifériás eszközök konfigurálásához a PPP_InitTypeDef struktúrát használjuk, amelyet a PPP_Init() függvénynek adunk át.
  • Az inicializálás megszüntetéséhez (az érték alapértelmezettre állításához) használhatja a PPP_DeInit() függvényt.
  • A perifériák engedélyezését vagy letiltását lehetővé tevő függvény neve PPP_Cmd().
  • A megszakítás engedélyezése/letiltása függvény neve PPP_ITConfig.

VAL VEL teljes listaújra megnézheti a könyvtár támogatási fájlját. Most írjuk át a villogó LED-et a szabványos perifériakönyvtár segítségével!

A munka megkezdése előtt nézzük meg az stm32f10x.h fájlt, és keressük meg a sort:

#define USE_STDPERIPH_DRIVER

Ha a projektet a nulláról konfigurálja a letöltött archívum könyvtári fájljaival, akkor törölnie kell ezt a sort. Lehetővé teszi a szabványos könyvtár használatát. Ez a definíció (makró) arra utasítja az előfeldolgozót, hogy tartalmazza az stm32f10x_conf.h fájlt:

#ifdef USE_STDPERIPH_DRIVER #include "stm32f10x_conf.h" #endif

Ez a fájl modulokat tartalmaz. Ha csak meghatározottakra van szüksége, tiltsa le a többit, ezzel időt takaríthat meg a fordítás során. Nekünk, ahogy azt sejteni lehetett, szükségünk van RTC és GPIO modulokra (a jövőben azonban szükségünk lesz a _bkp.h, _flash, _pwr.h, _rtc.h, _spi.h, _tim.h, _usart.h fájlokra is):

#include "stm32f10x_flash.h" // for init_pll() #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h"

Mint legutóbb, először engedélyeznie kell a B port órajelét. Ezt az stm32f10x_rcc.h fájlban deklarált függvény teszi meg:

Érvénytelen RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

A FunctionalState enum az stm32f10x.h fájlban van meghatározva:

Typedef enum (DISABLE = 0, ENABLE = !DISABLE) FunctionalState;

Deklaráljunk egy szerkezetet a lábunk felállításához (az stm32f10x_gpio.h fájlban található):

GPIO_InitTypeDef LED;

Most ki kell töltenünk. Nézzük ennek a szerkezetnek a tartalmát:

Typedef struct ( uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode; ) GPIO_InitTypeDef;

Az összes szükséges felsorolás és konstans ugyanabban a fájlban található. Ekkor az újraírt init_leds() függvény a következő formában jelenik meg:

Void led_init() ( // Órajel engedélyezése RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // A szerkezet deklarálása és kitöltése GPIO_InitTypeDef LED; LED.GPIO_Pin = GPIO_Pin_0; LED.GPIO_Pin = GPIO_Pin_0; LED_GPIO_Speed=GPIOPe Mode_ Out_PP; // Inicializálja a GPIO_Init(GPIOB, &LED); ) portot

Írjuk át a main() függvényt:

Int main(void) ( led_init(); while (1) ( GPIO_SetBits(GPIOB, GPIO_Pin_0); delay(10000000); GPIO_ResetBits(GPIOB, GPIO_Pin_0); delay(10000000); ) )

A lényeg, hogy átérezzük az inicializálási sorrendet: kapcsoljuk be a periféria órát, deklaráljuk a szerkezetet, töltsük ki a struktúrát, hívjuk meg az inicializálási metódust. Más perifériás eszközök általában hasonló módon vannak konfigurálva.

Ebben a kiadványban megpróbálok az STMicroelectronics gyártó cég szabványos perifériáinak könyvtárán alapuló STM32F10x mikrokontrollerekkel való gyors kezdéshez a főbb pontokra összpontosítani.

A cikk az Eclipse CDT-t fogja használni fejlesztői környezetként. Mivel a fő hangsúly a programkódon lesz, biztonságosan elvégezheti az összes manipulációt a Code::Blocks-ban.

Az ARM mikrokontrollerek általános projektstruktúráját a cikkem ismerteti.

Itt röviden emlékeztetem Önt arra, hogy egy ARM mikrovezérlők (különösen az STM32F10x) projekt elkészítéséhez szükség lesz egy linker szkriptre és egy C-Startup fájlra.

A linker script egy olyan fájl, amely utasításokat tartalmaz a programkód és az adatok mikrokontroller memóriájában való elhelyezéséhez. Parancsot adhat a programkódnak a Flash program memóriába vagy az SRAM adatmemóriába való betöltésére.

A különböző mennyiségű program- és adatmemóriával rendelkező mikrovezérlők eltérő elrendezési szkripteket igényelnek. Beszerezhetők a mikrokontroller gyártójától - STMicroelectronics.
Csomagolja ki az STM32F10x szabványos perifériakönyvtárat az ARM_Toolchain/Lib/stm32f10x_stdperiph_lib.zip archívumból.
Példaprojekteket tartalmaz különféle fejlesztői környezetekhez (IAR EWB, Keil uVision, Atollic True Studio stb.). Számunkra az Atollic True Studio a legközelebb, mivel ez az Eclipse egy módosítása.
Menjen a Project/StdPeriph_Template/TrueSTUDIO könyvtárba, ott több alkönyvtár található, amelyek neve megegyezik az STM3210x-EVAL fejlesztői kártyák nevével.

Nézze meg, melyik kártya használja ugyanazt a mikrokontroller vonalat, mint az Öné. Másolja az stm32_flash.ld fájlt a megfelelő könyvtárból a projektbe.

Lehetőség van olyan univerzális szkript létrehozására is, amelyben csak a program és az adatmemória mennyisége változik a használt mikrokontrollernek megfelelően.

Az STM32 mikrokontrollerek indítókódja (C-Startup) C vagy Assembler nyelven írható.
Bár az STM32F10x Standard Peripheral Library-t (rövidítve STM32F10x SPL) gyakran kritizálják hibái miatt, ez a legegyszerűbb módja annak, hogy gyorsan elkezdhessük az STM32 programozását.
De mindig azt akarod, hogy legyen valamiféle alternatíva. Sőt, sok van belőlük, pl programozás assembly nyelven :)

Ez a legnehezebb és legértelmetlenebb út. A második mód a CMSIS könyvtár használata, amely szintaxist biztosít a C nyelvi struktúrák eléréséhez a különböző mikrokontroller-perifériák eléréséhez. A legegyszerűbb és leglogikusabb módja (szerintem) a könyvtárak használata.

Ha kategorikusan ellenzi az STM32F10x SPL-t, akkor van egy másik alternatíva, különösen az Ön számára - a libopencm3 könyvtár. Ebben a példák nagy része az STM32F10x mikrovezérlők fő sorozata köré összpontosul, de csak idő kérdése, hogy mikor jelennek meg más sorozatok (STM32F2xx/4xx) példái. Bármikor csatlakozhat a libopencm3 projekthez, és felgyorsíthatja ezt a folyamatot.

A CMSIS szabvány szintén választható a programokban való használatra.
Enélkül is megteheti, ha némi erőfeszítést és időt fordít a HAL (Hardware Abstraction Layer) szint megvalósítására a C programozási nyelvben.

Egyes esetekben ez a módszer lehet az egyetlen hozzáférhető módon. Például az Ön szervezete ARM által fejlesztett számítási magokon és iparág-specifikus perifériákon alapuló egyedi chipeket használ.

Vagy C nyelvű szoftvert kell implementálnia az ARM9 maggal rendelkező mikrokontrollerekhez, amelyekhez a gyártók a készek használatára összpontosítanak. operációs rendszer(Linux, QNX, Windows CE), ezért a gyártók nem biztosíthatnak programkönyvtárakat a C nyelven való programozáshoz tiszta formában vagy egy könnyebb RTOS-szal kombinálva.

Szerencsére a Cortex-M3 magra épülő mikrokontrollerek gyártói nagyszámú kódkönyvtárat biztosítanak a fejlesztőknek. Ez vonatkozik az STM32 mikrokontrollerekre is.
Folytassuk az STM32F10x SPL könyvtár vizsgálatát. Egy példa segítségével megvizsgáljuk.
Megnyithatja ezt a példát, vagy létrehozhatja saját projektjét a semmiből, hogy jobban megértse a teljes folyamatot, ami történik.

A második esetben felsorolom a szükséges lépéseket:

  • Hozzon létre egy új üres projektet az Eclipse-ben
  • Másolja be az elrendezési szkriptet és az indítófájlt a projektbe
  • Hozzon létre egy újat vagy másoljon egy sablont Makefile
  • Ha a példámból származó Makefile-t sablonként használja, létre kell hoznia az src, inc, bin, obj könyvtárakat a projekten belül, és létre kell hoznia a Debug és Release alkönyvtárakat a bin és obj könyvtárakon belül.
  • Másolja ki a szükséges forrás- és fejlécfájlokat a CMSIS és STM32F10x SPL könyvtárakból.
  • Végezze el a szükséges módosításokat a Makefile sablon felhasználói beállítások részében, ha van ilyen.
  • Hozzon létre új célokat „Debug”, „cleanDebug”, „Release”, „cleanRelease”, „Program” az Eclipse „make target” ablakában.
  • Indítsa el a „Debug” célt, és kövesse nyomon a végrehajtását a „Console” ablakban.

Az anyag jobb megértése érdekében a cikket több független bekezdésre osztottam, amelyek mindegyike az STM32F10x SPL könyvtárral való munka egyetlen aspektusát írja le.

Az STM32F10x SPL konfigurálása makródefiníciókkal

A könyvtár konfigurálásához előre meghatározott makróértékeket használunk, amelyeket most figyelembe veszünk.
Előfeldolgozó direktívával beállíthatók a fejlécfájlokon belül #define vagy adja át a makródefiníciók értékeit a kulcson keresztül -D GCC fordító.
Példámban a második módszert használom.
A Makefile változóban DEFINE Az STM32F10x SPL könyvtár fordításához szükséges makrókat tartalmazza.
Makró definíció STM32F10X_MD megadja, hogy a használt mikrokontroller a vonalhoz tartozik-e Közepes sűrűségű.
Ide tartoznak a 64 és 128 kB közötti Flash memóriával rendelkező mikrokontrollerek.
Az alábbi táblázat felsorolja a mikrovezérlők különböző sorozataihoz tartozó makrók neveit:

Sorozat neve Makró Leírás
Alacsony sűrűségű érték vonal STM32F10X_LD_VL Flash memória kapacitással 16 - 32 kB
Kis sűrűségű STM32F10X_LD
Flash memória kapacitással 16 - 32 kB
Közepes sűrűségű értéksor STM32F10X_MD_VL Flashmemória
64 - 128 kB
Közepes sűrűségű STM32F10X_MD STM32F101xx, STM32F102xx, STM32F103xx sorozatú mikrovezérlők Flash memóriával 64 - 128 kB
Nagy sűrűségű érték vonal STM32F10X_HD_VL STM32F100xx sorozatú mikrokontrollerek hangerővel
Flash memória 256 - 512 kB
Nagy sűrűségű STM32F10X_HD hangerővel
Flash memória 256-512kB
XL-sűrűség STM32F10X_XL
Flash memória 512 - 1024 kB
Csatlakozási vonal STM32F10X_CL

A mikrokontroller órajel-frekvenciájának beállításához törölnie kell a szükséges órajel-frekvencia értékkel rendelkező makrót a system_stm32f10x.c fájlban.

#ha van megadva (STM32F10X_LD_VL) || (meghatározott STM32F10X_MD_VL) || (definiálva: STM32F10X_HD_VL) #define SYSCLK_FREQ_24MHz 24000000 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000LK_00F6 240000LK_000 SYQ_30MHz 00 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 * / #define SYSCLK_FREQ_72MHz 72000000 #endif

#ha van megadva (STM32F10X_LD_VL) || (meghatározott STM32F10X_MD_VL) || (meghatározott STM32F10X_HD_VL)

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

#define SYSCLK_FREQ_24MHz 24000000

#más

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz 24000000 */

/* #define SYSCLK_FREQ_36MHz 36000000 */

/* #define SYSCLK_FREQ_48MHz 48000000 */

/* #define SYSCLK_FREQ_56MHz 56000000 */

#define SYSCLK_FREQ_72MHz 72000000

#endif

Rendeltetésszerű használat kvarc rezonátor 8 MHz-es frekvenciával az összes fő esetében
sorozatú mikrokontrollerek, kivéve a Connectivity vonalat, amelyhez 25 MHz-es kvarc rezonátor telepítése szükséges.
Ha kvarcrezonátorokat használ más frekvenciaértékekkel, akkor módosítania kell a HSE_VALUE makró értékét az stm32f10x.h fejlécfájlban, és ennek megfelelően módosítania kell az összes függő függvényt.
A USE_STDPERIPH_DRIVER makró célját nem nehéz kitalálni – az STM32F10x szabványos perifériakönyvtárat kell használni.
USE_FULL_ASSERT – használja az ASSERT makrót a program hibakereséséhez.

Az assert_param makró használata a könyvtárban

Minden STM32F10x SPL könyvtárfüggvény az assert_param makrót használja az argumentumok ellenőrzésére.
Ez a makró ellenőrzi a tesztelt függvény argumentumát tartalmazó kifejezést, hogy egyenlő-e nullával. Ha a kifejezés értéke nulla, akkor az argumentumhibakezelő assert_failed függvény meghívásra kerül, ellenkező esetben (a kifejezés nem nulla) az argumentumellenőrzés sikeres.
Meg kell valósítania az assert_failed függvényt a programban.
Megjeleníti a hibaüzenetet, a fájl nevét és a hibát okozó kódsor számát.
A debug_printf makró az USART-n keresztül is kiadható a standard new_lib könyvtár vagy például Mr. Chen könyvtár használatával.

#define debug_printf xprintf /* printf */ #ifdef USE_FULL_ASSERT void assert_failed(uint8_t* fájl, uint32_t sor) ( debug_printf("Hibás paraméterérték: %s fájl a %d\r\n sorban", fájl, (int)sor) ; while (1) ( ) )/* assert_failed */ #endif/*USE_FULL_ASSERT*/

#define debug_printf xprintf /* printf */

#ifdef USE_FULL_ASSERT

void assert_failed (uint8_t * fájl , uint32_t sor)

debug_printf( "Hibás paraméterérték: %s fájl a %d\r\n sorban", fájl , (int ) sor ) ;

míg (1)

) /* assert_failed */

#endif/*USE_FULL_ASSERT*/

A kódban megvalósított assert_failed függvény csak akkor kerül felhasználásra, ha a USE_FULL_ASSERT makró deklarálva van. Ellenkező esetben az összes hibakereső kód kizárásra kerül a forrásból. Ez a funkció az illesztőprogram-könyvtár-beállítások stm32f10x_conf.h fejlécfájljában van megvalósítva.

#ifdef USE_FULL_ASSERT #define assert_param(expr) ((kifejezés) ? (void)0: assert_failed((uint8_t *)__FILE__, __LINE__)) void assert_failed(uint8_t* fájl, uint32_t sor); #else #define assert_param(expr) ((void)0) #endif /* USE_FULL_ASSERT */

#ifdef USE_FULL_ASSERT

#define assert_param(expr) ((kifejezés) ? (void)0: assert_failed((uint8_t *)__FILE__, __LINE__))

void assert_failed (uint8_t * fájl , uint32_t sor ) ;

#más

#define assert_param(expr) ((void)0)

#endif /* USE_FULL_ASSERT */

Nincs itt sok magyaráznivaló. Nézzünk egy példát az assert_param használatára.

void set_param(uint8_t * param, uint8_t érték) ( assert_param(param != NULL); *param = érték; )/*set_param*/

void set_param (uint8_t * param , uint8_t érték )

assert_param (param != NULL ) ;

* param = érték ;

) /*set_param*/

A függvény egy argumentumként átadott mutatón keresztül állítja be a paraméter értékét. Ha a USE_FULL_ASSERT makró nincs deklarálva, akkor feltételezhetjük, hogy a sorok
Az assert_param(param != NULL) egyszerűen nincs a kódban, különben a paraméter be van jelölve ebben a definícióban.
Ha a mutató nincs definiálva, akkor a param != NULL érték hamis lesz, és az assert_failed függvény lefut, amely az USART-n keresztül kiadja a hibás fájl nevét és sorszámát, majd ciklust, megakadályozva ezzel az érték megadását. egy meghatározatlan címhez van rendelve a memóriában.
Egyáltalán nem kötelező az assert_param makrót használnia a kódban, hanem a könyvtári kódban
STM32F10x SPL mindenhol használják.
A set_param függvény argumentumhiba-ellenőrzéssel megvalósítható az assert_param használata nélkül.

#define ERROR (-1) #define OK (0) int set_param(uint8_t * param, uint8_t value) (>int r = HIBA; if (param == NULL) visszatér r; *param = érték; r = OK; return r ; )/*set_param*/

#define ERROR (-1)

#define OK (0)

int set_param (uint8_t * param , uint8_t érték)

int r = HIBA ;

if (param == NULL )

return r ;

* param = érték ;

r = OK ;

return r ;

) /*set_param*/

C-Startup fájl az STM32F10x SPL könyvtárban

A start kódban a mikrokontroller kezdetben inicializálódik, a verem konfigurálva van, a BSS szakasz visszaáll, és a main() fő függvény meghívódik.
A kezdőkódnak nincs közvetlen kapcsolata az STM32F10x SPL könyvtárral. Ebben a rendszerindító kódban azonban a program main() függvényének meghívása előtt a mikrokontroller SystemInit() inicializálási függvénye kerül meghívásra, amely a CMSIS része.
Könnyen megtalálható a CMSIS könyvtárban.
Lépjen a Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/TrueSTUDIO könyvtárba, és másolja ki a szükséges fájlt. Már csak azt kell kideríteni, hogy a projektben használt mikrokontroller melyik vonalhoz tartozik.
Ehhez tekintse meg a következő táblázatot:

Sorozat neve Fájl név Leírás
Alacsony sűrűségű érték vonal startup_stm32f10x_ld_vl.s STM32F100xx sorozatú mikrokontrollerek hangerővel
Flash memória 16-32kB
Kis sűrűségű startup_stm32f10x_ld.s STM32F101xx, STM32F102xx, STM32F103xx mikrovezérlők
Flash memória kapacitással 16 - 32 kB
Közepes sűrűségű értéksor startup_stm32f10x_md_vl.s STM32F100xx sorozatú mikrovezérlők
Közepes sűrűségű startup_stm32f10x_md.s STM32F101xx, STM32F102xx, STM32F103xx mikrovezérlők
Flash memória kapacitással 64 - 128 kB
Nagy sűrűségű érték vonal startup_stm32f10x_hd_vl.s STM32F100xx sorozatú mikrovezérlők
Nagy sűrűségű startup_stm32f10x_hd.s STM32F101xx, STM32F103xx sorozatú mikrovezérlők
Flash memória kapacitással 256 - 512 kB
XL-sűrűség startup_stm32f10x_xl.s STM32F101xx, STM32F103xx sorozatú mikrovezérlők
Flash memória kapacitással 512 - 1024 kB
Csatlakozási vonal startup_stm32f10x_cl.s STM32F105xx és STM32F107xx sorozatú mikrovezérlők

Az indítófájl tartalmazza a megszakítási és kivételvektor-kezelők nevét, de csak a reset vektorkezelő van megvalósítva, amelyen belül a main() függvény meghívása előtt az összes kezdeti inicializálás megtörténik.
Az összes többi kivételkezelő megvalósítása az alkalmazásprogramozó felelőssége. Ha a programod nem használ kezelőket, akkor nem szükséges regisztrálni őket. Ha kivétel történik, akkor az alapértelmezett kezelő kerül felhasználásra – a programkód hurkolása.

A CMSIS könyvtár összetétele

Ahogy a kiadványban korábban írtuk, a CMSIS könyvtár hozzáférést biztosít a mikrovezérlők perifériás moduljaihoz a C nyelvi struktúrák elemeit használva.
Ennek a könyvtárnak a megvalósítása két részre oszlik. Az első rész hozzáférést biztosít a Cortex-M3 mag perifériájához, a második rész pedig hozzáférést biztosít a perifériához konkrét modell mikrokontroller.
Mivel a CMSIS szabvány minden Cortex-M3 maggal rendelkező mikrokontrollerre vonatkozik, az első rész megvalósítása minden gyártónál azonos lesz, de a második rész gyártónként eltérő lesz.
A CMSIS számos fejléc- és forrásfájlt tartalmaz. Az első rész a következő fájlokat tartalmazza:

  • mag_cm3.h
  • mag_cm3.c

A CMSIS második része tartalmazza a C-Startup fájlt, valamint a következő fájlokat:

  • stm32f10x.h
  • system_stm32f10x.h
  • system_stm32f10x.c

Az stm32f10x.h fejléc makródefiníciókat tartalmaz az stm32f10x mikrovezérlők perifériamoduljainak eléréséhez.
A system_stm32f10x.h és system_stm32f10x.c fájlok végrehajtják a mikrokontroller kezdeti inicializálását.

Az STM32F10x SPL könyvtár összetétele és konfigurációja

A könyvtár az stm32f10x_ előtaggal rendelkező perifériamodulokkal azonos nevű forrás- és fejlécfájlokból áll.
Például az USART modullal való interakció megvalósítását az stm32f10x_usart.h és az stm32f10x_usart.c fájl tartalmazza.
Vannak konvenciók a könyvtári elemek elnevezésére és bizonyos kódolási szabályokra, amelyeket a dokumentáció ismertet.
A könyvtár tartalmazza a perifériás mikrovezérlő modulok illesztőprogramjainak megvalósítását.
A könyvtárelemek nevei a következő rövidítéseket használják a perifériás modulokra:

Betűszó Periféria modul
ADC analóg-digitális átalakító
BKP biztonsági mentési regiszterek
TUD CAN interfész
CEC fogyasztás szabályozó
CRC ellenőrző összeg számítási modul
DAC digitális-analóg átalakító
DBGMCU mikrokontroller hibakeresés
DMA közvetlen memória hozzáférés vezérlő
EXTI külső megszakításvezérlő
FSMC külső memóriavezérlő
VAKU Flash program memória
GPIO általános célú I/O portok
I2C I2C interfész
I2S I2S (Hang) interfész
IWDG független watchdog időzítő
NVIC beágyazott megszakításvezérlő
PWR teljesítményvezérlő
RCC reset és óravezérlő
RTC valós idejű vezérlő (óra)
SDIO SDIO interfész
SPI SPI interfész
SysTick rendszer időzítő
TIM alap vagy haladó időzítő
USART univerzális soros szinkron-aszinkron
Rádió adó-vevő
WWDG ablakőrző

Ezen betűszavak alapján alakulnak ki a könyvtár szoftvermoduljainak nevei. Nem kell a könyvtár összes modulját használnia.
Ahhoz, hogy csak a szükséges modulokat használja a projektben, a könyvtárat be kell állítani.
Ebből a célból minden STM32F10x SPL könyvtárat használó projektnek rendelkeznie kell egy stm32f10x_conf.h fejlécfájllal.

#include "stm32f10x_gpio.h" //#include "stm32f10x_i2c.h" //#include "stm32f10x_iwdg.h" //#include "stm32f10x_pwr.h" #include "stm32f10x_i2c.h"_r

#include "stm32f10x_gpio.h"

//#include "stm32f10x_i2c.h"

//#include "stm32f10x_iwdg.h"

//#include "stm32f10x_pwr.h"

#include "stm32f10x_rcc.h"

A szükséges modul engedélyezéséhez törölnie kell az utasítás megjegyzését #beleértve a megfelelő fejlécfájlokkal.
Az stm32f10x_conf.h fejlécfájlt az stm32f10x.h tartalmazza, így az STM32F10x SPL könyvtár funkcióinak használatához csak egy stm32f10x.h fejlécfájlt kell szerepeltetnie a forráskódban.

// az stm32f10x.h fájlban #ifdef USE_STDPERIPH_DRIVER #include "stm32f10x_conf.h" #endif

Ismétlem, hogy a projektnek meg kell határoznia a USE_STDPERIPH_DRIVER, USE_FULL_ASSERT makrókat és egy makrót is, amely megadja a használt mikrokontroller sorozatát (például STM32F10X_MD a Medium density vonalhoz).
Ha a szabványos kvarc frekvencia értéket használja, és a vezérlő maximum 72 MHz órajelen működik, akkor nem kell mást módosítania.
Hozzá kell adnia a Makefile-hoz fordítandó könyvtári fájlok listáját.
Például:

SRC += stm32f10x_rcc.c SRC += stm32f10x_gpio.c

SRC += stm32f10x_rcc . c

SRC += stm32f10x_gpio . c

Az STM32F10x SPL könyvtár használata. Működési mechanizmusok

A perifériakönyvtár használatával történő programozás megkezdéséhez a legegyszerűbb, ha megnézzük a könyvtárhoz mellékelt példákat. A példák kódjának megértéséhez azonban alapvető ismeretekkel kell rendelkeznie a könyvtár szintaxisáról és használatáról.
A korábban felsorolt ​​perifériás mikrovezérlő modulok mindegyike kezdetben deaktiválva van, órajelet nem kapnak, és nem fogyasztanak áramot.
A perifériamodul használatához először órajelet kell biztosítania számára. Az órajelet az RCC óra és visszaállító modul szolgáltatja.
Ebből a célból a könyvtár a következő funkciókkal rendelkezik:

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PPPx, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_PPPx, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_PPPx, ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PPPx, ENABLE);

RCC_APB2PeriphClockCmd (RCC_APB2Periph_PPPx, ENABLE) ;

RCC_APB1PeriphClockCmd (RCC_APB1Periph_PPPx, ENABLE) ;

Itt a PPP a modul aktonímájának nevét jelöli (például ADC vagy USART), x pedig a periféria modul száma.
Először is meg kell találnia, hogy a használt modul melyik buszra csatlakozik.
Összességében a Cortex-M3 magarchitektúrával rendelkező mikrovezérlőknek három busza van:
utasítás busz, adatbusz és rendszerbusz. Az utasításbusz a magot a Flash programmemóriához köti. Az adat- és rendszerbuszokat egy AHB (ARM Hi-Speed ​​​​Bus) buszmátrixba egyesítik, amely a magfrekvencián működik. Az AHB busz frekvenciája azonban csökkenthető osztók beépítésével. Az AHB busz nagy sebességű eszközöket köt össze, például a magot és a DMA modult.
Az I/O eszközök az APB1 és APB2 (ARM Peripheral Bus) közbenső buszokon keresztül csatlakoznak az AHB buszhoz.
Az APB2 busz maximális üzemi frekvenciája 72 MHz, az APB1 busz frekvenciája
36 MHz-re korlátozva.
A dokumentációból megtudhatja, hogy az Ön által használt perifériamodul melyik buszhoz csatlakozik, vagy nézze meg az stm32f10x_rcc.h fejlécfájlt.
Nyissa meg ezt a fájlt, és keresse meg egymás után az RCC_AHBPeriph, RCC_APB1Periph és RCC_APB2Periph értékeket.

#define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001) #define RCC_AHBPeriph_DMA2 ((uint32_t)0x00000002) #define RCC_AHBPeriph_SRAM ((uint32_t) #FLIT (RCC_40_00BIT)00x0_ph_0BIT (uint32_t) 0x00000010) #define RCC_AHBPeriph_CRC ((uint32_t)0x00000040)

#define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001)

#define RCC_AHBPeriph_DMA2 ((uint32_t)0x00000002)

#define RCC_AHBPeriph_SRAM ((uint32_t)0x00000004)

#define RCC_AHBPeriph_FLITF ((uint32_t)0x00000010)

#define RCC_AHBPeriph_CRC ((uint32_t)0x00000040)

A makrók neve alapján határozzuk meg, hogy mely modulok melyik buszhoz csatlakoznak. A józan ész segítségével is megállapíthatja, hogy melyik gumiabroncs tartozik a három közül valamelyikhez. Például az USART modul egy bemeneti/kimeneti eszköz, ami azt jelenti, hogy az egyik APB buszhoz csatlakozik. Az USART egy meglehetősen kis sebességű interfész, ezért valószínűleg az APB1 buszhoz csatlakozik.

#define RCC_APB1Periph_USART2 ((uint32_t)0x00020000) #define RCC_APB1Periph_USART3 ((uint32_t)0x00040000) #define RCC_APB1Periph_UART4 ((uint32_t)0APU50xCC0_t) ((uint32_t)0x00100000)

Miután elküldte az órajelet a perifériamodulnak, az inicializálási funkció meghívásával konfigurálhatja annak paramétereit:

PPP_Init(PPP, &PPP_InitStructure);

PPP_Init (PPP , & amp; PPP_InitStructure ) ;

Mivel a perifériamodul inicializálásához sok paramétert kell átadni az inicializálási függvénynek, argumentumként egy struktúrára mutató mutatót használunk. Magát a struktúrát az inicializálási paraméterekkel a memóriában kell létrehozni az inicializálási függvény meghívása előtt, a struktúra elemeihez hozzá kell rendelni a szükséges értékeket:

PPP_InitTypeDef PPP_InitStructure = (érték1, érték2, ..., értékN);/* a struktúra inicializálása deklaráláskor */

Először létrehozhat egy struktúrát, majd hozzárendelheti a szükséges értékeket az elemeihez:

PPP_InitTypeDef PPP_InitStructure; PPP_InitStructure.member1 = érték1; PPP_InitStructure.member2 = érték2; PPP_InitStructure.memberN = valN;

PPP_InitTypeDef PPP_InitStructure ;

PPP_InitStructure . tag1 = érték1 ;

PPP_InitStructure . tag2 = val2 ;

PPP_InitStructure . tagN = valN ;

Nézzünk egy példát az stm32f10xQuickstart projektből:

GPIO_InitTypeDef GPIO_InitStructure; #ifdef USE_STM32H_103 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENGEDÉLYEZÉS); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_InitTypeDef GPIO_InitStructure ;

#ifdef USE_STM32H_103

RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC, ENABLE) ;

GPIO_InitStructure . GPIO_Pin = GPIO_Pin_12 ;

GPIO_InitStructure . GPIO_Speed ​​= GPIO_Speed_50MHz ;

GPIO_InitStructure . GPIO_Mode = GPIO_Mode_Out_PP ;

GPIO_Init(GPIOC, & GPIO_InitStructure);

A GPIO_InitStructure struktúra elemeihez hozzá van rendelve a pin szám, a port mód és sebessége.
A GPIO_Init függvény meghívásával a GPIOC port 12. sora inicializálódik.
A GPIO_Init függvény első argumentuma a GPIOC periféria memóriaterületére mutató mutató, amelyet egy GPIO_TypeDef struktúrára mutató mutatóvá alakítanak át.

// stm32f10x.h #define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)0x10000) ) typedef struct ( __IO uint32_t CRL; __IO uint32_t CRH __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR; __IO uint32_t BRR; __IO uint32_t LCKR; ) GPIO_TypeDef;

// stm32f10x.h

#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

#define PERIPH_BASE ((uint32_t)0x40000000)

typedef struktúra

IO uint32_t CRL ;

IO uint32_t CRH ;

IO uint32_t IDR ;

IO uint32_t ODR ;

IO uint32_t BSRR ;

IO uint32_t BRR ;

IO uint32_t LCKR ;

) GPIO_TypeDef ;

A GPIO_InitStructure struktúra GPIO_InitTypeDef típusú, a fejlécfájlban leírtak szerint
stm32f10x_gpio.h:

//stm32f10x_gpio.h typedef struct ( uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode; )GPIO_InitTypeDef; typedef enum ( GPIO_Speed_10MHz = 1, GPIO_Speed_2MHz, GPIO_Speed_50MHz )GPIOSpeed_TypeDef; typedef enum ( GPIO_Mode_AIN = 0x0, GPIO_Mode_IN_FLOATING = 0x04, GPIO_Mode_IPD = 0x28, GPIO_Mode_IPU = 0x48, GPIO_Mode_Out_OD = 0x14, GPIO_Mód_1 = GPIOut_PPx0 C, GPIO_Mode_AF_PP = 0x18 )GPIOMode_TypeDef;

//stm32f10x_gpio.h

typedef struktúra

uint16_t GPIO_Pin ;

GPIOSpeed_TypeDef GPIO_Speed;

GPIOMode_TypeDef GPIO_Mode ;

) GPIO_InitTypeDef ;

typedef enum

GPIO_Speed_10MHz = 1,

GPIO_Speed_2MHz,

GPIO_Speed_50MHz

) GPIOSpeed_TypeDef ;

typedef enum

(GPIO_Mode_AIN = 0x0,

GPIO_Mode_IN_FLOATING = 0x04,

GPIO_Mode_IPD = 0x28,

GPIO_Mode_IPU = 0x48,

GPIO_Mode_Out_OD = 0x14,

GPIO_Mode_Out_PP = 0x10,

GPIO_Mode_AF_OD = 0x1C,

GPIO_Mode_AF_PP = 0x18

) GPIOMode_TypeDef ;

Amint látja, az inicializált struktúra adattípusai használhatók egyedi típusok, mint a GPIOSpeed_TypeDef, és a perifériás regiszterek inicializálásának megkönnyítése érdekében meghatározott értékekkel rendelkező adattípusok, például GPIOMode_TypeDef.
Minden GPIO tű konfigurálásához 4 bit van lefoglalva.
A következő kép a GPIO nulla bitjének formátumát mutatja:

Mode – kimeneti üzemmód (bemenet/kimenet). Pontosabban, ezek az értékek valamivel nagyobbak; a kimeneti portként konfigurált portok korlátozzák a kimeneti jel maximális frekvenciáját.

Mód Leírás
00 bejárat
01 kimeneti frekvencia 10 MHz-ig
10 kimeneti frekvencia 2 MHz-ig
11 kimeneti frekvencia 50 MHz-ig

CNF – kimeneti konfigurációs bitek. Működési módtól függően:

Fogadja el, hogy a tűkonfigurációs regiszter ilyen struktúrájával a konfiguráció összes bitjének saját maga beállítása rendkívül kényelmetlen lesz. Sokkal egyszerűbb lesz ezt megtenni a GPIO_Init függvénytár funkcióval.
A periféria modul inicializálása után aktiválni kell a PPP_Cmd funkcióval:

PPP_Cmd(PPP, ENGEDÉLYEZÉS);

PPP_Cmd(PPP, ENGEDÉLYEZÉS);

Ez a funkció nem létezik GPIO moduloknál, inicializálás után azonnal használhatja a GPIO lábakat. Emlékeztetni kell arra, hogy a könyvtár csak interfészt biztosít a mikrokontroller hardveréhez. Ha a hardvermodul nem rendelkezik aktiválási/deaktiválási jelzővel, akkor a függvényhívás PPP_Cmd(PPP, ENGEDÉLYEZÉS) lehetetlen.
A GPIOx láb állapotának szabályozásához kimeneti módban és az érték bemeneti vagy kimeneti módban történő olvasásához a könyvtár a következő funkciókat kínálja:

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

void GPIO_SetBits (GPIO_TypeDef * GPIOx , uint16_t GPIO_Pin ) ;

void GPIO_ResetBits (GPIO_TypeDef * GPIOx , uint16_t GPIO_Pin ) ;

uint8_tGPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_tGPIO_Pin) ;

uint16_tGPIO_ReadOutputData(GPIO_TypeDef* GPIOx) ;

uint8_tGPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_tGPIO_Pin) ;

uint16_tGPIO_ReadInputData(GPIO_TypeDef* GPIOx) ;

A többi periféria modul konfigurálása és működése ugyanúgy történik. Vannak azonban eltérések az adott hardvermodul sajátosságai miatt, ezért erősen ajánlom, hogy először tekintsen meg példákat a kiválasztott modul STM32F10x SPL könyvtárhoz való használatára.

Megszakítások és kivételek kezelése

A Cortex-M3 mag tartalmaz egy beágyazott vektorizált megszakításvezérlőt. A vezérlő legfeljebb 240 olyan forrást támogat, amelyek processzormag-megszakításokat okozhatnak. A 240 lehetséges vektorból hány vektort implementálunk egy adott mikrokontroller modellben, az a gyártótól függ. Az Stm32f10x mikrokontrollerek legfeljebb 43 vektorral rendelkezhetnek, ezeket a megszakítási vonalakat maszkolhatónak nevezzük. Ezen kívül van még 15 Cortex-M3 magmegszakítási vektor és egy külső, nem maszkolható EXTI megszakítás.
A vezérlő támogatja a beágyazott megszakításokat, ahol egy másik megszakítás előfordulhat egy kezelőn belül. Ebben a tekintetben minden megszakítási forrásnak megvan a saját prioritása. 16 megszakítási prioritási szint támogatott.
A Cortex-M3 magmegszakítási vektorok rendelkeznek a legmagasabb prioritási értékkel.
A három legmagasabb megszakítási szint vektorokhoz van hozzárendelve, és nem módosíthatók:

Szám Kezelő Prioritás Leírás
1 Reset_Handler -3 (legmagasabb) Vektor visszaállítása
2 NMI_Handler -2 Nem maszkolható megszakítás
3 HardFault_Handler -1 Vészhelyzetek

Az összes többi megszakítási vektorhoz 0 és 15 közötti prioritási szintek rendelhetők.
A legmagasabb prioritási szint alacsonyabb értéknek felel meg. A prioritási szint nem csak egy egyedi vektorhoz rendelhető, hanem vektorok egész csoportjához is. Ez a funkció megkönnyíti a nagyszámú megszakítási vektorral való munkát.
A prioritási csoport beállításához az STM32F10x SPL könyvtár egy funkcióját kell használni.

Régóta, sőt nagyon sokáig nem jelentek meg új cikkek cikkünkben, úgyhogy itt az ideje, hogy utolérjük 😉 Ma megkezdjük az STM32F4 tanulmányozását. És valószínűleg azzal kezdjük, hogy létrehozunk egy új projektet ezekhez a vezérlőkhöz, bár őszintén szólva nem akartam erről cikket írni, mert új projekt itt elvileg ugyanúgy jön létre, mint az STM32F103 (). De még mindig megtörténik, hogy bizonyos nehézségek merülnek fel az STM32F4-nél, ezért ennek ellenére nézzük meg ezt a folyamatot részletesen)

Tehát indítsuk el a Keilt, hozzunk létre egy új projektet - Projekt -> Új uVision projekt. Az új projektet elmentjük valamilyen mappába, majd ki kell választanunk a használni kívánt mikrovezérlőt. Nos, válasszunk, legyen az STM32F407VG:

Kész, a megjelenő párbeszédpanelen kattintson az „Igen” gombra, és az első fájl hozzáadódik a projektünkhöz - startup_stm32f4xx.s. Csakúgy, mint korábban, most is könyvtárakat fogunk használni CMSISÉs Szabványos perifériakönyvtár, de természetesen már az STM32F4xx vezérlőkhöz. Tehát mindenképpen le kell töltenünk őket, és hozzá kell adnunk a szükséges fájlokat a még üres projektünkhöz. Egyébként nem egyszer hallottam különböző emberektől, hogy találkoznak néhány „nem olyan” könyvtárral az F4-hez, és még a legegyszerűbb projekt sincs összerakva. Magam még nem találkoztam ezzel, de itt vannak az általam használt tesztelt könyvtárak:

Szóval, letöltöttük, minden készen áll, most hozzáadjuk a fájlokat a projekthez. A képen látható, mire lesz szükséged:

Nos, az előkészítés befejeződött, most hozzunk létre egy új .c fájlt, amely tartalmazza majd a kódunkat. Menjünk-hoz Fájl->Új, egy üres fájl nyílik meg a Keilben, kattintson rá Fájl->Mentés máskéntés mentse el például teszt.c néven. Mentéskor ne felejtse el megadni a fájl kiterjesztését (.c). A fájl elkészült, nagyszerű, de hozzá kell adnunk a projektünkhöz. Nos, tulajdonképpen nincs benne semmi bonyolult 😉 Írjunk ebbe a fájlba egy üres tesztprogramot:

#include "stm32f4xx.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" /*******************************************************************/ int main() ( while (1 ) ( __NOP() ; ) ) /*******************************************************************/

Szinte minden készen van, már csak a projektbeállításokat kell megnézni - Projekt->Opciók a célhoz… Megnyílik egy ablak sok füllel, itt csak néhányra vagyunk kíváncsiak. Nyissa meg a lapot C/C++és a Define mezőbe ezt írjuk:

Hát lent a mezőn elérési utat kell hozzáadnia a projektben szereplő összes fájlhoz. A lépés befejezése után megnyomhatja az F7 (Build) billentyűt, és a projekt hibák és figyelmeztetések nélkül készül el. Mint látható, semmi bonyolult)

De általában én személy szerint egy kicsit másképp csinálom a dolgokat. Nézze meg ennek a megközelítésnek a hátrányait. Szóval letöltöttük valahonnan a CMSIS és SPL könyvtárakat, hozzáadtunk fájlokat ezekből a mappákból, felírtuk a fájlok elérési útját, minden rendben van. DE! A projekt nem épül másik számítógépre, mivel az elérési utak mind abszolútak, vagyis a számítógéped meghatározott mappáira mutatnak. Egy másik gépen pedig újra el kell végeznie a lépéseket egy új projekt létrehozásához. Ez óriási mínusz. Ezért egy új projekthez általában külön mappát hozok létre, ebben almappákat hozok létre a CMSIS, SPL és egyéb használt könyvtárak számára, és ezekbe helyezem az összes fájlt, amelyre az egyes projektekben szükségem van. Például hozzuk létre az STM32F4_Test mappát az új projektünkhöz és a benne lévő következő mappákat:

Mindent a CMSIS és SPL mappába tettem szükséges fájlokat, amelyet a projekt létrehozásakor adtunk hozzá a cikk elején. Most elindítjuk a Keil-t, létrehozunk egy új projektet, és elmentjük a Project almappába, hogy minden projektfájl egy helyen legyen, és ne okozzon káoszt)

A projekt elkészült, most, mint korábban, egyszerűen hozzáadjuk az összes fájlt az STM32F4_CMSIS és STM32F4_SPL mappákból. A main() függvényt tartalmazó .c tesztfájlunkat a Source mappába helyezzük, és hozzáadjuk a projekthez. Már csak a beállítások konfigurálása van hátra =) Minden ugyanaz - a define mezőbe írjuk:

USE_STDPERIPH_DRIVER,STM32F4XX



Összeállítjuk a projektet - nincs hiba, a repülés normális! Elvileg végül ugyanazt kaptuk, de most a projektet azonnal összeállítják bármely másik számítógépen, minden probléma nélkül, és ez nagyon kényelmes és hasznos) Abszolút minden projektfájl a közelben található, ugyanabban a mappában, és az utak viszonylagossá váltak és nem kell megváltoztatni őket.
Tulajdonképpen ez minden, a közeljövőben mindenképpen teszünk valamit az STM32F4 programozásáért, úgyhogy hamarosan találkozunk!;)

Teljes projekt a példa cikkből -

Jeleztem, hogy a szabványos könyvtár csatlakozik a rendszerhez. Valójában a CMSIS kapcsolódik - az MK általánosított szerkezeti ábrázolásának rendszere, valamint az SPL - a szabványos perifériakönyvtár. Nézzük mindegyiket:

CMSIS
Ez egy fejlécfájl és egy kis kódkészlet az MK magjával és perifériájával végzett munka egységesítésére és strukturálására. Valójában ezek nélkül a fájlok nélkül lehetetlen normálisan dolgozni az MK-val. A könyvtárat az MK-hoz mellékelt dokumentációs oldalon érheti el.
Ezt a könyvtárat a leírás szerint azért hozták létre, hogy egységesítse a felületeket, amikor a Cortex család bármely MK-jával dolgozik. A valóságban azonban kiderül, hogy ez csak egy gyártóra igaz, pl. Más cég mikrokontrollerére váltva szinte a nulláról kénytelen tanulmányozni annak perifériáit.
Bár azok a fájlok, amelyek az MK processzormagjához kapcsolódnak, minden gyártótól azonosak (már csak azért is, mert ugyanaz a processzormag-modelljük van - az ARM IP-blokkjai formájában).
Ezért a rendszermag olyan részeivel való munkavégzés, mint a regiszterek, utasítások, megszakítások és társprocesszor-egységek, mindenki számára szabványos.
Ami a perifériát illeti, az STM32 és az STM8 (hirtelen) szinte hasonló, és ez részben igaz az ST által kiadott többi MK-ra is. A gyakorlati részben megmutatom, milyen egyszerű a CMSIS használata. A használat nehézségei azonban azzal járnak, hogy az emberek vonakodnak elolvasni a dokumentációt és megérteni az MK-tervet.

SPL
Standard Peripheral Library - szabványos periféria könyvtár. Ahogy a neve is sugallja, ennek a könyvtárnak az a célja, hogy absztrakciót hozzon létre az MK perifériájára. A könyvtár fejlécfájlokból áll, amelyekben az MK-perifériák konfigurálásához és kezeléséhez szükséges, ember által olvasható konstansokat deklarálnak, valamint magába a könyvtárba gyűjtött forráskódfájlokat a perifériákkal végzett műveletekhez.
Az SPL a CMSIS egy absztrakciója, amely nem csak egy gyártó összes MCU-jához, hanem általában minden Cortex-Mxx processzormaggal rendelkező MCU-hoz közös felületet biztosít a felhasználónak.
Úgy gondolják, hogy kezdőknek kényelmesebb, mert... lehetővé teszi, hogy ne a perifériák működésére gondoljon, hanem a kód minősége, a megközelítés univerzalitása és az interfészek kötöttsége bizonyos korlátozásokat támaszt a fejlesztővel szemben.
Ezenkívül a könyvtár funkcionalitása nem mindig teszi lehetővé bizonyos összetevők, például az USART (univerzális szinkron-aszinkron soros port) konfigurációjának pontos megvalósítását bizonyos feltételek mellett. A gyakorlati részben leírom a könyvtár ezen részével való munkát is.

Sziasztok. Ahogy emlékszel az általunk készített legutóbbi cikkben Szoftver csomag STM32 mikrokontrollerekkel dolgozni, és lefordította az első programot. Ebben a bejegyzésben megismerkedünk az alaplap felépítésével, a mikrokontrollerrel és a munkához elérhető könyvtárakkal.

Alább egy kép a tábláról STM32F3 Discovery , ahol: 1 — MEMS érzékelő. L3GD20 3 tengelyes digitális giroszkóp. 2 – MEMS rendszer egy házban, amely egy 3 tengelyes digitális lineáris gyorsulásmérőt és egy 3 tengelyes digitális geomágneses LSM303DLHC érzékelőt tartalmaz. 4 – LD1 (PWR) – 3,3 V tápegység. 5 – LD2 – piros/zöld LED. Az alapértelmezett a piros. A zöld az ST-LINK/v2 (vagy V2-B) és a PC közötti kommunikációt jelenti. Van ST-LINK/v2-B-m, valamint egyedi kijelzőm USB csatlakozó. 6. -LD3/10 (piros), LD4/9 (kék), LD5/8 (narancs) és LD6/7 (zöld). Az utolsó bejegyzésben felvillantottuk az LD4 LED-et. 7. – Két gomb: egyéni USER és reset RESET. 8. - USB USER Mini-B csatlakozóval.

9 - USB hibakereső/programozó ST-LINK/V2. 1 0. - Mikrokontroller STM32F303VCT6. 11. – Külső nagyfrekvenciás generátor 8 MHz. 12. – Itt kellene egy kisfrekvenciás generátor, sajnos nincs forrasztva. 13. – SWD – interfész. 14. – A külső vagy belső vezérlők programozásának kiválasztására szolgáló jumpereket, első esetben el kell távolítani. 15 – Jumper JP3 – áthidaló ampermérő csatlakoztatására a vezérlő fogyasztásának mérésére. Egyértelmű, hogy ha törlik, akkor a kövünk nem indul el. 16. – STM32F103C8T6 van rajta hibakereső kártya. 17. — LD3985M33R Szabályozó kis feszültségeséssel és zajszinttel, 150mA, 3,3V.

Most pedig nézzük meg közelebbről az STM32F303VCT6 mikrokontroller architektúráját. Övé Műszaki adatok: LQFP-100 ház, ARM Cortex-M4 mag, maximális magfrekvencia 72 MHz, programmemória kapacitása 256 KB, memória típusa FLASH programok, hangerő véletlen hozzáférésű memória SRAM 40 kbyte, RAM 8 kbyte, bemenetek/kimenetek száma 87, interfészek (CAN, I²C, IrDA, LIN, SPI, UART/USART, USB), perifériák (DMA, I2S, POR, PWM, WDT), ADC/DAC 4 db *12 bit/2*12bit, tápfeszültség 2...3,6 V, üzemi hőmérséklet –40...+85 C. Az alábbi ábrán egy kivezetés látható, ahol 87 bemeneti/kimeneti portot látunk, ebből 45 Normál I/O-k (TC, TTa), 42 db 5 V-os toleráns I/O-k (FT, FTf) – 5 V-tal kompatibilis (a lapon jobb oldalon 5 V, bal oldalon 3,3 V-os érintkezők találhatók). Mindegyik digitális I/O vonal általános I/O vonalként szolgálhat.
célállomás vagy alternatív funkció. A projektek előrehaladtával fokozatosan megismerkedünk a perifériával.

Tekintsük az alábbi blokkdiagramot. A szív egy 32 bites ARM Cortex-M4 mag, amely 72 MHz-ig működik. Beépített lebegőpontos FPU-val és memóriavédelmi egységgel MPU-val, beépített makrókövető cellákkal - Embedded Trace Macrocell (ETM) - található, amelyek segítségével a mikrokontrolleren belül nyomon követhető a fő program végrehajtása. Képesek folyamatosan kiadni ezeket a megfigyeléseket az ETM érintkezőkön keresztül, amíg az eszköz működik. NVIC (Nested vectored interrupt controller) – megszakításvezérlő modul. TPIU (Trace Port Interface Unit). FLASH memóriát tartalmaz – 256 KB, SRAM 40 KB, RAM 8 KB. A mag és a memória között egy buszmátrix található, amely lehetővé teszi az eszközök közvetlen csatlakoztatását. Itt is kétféle buszmátrix AHB és APB látható, ahol az első termelékenyebb, és nagy sebességű kommunikációra használják. belső alkatrészek, utóbbi pedig a perifériákhoz (bemeneti/kimeneti eszközökhöz) való. A vezérlő 4 db 12 bites ADC-vel (ADC) (5Mbit/s) és hőmérséklet-érzékelővel, 7 komparátorral (GP Comparator1...7), 4 programozható műveleti erősítővel (OpAmp1...4) rendelkezik (PGA (Programmable Gain Array)) ), 2 db 12 bites DAC csatorna (DAC), RTC (valós idejű óra), két watchdog időzítő - független és ablakos (WinWatchdog és Ind. WDG32K), 17 általános célú és többfunkciós időzítő.

Általánosságban a vezérlő architektúráját néztük meg. Most nézze meg az elérhető szoftverkönyvtárakat. Az áttekintést követően a következőket emelhetjük ki: CMSIS, SPL és HAL. Nézzük meg mindegyiket egy egyszerű példa segítségével a LED villogására.

1). CMSIS(Cortex Microcontroller Software Interface Standard) – szabványos könyvtár a Cortex®-M-hez. Eszköztámogatást biztosít és leegyszerűsíti szoftveres interfészek. A CMSIS konzisztens és egyszerű felületek a kernelhez, a perifériákhoz és a valós idejű operációs rendszerekhez. Használata professzionális programírási mód, mert... regiszterekbe való közvetlen írással jár, ennek megfelelően az adatlapok folyamatos olvasására és tanulmányozására van szükség. Hardvergyártótól független.
A CMSIS a következő összetevőket tartalmazza:
- CMSIS-CORE: Következetes rendszerindítás és periféria-hozzáférés;
- CMSIS-RTOS: Determinisztikus valós idejű szoftvervégrehajtás szoftver valós idő);
- CMSIS-DSP: A digitális jelfeldolgozás gyors megvalósítása digitális feldolgozás jelek);
- CMSIS-Driver: Általános periféria interfészek köztes szoftverekhez és alkalmazáskódokhoz (általános periféria interfészek köztes szoftverekhez és alkalmazáskódokhoz);
- CMSIS-Pack: Könnyű hozzáférés az újrafelhasználható szoftverkomponensekhez szoftver komponensek);
- CMSIS-SVD: Az eszköz és a perifériák egységes nézete perifériás eszközök);
- CMSIS-DAP: Csatlakozás alacsony költségű kiértékelő hardverhez. Hibakereső szoftver.

Például írjunk programot – villogjunk egy LED-et. Ehhez szükségünk van a nyilvántartásokat leíró dokumentációra. Esetemben RM0316 Használati útmutató STM32F303xB/C/D/E, STM32F303x6/8, STM32F328x8, STM32F358xC, STM32F398xE fejlett ARM ® alapú MCU-k, valamint az adott láb leírása, amelyért felelős DS9118: ARM®-alapú Cortex®-M4 32b MCU+FPU, akár 256KB Flash+ 48KB SRAM, 4 ADC, 2 DAC csatorna, 7 komp, 4 PGA, időzítők, 2,0-3,6 V. Kezdetben a portot fogjuk órajelezni a programban, mert Alapértelmezés szerint minden le van tiltva, ami csökkenti az energiafogyasztást. Nyissa meg a kézikönyvet, és nézze meg a Reset and clock control részt, majd az RCC regisztertérképet, és nézze meg, melyik regiszter felelős az IOPEEN engedélyezéséért

Térjünk át ennek a regiszternek a perifériáinak órajelének leírására AHB perifériaóra engedélyezési regiszter (RCC_AHBENR), ahol azt látjuk, hogy ez a port a 21. bit alatt van. Kapcsolja be az RCC->AHBENR|=(1<<21) . Далее сконфигурируем регистры GPIO. Нас интересует три: GPIOE_MODER и GPIOx_ODR . C помощью них повторим программу с предыдущей статьи, затактируем PE8. Первый отвечает за конфигурацию входа выхода, выбираем 01: General purpose output mode. GPIOE->MODER|=0×10000 . A második az alacsony/magas szint bekapcsolására szolgál a lábon. Alább a program:

#include "stm32f3xx.h " //Mikrovezérlő fejlécfájlja
unsigned int i;
érvénytelen késleltetés() (
for (i=0;i<500000;i++);
}
int main (érvénytelen) (
RCC->AHBENR|=(1<<21);
GPIOE->MODER|=0×10000;
míg (1)(
késleltetés();
GPIOE->ODR|=0×100;
késleltetés();
GPIOE->ODR&=~(0×100);
} }

2). SPL(Standard Peripherals Library)- ez a könyvtár az ST Electronics összes processzorát kombinálja. A kód hordozhatóságának javítására tervezték, és elsősorban kezdő fejlesztőknek szól. Az ST az SPL „alacsony rétegnek” nevezett helyettesítésén dolgozik, amely kompatibilis a HAL-lal. Az alacsony rétegű (LL) illesztőprogramokat úgy tervezték, hogy szinte könnyű, szakértő-orientált réteget biztosítsanak, amely közelebb áll a hardverhez, mint a HAL. A HAL mellett LL API-k is rendelkezésre állnak. Példa ugyanerre a programra SPL-ben.

#beleértve
#beleértve
#beleértve
#define LED GPIO_Pin_8
int main() (
hosszú i;
GPIO_InitTypeDef gpio;
// A kék LED az E porthoz csatlakozik, 8. érintkező (AHB busz)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
// Az E port konfigurálása (LED)
GPIO_StructInit(&gpio); //adatszerkezeti változó deklarálása és inicializálása
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_Pin = LED;
GPIO_Init(GPIOE, &gpio);
// Villogó LED-ek
míg (1) (
//Tovább
GPIO_SetBits(GPIOE, LED);
for (i = 0; i< 500000; i++);
// Minden kikapcsolva
GPIO_ResetBits(GPIOE, LED);
for (i = 0; i< 500000; i++);
} }

Mindegyik funkció leírása a műszaki dokumentációban található UM1581 Felhasználói kézikönyv Az STM32F30xx/31xx szabványos perifériakönyvtár leírása. Itt három fejlécfájlt kapcsolunk össze, amelyek tartalmazzák a szükséges adatokat, struktúrákat, reset és szinkronizálás vezérlési funkciókat, valamint a bemeneti/kimeneti portok konfigurálását.

3). HAL- (Hardver hozzáférési szint, hardver absztrakciós réteg)- Egy másik közös könyvtár a fejlesztéshez. Ezzel a konfigurációhoz az előző cikkben használt CubeMX program is megjelent. Ott is írtunk egy programot a LED villogtatására ezzel a könyvtárral. Amint az alábbi ábrán látható, a kocka HAL és CMSIS illesztőprogramokat állít elő. Nos, írjuk le a főbb használt fájlokat:
- system_stm32f3x.c és system_stm32f3x.h- minimális funkciókészlet biztosítása az időmérő rendszer konfigurálásához;
— core_cm4.h – hozzáférést biztosít a mag és perifériáinak regisztereihez;
- stm32f3x.h - mikrokontroller fejlécfájlja;
— startup_system32f3x.s — indítási kód, megszakítási vektorok táblázatát tartalmazza stb.

#include "fő.h"
#include "stm32f3xx_hal.h"
void SystemClock_Config(void); /*Órakonfigurációs funkciók deklarálása*/
static void MX_GPIO_Init(void); /*I/O inicializálása*/
int main (érvénytelen) (
/*Az összes periféria visszaállítása, Inicializálja a Flash interfészt és a Systicket.*/
HAL_Init();
/* A rendszeróra konfigurálása */
SystemClock_Config();
/* Az összes beállított periféria inicializálása */
MX_GPIO_Init();
míg (1) (
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_8); //A láb állapotának váltása
HAL_Késleltetés(100); )
}
void SystemClock_Config (void){
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NINCS;
if (HAL_RCC_OscConfig (&RCC_OscInitStruct) != HAL_OK){

}
/**Inicializálja a CPU, AHB és APB buszok órajeleit */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig (&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){
_Error_Handler(__FILE__, __LINE__);
}
/**A Systick megszakítási idejének konfigurálása*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**A Systick konfigurálása */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn megszakítási konfiguráció */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/** A lábak konfigurálása analóg bemeneti kimenetként EVENT_OUT EXTI */
static void MX_GPIO_Init (void){
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO portok óra engedélyezése */
__HAL_RCC_GPIOE_CLK_ENABLE();
/*GPIO pin kimeneti szint beállítása */
HAL_GPIO_WritePin (GPIOE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*GPIO érintkezők konfigurálása: PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed ​​​​= GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}
void _Error_Handler(char * fájl, int sor){
míg (1) (
} }
#ifdef USE_FULL_ASSERT

Érvénytelen az assert_failed (uint8_t* fájl, uint32_t sor){
}
#endif
Az előző példához hasonlóan itt is megtekinthetjük például az egyes funkciók leírását a dokumentációban UM1786 Felhasználói kézikönyv Az STM32F3 HAL és az alacsony rétegű illesztőprogramok leírása.

Összefoglalhatjuk, hogy az első, CMSIS-t használó lehetőség kevésbé körülményes. Minden könyvtárhoz van dokumentáció. A következő projektekben az STCube konfigurációs programmal használjuk a HAL-t és a CMSIS-t, és lehetőség szerint közvetlenül, szoftvercsomagolók nélkül használunk regisztereket. Ma itt álljunk meg. A következő cikkben az építés alapelveit tekintjük át okos otthon. Viszlát mindenkinek.




Top