STM32F407(STM32F4-DISCOVERY) - Hindi karaniwang diskarte - Standard library part 1. Naka-file na USB Middleware. Pagkonekta ng library sa proyekto

Kinakailangan ang software para sa pag-unlad. Sa artikulong ito sasabihin ko sa iyo kung paano i-configure at ikonekta ito nang tama. Ang lahat ng mga komersyal na kapaligiran tulad ng IAR EWARM o Keil uVision ay karaniwang nagsasagawa ng pagsasamang ito sa kanilang sarili, ngunit sa aming kaso ang lahat ay kailangang i-configure nang manu-mano, na gumugugol ng maraming oras dito. Ang kalamangan ay mayroon kang pagkakataong maunawaan kung paano gumagana ang lahat mula sa loob, at sa hinaharap, flexible na i-customize ang lahat para sa iyong sarili. Bago simulan ang pag-setup, tingnan natin ang istruktura ng kapaligiran kung saan tayo gagana:

Ang Eclipse ay gagamitin upang maginhawang mag-edit ng mga file ng pagpapatupad ng function ( .c), mga file ng header ( .h), pati na rin ang mga assembler file ( .S). Sa pamamagitan ng "maginhawa" ang ibig kong sabihin ay ang paggamit ng code completion, syntax highlighting, refactoring, navigation sa pamamagitan ng mga function at ang kanilang mga prototype. Ang mga file ay awtomatikong pinapakain sa mga kinakailangang compiler, na bumubuo ng object code (sa mga file .o). Sa ngayon, ang code na ito ay hindi naglalaman ng ganap na mga address ng mga variable at function at samakatuwid ay hindi angkop para sa pagpapatupad. Ang mga resultang object file ay pinagsama-sama ng isang linker. Upang malaman kung aling mga bahagi ng espasyo ng address ang gagamitin, ang kolektor ay gumagamit ng isang espesyal na file ( .ld), na tinatawag na linker script. Karaniwan itong naglalaman ng isang kahulugan ng mga address ng seksyon at ang kanilang mga laki (nakamapang seksyon ng code sa flash, seksyon ng variable na nakamapa sa RAM, atbp.).

Sa huli, bumubuo ang linker ng .elf file (Executable at Linkable Format), na naglalaman, bilang karagdagan sa mga tagubilin at data, impormasyon sa pag-debug na ginagamit ng debugger. Ang format na ito ay hindi angkop para sa regular na pag-flash ng firmware gamit ang vsprog program, dahil nangangailangan ito ng mas primitive na memory image file (halimbawa, Intel HEX - .hex). Upang mabuo ito, mayroon ding tool mula sa Sourcery CodeBench set (arm-none-eabi-objcopy), at perpektong isinasama ito sa eclipse gamit ang naka-install na ARM plugin.

Upang maisagawa ang pag-debug mismo, tatlong mga programa ang ginagamit:

  1. mismong eclipse, na nagpapahintulot sa programmer na "biswal" na gumamit ng pag-debug, maglakad sa mga linya, mag-hover sa mga variable upang tingnan ang kanilang mga halaga, at iba pang kaginhawahan
  2. arm-none-eabi-gdb - Ang kliyente ng GDB ay isang debugger na lihim na kinokontrol ng mga eclips (sa pamamagitan ng stdin) bilang tugon sa mga pagkilos na tinukoy sa hakbang 1. Sa turn, kumokonekta ang GDB sa OpenOCD Debug server, at lahat ng input command ay isinalin ng GDB debugger sa mga command na mauunawaan para sa OpenOCD. GDB channel<->Ang OpenOCD ay ipinatupad gamit ang TCP protocol.
  3. Ang OpenOCD ay isang debug server na maaaring direktang makipag-ugnayan sa programmer. Tumatakbo ito sa harap ng kliyente at naghihintay ng koneksyon sa TCP.

Ang scheme na ito ay maaaring mukhang walang silbi sa iyo: bakit hiwalay na gamitin ang client at server at magsagawa ng hindi kinakailangang pagsasalin ng command, kung ang lahat ng ito ay magagawa sa isang debugger? Ang katotohanan ay ang ganitong arkitektura ay theoretically nagbibigay-daan para sa maginhawang pagpapalitan ng kliyente at server. Halimbawa, kung kailangan mong gumamit ng isa pang programmer sa halip na versaloon, na hindi susuportahan ang OpenOCD, ngunit susuportahan ang isa pang espesyal na Debug server (halimbawa, texane/stlink para sa stlink programmer - na matatagpuan sa STM32VLDdiscovery debug board), pagkatapos tatakbo ka lang ng OpenOCD sa halip na ilunsad ang nais na server at lahat ay dapat gumana, nang walang anumang karagdagang mga hakbang. Kasabay nito, posible ang kabaligtaran na sitwasyon: sabihin nating gusto mong gamitin ang IAR EWARM environment kasama ang versaloon sa halip na ang kumbinasyon ng Eclipse + CodeBench. Ang IAR ay may sariling built-in na Debug client, na matagumpay na makikipag-ugnayan sa OpenOCD at mamamahala nito, pati na rin makatanggap ng kinakailangang data bilang tugon. Gayunpaman, ang lahat ng ito kung minsan ay nananatili lamang sa teorya, dahil ang mga pamantayan para sa komunikasyon sa pagitan ng kliyente at server ay hindi mahigpit na kinokontrol, at maaaring mag-iba sa ilang mga lugar, ngunit ang mga pagsasaayos na tinukoy ko sa st-link+eclipse at IAR+versaloon ay gumana para sa akin.

Karaniwan ang kliyente at server ay tumatakbo sa parehong makina at ang koneksyon sa server ay nangyayari sa localhost:3333(Para sa openocd), o localhost:4242(para sa texane/stlink st-util). Ngunit walang pumipigil sa iyo na buksan ang port 3333 o 4242 (at ipasa ang port na ito sa router sa panlabas na network) at ang iyong mga kasamahan mula sa ibang lungsod ay magagawang ikonekta at i-debug ang iyong hardware. Ang trick na ito ay kadalasang ginagamit ng mga embedder na nagtatrabaho sa mga malalayong site kung saan limitado ang access.

Magsimula na tayo

Ilunsad ang eclipse at piliin ang File->New->C Project, piliin ang uri ng proyekto na ARM Linux GCC (Sorcery G++ Lite) at ang pangalang "stm32_ld_vl" (Kung mayroon kang STV32VLDdiscovery, mas lohikal na pangalanan itong "stm32_md_vl") :

I-click ang Tapusin at i-minimize o isara ang Welcome window. Kaya, ang proyekto ay nilikha, at ang stm32_ld_vl folder ay dapat na lumitaw sa iyong workspace. Ngayon ay kailangan itong punan ng mga kinakailangang aklatan.

Tulad ng naiintindihan mo mula sa pangalan ng proyekto, gagawa ako ng isang proyekto para sa view ng ruler mababang-density na linya ng halaga(LD_VL). Upang lumikha ng isang proyekto para sa iba pang mga microcontroller dapat mong palitan ang lahat ng mga file at tukuyin ang pangalan kung saan mayroon _LD_VL (o_ld_vl) sa mga kailangan mo, alinsunod sa talahanayan:

Uri ng ruler Pagtatalaga Mga Microcontroller (x ay maaaring magbago)
Low-density na linya ng halaga _LD_VL STM32F100x4 STM32F100x6
Mababang-densidad _LD STM32F101x4 STM32F101x6
STM32F102x4 STM32F102x6
STM32F103x4 STM32F103x6
Linya ng halaga ng medium-density _MD_VL STM32F100x8 STM32F100xB
Katamtamang densidad
_MD
STM32F101x8 STM32F101xB
STM32F102x8 STM32F102xB
STM32F103x8 STM32F103xB
High density Value line _HD_VL STM32F100xC STM32F100xD STM32F100xE
Mataas na density _HD STM32F101xC STM32F101xD STM32F101xE
STM32F103xC STM32F103xD STM32F103xE
XL-densidad _XL STM32F101xF STM32F101xG
STM32F103xF STM32F103xG
Linya ng pagkakakonekta _CL STM32F105xx at STM32F107xx

Upang maunawaan ang lohika sa likod ng talahanayan, dapat na pamilyar ka sa pag-label ng STM32. Iyon ay, kung mayroon kang VLDdiscovery, pagkatapos ay kailangan mong palitan ang lahat ng konektado sa _LD_VL ng _MD_VL, dahil ang STM32F100RB chip, na kabilang sa linya ng halaga ng Medium-density, ay ibinebenta sa pagtuklas.

Pagdaragdag ng CMSIS at STM32F10x Standard Peripherals Library sa proyekto

CMSIS(Cortex Microcontroller Software Interface Standard) ay isang standardized na library para sa pagtatrabaho sa Cortex microcontrollers na nagpapatupad ng HAL (Hardware Abstraction Layer) na antas, iyon ay, pinapayagan ka nitong mag-abstract mula sa mga detalye ng pagtatrabaho sa mga rehistro, paghahanap ng mga address ng rehistro gamit ang mga datasheet, atbp. Ang library ay isang hanay ng mga source code sa C at Asm. Ang pangunahing bahagi ng library ay pareho para sa lahat ng Cortex (Maging ito ST, NXP, ATMEL, TI o sinuman), at binuo ng ARM. Ang ibang bahagi ng library ay may pananagutan para sa mga peripheral, na natural na naiiba sa bawat tagagawa. Kaya sa huli kumpletong aklatan ay ipinamamahagi pa rin ng tagagawa, kahit na ang pangunahing bahagi ay maaari pa ring i-download nang hiwalay sa website ng ARM. Ang library ay naglalaman ng mga kahulugan ng address, clock generator initialization code (maginhawang napapasadya sa pamamagitan ng mga pagtukoy), at lahat ng iba pa na nagse-save sa programmer mula sa manu-manong pagpapasok sa kanyang mga proyekto ng kahulugan ng mga address ng lahat ng uri ng mga peripheral na rehistro at pagtukoy ng mga piraso ng mga halaga ng ang mga rehistrong ito.

Ngunit ang mga lalaki mula sa ST ay lumayo pa. Bukod sa CMSIS support ay nagbibigay sila ng isa pang library para sa STM32F10x na tinatawag Karaniwang Peripheral Library(SPL), na maaaring magamit bilang karagdagan sa CMSIS. Nagbibigay ang library ng mas mabilis at mas maginhawang access sa mga peripheral, at kinokontrol din (sa ilang mga kaso) ang tamang operasyon ng mga peripheral. Samakatuwid, ang library na ito ay madalas na tinatawag na isang set ng mga driver para sa mga peripheral na module. Ito ay sinamahan ng isang pakete ng mga halimbawa, na nahahati sa mga kategorya para sa iba't ibang mga peripheral. Available din ang library hindi lamang para sa STM32F10x, kundi pati na rin sa iba pang serye.

Maaari mong i-download ang buong bersyon 3.5 ng SPL+CMSIS dito: STM32F10x_StdPeriph_Lib_V3.5.0 o sa website ng ST. I-unzip ang archive. Lumikha ng mga folder ng CMSIS at SPL sa folder ng proyekto at simulan ang pagkopya ng mga file sa iyong proyekto:

Ano ang dapat kopyahin

Kung saan kokopyahin (isinasaalang-alang
na ang folder ng proyekto ay stm32_ld_vl)

Paglalarawan ng File
Mga Aklatan/CMSIS/CM3/
CoreSupport/ core_cm3.c
stm32_ld_vl/CMSIS/ core_cm3.c Paglalarawan ng Cortex M3 core
Mga Aklatan/CMSIS/CM3/
CoreSupport/ core_cm3.h
stm32_ld_vl/CMSIS/core_cm3.h Mga Header ng Paglalarawan ng Kernel

ST/STM32F10x/ system_stm32f10x.c
stm32_ld_vl/CMSIS/system_stm32f10x.c Mga function ng pagsisimula at
kontrol ng orasan
Mga Aklatan/CMSIS/CM3/DeviceSupport/
ST/STM32F10x/ system_stm32f10x.h
stm32_ld_vl/CMSIS/system_stm32f10x.h Mga header para sa mga function na ito
Mga Aklatan/CMSIS/CM3/DeviceSupport/
ST/STM32F10x/ stm32f10x.h
stm32_ld_vl/CMSIS/stm32f10x.h Pangunahing paglalarawan ng mga peripheral
Mga Aklatan/CMSIS/CM3/DeviceSupport/
ST/STM32F10x/startup/gcc_ride7/
startup_stm32f10x_ld_vl.s
stm32_ld_vl/CMSIS/startup_stm32f10x_ld_vl.S
(!!! Attention file extension CAPITAL S)
Vector table file
interrupts at init-s sa asm
Project/STM32F10x_StdPeriph_Template/
stm32f10x_conf.h
stm32_ld_vl/CMSIS/ stm32f10x_conf.h Template para sa pagpapasadya
mga peripheral na module

inc/ *
stm32_ld_vl/SPL/inc/ * SPL header file
Mga Aklatan/STM32F10x_StdPeriph_Driver/
src/ *
stm32_ld_vl/SPL/src/ * Pagpapatupad ng SPL

Pagkatapos kopyahin, pumunta sa Eclipse at gawin ang Refresh sa menu ng konteksto ng proyekto. Bilang isang resulta, sa Project Explorer dapat kang makakuha ng parehong istraktura tulad ng sa larawan sa kanan.

Maaaring napansin mo na sa folder ng Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/ may mga folder para sa iba't ibang IDE (iba't ibang mga compiler ang ginagamit ng iba't ibang IDE). Pinili ko ang Ride7 IDE dahil gumagamit ito ng GNU compiler Mga kasangkapan para sa Naka-embed na ARM, tugma sa aming Sourcery CodeBench.

Ang buong library ay na-configure gamit ang isang preprocessor (gamit ang mga tinukoy), ito ay magbibigay-daan sa iyo upang malutas ang lahat ng kinakailangang mga sangay sa yugto ng compilation (o sa halip, kahit na bago ito) at maiwasan ang pagkarga sa pagpapatakbo ng controller mismo (na magiging sinusunod kung ang pagsasaayos ay isinagawa sa RunTime). Halimbawa, ang lahat ng kagamitan ay iba para sa iba't ibang linya, at samakatuwid para sa library na "malaman" kung aling linya ang gusto mong gamitin, hihilingin sa iyong alisin ang komento sa file. stm32f10x.h isa sa mga define (naaayon sa iyong linya):

/* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */
/* #define STM32F10X_LD_VL */ /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */
/* #define STM32F10X_MD */ /*!< STM32F10X_MD: STM32 Medium density devices */

At iba pa...

Ngunit hindi ko inirerekumenda na gawin ito. Hindi namin hawakan ang mga file ng library sa ngayon, at tutukuyin namin ito sa ibang pagkakataon gamit ang mga setting ng compiler sa Eclipse. At pagkatapos ay tatawagin ng Eсlipse ang compiler na may susi -D STM32F10X_LD_VL, na para sa preprocessor ay ganap na katumbas ng sitwasyon kung hindi ka nagkomento "#define STM32F10X_LD_VL". Kaya, hindi namin babaguhin ang code bilang isang resulta, kung nais mo, balang araw magagawa mong ilipat ang library sa isang hiwalay na direktoryo at hindi kopyahin ito sa folder ng bawat bagong proyekto.

Linker script

Sa menu ng konteksto ng proyekto, piliin ang Bago->File->Other->General->File, Next. Pumili root folder proyekto (stm32_ld_vl). Ilagay ang pangalan ng file na "stm32f100c4.ld" (o "stm32f100rb.ld" para sa pagtuklas). Ngayon kopyahin at i-paste sa eclipse:

ENTRY(Reset_Handler) MEMORY ( FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K ) _estack = ORIGIN(RAM) + LENGTH MIN_HEAP_SIZE = 0; MIN_STACK_SIZE = 256; SECTIONS ( /* Interrupt vector table */ .isr_vector: ( . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); ) >FLASH /* Ang program code at iba pang data ay napupunta sa FLASH * / .text: ( . = ALIGN(4); /* Code */ *(.text) *(.text*) /* Constants */ *(.rodata) *(.rodata*) /* ARM->Thumb at Thumb->ARM glue code */ *(.glue_7) *(.glue_7t) KEEP (*(.init)) KEEP (*(.fini)) . ARM.extab* .gnu.linkonce.armextab.*) ) >FLASH .ARM: ( __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; ) >FLASH .ARM. attributes) ) > FLASH .preinit_array: ( PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); ) >FLASH .init_array: ( PROVIDE_HIDDEN (.star__init_array); )) PANATILIIN (*(SORT(.fini_array.*))) PROVIDE_HIDDEN (__fini_array_end = .);

) >FLASH_sidata = .; /* Inisyal na data */ .data: AT (_sidata) ( . = ALIGN(4); _sdata = .; /* lumikha ng pandaigdigang simbolo sa pagsisimula ng data */ *(.data) *(.data*) . = ALIGN (4); _edata = .; /* tukuyin ang isang pandaigdigang simbolo sa dulo ng data */ ) >RAM /* Uninitialized data */ . = ALIGN(4);

.bss: ( /* Ito ay ginagamit ng startup para masimulan ang .bss secion */ _sbss = .; /* tukuyin ang isang pandaigdigang simbolo sa bss start */ __bss_start__ = _sbss; *(.bss) *(.bss *) *(COMMON) = ALIGN(4); /* tukuyin ang isang pandaigdigang simbolo sa bss end */ __bss_end__ = _ebss;

MAGBIGAY(_end = _ebss);

Pumunta sa Project->Properties->C/C++ Build->Settings->Tool Settings, at simulan ang pag-set up ng build tool:

1) Target Precessor

Pinipili namin kung sa aling Cortex core gagana ang compiler.

  • Processor: cortex-m3

2) ARM Sourcery Linux GCC C Compiler -> Preprocessor

Nagdagdag kami ng dalawang define sa pamamagitan ng pagpasa sa mga ito sa -D switch sa compiler.

  • STM32F10X_LD_VL - tumutukoy sa pinuno (isinulat ko ang tungkol sa pagtukoy sa itaas)
  • USE_STDPERIPH_DRIVER - nagsasabi sa CMSIS library na dapat nitong gamitin ang driver ng SPL

3) ARM Sourcery Linux GCC C Compiler -> Mga Direktoryo

Magdagdag ng mga path sa library includs.

  • "$(workspace_loc:/$(ProjName)/CMSIS)"
  • "$(workspace_loc:/$(ProjName)/SPL/inc)"

Ngayon, halimbawa, kung isusulat natin:

#include "stm32f10x.h

Pagkatapos ay dapat munang hanapin ng compiler ang file stm32f10x.h sa direktoryo ng proyekto (palagi niyang ginagawa ito), hindi niya ito mahahanap doon at magsisimulang maghanap sa folder ng CMSIS, ang landas na aming ipinahiwatig, at hahanapin ito.

4) ARM Sourcery Linux GCC C Compiler -> Optimization

Paganahin natin ang pag-optimize ng mga function at data

  • -ffunction-seksyon
  • -fdata-seksyon

Bilang resulta, ang lahat ng mga function at elemento ng data ay ilalagay sa magkahiwalay na mga seksyon, at mauunawaan ng kolektor kung aling mga seksyon ang hindi ginagamit at itapon lamang ang mga ito.

5) ARM Sourcery Linux GCC C Compiler -> Pangkalahatan

Idagdag ang path sa aming linker script: “$(workspace_loc:/$(ProjName)/stm32f100c4.ld)” (o kahit anong tawag mo rito).

At itakda ang mga pagpipilian:

  • Huwag gumamit ng mga karaniwang panimulang file - huwag gamitin karaniwang mga file ilunsad.
  • Alisin ang mga hindi nagamit na seksyon - alisin ang mga hindi ginagamit na seksyon

Ayan, kumpleto na ang setup. OK.

Marami na kaming nagawa mula noong ginawa ang proyekto, at may ilang bagay na maaaring napalampas ng Eclipse, kaya kailangan naming sabihin dito na muling isaalang-alang ang istraktura ng file ng proyekto. Upang gawin ito, mula sa menu ng konteksto ng proyekto na kailangan mong gawin Index -> muling itayo.

Hello LEDs sa STM32

Oras na para lumikha pangunahing file proyekto: File -> Bago -> C/C++ -> Source File. Susunod. Pangalan ng file Source file: main.c.

Kopyahin at i-paste ang sumusunod sa file:

#include "stm32f10x.h" uint8_t i=0; int main(void) ( RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // I-enable ang PORTB Periph clock RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // I-enable ang TIM2 Periph clock // I-disable ang JTAG para sa pag-release ng LED PIN RCC->APB2_ENRIO |= AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; // I-clear ang PB4 at PB5 control register bits GPIOB->CRL &= ~(GPIO_CRL_MODE4 | GPIO_CRL_CNF4 | GPIO_CRL_MODE5 | GPIO_CRL_CNF5); Push Pull output sa max 10Mhz GPIOB->CRL |= GPIO_CRL_MODE4_0 | GPIO_CRL_MODE5_0;

TIM2->PSC = SystemCoreClock / 1000 - 1; // 1000 tick/sec TIM2->ARR = 1000; // 1 Interrupt/1 sec TIM2->DIER |= TIM_DIER_UIE; // Paganahin ang tim2 interrupt TIM2->CR1 |= TIM_CR1_CEN; // Start count NVIC_EnableIRQ(TIM2_IRQn); // Paganahin ang IRQ habang(1); // Infinity loop ) void TIM2_IRQHandler(void) ( TIM2->SR &= ~TIM_SR_UIF; //Clean UIF Flag kung (1 == (i++ & 0x1)) ( GPIOB->BSRR = GPIO_BSRR_BS4; // Itakda ang PB4 bit GPIOB ->BSRR = GPIO_BSRR_BR5; // I-reset ang PB5 bit ) else ( GPIOB->BSRR = GPIO_BSRR_BS5; // Itakda ang PB5 bit GPIOB->BSRR = GPIO_BSRR_BR4; // I-reset ang PB4 bit )

Bagama't isinama namin ang SPL library, hindi ito ginamit dito. Ang lahat ng mga tawag sa mga field tulad ng RCC->APB2ENR ay ganap na inilalarawan sa CMSIS.

Magagawa mo ang Project -> Build All. Kung maayos ang lahat, dapat na lumabas ang file na stm32_ld_vl.hex sa Debug folder ng proyekto. Awtomatiko itong nabuo mula sa duwende ng mga built-in na tool. Pina-flash namin ang file at nakikita kung paano kumikislap ang mga LED sa dalas ng isang beses bawat segundo:

Vsprog -sstm32f1 -ms -oe -owf -I /home/user/workspace/stm32_ld_vl/Debug/stm32_ld_vl.hex -V "tvcc.set 3300"

Naturally, sa halip na /home/user/workspace/ dapat mong ipasok ang iyong landas patungo sa workspace.

Para sa STM32VLDdiscovery

Ang code ay bahagyang naiiba mula sa ibinigay ko sa itaas para sa aking debug board. Ang pagkakaiba ay nakasalalay sa mga pin kung saan "nakabitin" ang mga LED. Kung sa aking board ito ay PB4 at PB5, pagkatapos ay sa Discovery ito ay PC8 at PC9.

Sa ilalim ng Windows, maaari mong i-flash ang resultang hex(/workspace/stm32_md_vl/Debug/stm32_md_vl.hex) gamit ang utility mula sa ST.

Well, sa ilalim linux utility st-flash. PERO!!! Ang utility ay hindi gumagamit ng Intel HEX hex na format (na nabuo bilang default), kaya napakahalaga na piliin ang binary na format sa mga setting ng paglikha ng Flash na imahe:

Hindi magbabago ang extension ng file (mananatili itong hex gaya noon), ngunit magbabago ang format ng file. At pagkatapos lamang nito magagawa mo:

St-flash write v1 /home/user/workspace/stm32_md_vl/Debug/stm32_md_vl.hex 0x08000000

Sa pamamagitan ng paraan, tungkol sa extension at format: karaniwang binary file ay minarkahan ng .bin extension, habang ang mga file sa Intel HEX format ay tinatawag na .hex extension. Ang pagkakaiba sa dalawang format na ito ay mas teknikal kaysa sa functional: ang binary na format ay naglalaman lamang ng mga byte ng mga tagubilin at data na isusulat lang sa controller ng programmer "as is". Ang IntelHEX, sa kabilang banda, ay walang binary na format, ngunit isang teksto: ang eksaktong parehong mga byte ay nahahati sa 4 na bits at ipinakita ang character sa pamamagitan ng character sa ASCII format, at ang mga character na 0-9, A-F lamang ang ginagamit (bin at hex ay mga sistema ng numero na may maraming base, ibig sabihin, 4 bits bawat bin ay maaaring katawanin bilang isang solong hex digit). Kaya ang format na ihex ay higit sa 2 beses ang laki ng isang regular na binary file (bawat 4 na bit ay pinapalitan ng isang byte + line break para sa madaling pagbabasa), ngunit maaari itong basahin sa isang regular na text editor. Samakatuwid, kung ipapadala mo ang file na ito sa isang tao, o gagamitin ito sa iba pang mga programa sa programming, ipinapayong palitan ang pangalan nito na stm32_md_vl.bin upang hindi mailigaw ang mga tumitingin sa pangalan nito.

Kaya nag-set up kami ng firmware build para sa stm32. Sa susunod sasabihin ko sayo kung paano

Kaya, nakabalik na kami sa aming mga paa, sa kahulugan na mayroon kaming lahat ng kailangan namin na konektado sa mga pin ng microcontroller sa STM32VL Discovery board, natutunan naming magsalita sa C programming language, oras na upang lumikha ng isang proyekto para sa unang baitang.

Pagsusulat ng isang programa

Matapos mong gawin at i-configure ang proyekto, maaari mong simulan ang pagsulat ng aktwal na programa. Tulad ng nakaugalian para sa lahat ng mga programmer, ang unang program na isinulat upang gumana sa isang computer ay isang programa na nagpapakita ng inskripsyon na "HelloWorld" sa screen, at para sa lahat ng mga microcontroller, ang unang programa para sa isang microcontroller ay gumagawa ng mga kumikislap na LED. Hindi kami magiging eksepsiyon sa tradisyong ito at magsusulat ng program na magkokontrol sa LD3 LED sa STM32VL Discovery board.

Pagkatapos lumikha ng isang walang laman na proyekto sa IAR, gumagawa ito ng kaunting program code:

Ngayon ang aming programa ay palaging "iikot" sa isang loop habang.

Upang makontrol natin ang LED, kailangan nating paganahin ang clocking ng port kung saan ito nakakonekta at i-configure ang kaukulang output ng microcontroller port. Tulad ng napag-usapan namin kanina sa unang bahagi, para sa pagpapahintulot sa port clocking SA kaunting sagot IOPCEN magparehistro RCC_APB2ENR. Ayon sa dokumento " RM0041Sanggunianmanwal.pdf»upang paganahin ang port bus clocking SA kinakailangan sa rehistro RCC_APB2ENR itakda ang bit IOPCEN bawat yunit. Upang kapag ang bit na ito ay naitakda, hindi namin i-reset ang iba pang nakatakda sa rehistrong ito, kailangan namin kasalukuyang estado magparehistro, ilapat ang lohikal na operasyon ng karagdagan (lohikal na "O") at pagkatapos ay isulat ang resultang halaga sa mga nilalaman ng rehistro. Alinsunod sa istraktura ng ST library, ang pag-access sa isang halaga ng rehistro para sa pagbabasa at pagsulat ay ginagawa sa pamamagitan ng isang pointer sa istraktura RCC-> APB2 ENR. Kaya, ang pag-alala sa materyal mula sa ikalawang bahagi, maaari mong isulat ang sumusunod na code na nagtatakda ng bit IOPCEN sa rehistro RCC_APB2ENR:

Tulad ng nakikita mo mula sa file na "stm32f10x.h", ang bit value IOPCEN tinukoy bilang 0x00000010, na tumutugma sa ikaapat na bit ( IOPCEN) magparehistro APB2ENR at tumutugma sa halagang ipinahiwatig sa datasheet.

Ngayon ay i-configure natin ang output sa parehong paraan 9 daungan SA. Upang gawin ito, kailangan nating i-configure ang port pin na ito sa output sa push-pull mode. Ang rehistro ay responsable para sa pagtatakda ng port input/output mode GPIOC_CRH, tiningnan na namin ito, ang paglalarawan nito ay nasa seksyong "7.2.2 Port configuration register high" na seksyon ng datasheet. Upang itakda ang output sa output mode pinakamataas na pagganap 2MHz, kinakailangan sa rehistro GPIOC_CRH i-install MODE9 sa isa at i-reset ang bit MODE9 sa zero. Ang mga bit ay responsable para sa pagtatakda ng output operating mode bilang pangunahing function na may push-pull output CNF9 At CNF9 , upang i-configure ang operating mode na kailangan namin, ang parehong mga bit na ito ay dapat na i-reset sa zero.

Ngayon ang pin ng port kung saan nakakonekta ang LED ay nakatakda sa output, upang makontrol ang LED kailangan nating baguhin ang pin state ng port sa pamamagitan ng pagtatakda ng output sa logic one. Mayroong dalawang paraan upang baguhin ang port pin state, ang una ay direktang isulat sa port status register ang mga binagong nilalaman ng port register, tulad ng pag-configure namin sa port. Ang pamamaraang ito Hindi inirerekumenda na gamitin ito dahil sa posibilidad ng isang sitwasyon kung saan ang isang hindi tamang halaga ay maaaring isulat sa rehistro ng port. Ang sitwasyong ito maaaring mangyari kung sa panahon ng pagbabago sa estado ng rehistro, mula sa sandaling nabasa na ang estado ng rehistro at hanggang sa sandali na ang binagong estado ay isinulat sa rehistro, anumang peripheral na aparato o mababago ng isang interrupt ang estado ng port na iyon. Sa pagkumpleto ng operasyon upang baguhin ang estado ng rehistro, ang halaga ay isusulat sa rehistro nang hindi isinasaalang-alang ang mga pagbabagong naganap. Bagama't napakababa ng posibilidad na mangyari ang sitwasyong ito, sulit pa rin ang paggamit ng ibang paraan kung saan hindi kasama ang inilarawang sitwasyon. Para sa layuning ito, mayroong dalawang rehistro sa microcontroller GPIOx_BSRR At GPIOx_BRR. Kapag nagsusulat ng isang lohikal sa kinakailangang bit ng rehistro GPIOx_BRR ang kaukulang port pin ay ire-reset sa logical zero. Magrehistro GPIOx_BSRR maaaring magsagawa ng parehong setting at pag-reset ng estado ng mga port pin upang itakda ang port pin sa isang lohikal na yunit, ito ay kinakailangan upang itakda ang mga bit BSN, naaayon sa bilang ng kinakailangang bit, ang mga bit na ito ay matatagpuan sa mababang rehistro ng byte. Upang i-reset ang port output state sa logical zero, kailangan mong isulat ang mga bits BRn kaukulang mga pin, ang mga bit na ito ay matatagpuan sa mga pinaka makabuluhang bit ng port register.

Ang LED LD3 ay konektado sa pin 9 daungan SA. Upang i-on ang LED na ito, kailangan naming maglapat ng lohikal sa kaukulang port pin upang "ilawan" ang LED.

Magdagdag tayo ng code para sa pagse-set up ng LED port output sa ating programa, at magdagdag din ng software delay function para bawasan ang LED switching frequency:

//Huwag kalimutang isama ang header file na naglalarawan sa mga rehistro ng microcontroller

#include "stm32f10x.h"

walang bisa Pagkaantala ( walang bisa);

walang bisa Pagkaantala ( walang bisa)
{
hindi pinirmahan mahaba ako;
para sa(i=0; i<2000000; i++);
}

//Ang aming pangunahing function

walang bisa pangunahing( walang bisa)
{


RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;

//clear ang MODE9 bits (i-reset ang MODE9_1 at MODE9_0 bits sa zero)
GPIOC->CRH &= ~GPIO_CRH_MODE9;

//Itakda ang MODE9_1 bit upang i-configure ang output sa output na may bilis na 2MHz
GPIOC->CRH |= GPIO_CRH_MODE9_1;

// i-clear ang CNF bits (itinakda bilang isang pangkalahatang layunin na output, simetriko (push-pull))
GPIOC->CRH &= ~GPIO_CRH_CNF9;

habang(1)
{

//Pagtatakda ng pin 9 ng port C sa lohikal na isa ("ilawan" ang LED)
GPIOC->BSRR = GPIO_BSRR_BS9;


Pagkaantala();


GPIOC->BSRR = GPIO_BSRR_BR9;


Pagkaantala();

}
}

I-download ang archive na may source code ng program na nakasulat gamit direktang kontrol Ang mga rehistro ng microcontroller ay matatagpuan sa link.

Ang aming unang magagamit na programa ay isinulat kapag isinusulat ito, upang patakbuhin at i-configure ang mga peripheral, ginamit namin ang data mula sa opisyal na datasheet " RM0041Sanggunianmanwal.pdf", ang mapagkukunang ito ng impormasyon tungkol sa mga rehistro ng microcontroller ay ang pinaka-tumpak, ngunit upang magamit ito kailangan mong muling basahin ang maraming impormasyon, na nagpapalubha ng mga programa sa pagsulat. Upang mapadali ang proseso ng pag-set up ng mga microcontroller peripheral, mayroong iba't ibang mga generator ng code, opisyal na utility mula sa kumpanya ng ST ang programa ng Microxplorer ay ipinakita, ngunit ito ay maliit pa rin ang pag-andar at sa kadahilanang ito mga developer ng third party ay nilikha alternatibong programa"STM32 Program Code Generator » . Binibigyang-daan ka ng program na ito na madaling makuha ang peripheral configuration code gamit ang isang maginhawa, intuitive na graphical na interface (tingnan ang Fig. 2).


kanin. 2 Screenshot ng STM32 code generator program

Tulad ng makikita mula sa Figure 2, ang LED output configuration code na nabuo ng programa ay tumutugma sa code na isinulat namin kanina.

Upang patakbuhin ang nakasulat na programa, pagkatapos i-compile ang source code, kailangan naming i-load ang aming programa sa microcontroller at tingnan kung paano ito tumatakbo.

Video ng LED blinking program debugging mode

Video ng LED blinking program sa STM32VL Discovery board

Mga function ng library para sa pagtatrabaho sa mga peripheral

Upang gawing simple ang gawain sa pag-set up ng mga microcontroller peripheral register, ang kumpanya ng ST ay bumuo ng mga aklatan, salamat sa paggamit nito, hindi mo kailangang basahin nang lubusan ang datasheet, dahil kapag ginagamit ang mga aklatang ito, ang gawain ng pagsulat ng isang programa ay magiging mas malapit sa pagsulat ng mga programang may mataas na antas, dahil sa katotohanan na ang lahat ng mga pag-andar na mababa ang antas ay ipinatupad sa antas ng pag-andar ng aklatan. Gayunpaman, hindi dapat ganap na iwanan ng isang tao ang paggamit ng direktang trabaho sa mga rehistro ng microcontroller, dahil ang mga function ng library ay nangangailangan ng mas maraming oras ng processor para sa kanilang pagpapatupad, at bilang isang resulta, ang kanilang paggamit sa mga kritikal na seksyon ng programa ay hindi makatwiran. Ngunit gayunpaman, sa karamihan ng mga kaso, ang mga bagay tulad ng pagsisimula ng mga peripheral ay hindi kritikal sa oras ng pagpapatupad, at ang kaginhawahan ng paggamit ng mga function ng library ay mas pinipili.

Ngayon ay isulat natin ang ating programa gamit ang ST library. Ang programa ay nangangailangan ng pag-set up ng mga input/output port upang magamit ang mga function ng library para sa pag-set up ng mga port, kailangan mong ikonekta ang header file "; stm32f10x_gpio.h"(tingnan ang talahanayan. 1). Maaaring ikonekta ang file na ito sa pamamagitan ng pag-uncomment sa kaukulang linya sa nakakonektang header configuration file « stm32f10x_conf.h" Sa dulo ng file " stm32f10x_gpio.h» mayroong isang listahan ng mga deklarasyon ng function para sa pagtatrabaho sa mga port. Ang isang detalyadong paglalarawan ng lahat ng magagamit na mga function ay matatagpuan sa file na " stm32f10x_stdperiph_lib_um.chm", ang isang maikling paglalarawan ng mga pinakakaraniwang ginagamit ay ibinibigay sa Talahanayan 2.

Talahanayan 2. Paglalarawan ng mga pangunahing function ng pagsasaayos ng port

Function

Paglalarawan ng function, naipasa at ibinalik na mga parameter

GPIO_DeInit(
GPIO_TypeDef* GPIOx)

Itinatakda ang mga rehistro ng configuration ng GPIOx port sa kanilang mga default na halaga.

GPIO_Init(
GPIO_TypeDef* GPIOx,

Itinatakda ang mga rehistro ng configuration ng port ng GPIOx alinsunod sa mga tinukoy na parameter sa istraktura ng GPIO_InitStruct

GPIO_StructInit(
GPIO_InitTypeDef* GPIO_InitStruct)

Pinunan ang lahat ng mga patlang ng istraktura ng GPIO_InitStruct na may mga default na halaga

uint8_t GPIO_ReadInputDataBit(
GPIO_TypeDef* GPIOx,
uint16_t GPIO_Pin);

Binabasa ang input value ng GPIO_Pin pin ng GPIOx port

uint16_t GPIO_ReadInputData (
GPIO_TypeDef* GPIOx)

Binabasa ang mga halaga ng input ng lahat ng GPIOx port pin

GPIO_SetBits(
GPIO_TypeDef* GPIOx,
uint16_t GPIO_Pin)

Ang pagtatakda ng output value ng GPIO_Pin pin ng GPIOx port sa logic one

GPIO_ResetBits(
GPIO_TypeDef* GPIOx,
uint16_t GPIO_Pin)

I-reset ang output value ng GPIO_Pin pin ng GPIOx port sa logic zero

GPIO_WriteBit(
GPIO_TypeDef* GPIOx,
uint16_t GPIO_Pin,
BitAction BitVal)

Isulat ang halaga ng BitVal sa GPIO_Pin pin ng GPIOx port

GPIO_Write(
GPIO_TypeDef* GPIOx,
uint16_t PortVal)

Isulat ang halaga ng PortVal sa GPIOx port

Tulad ng makikita mula sa paglalarawan ng mga pag-andar, bilang mga parameter para sa mga setting ng port, atbp., hindi maraming iba't ibang mga indibidwal na parameter ang ipinasa sa function, ngunit isang istraktura. Ang mga istruktura ay pinagsamang data na may ilang lohikal na kaugnayan. Hindi tulad ng mga array, ang mga istruktura ay maaaring maglaman ng data ng iba't ibang uri. Sa madaling salita, ang isang istraktura ay kumakatawan sa isang koleksyon ng iba't ibang mga variable na may iba't ibang uri, pinagsama sa isang natatanging variable. Ang mga variable na matatagpuan sa istrukturang ito ay tinatawag na mga patlang ng istraktura, at ang mga ito ay naa-access sa sumusunod na paraan: isulat muna ang pangalan ng istraktura, pagkatapos ay magsulat ng isang tuldok at ang pangalan ng patlang ng istraktura (ang pangalan ng variable sa istrukturang ito).

Ang listahan ng mga variable na kasama sa mga istruktura para sa mga function na gumagana sa mga port ay inilarawan sa parehong file na bahagyang mas mataas sa paglalarawan ng mga function. Kaya, halimbawa, ang istraktura " GPIO_InitTypeDef"ay may sumusunod na istraktura:

typedef struct
{

uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
Ang parameter na ito ay maaaring maging anumang halaga ng @ref GPIO_pins_define */

GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.
Ang parameter na ito ay maaaring isang halaga ng @ref GPIOSpeed_TypeDef */

GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.
Ang parameter na ito ay maaaring isang halaga ng @ref GPIOMode_TypeDef */

)GPIO_InitTypeDef;

Ang unang field ng istrukturang ito ay naglalaman ng variable na " GPIO_ Pin"type hindi pinirmahan maikli, sa variable na ito kinakailangan na itala ang mga flag ng mga numero ng kaukulang mga pin kung saan dapat gawin ang mga kinakailangang setting. Maaari mong i-configure ang ilang mga pin nang sabay-sabay sa pamamagitan ng pagtukoy ng ilang mga constant bilang isang parameter gamit ang operator bitwise O(cm. ). Ang isang bitwise O ay "kokolekta" ang lahat ng mga mula sa nakalistang mga constant, at ang mga constants mismo ay isang maskara na nilayon lamang para sa gayong paggamit. Ang mga macro definition ng mga constant ay nakalista sa parehong file sa ibaba.

Ang pangalawang larangan ng istraktura " GPIO_InitTypeDef» nagtatakda ng pinakamataas na posibleng bilis ng output ng port. Ang listahan ng mga posibleng halaga para sa field na ito ay nakalista sa itaas:

Paglalarawan ng mga posibleng halaga:

  • GPIO_Mode_AIN- analog input (Ingles: Analog INput);
  • GPIO_Mode_IN_FLOATING- input nang hindi humihigpit, nakalawit (English Input float) sa hangin
  • GPIO_Mode_IPD- input pull-down
  • GPIO_Mode_IPU- input pull-up
  • GPIO_Mode_Out_OD- Output Open Drain
  • GPIO_Mode_Out_PP- output sa dalawang estado (Ingles: Output Push-Pull - pabalik-balik)
  • GPIO_Mode_AF_OD- open drain output para sa mga alternatibong function (English Alternate Function). Ginagamit sa mga kaso kung saan ang output ay dapat kontrolin ng mga peripheral na naka-attach sa konklusyong ito port (halimbawa, Tx pin USART1, atbp.)
  • GPIO_Mode_AF_PP- ang parehong bagay, ngunit may dalawang estado

Sa katulad na paraan, maaari mong tingnan ang istraktura ng mga variable ng iba pang mga istraktura na kinakailangan para sa pagtatrabaho sa mga function ng library.

Upang gumana sa mga istruktura, sila, tulad ng mga variable, ay dapat na ipahayag at italaga ng isang natatanging pangalan, pagkatapos nito ay maaari mong ma-access ang mga patlang ng ipinahayag na istraktura sa pamamagitan ng pangalan na itinalaga dito.

//Ipahayag ang istraktura

/*
Bago mo simulan ang pagpuno sa mga patlang ng istraktura, inirerekumenda na simulan ang mga nilalaman ng istraktura na may default na data na ito ay ginagawa upang maiwasan ang pagsusulat ng maling data kung, sa ilang kadahilanan, hindi lahat ng mga patlang ng istraktura ay napunan; .

Upang maipasa ang mga halaga ng istraktura sa isang function, dapat mong unahan ang pangalan ng istraktura gamit ang & simbolo. Ang simbolo na ito ay nagsasabi sa compiler na kinakailangang ipasa sa function hindi ang mga halaga mismo na nilalaman sa istraktura, ngunit ang address sa memorya kung saan matatagpuan ang mga halagang ito. Ginagawa ito upang mabawasan ang bilang ng mga kinakailangang aksyon ng processor upang kopyahin ang mga nilalaman ng istraktura, at nakakatipid din ng RAM. Kaya, sa halip na ipasa ang maraming byte na nilalaman sa istraktura sa function, isa lamang ang ipapasa na naglalaman ng address ng istraktura.
*/

/* Isulat sa field ng GPIO_Pin ng istraktura ng GPIO_Init_struct ang pin number ng port na iko-configure pa namin */

GPIO_Init_struct.GPIO_Pin=GPIO_Pin_9;

/* Ganun din punan ang field na GPIO_Speed ​​​​*/

/*
Pagkatapos naming magfill-out mga kinakailangang field istraktura, ang istrakturang ito ay dapat na maipasa sa isang function na gagawa ng kinakailangang pagpasok sa naaangkop na mga rehistro. Bilang karagdagan sa istraktura na may mga setting para sa function na ito, kinakailangan ding ipasa ang pangalan ng port kung saan nilalayon ang mga setting.
*/

Halos lahat ng mga peripheral ay na-configure sa humigit-kumulang sa parehong paraan;

Ngayon ay isulat natin ang ating LED blinking program gamit lamang ang mga function ng library.

//Huwag kalimutang isama ang header file na may paglalarawan ng microcontroller registers

#include "stm32f10x.h"
#include "stm32f10x_conf.h"

//ideklara ang function ng pagkaantala ng software

walang bisa Pagkaantala ( walang bisa);

//ang function ng pagkaantala ng software mismo

walang bisa Pagkaantala ( walang bisa)
{
hindi pinirmahan mahaba ako;
para sa(i=0; i<2000000; i++);
}

//Ang aming pangunahing function

walang bisa pangunahing( walang bisa)
{

//Pahintulutan ang port C bus clocking
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

//Ipahayag ang isang istraktura para sa pag-configure ng port
GPIO_InitTypeDef GPIO_Init_struct;

//Punan ang istraktura ng mga paunang halaga
GPIO_StructInit(&GPIO_Init_struct);

/* Isulat sa field ng GPIO_Pin ng istraktura ng GPIO_Init_struct ang pin number ng port na iko-configure pa namin */
GPIO_Init_struct.GPIO_Pin = GPIO_Pin_9;

// Punan ang mga field ng GPIO_Speed ​​​​at GPIO_Mode sa parehong paraan
GPIO_Init_struct.GPIO_Speed= GPIO_Speed_2MHz;
GPIO_Init_struct.GPIO_Mode = GPIO_Mode_Out_PP;

//Ipasa ang napunong istraktura upang magsagawa ng mga aksyon para i-configure ang mga rehistro
GPIO_Init(GPIOC, &GPIO_Init_struct);

//Ang aming pangunahing walang katapusang loop
habang(1)
{
//Pagtatakda ng pin 9 ng port C sa logical one (LED lit)
GPIO_SetBits(GPIOC, GPIO_Pin_9);

//Magdagdag ng pagkaantala ng software upang ang LED ay kumikinang nang ilang sandali
Pagkaantala();

// I-reset ang estado ng pin 9 ng port C sa logical zero
GPIO_ResetBits(GPIOC, GPIO_Pin_9);

//Magdagdag muli ng pagkaantala ng software
Pagkaantala();
}
}

link.

Mula sa halimbawa sa itaas, malinaw na ang paggamit ng mga function ng library para sa pagtatrabaho sa mga peripheral ay nagpapahintulot sa iyo na dalhin ang mga programa sa pagsusulat para sa isang microcontroller na mas malapit sa object-oriented programming, at binabawasan din ang pangangailangan para sa madalas na pag-access sa datasheet upang mabasa ang mga paglalarawan ng microcontroller nagrerehistro, ngunit ang paggamit ng mga function ng library ay nangangailangan ng mas mataas na kaalaman sa programming language . Dahil dito, para sa mga taong hindi partikular na pamilyar sa programming, ang isang mas simpleng opsyon para sa pagsusulat ng mga programa ay isang paraan upang magsulat ng mga programa nang hindi gumagamit ng mga function ng library, na may direktang access sa mga rehistro ng microcontroller. Para sa mga taong alam ang programming language, ngunit hindi gaanong bihasa sa microcontrollers, sa partikular na STM32, ang paggamit ng mga function ng library ay makabuluhang pinapasimple ang proseso ng pagsulat ng mga programa.

Ang sitwasyong ito, pati na rin ang katotohanan na inalagaan ng ST ang isang mataas na antas ng pagiging tugma, kapwa sa hardware at software, ng iba't ibang microcontrollers nito, ay ginagawang mas madaling pag-aralan ang mga ito, dahil hindi na kailangang suriin ang mga tampok na istruktura ng iba't ibang mga controllers na serye ng STM32 at nagbibigay-daan sa iyong pumili ng alinman sa mga microcontroller na magagamit sa linya ng STM32 bilang isang microcontroller para sa pag-aaral.

Interrupt handler

Ang mga microcontroller ay may isang kapansin-pansing kakayahan - upang ihinto ang pagpapatupad ng pangunahing programa para sa isang tiyak na kaganapan, at magpatuloy sa pagpapatupad ng isang espesyal na subroutine - humahadlang sa handler. Ang mga interrupt source ay maaaring panlabas na mga kaganapan - mga pagkaantala para sa pagtanggap/pagpapadala ng data sa pamamagitan ng anumang interface ng paglilipat ng data, o isang pagbabago sa output state, o mga panloob - timer overflow, atbp. Ang isang listahan ng mga posibleng interrupt source para sa mga serye ng STM32 na microcontroller ay ibinibigay sa datasheet " RM0041 Reference manual"sa seksyon" 8 Mga pagkagambala at mga kaganapan».

Dahil ang interrupt handler ay isa ring function, ito ay isusulat bilang isang regular na function, ngunit para malaman ng compiler na ang function na ito ay isang partikular na interrupt handler, ang mga paunang-natukoy na pangalan ay dapat piliin bilang ang function na pangalan, kung saan makagambala sa mga vector redirection. ay tinukoy. Ang isang listahan ng mga pangalan ng mga function na ito na may maikling paglalarawan ay matatagpuan sa assembler file " startup_stm32f10x_md_vl.s" Ang isang interrupt handler ay maaaring may ilang interrupt-cause source, halimbawa ang interrupt handler function na " USART1_IRQHandler"maaaring tawagan kapag ang pagtatapos ng pagtanggap at pagtatapos ng paghahatid ng isang byte, atbp.

Upang magsimulang magtrabaho sa mga interrupts, dapat mong i-configure at simulan ang NVIC interrupt controller. Sa arkitektura ng Cortex M3, ang bawat interrupt ay maaaring italaga ng sarili nitong priority group para sa mga kaso kung saan maraming mga interrupt ang nangyari nang sabay-sabay. Pagkatapos ay kailangan mong i-configure ang interrupt source.

Ang NVIC_IRQChannel field ay nagpapahiwatig kung aling interrupt ang gusto naming i-configure. Ang patuloy na USART1_IRQn ay tumutukoy sa channel na responsable para sa mga interrupt na nauugnay sa USART1. Ito ay tinukoy sa file na " stm32f10x.h", ang iba pang katulad na mga constant ay tinukoy din doon.

Ang susunod na dalawang patlang ay nagpapahiwatig ng interrupt na priyoridad (ang pinakamataas na halaga para sa dalawang parameter na ito ay tinutukoy ng napiling pangkat ng priyoridad). Ang huling field ay aktwal na nagbibigay-daan sa paggamit ng isang interrupt.

Upang gumana NVIC_Init, tulad ng kapag nagse-set up ng mga port, ang isang pointer sa isang istraktura ay ipinasa upang ilapat ang mga setting na ginawa at isulat ang mga ito sa kaukulang mga rehistro ng microcontroller.

Ngayon sa mga setting ng module kailangan mong itakda ang mga parameter kung saan ang module na ito ay bubuo ng isang interrupt. Una kailangan mong paganahin ang interrupt; ito ay ginagawa sa pamamagitan ng pagtawag sa function pangalan_ITConfig(), na matatagpuan sa header file ng peripheral device.

//I-enable ang mga interrupts sa pagkumpleto ng byte transfer sa pamamagitan ng USART1
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

//Paganahin ang mga interrupts kapag natanggap ang isang byte sa pamamagitan ng USART1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

Ang isang paglalarawan ng mga parameter na ipinasa sa function ay makikita sa source code file ng peripheral device, sa itaas lamang ng lokasyon ng mismong function. Ang function na ito ay nagbibigay-daan o hindi pinapagana ang mga interrupts para sa iba't ibang mga kaganapan mula sa tinukoy na peripheral module. Kapag ang function na ito ay naisakatuparan, ang microcontroller ay makakabuo ng mga interrupts para sa mga kaganapan na kailangan namin.

Pagkatapos nating makapasok sa interrupt handling function, kailangan nating suriin kung aling kaganapan ang naganap na interrupt, at pagkatapos ay i-reset ang flag, kung hindi, sa paglabas ng interrupt, magpapasya ang microcontroller na hindi namin naproseso ang interrupt, dahil ang interrupt na flag ay set pa rin.

Upang magsagawa ng iba't ibang, maliit, paulit-ulit na mga aksyon na may isang tiyak na panahon, ang mga microcontroller na may Cortex-M3 core ay may isang timer ng system na espesyal na idinisenyo para dito. Kasama sa mga function ng timer na ito ang pagtawag lamang ng interrupt sa mahigpit na tinukoy na mga agwat ng oras. Karaniwan, ang interrupt na tinatawag ng timer na ito ay naglalaman ng code upang sukatin ang tagal ng iba't ibang proseso. Ang deklarasyon ng function ng setting ng timer ay matatagpuan sa file na " core_ cm3. h" Tinutukoy ng argumentong ipinasa sa function ang bilang ng mga ikot ng orasan ng system bus sa pagitan ng mga pagitan ng pagtawag sa tagapangasiwa ng interrupt na tagapamahala ng system timer.

SysTick_Config(clk);

Ngayong nahaharap na tayo sa mga pagkagambala, muling isulat natin ang ating programa gamit ang timer ng system bilang elemento ng timing. Mula sa timer" SysTick” ay isang system at maaaring gamitin ng iba't ibang functional block ng aming programa, kung gayon ay makatwirang ilipat ang function ng pag-abala ng system timer sa isang hiwalay na file, at mula sa function na ito, tawagan ang mga function para sa bawat functional block nang hiwalay.

Isang halimbawa ng "main.c" na file para sa isang LED blinking program gamit ang isang interrupt:

//Isama ang isang header file na naglalarawan sa mga rehistro ng microcontroller

#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include "main.h"

unsigned int LED_timer;

//Function na tinawag mula sa system timer interrupt handler function

walang bisa SysTick_Timer_main( walang bisa)
{
//Kung ang variable ng LED_timer ay hindi pa umabot sa 0,
kung(LED_timer)
{
//Suriin ang halaga nito, kung ito ay higit sa 1500, i-on ang LED
kung(LED_timer>1500) GPIOC->BSRR= GPIO_BSRR_BS9;

//kung hindi man kung mas mababa sa o katumbas ng 1500 pagkatapos ay i-off ito
iba pa GPIOC->BSRR= GPIO_BSRR_BR9;

//Bawasan ang variable na LED_timer
LED_timer--;
}

//Kung ang halaga ng variable ay umabot sa zero, magtakda ng bagong halaga na 2000
iba pa LED_timer=2000;
}

//Ang aming pangunahing function

walang bisa pangunahing( walang bisa)
{

//Pahintulutan ang port C bus clocking
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

//Ipahayag ang isang istraktura para sa pag-configure ng port
GPIO_InitTypeDef GPIO_Init_struct;

//Punan ang istraktura ng mga paunang halaga
GPIO_StructInit(&GPIO_Init_struct);

/* Isulat sa field ng GPIO_Pin ng istraktura ng GPIO_Init_struct ang pin number ng port na iko-configure pa namin */
GPIO_Init_struct.GPIO_Pin = GPIO_Pin_9;

// Punan ang mga field ng GPIO_Speed ​​​​at GPIO_Mode sa parehong paraan
GPIO_Init_struct.GPIO_Speed= GPIO_Speed_2MHz;
GPIO_Init_struct.GPIO_Mode = GPIO_Mode_Out_PP;

//Ipasa ang napunong istraktura upang magsagawa ng mga aksyon para i-configure ang mga rehistro
GPIO_Init(GPIOC, &GPIO_Init_struct);

//pumili ng priority group para sa mga interrupts
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

//I-configure ang system timer na may pagitan na 1ms
SysTick_Config(24000000/1000);

//Ang aming pangunahing walang katapusang loop
habang(1)
{
//Sa pagkakataong ito ay walang laman, lahat ng LED control ay nangyayari sa mga interrupt
}
}

Bahagi ng source code sa file na "stm32f10x_it.c":


#include "main.h"

/**
* @brief Ang function na ito ay humahawak sa SysTick Handler.
* @param Wala
* @retval Wala
*/

walang bisa SysTick_Handler( walang bisa)
{
SysTick_Timer_main();
}

Ang isang halimbawa ng gumaganang draft ng isang programa para sa pag-blink ng LED gamit ang isang interrupt ay maaaring ma-download mula sa link.

Ito ay nagtatapos sa aking kuwento tungkol sa mga pangunahing kaalaman sa pagbuo ng mga programa para sa STM32 microcontroller. Ibinigay ko ang lahat ng impormasyong kinakailangan upang makapag-iisa pang makapag-aral ng mga microcontroller ng STM32. Ang materyal na ibinigay ay isang panimulang punto lamang, dahil buong paglalarawan ang pagtatrabaho sa mga microcontroller ay hindi mailarawan sa loob ng balangkas ng anumang artikulo. Bilang karagdagan, ang pag-aaral ng mga microcontroller nang hindi nakakakuha ng praktikal na karanasan ay imposible, at ang tunay na karanasan ay unti-unting dumarating sa mga taon ng trabaho, mga eksperimento, na may akumulasyon ng iba't ibang mga pag-unlad ng software at hardware, pati na rin ang pagbabasa ng iba't ibang mga artikulo at dokumentasyon sa mga microcontroller. Ngunit huwag hayaang takutin ka nito, dahil ang impormasyong ibinigay sa artikulo ay sapat na upang lumikha ng iyong unang aparato sa isang microcontroller, at maaari kang makakuha ng karagdagang kaalaman at karanasan sa iyong sarili, pagbuo ng higit pa at mas kumplikado at pinakamahusay na mga aparato at pagpapabuti ng iyong mga kasanayan.

Umaasa ako na naging interesado ako sa iyo sa pag-aaral ng mga microcontroller at pagbuo ng mga device batay sa mga ito, at ang aking mga gawa ay magiging kapaki-pakinabang at kawili-wili sa iyo.

Ipinahiwatig ko na ang karaniwang library ay konektado sa system. Sa katunayan, ang CMSIS ay konektado - ang sistema ng pangkalahatang istrukturang representasyon ng MK, pati na rin ang SPL - ang karaniwang peripheral library. Tingnan natin ang bawat isa sa kanila:

CMSIS
Ito ay isang hanay ng mga file ng header at isang maliit na hanay ng code para sa pag-iisa at pag-istruktura ng trabaho sa core at periphery ng MK. Sa katunayan, kung wala ang mga file na ito imposibleng gumana nang normal sa MK. Makukuha mo ang library sa MK page.
Ang library na ito, ayon sa paglalarawan, ay nilikha upang pag-isahin ang mga interface kapag nagtatrabaho sa alinmang MK ng pamilyang Cortex. Gayunpaman, sa katotohanan lumalabas na ito ay totoo lamang para sa isang tagagawa, i.e. Sa pamamagitan ng paglipat sa isang microcontroller mula sa ibang kumpanya, napipilitan kang pag-aralan ang mga peripheral nito halos mula sa simula.
Bagama't ang mga file na iyon na nauugnay sa core ng processor ng MK ay magkapareho sa lahat ng mga tagagawa (kung dahil lamang sa mayroon silang parehong modelo ng core ng processor - na ibinigay sa anyo ng mga bloke ng IP ng ARM).
Samakatuwid, ang pagtatrabaho sa mga bahagi ng kernel bilang mga rehistro, mga tagubilin, mga interrupt at mga yunit ng coprocessor ay pamantayan para sa lahat.
Tulad ng para sa paligid, ang STM32 at STM8 (bigla) ay halos magkatulad, at ito ay bahagyang totoo din para sa iba pang mga MK na inilabas ng ST. Sa praktikal na bahagi, ipapakita ko kung gaano kadali gamitin ang CMSIS. Gayunpaman, ang mga paghihirap sa paggamit nito ay nauugnay sa pag-aatubili ng mga tao na basahin ang dokumentasyon at maunawaan ang disenyo ng MK.

SPL
Standard Peripheral Library - karaniwang peripheral library. Gaya ng ipinahihiwatig ng pangalan, ang layunin ng library na ito ay lumikha ng abstraction para sa paligid ng MK. Binubuo ang library ng mga header file kung saan ang mga constant na nababasa ng tao para sa pag-configure at pagtatrabaho sa mga peripheral ng MK ay idineklara, pati na rin ang mga source code file na kinokolekta sa mismong library para sa mga operasyon na may mga peripheral.
Ang SPL ay isang abstraction sa CMSIS na ipinapakita sa user karaniwang interface para sa lahat ng MK hindi lamang mula sa isang tagagawa, ngunit sa pangkalahatan ay lahat ng MK na may Cortex-Mxx processor core.
Ito ay pinaniniwalaan na ito ay mas maginhawa para sa mga nagsisimula, dahil... nagbibigay-daan sa iyo na huwag isipin kung paano gumagana ang mga peripheral, ngunit ang kalidad ng code, ang pagiging pangkalahatan ng diskarte at ang pagpilit ng mga interface ay nagpapataw ng ilang mga paghihigpit sa developer.
Gayundin, hindi palaging pinapayagan ka ng functionality ng library na tumpak na i-configure ang mga setting ng ilang bahagi tulad ng USART (universal synchronous-asynchronous serial port) sa ilalim ng ilang partikular na kundisyon. Sa praktikal na bahagi, ilalarawan ko rin ang pagtatrabaho sa bahaging ito ng aklatan.

Kapag lumilikha ng iyong unang aplikasyon sa isang STM32 microcontroller, maaari kang pumunta sa maraming paraan. Ang una, klasiko, kinukuha namin ang eksaktong paglalarawan ng controller sa website na www.st.com, na lumalabas sa ilalim ng pangalang "Reference Manual" at binabasa ang paglalarawan ng mga peripheral na rehistro. Pagkatapos ay sinusubukan naming i-record ang mga ito at tingnan kung paano gumagana ang mga peripheral. Ang pagbabasa ng dokumentong ito ay lubhang kapaki-pakinabang, ngunit sa unang yugto ng pag-master ng isang microcontroller, maaari mong tanggihan ito, kakaiba na tila. Ang mga inhinyero ng STMicroelectronics ay nagsulat ng isang library ng driver karaniwang mga peripheral. Bukod dito, marami silang naisulat na mga halimbawa ng paggamit ng mga driver na ito, na maaaring mabawasan ang pagprograma ng iyong aplikasyon sa pagpindot sa Ctrl+C at Ctrl+V key, na sinusundan ng bahagyang pag-edit ng halimbawa ng paggamit ng driver upang umangkop sa iyong mga pangangailangan. Kaya, ang pagkonekta ng isang peripheral driver library sa iyong proyekto ay ang pangalawang paraan ng pagbuo ng isang application. Bilang karagdagan sa bilis ng pagsulat, may iba pang mga pakinabang ng pamamaraang ito: ang pagiging pangkalahatan ng code at ang paggamit ng iba pang mga proprietary library, tulad ng USB, Ethernet, drive control, atbp., na ibinibigay sa source code at paggamit. isang karaniwang peripheral driver. Mayroon ding mga disadvantages ng pamamaraang ito: Kung saan makakalampas ka gamit ang isang linya ng code, ang karaniwang STM32 peripheral driver ay magsusulat ng 10. Ang mismong peripheral library ay ibinibigay din sa anyo ng mga source file, upang masubaybayan mo kung alin ang bit nito. Ang rehistro ay binago ng ito o ang function na iyon. Kung ninanais, maaari kang lumipat mula sa pangalawang paraan ng pagsulat ng isang programa patungo sa una sa pamamagitan ng pagkomento sa bahagi ng code na gumagamit ng karaniwang library gamit ang iyong sarili, na direktang kumokontrol sa peripheral na rehistro. Bilang resulta ng pagkilos na ito, makakakuha ka sa bilis ng kontrol, ang halaga ng RAM at ROM, ngunit mawawala sa versatility ng code. Sa anumang kaso, inirerekomenda ng mga inhinyero ng Promelektronika ang paggamit ng library ng mga karaniwang peripheral kahit man lang sa unang yugto.

Ang pinakamalaking paghihirap ay naghihintay sa developer kapag kumokonekta sa library sa kanyang proyekto. Kung hindi mo alam kung paano ito gagawin, maaari kang gumugol ng maraming oras sa aktibidad na ito, na sumasalungat sa mismong ideya ng paggamit ng isang handa na driver. Ang materyal ay nakatuon sa pagkonekta sa karaniwang aklatan sa anumang pamilya ng STM32.

Ang bawat pamilya ng STM32 ay may sariling library ng mga karaniwang peripheral. Ito ay dahil sa ang katunayan na ang periphery mismo ay naiiba. Halimbawa, ang paligid ng STM32L controllers ay may power saving function bilang isa sa mga gawain nito, na nangangailangan ng pagdaragdag ng mga control function. Ang isang klasikong halimbawa ay isang ADC, na sa STM32L ay may kakayahan pagsara ng hardware, sa kawalan ng isang utos ng conversion sa mahabang panahon, ito ay isa sa mga kahihinatnan ng problema sa pag-save ng enerhiya. Ang mga ADC ng mga controller ng mga pamilyang STM32F ay walang ganoong function. Sa katunayan, dahil sa pagkakaroon ng mga pagkakaiba sa hardware sa mga peripheral, mayroon kaming iba't ibang mga library ng driver. Bilang karagdagan sa malinaw na pagkakaiba sa mga function ng controller, mayroong isang pagpapabuti sa mga peripheral. Kaya, ang mga peripheral ng mga pamilya ng controller na inilabas sa ibang pagkakataon ay maaaring maging mas maalalahanin at maginhawa. Halimbawa, may mga pagkakaiba sa kontrol ang mga peripheral ng STM32F1 at STM32F2 controllers. Sa opinyon ng may-akda, ang pamamahala ng mga peripheral ng STM32F2 ay mas maginhawa. At malinaw kung bakit: ang pamilyang STM32F2 ay inilabas sa ibang pagkakataon at pinayagan nito ang mga developer na isaalang-alang ang ilang mga nuances. Alinsunod dito, para sa mga pamilyang ito ay may mga indibidwal na peripheral control library. Ang ideya sa likod ng nasa itaas ay simple: sa pahina ng microcontroller na iyong gagamitin, mayroong isang peripheral library na angkop para dito.

Sa kabila ng mga pagkakaiba sa mga peripheral sa mga pamilya, itinatago ng mga driver ang 90% ng mga pagkakaiba sa loob ng kanilang sarili. Halimbawa, ang configuration function ng ADC na binanggit sa itaas ay mukhang pareho para sa lahat ng pamilya:

void ADC_Init(ADC_Nom, ADC_Param),

kung saan ang ADC_Nom ay ang ADC number sa form na ADC1, ADC2, ADC3, atbp.

ADC_Param – tagapagpahiwatig ng istraktura ng data, kung paano dapat i-configure ang ADC (kung ano ang magsisimula, kung gaano karaming mga channel ang idi-digitize, kung gagawin ito nang paikot, atbp.)

10% ng mga pagkakaiba sa pagitan ng mga pamilya, sa halimbawang ito, na kailangang itama kapag lumipat mula sa isang pamilya ng STM32 patungo sa isa pa, ay nakatago sa istruktura ng ADC_Param. Depende sa pamilya, maaaring mag-iba ang bilang ng mga field sa istrukturang ito. Ang pangkalahatang bahagi ay may parehong syntax. Kaya, ang paglilipat ng isang aplikasyon para sa isang pamilya ng STM32, na isinulat batay sa mga karaniwang peripheral na aklatan, sa isa pa ay napakasimple. Sa mga tuntunin ng universalization ng mga solusyon sa microcontrollers, STMicroelectronics ay hindi mapaglabanan!

Kaya, nag-download kami ng library para sa STM32 na ginagamit namin. Ano ang susunod? Susunod, kailangan naming lumikha ng isang proyekto at ikonekta ang mga kinakailangang file dito. Tingnan natin ang paglikha ng isang proyekto gamit ang IAR Embedded Workbench development environment bilang isang halimbawa. Ilunsad ang development environment at pumunta sa tab na "Proyekto", piliin ang item sa paggawa ng proyekto na "Gumawa ng proyekto":

Sa lalabas na bagong proyekto, ilagay ang mga setting sa pamamagitan ng pag-hover ng cursor sa pangalan ng proyekto, pag-right click at pagpili sa "Mga Opsyon" mula sa drop-down na menu:

Mga lugar ng memorya ng RAM at ROM:

Kapag na-click mo ang "I-save" na buton, mag-aalok ang kapaligiran na mag-record bagong file mga paglalarawan ng controller sa folder ng proyekto. Inirerekomenda ng may-akda ang paglikha ng isang indibidwal na *.icp file para sa bawat proyekto at iimbak ito sa folder ng proyekto.

Kung ide-debug mo ang iyong proyekto sa loob ng circuit, na inirerekomenda, pagkatapos ay ilagay ang uri ng debugger na ginamit:

Sa tab ng napiling debugger, ipinapahiwatig namin ang interface para sa pagkonekta sa debugger (sa aming kaso, ST-Link ang napili) sa controller:



Mula sa puntong ito, ang aming proyekto na walang mga aklatan ay handa nang i-compile at i-load sa controller. Ang ibang mga kapaligiran gaya ng Keil uVision4, Resonance Ride7, atbp. ay mangangailangan ng parehong mga hakbang.

Kung isusulat mo ang linya sa main.c file:

#include "stm32f10x.h" o

#include "stm32f2xx.h" o

#include "stm32f4xx.h" o

#include "stm32l15x.h" o

#include "stm32l10x.h" o

#include "stm32f05x.h"

na nagpapahiwatig ng lokasyon ng file na ito, o pagkopya ng file na ito sa folder ng proyekto, pagkatapos ay iuugnay ang ilang lugar ng memorya sa mga peripheral na rehistro ng kaukulang pamilya. Ang file mismo ay matatagpuan sa karaniwang folder ng library ng peripheral sa seksyon: \CMSIS\CM3\DeviceSupport\ST\STM32F10x (o isang katulad na pangalan para sa ibang mga pamilya). Mula ngayon, papalitan mo ang address ng peripheral register sa anyo ng isang numero na may pangalan nito. Kahit na hindi mo nilayon na gamitin ang karaniwang mga function ng library, inirerekomenda na gumawa ng ganoong koneksyon.

Kung gagamit ka ng mga interrupts sa iyong proyekto, inirerekumenda na isama ang start file na may extension na *.s, na matatagpuan sa path na \CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\iar, o katulad para sa ibang pamilya. Mahalagang tandaan na ang bawat kapaligiran ay may sariling file. Alinsunod dito, kung gagamit tayo ng IAR EWB, dapat nating kunin ang file mula sa folder ng IAR. Ito ay dahil sa bahagyang pagkakaiba sa syntax ng mga kapaligiran. Samakatuwid, upang agad na magsimula ang proyekto, sumulat ang mga inhinyero ng STMicroelectronics ng ilang bersyon ng mga startup file para sa ilan sa mga pinakasikat na development environment. Karamihan sa mga pamilya ng STM32 ay may isang file. Ang pamilyang STM32F1 ay may ilang mga trigger file:

  • startup_stm32f10x_cl.s – para sa STM32F105/107 microcontrollers
  • startup_stm32f10x_xl.s - para sa mga microcontroller STM32F101/STM32F103 768kb at higit pa
  • startup_stm32f10x_hd.s - para sa mga microcontroller STM32F101/STM32F103 c Flash memory 256-512 kb
  • startup_stm32f10x_md.s - para sa mga microcontroller STM32F101/ STM32F102/STM32F103 na may Flash memory 64-128 kB
  • startup_stm32f10x_ld.s - para sa STM32F101/ STM32F102/STM32F103 microcontroller na may Flash memory na mas mababa sa 64 kB
  • startup_stm32f10x_hd_vl.s para sa mga STM32F100 microcontroller na may 256-512 kB Flash memory
  • startup_stm32f10x_md_vl.s para sa STM32F100 microcontrollers na may 64-128 kB Flash memory
  • startup_stm32f10x_ld_vl.s para sa mga STM32F100 microcontroller na may 32kb Flash memory o mas kaunti

Kaya, depende sa pamilya, subfamily at development environment, idinaragdag namin ang launch file sa proyekto:

Dito nagtatapos ang microcontroller kapag nagsimula ang programa. Ang interrupt ay sunud-sunod na tinatawag ang SystemInit() function at pagkatapos ay __iar_program_start. Ang pangalawang function ay nagre-reset o nagsusulat nang maaga itakda ang mga halaga mga global na variable, pagkatapos nito ay mapupunta sa user program main(). Kino-configure ng SystemInit() function ang microcontroller clock. Siya ang sumasagot sa mga tanong:

  • Kailangan ko bang lumipat sa panlabas na kristal (HSE)?
  • Paano paramihin ang dalas mula sa HSI/HSE?
  • Kailangan bang ikonekta ang isang command load queue?
  • Ano ang kinakailangang pagkaantala kapag naglo-load ng isang command (dahil sa mababang bilis Gumagana ang flash memorya)
  • Paano hatiin ang clocking ng mga peripheral bus?
  • Kailangan bang ilagay ang code sa panlabas na RAM?

Ang SystemInit() function ay maaaring isulat nang manu-mano sa iyong proyekto. Kung idinisenyo mo ang function na ito bilang walang laman, ang controller ay gagana sa isang panloob na RC oscillator na may dalas na humigit-kumulang 8 MHz (depende sa uri ng pamilya). Pagpipilian 2 – ikonekta sa proyekto ang file system_stm32f10x.c (o isang katulad na pangalan depende sa uri ng pamilyang ginamit), na matatagpuan sa library sa kahabaan ng landas: Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x. Ang file na ito ay naglalaman ng SystemInit() function. Bigyang-pansin ang dalas ng panlabas na kristal na HSE_VALUE. Nakatakda ang parameter na ito sa stm32f10x.h header file. Ang karaniwang halaga ay 8 at 25 MHz, depende sa pamilya ng STM32. Ang pangunahing gawain ng SystemInit() function ay upang ilipat ang clocking sa panlabas na quartz at i-multiply ang frequency na ito sa isang tiyak na paraan. Ano ang mangyayari kung ang halaga ng HSE_VALUE ay tinukoy bilang 8 MHz, ang core ay dapat na naka-clock sa 72 MHz, ngunit sa katunayan ang board ay may 16 MHz na kristal? Bilang resulta ng naturang mga maling aksyon ang core ay makakatanggap ng orasan na 144 MHz, na maaaring lampas sa garantisadong operasyon ng system sa STM32. Yung. kapag ikinonekta ang system_stm32f10x.c file, kakailanganin mong tukuyin ang halaga ng HSE_VALUE. Ang lahat ng ito ay nangangahulugan na ang mga file system_stm32f10x.c, system_stm32f10x.h at stm32f10x.h (o mga katulad na pangalan para sa ibang mga pamilya) ay dapat na indibidwal para sa bawat proyekto. AT

Ginawa ng mga inhinyero ng STMicroelectronics ang Clock Configuration Tool, na nagbibigay-daan sa iyong i-configure nang tama ang system clock. Ito Excel file, na bumubuo ng file system_stm32xxx.c (katulad sa pangalan para sa isang naibigay na pamilya ng mga pamilya), pagkatapos tukuyin ang mga parameter ng input at output ng system. Tingnan natin ang pagpapatakbo nito gamit ang pamilyang STM32F4 bilang isang halimbawa.

Mga Opsyon: panloob na RC oscillator, panloob na RC oscillator na may frequency multiplication, o external quartz na may frequency multiplication. Pagkatapos piliin ang pinagmulan ng orasan, ipinapasok namin ang mga parameter ng nais na configuration ng system, tulad ng dalas ng pag-input (kapag gumagamit ng isang panlabas na quartz), dalas ng core ng orasan, mga divider ng dalas ng orasan ng peripheral bus, pagpapatakbo ng command fetch buffer, at iba pa. Sa pamamagitan ng pag-click sa pindutang "Bumuo", nakakakuha kami ng isang window


Kasama ang system_stm32f4xx.c file at ang mga analogue nito ay mangangailangan ng pagkonekta ng isa pang karaniwang peripheral library file. Upang kontrolin ang clocking, mayroong isang buong hanay ng mga function na tinatawag mula sa system_stm32xxxxxx.c file. Ang mga function na ito ay matatagpuan sa stm32f10x_rcc.c file at sa header nito. Alinsunod dito, kapag ikinonekta ang system_stm32xxxxxx.c file sa proyekto, kinakailangang isama ang stm32f10x_rcc.c, kung hindi, iuulat ng environment linker ang kawalan ng paglalarawan ng mga function na may pangalang RCC_xxxxxxx. Ang tinukoy na file ay matatagpuan sa peripheral library sa path: Libraries\STM32F10x_StdPeriph_Driver\src, at ang header nito ay \Libraries\STM32F10x_StdPeriph_Driver\inc.

Ang mga peripheral na file ng header ng driver ay kasama sa file na stm32f10x_conf.h, na nire-reference ng stm32f10x.h. Ang stm32f10x_conf.h file ay isang set lang ng mga header file para sa mga driver para sa mga partikular na controller peripheral na isasama sa proyekto. Sa una, ang lahat ng "#include" na mga header ay minarkahan bilang mga komento. Ang pagkonekta ng isang peripheral header file ay nagsasangkot ng pag-alis ng komento sa kaukulang pangalan ng file. Sa aming kaso, ito ang linyang #include "stm32f10x_rcc.h". Malinaw, ang stm32f10x_conf.h file ay indibidwal para sa bawat proyekto, dahil iba't ibang mga proyekto ang gumagamit ng iba't ibang peripheral.

At isang huling bagay. Kailangan mong tukuyin ang ilang mga direktiba sa compiler preprocessor at mga landas sa mga file ng header.



Maaaring magkaiba ang mga path patungo sa mga file ng header, depende sa lokasyon ng peripheral library na nauugnay sa folder ng proyekto, ngunit ang pagkakaroon ng "USE_STDPERIPH_DRIVER" ay sapilitan kapag kumukonekta sa karaniwang mga driver ng peripheral ng library.

Kaya, ikinonekta namin ang karaniwang aklatan sa proyekto. Bukod dito, ikinonekta namin ang isa sa karaniwang mga driver peripheral sa proyektong kumokontrol sa system clocking.

Nalaman namin kung ano ang hitsura ng istraktura ng silid-aklatan mula sa loob, ngayon ng ilang mga salita tungkol sa kung ano ang hitsura nito mula sa labas.



Kaya, ang pagkonekta sa stm32f10x.h header file sa application ay nangangailangan ng pagkonekta ng iba pang header file at code file. Ang ilan sa mga ipinapakita sa figure ay inilarawan sa itaas. Ang ilang mga salita tungkol sa natitira. Ang mga STM32F10x_PPP.x na file ay mga peripheral na driver file. Ang isang halimbawa ng pagkonekta ng naturang file ay ipinapakita sa itaas; ito ay RCC - ang periphery ng system clock control. Kung nais naming ikonekta ang mga driver ng iba pang mga peripheral, kung gayon ang pangalan ng mga konektadong file ay nakuha sa pamamagitan ng pagpapalit ng "PPP" sa pangalan ng peripheral, halimbawa, ADC - STM32F10x_ADC.c, o I/O port STM32F10x_GPIO.c, o DAC - STM32F10x_DAC.c. Sa pangkalahatan, malinaw na malinaw kung aling file ang kailangang ikonekta kapag kumokonekta sa isang partikular na peripheral. Ang mga file na "misc.c", "misc.h" ay kapareho ng STM32F10x_PPP.x, ang kernel lang ang kinokontrol ng mga ito. Halimbawa, ang pag-set up ng mga interrupt na vector, na naka-built sa kernel, o pamamahala sa SysTick timer, na bahagi ng kernel. Ang mga xxxxxxx_it.c file ay naglalarawan sa mga di-maskable na interrupt vector ng controller. Maaari silang dagdagan ng mga peripheral interrupt vectors. Ang file na core_m3.h ay naglalarawan sa CortexM3 core. Ang kernel na ito standardized at maaaring matagpuan sa mga microcontroller mula sa iba pang mga tagagawa. Para sa cross-platform universalization, ang STMicroelectronics ay nagtrabaho upang lumikha ng isang hiwalay na CortexM core library, pagkatapos nito ay na-standardize ito ng ARM at ipinamahagi ito sa iba pang mga tagagawa ng microcontroller. Kaya't ang paglipat sa STM32 mula sa mga controller mula sa iba pang mga tagagawa na may CortexM core ay magiging mas madali.

Kaya, maaari naming ikonekta ang karaniwang peripheral library sa anumang pamilya ng STM32. Ang matututo kung paano gawin ito ay makakatanggap ng premyo: napakasimpleng programming ng mga microcontroller. Bilang karagdagan sa mga driver sa anyo ng mga source file, ang library ay naglalaman ng maraming mga halimbawa ng paggamit ng mga peripheral. Halimbawa, isaalang-alang natin ang paglikha ng isang proyekto na kinasasangkutan ng mga output ng paghahambing ng timer. Gamit ang tradisyonal na diskarte, maingat nating pag-aralan ang paglalarawan ng mga rehistro ng peripheral na ito. Ngunit ngayon ay maaari nating pag-aralan ang teksto ng tumatakbong programa. Pumunta kami sa folder ng mga halimbawa ng mga karaniwang peripheral, na matatagpuan sa landas na ProjectSTM32F10x_StdPeriph_Examples. Narito ang mga folder ng mga halimbawa na may pangalan ng mga peripheral na ginamit. Pumunta sa folder na "TIM". Ang mga timer sa STM32 ay may maraming mga function at setting, kaya imposibleng ipakita ang mga kakayahan ng controller sa isang halimbawa lamang. Samakatuwid, sa loob ng tinukoy na direktoryo mayroong maraming mga halimbawa ng paggamit ng mga timer. Kami ay interesado sa pagbuo ng isang PWM signal sa pamamagitan ng isang timer. Pumunta sa folder na "7PWM_Output". Sa loob mayroong isang paglalarawan ng programa sa Ingles at isang hanay ng mga file:

main.c stm32f10x_conf.h stm32f10x_it.h stm32f10x_it.c system_stm32f10x.c

Kung ang proyekto ay walang mga pagkaantala, ang nilalaman ay ganap na matatagpuan sa main.c file. Kopyahin ang mga file na ito sa direktoryo ng proyekto. Ang pagkakaroon ng pinagsama-samang proyekto, makakatanggap kami ng isang programa para sa STM32 na magko-configure ng timer at I/O port upang makabuo ng 7 PWM signal mula sa timer 1. Susunod, maaari naming iakma ang nakasulat na code sa aming gawain. Halimbawa, bawasan ang bilang ng mga signal ng PWM, baguhin ang duty cycle, direksyon ng pagbibilang, atbp. Ang mga function at ang kanilang mga parameter ay mahusay na inilarawan sa file na stm32f10x_stdperiph_lib_um.chm. Ang mga pangalan ng mga pag-andar at ang kanilang mga parameter ay madaling nauugnay sa kanilang layunin para sa mga may alam ng kaunti wikang Ingles. Para sa kalinawan, narito ang bahagi ng halimbawang code:

/* Time Base configuration */ TIM_TimeBaseStructure.TIM_Prescaler = 0; // walang preselection ng pagbibilang ng mga pulso (16-bit na rehistro) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // ang pagbibilang ng direksyon ay pataas TIM_TimeBaseStructure.TIM_Period = TimerPeriod; // count up to the value of TimerPeriod (constant in the program) TIM_TimeBaseStructure.TIM_ClockDivision = 0; // walang pre-counter division TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // overflow counter para sa pagbuo ng mga kaganapan (hindi ginagamit sa programa) TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // pagpasok ng TimeBaseStructure values ​​​​sa mga rehistro ng timer 1 (pagpasok ng data dito // variable ay nasa itaas) /* Channel 1, 2,3 at 4 Configuration sa PWM mode */ // pagse-set up ng PWM outputs TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // PWM2 operating mode TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // paganahin ang output ng PWM timer signal TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // paganahin ang komplementaryong PWM timer output TIM_OCInitStructure.TIM_Pulse = Channel1Pulse; // pulse width Channel1Pulse – pare-pareho sa programang TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // pagtatakda ng output polarity TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // pagtatakda ng polarity ng komplementaryong output TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; // pagtatakda ng ligtas na estado ng PWM output TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; // pagtatakda ng ligtas na estado ng komplementaryong PWM output TIM_OC1Init(TIM1, &TIM_OCInitStructure); // pagpasok ng mga halaga ng TIM_OCInitStructure variable sa PWM registers ng channel 1 // timer 1 TIM_OCInitStructure.TIM_Pulse = Channel2Pulse; // baguhin ang lapad ng pulso sa OCInitStructure variable at ilagay ito sa TIM_OC2Init(TIM1, &TIM_OCInitStructure); // nagrerehistro ng PWM channel 2 timer1 TIM_OCInitStructure.TIM_Pulse = Channel3Pulse; // baguhin ang lapad ng pulso sa OCInitStructure variable at ilagay ito sa TIM_OC3Init(TIM1, &TIM_OCInitStructure); // nagrerehistro ng PWM channel 3 timer1 TIM_OCInitStructure.TIM_Pulse = Channel4Pulse; // baguhin ang lapad ng pulso sa OCInitStructure variable at ilagay ito sa TIM_OC4Init(TIM1, &TIM_OCInitStructure); // nagrerehistro ng PWM channel 4 timer1 /* TIM1 counter enable */ TIM_Cmd(TIM1, ENABLE); // start timer1 /* TIM1 Main Output Enable */ TIM_CtrlPWMOutputs(TIM1, ENABLE); // paganahin ang pagpapatakbo ng timer 1 na mga output ng paghahambing

Sa kanang bahagi, ang may-akda ay nag-iwan ng komento sa Russian para sa bawat linya ng programa. Kung bubuksan namin ang parehong halimbawa sa paglalarawan ng mga function ng library stm32f10x_stdperiph_lib_um.chm, makikita namin na ang lahat ng ginamit na mga parameter ng function ay may isang link sa kanilang sariling paglalarawan, kung saan ang kanilang mga posibleng halaga ay ipahiwatig. Ang mga function mismo ay mayroon ding link sa kanilang sariling paglalarawan at source code. Ito ay lubhang kapaki-pakinabang dahil... Alam kung ano ang nagagawa ng isang function, masusubaybayan natin kung paano ito ginagawa, kung aling mga piraso ng peripheral ang nagrerehistro at kung paano ito nakakaapekto. Ito ay, una, isa pang mapagkukunan ng impormasyon para sa mastering ng controller, batay sa praktikal na paggamit ng controller. Yung. magdesisyon ka muna teknikal na problema, at pagkatapos ay pag-aralan ang solusyon mismo. Pangalawa, ito ay isang larangan para sa pag-optimize ng programa para sa mga hindi nasisiyahan sa library sa mga tuntunin ng bilis at dami ng code.



Muli gusto kong magsulat tungkol sa isang simpleng pagsisimula sa STM32, sa pagkakataong ito lamang nang hindi gumagamit ng mga template o halimbawa ng sinuman - na may paliwanag sa bawat hakbang. Ang mga artikulo ay magkakaroon ng tuloy-tuloy na pagbilang ng mga hakbang.

1. I-install ang IAR

Pagbuo ng isang proyekto sa IAR

1. Preprocessor

  1. tinatanggal ang mga komento

2. Compiler

3. Linker

3. Gumawa ng bagong proyekto sa IAR

Pagkatapos ilunsad ang IAR, may lalabas na window sentro ng impormasyon, na hindi natin kailangan. I-click ang menu ng Project -> Lumikha ng Bagong Proyekto. Pumili ng toolchain: ARM (malamang na hindi ka magkakaroon ng iba pa sa listahang iyon), Mga template ng proyekto: C -> pangunahing.

Sa kaliwang window ("Workspace"), i-right click upang buksan ang menu at lumikha ng bagong grupo (Add ->

I-right click sa CMSIS

Sa grupo Startup

Tapos na kami sa CMSIS.

Sa grupo StdPeriphLib

Sa grupo Gumagamit

5. Pagse-set up ng proyekto

  1. Pangkalahatang mga opsyon -> Target ->
Piliin ang ST -> STM32F100 -> ST STM32F100xB. Ito ang aming controller. 2. Pangkalahatang mga opsyon –> Library Configuration –> CMSIS: lagyan ng check ang Use CMSIS checkbox. Kaya gagamitin namin ang CMSIS library na nakapaloob sa compiler. Mula noong bersyon 6.30, nagsimulang ipadala ang IAR gamit ang isang built-in na CMSIS, at ito ay tila mas mahusay - ngunit nagpakilala ito ng ilang pagkalito sa mga mas lumang proyekto. 3. C/C++ compiler –>
$PROJ_DIR$\

* Debugger -> Setup -> Driver: piliin ang ST–Link, dahil ito ang programmer na binuo sa Discovery board. Ngayon i-configure namin ang programmer mismo: * Debugger -> ST–LINK -> Interface: piliin ang SWD (ang programmer sa board ay konektado sa controller sa pamamagitan ng SWD, hindi sa pamamagitan ng JTAG). * Debugger ->
#include "stm32f10x_conf.h" 

void main()
{
habang(1)
{
}
}

<1000000; i++);


para sa(i=0; i<1000000; i++);

#include "stm32f10x_conf.h"

void main()
{





int i;
habang(1)
{

para sa(i=0; i<1000000; i++);

<1000000; i++); } }

archive kasama ang proyekto ng GPIO. Sa kabutihang palad, maaari mong i-save ang proyektong ito at gamitin ito bilang isang template upang hindi mo na kailangang dumaan muli sa lahat ng pag-setup. Ang buong cycle: 1. I/O ports (/index.php/stm32-from_zero_to_rtos-2_timers/ "STM32 - from zero to RTOS. 2: Timer and interrupts") (/index.php/stm32-from_zero_to_rtos-3_timer_outputs/ " STM32 - mula sa simula hanggang sa RTOS 3: Mga output ng timer") [Muling nais kong magsulat tungkol sa isang simpleng pagsisimula sa STM32, sa pagkakataong ito lamang nang hindi gumagamit ng mga template o halimbawa ng sinuman - na may paliwanag sa bawat hakbang. Ang mga artikulo ay magkakaroon ng tuloy-tuloy na pagbilang ng mga hakbang.

0. Kinukuha namin ang STM32VLDdiscovery board

Binili namin ito sa tindahan, nagkakahalaga ito ng 600 rubles. Kakailanganin mong mag-install ng mga driver sa board - Sa palagay ko hindi ito magiging sanhi ng anumang mga paghihirap.

1. I-install ang IAR

Magtatrabaho kami sa IAR - isang magandang IDE na may mahusay na compiler. Ito ay kulang sa kaginhawahan ng pagsulat ng code - ngunit para sa aming mga layunin ito ay lubos na sapat. Gumagamit ako ng IAR version 6.50.3, alam mo kung saan ito makukuha.

2. I-download ang peripheral library

Hindi ako mahilig magtrabaho sa mga rehistro sa yugto ng pag-aaral. Samakatuwid, iminumungkahi kong i-download ang peripheral library mula sa ST upang makakuha ng mga maginhawang function para sa pag-access sa lahat ng kinakailangang setting.

Lumikha ng isang folder na "STM32_Projects", ilagay ang folder ng Mga Aklatan doon mula sa na-download na archive (stsw-stm32078.zip/an3268/stm32vldiscovery_package), naglalaman ito ng CMSIS (isang library mula sa ARM para sa lahat ng Cortex microcontrollers, paglalarawan at mga address ng lahat ng mga mapagkukunan) at STM32F10dPerix. - isang peripheral library mula sa ST na may lahat ng mga tampok.

Lumilikha din kami ng isang folder doon "1. GPIO”, na magiging una naming proyekto.

Ang puno ng folder ay ipinapakita sa larawan. Gawin ito sa ganitong paraan, dahil mamaya ang mga kamag-anak na landas sa punong ito ay magiging napakahalaga.

Kaya, upang maunawaan kung ano ang pinag-uusapan natin, i-download ang 1100-pahinang dokumento sa mga controllers na ito.

Pagbuo ng isang proyekto sa IAR

Ito ay kinakailangan upang malinaw na maunawaan ang kakanyahan ng proseso ng pagpupulong ng proyekto. Para sa kaginhawahan, hahati-hatiin natin ito sa mga yugto.

1. Preprocessor

Ang preprocessor ay dumaan sa lahat ng .c na file ng proyekto (kapwa main.c at lahat ng file sa workspace). Ginagawa nito ang sumusunod:

  1. tinatanggal ang mga komento
  2. nagpapalawak ng #include na mga direktiba, na pinapalitan ang mga ito ng mga nilalaman ng tinukoy na file. Ang prosesong ito ay nagaganap nang paulit-ulit, simula sa .c na file at paglalagay ng bawat #include .h na nakatagpo, at kung ang #include na mga direktiba ay makikita rin sa .h file, ang preprocessor ay papasok din sa kanila. Nagreresulta ito sa isang puno ng mga inklusyon. Pakitandaan: hindi nito pinangangasiwaan ang sitwasyon ng double inclusions, i.e. ang parehong .h file ay maaaring isama nang maraming beses kung ito ay #included sa maraming lugar sa proyekto. Ang sitwasyong ito ay kailangang hawakan ng mga defin.
  3. nagsasagawa ng mga macro substitution - nagpapalawak ng mga macro
  4. nangongolekta ng mga direktiba ng compiler.

Ang preprocessor ay bumubuo ng mga .i na file, na medyo maginhawa kapag naghahanap ng mga error sa pagbuo - kung dahil lamang sa lahat ng mga macro ay ganap na isiwalat sa mga ito. Maaaring paganahin ang pag-save ng mga file na ito sa mga setting ng proyekto.

Sa puntong ito, ang tagabuo ay may lahat ng .c na file sa proyekto na handa nang i-compile - bilang mga .i na file. Wala pang koneksyon sa pagitan ng mga file.

2. Compiler

Pagkatapos dumaan sa preprocessor, ino-optimize at kino-compile ng compiler ang bawat .i file, na lumilikha ng binary code. Dito kailangan mong tukuyin ang uri ng processor, magagamit na memorya, programming language, antas ng pag-optimize, at mga katulad na bagay.

Ano ang ginagawa ng compiler kapag nakatagpo ito ng function na tawag sa ilang .c file na hindi inilarawan sa file na ito? Hinahanap niya ito sa mga headline. Kung sinasabi ng mga header na ang function ay nasa isa pang .c file, nag-iiwan lang ito ng pointer sa ibang file sa lugar na ito.

Sa puntong ito, naipon ng tagabuo ang lahat ng .c file ng proyekto sa mga .o na file. Ang mga ito ay tinatawag na compiled modules. Ngayon ay may mga koneksyon sa pagitan ng mga file sa anyo ng mga pointer sa mga lugar kung saan tinatawag ang mga "banyagang" function - ngunit ito ay iba't ibang mga file pa rin.

3. Linker

Halos lahat ay handa na, kailangan mo lamang suriin ang lahat ng mga koneksyon sa pagitan ng mga file - dumaan sa main.o at palitan ang mga pointer sa mga function ng ibang tao - pinagsama-samang mga module. Kung ang ilang function mula sa mga aklatan ay hindi ginagamit, ito ay alinman ay hindi isasama sa lahat sa nakaraang yugto, o hindi papalitan kahit saan ng linker (depende sa paraan ng pagpapatakbo ng assembler). Sa anumang kaso, hindi ito isasama sa natapos na binary code.

Ang linker ay maaari ding magsagawa ng ilang panghuling aksyon sa binary, tulad ng pagkalkula ng checksum nito.

Ang unang proyekto ay gumagana sa mga I/O port

3. Gumawa ng bagong proyekto sa IAR

Pagkatapos ilunsad ang IAR, lilitaw ang isang window ng information center, na hindi namin kailangan. I-click ang menu ng Project -> Lumikha ng Bagong Proyekto. Pumili ng toolchain: ARM (malamang na hindi ka magkakaroon ng iba pa sa listahang iyon), Mga template ng proyekto: C -> pangunahing.

Mayroon ka na ngayong bagong walang laman na proyektong C at isang main.c file.

4. Ikonekta ang mga aklatan sa proyekto

Sa kaliwang window ("Workspace"), i-right-click ang menu at lumikha ng bagong grupo (Add -> Add Group), tawagan natin itong CMSIS. Gawin natin ang mga pangkat na StdPeriphLib, Startup at User sa parehong paraan. Ngayon ay nagdaragdag kami ng mga file sa mga pangkat (salungguhitan ko ang lahat ng mga file upang gawing mas madaling sundin).

I-right click sa CMSIS, Magdagdag, Magdagdag ng mga file - pumunta sa Mga Aklatan/CMSIS/CM3, mula sa folder na DeviceSupport/ST/STM32F10x (suporta sa chip) kunin ang system_stm32f10x.c (ito ay isang paglalarawan ng paligid ng isang partikular na mga setting ng kristal at orasan). Sa folder ng CoreSupport (suporta sa kernel) mayroon ding core_cm3.c (ito ay isang paglalarawan ng core ng Cortex M3), ngunit hindi namin ito kukunin - dahil nasa compiler na ito. Isusulat ko pa ang tungkol dito.

Sa grupo Startup idagdag ang file na startup_stm32f10x_md_vl.s mula sa folder na Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/iar. Ito ang mga aksyon na kailangang gawin sa pagsisimula. Halos lahat ito ay tungkol sa pagse-set up ng iba't ibang interrupt handler (ang mga handler mismo ay medyo malayo). Mayroon ding mga file para sa iba pang mga kristal, ngunit interesado kami sa md_vl - nangangahulugan ito ng medium density (average na dami ng memorya, mayroon ding mga kristal na may maliit at malaking volume), linya ng halaga (linya ng pagsusuri - ang STM32F100 na kristal ay inilaan lamang para sa pagtatasa ng kakayahan, at paglipat sa mga sumusunod na pamilya).

Tapos na kami sa CMSIS.

Sa grupo StdPeriphLib idagdag ang mga file na stm32f10x_rcc.c at stm32f10x_gpio.c mula sa folder ng Libraries/STM32F10x_StdPeriph_Driver/src. Ang una ay ang mga function ng pagtatrabaho sa sistema ng orasan, at ang pangalawa ay gumagana sa mga I/O pin.

Sa grupo Gumagamit hilahin ang aming pangunahing.c . Ito ay hindi kinakailangan, ngunit ito ay mas maganda.

Ang puno ng proyekto ng GPIO ay ganito na ngayon:

Handa na ang workspace, hindi na kami magdadagdag pa nito.

Ang natitira na lang ay maglagay ng isa pang file sa folder ng proyekto na nag-uugnay sa mga header sa lahat ng mga peripheral library file. Maaari mo itong isulat sa iyong sarili, ngunit mas madaling kumuha ng handa na. Pumunta kami sa stsw-stm32078.zip/an3268/stm32vldiscovery_package/Project/Examples/GPIOToggle - doon kinuha namin ang file na stm32f10x_conf.h (project configuration) at ilagay ito sa folder na “1. GPIO". Ito ang tanging handa na file na kinukuha namin.

Ang stm32f10x_conf.h ay isa lamang dump ng mga kasama ng mga kinakailangang module at assert function. Ang function na ito ay tatawagin kapag may mga error kapag nagtatrabaho sa mga peripheral library function: halimbawa, paglalagay ng ilang basura sa GPIO_WriteBit function sa halip na GPIOC - sa madaling salita, naglaro ito nang ligtas ang ST. Sa function na ito maaari mo lamang simulan ang isang walang katapusang loop - habang(1); Kailangan pa rin nating pumunta sa stm32f10x_conf.h - upang magkomento sa mga linya para sa pagsasama ng mga file ng mga hindi kinakailangang peripheral, na naiwan lamang ang stm32f10x_rcc.h, stm32f10x_gpio.h at misc.h - para maisulat namin ito mismo.

5. Pagse-set up ng proyekto

Mag-right-click sa pangalan ng proyekto sa window ng Workspace:

  1. Mga pangkalahatang opsyon -> Target -> Variant ng processor: piliin ang "Device", pindutin ang button sa kanan
Piliin ang ST -> STM32F100 -> ST STM32F100xB. Ito ang aming controller. 2. Pangkalahatang mga opsyon –> Library Configuration –> CMSIS: lagyan ng check ang Use CMSIS checkbox. Kaya gagamitin namin ang CMSIS library na nakapaloob sa compiler. Mula noong bersyon 6.30, nagsimulang ipadala ang IAR gamit ang isang built-in na CMSIS, at ito ay tila mas mahusay - ngunit nagpakilala ito ng ilang pagkalito sa mga mas lumang proyekto. 3. C/C++ compiler -> Preprocessor. Dito isinulat namin ang mga landas sa mga folder ng library:
$PROJ_DIR$\
$PROJ_DIR$\..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
$PROJ_DIR$\..\Libraries\STM32F10x_StdPeriph_Driver\inc
Ang ibig sabihin ng macro na $PROJ_DIR$ kasalukuyang folder(folder ng proyekto), at.. - ilipat ang isang antas na mas mataas. Tinukoy namin ang mga path patungo sa folder na may paglalarawan ng kristal, pati na rin ang mga header file ng peripheral library, dahil ang lahat ng .c file sa proyekto ay kasama ang kanilang mga header, at dapat alam ng compiler kung saan hahanapin ang mga ito. Dito kailangan mo ring isulat ang USE\_STDPERIPH\_DRIVER sa mga Defined na simbolo. Ito ay magkokonekta kinakailangang mga file mga configuration (halimbawa, ang nabanggit na stm32f10x_conf.h) sa proyekto. Kaya ang tab na Preprocessor ay magiging ganito: * Debugger -> Setup -> Driver: piliin ang ST–Link, dahil ito ang programmer na binuo sa Discovery board. Ngayon i-configure namin ang programmer mismo: * Debugger -> ST–LINK -> Interface: piliin ang SWD (ang programmer sa board ay konektado sa controller sa pamamagitan ng SWD, hindi sa pamamagitan ng JTAG). * Debugger -> I-download: lagyan ng tsek ang kahon Gamitin ang (mga) flash loader, "Mag-upload ng firmware sa flash memory." Ito ay lohikal, kung wala ito walang babaha.## 6. Pagsusulat ng code Una, isusulat ko kung ano ang gagawin ng code na ito. Magpapakita siya simpleng bagay, kumikislap na LED (PC8 sa Discovery board) na may pause sa isang walang katapusang loop. Kasama namin ang file ng header ng configuration ng proyekto, stm32f10x\_conf.h. Dito makikita natin ang linyang #include “stm32f10x\_exti.h” - ito ang linya 35, at ikomento ito ng dalawang slash. Ang katotohanan ay hindi kakailanganin ng aming proyekto ang EXTI module. Sa main.c file ay mayroon nang function int main, at ang tanging aksyon dito ay bumalik 0. Tinatanggal namin ang linyang ito (hindi namin ibabalik ang anumang mga halaga), baguhin ang uri ng function sa void (para sa parehong dahilan ), at magsulat ng isang walang katapusang loop:
#include "stm32f10x_conf.h" 

void main()
{
habang(1)
{
}
}

### Paglulunsad ng GPIO module Ang mga input/output port sa STM32 ay tinatawag na GPIO - General Purpose Input/Output. Kaya naman isinama namin ang stm32f10x_gpio.c library. Gayunpaman, hindi lang ito ang kailangan natin, isang maliit na teorya: Ang lahat ng mga peripheral sa chip ay hindi pinagana bilang default, parehong mula sa kapangyarihan at mula sa dalas ng orasan. Upang i-on ito, kailangan mong magpadala ng signal ng orasan. Ito ay pinamamahalaan ng RCC module, at mayroong isang file na stm32f10x_rcc.c upang gumana dito. Ang GPIO module ay nakabitin sa APB2 bus. Mayroon ding AHB (isang analogue ng processor-northbridge bus) at APB1 (pati na rin ang APB2 - isang analogue ng northbridge-southbridge bus). Samakatuwid, ang unang bagay na kailangan nating gawin ay paganahin ang GPIOC module clocking. Ito ang module na responsable para sa PORTC; meron ding GPIOA, GPIOB at iba pa. Ginagawa ito tulad nito: RCC\_APB2PeriphClockCmd(RCC\_APB2Periph_GPIOC, ENABLE); Ito ay simple - tinatawag namin ang function ng pagpapadala ng signal ng orasan mula sa APB2 bus patungo sa GPIOC module, at sa gayon ay i-on ang module na ito. Siyempre, ginagawa namin ito sa pinakadulo simula. walang laman na mga function pangunahing. Narito lamang ang mga pangunahing kaalaman na kailangan mong maunawaan. Mayroon din akong higit pang [detalyadong artikulo tungkol sa GPIO module](/index.php/stm32-%e2%86%92-%d0%bf%d0%be%d1%80%d1%82%d1%8b- gpio / "STM32 → GPIO port"). ### Pag-configure ng module ng GPIOC Napakakaunting natitira, kailangan mong i-configure ang module ng GPIOC. Ini-install namin ang output leg (mayroon ding input at alternatibong function), inaayos ang sharpness ng mga fronts (para sa layunin ng EM compatibility), at ang output driver (push-pull o open source). Ginagawa namin ito kaagad pagkatapos na simulan ang port. GPIO\_InitTypeDef GPIO\_InitStructure; GPIO\_InitStructure.GPIO\_Speed ​​​​= GPIO\_Speed\_2MHz; GPIO\_InitStructure.GPIO\_Mode = GPIO\_Mode\_Out_PP; GPIO\_InitStructure.GPIO\_Pin = GPIO\_Pin\_8; GPIO\_Init(GPIOC, &GPIO\_InitStructure); Well, iyon lang, pagkatapos nito ang PC8 leg ay gagana bilang isang push-pull output na may medyo makinis na mga gilid (maximum switching frequency 2 MHz. Ang mga sharp edge ay 50 MHz). Hindi natin mapapansin ang kinis ng mga harapan gamit ang mata, ngunit makikita ito sa isang oscilloscope. ### I-on ang LED Tawagan ang function na GPIO\_WriteBit(GPIOC, GPIO\_Pin\_8, Bit\_SET); Ang LED ay i-on. ### I-on at i-off ito sa isang loop Sa while(1) loop isinusulat namin ang code para sa pag-on, pag-pause, pag-off nito at pag-pause muli:

GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);  para sa(i=0; i<1000000; i++);

GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET);
para sa(i=0; i<1000000; i++);

Kaya, ang buong main.c file ay ganito ang hitsura:

#include "stm32f10x_conf.h"

void main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed ​​​​= GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);

int i;
habang(1)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);
para sa(i=0; i<1000000; i++);

GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET); para sa(i=0; i<1000000; i++); } }

## 7. Ilunsad natin! Ikinonekta namin ang STM32VLDdiscovery board sa computer sa pamamagitan ng microUSB, i-click ang button na I-download at Debug sa IAR. Ang programa ay na-upload sa microcontroller (mapapansin mo ang isang window na may progress bar na mabilis na nagsasara - ang laki ng program ay napakaliit), at magsisimula ang pag-debug. Huminto ang IAR sa unang pagtuturo ng code (ito ay medyo maginhawa kapag nagde-debug), kailangan mong simulan ito gamit ang Go button. Dapat gumana ang lahat - ang PC8 blue LED sa STM32VLDdiscovery board ay dapat Gaya ng dati, maaari mong i-download ang archive gamit ang proyekto ng GPIO. Sa kabutihang palad, maaari mong i-save ang proyektong ito at gamitin ito bilang isang template upang hindi mo na kailangang dumaan muli sa lahat ng pag-setup. Ang buong cycle: 1. I/O ports (/index.php/stm32-from_zero_to_rtos-2_timers/ "STM32 - from zero to RTOS. 2: Timer and interrupts") (/index.php/stm32-from_zero_to_rtos-3_timer_outputs/ " STM32 - mula sa zero hanggang RTOS 3: Mga output ng timer")

](/index.php/stm32-from_zero_to_rtos-4_exti_nvic/ “STM32 - from zero to RTOS. 4: External interrupts and NVIC”) 5. I-install ang FreeRTOS