STM32F407(STM32F4-DISCOVERY) - Standart dışı yaklaşım - Standart kitaplık bölüm 1. Makro tanımlarını kullanarak STM32F10x SPL'yi yapılandırma

Bu noktaya kadar standart çekirdek kütüphanesi olan CMSIS'i kullandık. Bir bağlantı noktasını istenen çalışma moduna yapılandırmak için, belirli bir işlevden sorumlu kaydı bulmak üzere başvurmamız ve ayrıca bu süreçle ilgili diğer bilgileri bulmak için büyük bir belgede arama yapmamız gerekiyordu. Bir zamanlayıcı veya ADC ile çalışmaya başladığımızda işler daha da sancılı ve rutin hale gelecektir. Buradaki kayıtların sayısı G/Ç bağlantı noktalarından çok daha fazladır. Manuel ayarçok zaman alır ve hata yapma olasılığını artırır. Bu nedenle birçok kişi standart çevre kitaplığı StdPeriph ile çalışmayı tercih ediyor. Ne veriyor? Çok basit - soyutlama düzeyi artar, belgelere girmenize ve çoğunlukla kayıtlar hakkında düşünmenize gerek kalmaz. Bu kütüphanede MK çevresinin tüm çalışma modları ve parametreleri yapılar şeklinde anlatılmaktadır. Artık bir çevre birimi aygıtını yapılandırmak için yalnızca aygıt başlatma işlevini doldurulmuş bir yapıyla çağırmanız gerekir.

Aşağıda soyutlama seviyelerinin şematik temsilini içeren bir resim bulunmaktadır.

Mikrodenetleyicinin nasıl çalıştığını göstermek için çekirdeğe "en yakın" olan CMSIS ile çalıştık. Bir sonraki adım, şimdi nasıl kullanılacağını öğreneceğimiz standart kütüphanedir. Daha sonra aygıt sürücüleri gelir. Herhangi bir cihazı kontrol etmek için uygun bir yazılım arayüzü sağlayan *.c \ *.h dosyaları olarak anlaşılırlar. Örneğin, bu kursta size max7219 yongası ve esp8266 WiFi modülü için sürücüler sunacağız.

Standart bir proje aşağıdaki dosyaları içerecektir:


Öncelikle bunlar tabi ki standart kütüphanenin kernel ile çalışmasını sağlayan CMSIS dosyaları, onlardan bahsetmiştik. İkincisi, standart kütüphane dosyaları. Üçüncüsü, kullanıcı dosyaları.

Kütüphane dosyaları, hedef MK'ye ayrılmış sayfada (bizim için stm32f10x4'tür) bölümde bulunabilir. Tasarım Kaynakları(CooCox IDE'de bu dosyalar geliştirme ortamı deposundan indirilir). Her çevre birimi iki dosyaya karşılık gelir - başlık (*.h) ve kaynak kodu(*.C). Detaylı Açıklama web sitesindeki kütüphane arşivinde bulunan destek dosyasında bulunabilir.

  • stm32f10x_conf.h - kitaplık yapılandırma dosyası. Kullanıcı modülleri bağlayabilir veya bağlantısını kesebilir.
  • stm32f10x_ppp.h - çevre birimi başlık dosyası. Ppp yerine gpio veya adc olabilir.
  • stm32f10x_ppp.c - C dilinde yazılmış çevresel aygıt sürücüsü.
  • stm32f10x_it.h - tüm olası kesme işleyicilerini (prototiplerini) içeren başlık dosyası.
  • stm32f10x_it.c, Cortex M3'teki istisna durumlara yönelik kesme hizmeti rutinini (ISR) içeren bir şablon kaynak kod dosyasıdır. Kullanıcı, kullanılan çevre birimleri için kendi ISR'lerini ekleyebilir.

Standart kitaplık ve çevre birimleri, işlevlerin ve gösterimlerin adlandırılmasında bir kurala sahiptir.

  • PPP, ADC gibi çevre birimlerinin kısaltmasıdır.
  • Sistem, başlık ve kaynak kodu dosyaları - stm32f10x_ ile başlayın.
  • Bir dosyada kullanılan sabitler o dosyada tanımlanır. Birden fazla dosyada kullanılan sabitler başlık dosyalarında tanımlanır. Çevresel kütüphanedeki tüm sabitler çoğunlukla BÜYÜK harfle yazılır.
  • Kayıtlar sabitler olarak kabul edilir ve aynı zamanda BÜYÜK harfler olarak da adlandırılır.
  • Çevre birimine özgü işlev adları, USART_SendData() gibi bir kısaltma içerir.
  • Her çevresel cihazı yapılandırmak için PPP_Init() işlevine aktarılan PPP_InitTypeDef yapısı kullanılır.
  • Başlatmayı kaldırmak (değeri varsayılana ayarlamak) için PPP_DeInit() işlevini kullanabilirsiniz.
  • Çevre birimlerini etkinleştirmenizi veya devre dışı bırakmanızı sağlayan işleve PPP_Cmd() adı verilir.
  • Kesme etkinleştirme/devre dışı bırakma işlevine PPP_ITConfig adı verilir.

İLE tam liste kütüphane destek dosyasına tekrar bakabilirsiniz. Şimdi standart çevre birimi kitaplığını kullanarak yanıp sönen LED'i yeniden yazalım!

Çalışmaya başlamadan önce stm32f10x.h dosyasına bakalım ve satırı bulalım:

#define USE_STDPERIPH_DRIVER

İndirilen arşivdeki kitaplık dosyalarını kullanarak projeyi sıfırdan yapılandırırsanız bu satırın açıklamasını kaldırmanız gerekecektir. Standart kütüphaneyi kullanmanıza izin verecektir. Bu tanım (makro), ön işlemciye stm32f10x_conf.h dosyasını ekleme komutunu verecektir:

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

Bu dosya modülleri içerir. Yalnızca belirli olanlara ihtiyacınız varsa geri kalanını devre dışı bırakın; bu, derleme sırasında zaman kazandıracaktır. Tahmin edebileceğiniz gibi RTC ve GPIO modüllerine ihtiyacımız var (ancak gelecekte _bkp.h, _flash, _pwr.h, _rtc.h, _spi.h, _tim.h, _usart.h'ye de ihtiyacımız olacak):

#include "stm32f10x_flash.h" // init_pll() için #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h"

Geçen seferki gibi, önce B bağlantı noktasının saat ölçümünü etkinleştirmeniz gerekir. Bu, stm32f10x_rcc.h'de bildirilen işlev tarafından yapılır:

Void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

FunctionalState numaralandırması stm32f10x.h'de tanımlanmıştır:

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

Bacağımızı kurmak için bir yapı tanımlayalım (bunu stm32f10x_gpio.h dosyasında bulabilirsiniz):

GPIO_InitTypeDef LED'i;

Şimdi onu doldurmamız gerekiyor. Bu yapının içeriğine bakalım:

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

Gerekli tüm numaralandırmalar ve sabitler aynı dosyada bulunabilir. Daha sonra yeniden yazılan init_leds() işlevi aşağıdaki biçimi alacaktır:

Void led_init() ( // Saatlemeyi etkinleştirin RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Yapıyı bildirin ve doldurun GPIO_InitTypeDef LED; LED.GPIO_Pin = GPIO_Pin_0; LED.GPIO_Speed ​​= GPIO_Speed_2MHz; LED.GPIO_Mode = GPIO_Mode_Out_PP; // Bağlantı noktasını başlatın GPIO_Init( GPIOB, &LED); )

Main() fonksiyonunu yeniden yazalım:

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

Önemli olan, başlatma sırasını anlamaktır: çevresel saati açın, yapıyı bildirin, yapıyı doldurun, başlatma yöntemini çağırın. Diğer çevresel aygıtlar genellikle benzer şekilde yapılandırılır.

Bu yayında, üretim şirketi STMicroelectronics'in standart çevre birimleri kütüphanesini temel alan STM32F10x mikrodenetleyicilere hızlı bir şekilde başlamanın ana noktalarına odaklanmaya çalışacağım.

Makalede geliştirme ortamı olarak Eclipse CDT kullanılacaktır. Ana odak noktası program kodu olacağından Code::Blocks'ta tüm işlemleri güvenle yapabilirsiniz.

ARM mikrodenetleyicilerin genel proje yapısı yazımda anlatılmıştır.

Burada kısaca hatırlatacağım, ARM mikrodenetleyicilerine (özellikle STM32F10x) yönelik bir proje oluşturmak için bir linker script'ine ve bir C-Startup dosyasına ihtiyacınız olacak.

Bağlayıcı komut dosyası, program kodunu ve verilerini mikro denetleyicinin belleğine yerleştirme talimatlarını içeren bir dosyadır. Program kodunuzun Flash program belleğine veya SRAM veri belleğine yüklenmesi komutunu verebilir.

Farklı miktarda program ve veri belleğine sahip mikrodenetleyiciler, farklı düzen komut dosyaları gerektirir. Mikrodenetleyici üreticisi STMicroelectronics'ten temin edilebilirler.
STM32F10x standart çevre birimi kitaplığını ARM_Toolchain/Lib/stm32f10x_stdperiph_lib.zip arşivinden açın.
Çeşitli geliştirme ortamlarına (IAR EWB, Keil uVision, Atollic True Studio vb.) yönelik örnek projeler içerir. Bizim için en yakın olanı Atollic True Studio, çünkü Eclipse'in bir modifikasyonu.
Project/StdPeriph_Template/TrueSTUDIO dizinine gidin, burada adları STM3210x-EVAL geliştirme kartlarının adlarına karşılık gelen birkaç alt dizin vardır.

Bu kartlardan hangisinin sizinkiyle aynı mikrodenetleyici hattını kullandığını öğrenin. Stm32_flash.ld dosyasını uygun dizinden projenize kopyalayın.

Kullanılan mikrodenetleyiciye göre sadece program ve veri hafızası miktarının değiştirileceği evrensel bir script oluşturmak da mümkündür.

STM32 mikrodenetleyiciler için başlatma kodu (C-Startup) C veya Assembler dilinde yazılabilir.
STM32F10x Standart Çevre Birim Kitaplığı (STM32F10x SPL olarak kısaltılır) sıklıkla hataları nedeniyle eleştirilse de, STM32 programlamaya başlarken hızlı bir şekilde başlamanın en kolay yoludur.
Ama her zaman bir çeşit alternatifin olmasını istersiniz. Aslında bunlardan çok var mesela; Assembly dilinde programlama :)

Bu en zor ve anlamsız yoldur. İkinci yol, çeşitli mikro denetleyici çevre birimlerine erişmek için C dili yapılarına erişim için sözdizimi sağlayan CMSIS kütüphanesini kullanmaktır. En basit ve en mantıklı yol (bence) kütüphaneleri kullanmaktır.

STM32F10x SPL'ye kategorik olarak karşıysanız, o zaman özellikle sizin için başka bir alternatif daha var - libopencm3 kütüphanesi. Buradaki örneklerin çoğu, STM32F10x mikro denetleyicilerin ana serisi etrafında yoğunlaşmıştır, ancak diğer serilere (STM32F2xx/4xx) yönelik örneklerin ortaya çıkması yalnızca zaman meselesidir. Dilediğiniz zaman libopencm3 projesine katılarak bu süreci hızlandırabilirsiniz.

CMSIS standardının programlarınızda kullanılması da isteğe bağlıdır.
C programlama dilinde HAL (Donanım Soyutlama Katmanı) düzeyini uygulamak için biraz çaba ve zaman harcayarak bu olmadan da yapabilirsiniz.

Bazı durumlarda bu yöntem tek yöntem olabilir. erişilebilir bir şekilde. Örneğin kuruluşunuz, ARM tarafından geliştirilen bilgi işlem çekirdeklerini ve sektöre özgü çevre birimlerini temel alan özel çipler kullanıyor.

Veya üreticilerin hazır kullanıma odaklandığı ARM9 çekirdekli mikrodenetleyiciler için C dilinde yazılım uygulamanız gerekir. işletim sistemleri(Linux, QNX, Windows CE), bu nedenle üreticiler, C dilinde programlama için saf biçimde veya daha hafif bir RTOS ile birlikte kitaplıklar sağlamayabilir.

Neyse ki, Cortex-M3 çekirdeğini temel alan mikrodenetleyici üreticileri, geliştiricilere çok sayıda kod kitaplığı sağlıyor. Bu aynı zamanda STM32 mikrodenetleyicileri için de geçerlidir.
STM32F10x SPL kütüphanesini incelemeye devam edelim. Bir örnek kullanarak bunu ele alacağız.
Olan bitenin tüm sürecini daha iyi anlamak için bu örneği açabilir veya sıfırdan kendi projenizi oluşturabilirsiniz.

İkinci durum için gerekli adımları listeleyeceğim:

  • Eclipse'de yeni bir boş proje oluşturun
  • Düzen betiğini ve başlangıç ​​dosyasını projeye kopyalayın
  • Yeni bir şablon oluşturun veya bir şablonu kopyalayın
  • Örneğimdeki Makefile'ı şablon olarak kullanırken proje içerisinde src, inc, bin, obj dizinlerini oluşturup, bin ve obj dizinleri içerisinde Debug ve Release alt dizinlerini oluşturmanız gerekiyor.
  • Gerekli kaynak ve başlık dosyalarını CMSIS ve STM32F10x SPL kitaplıklarından kopyalayın.
  • Kullanılıyorsa Makefile şablonunun kullanıcı ayarları bölümünde gerekli değişiklikleri yapın.
  • Eclipse “make target” penceresinde “Debug”, “cleanDebug”, “Release”, “cleanRelease”, “Program” gibi yeni hedefler oluşturun.
  • “Hata Ayıklama” hedefini başlatın ve yürütülmesini “Konsol” penceresinde izleyin.

Materyali daha iyi anlamak için makaleyi, her biri STM32F10x SPL kütüphanesiyle çalışmanın yalnızca bir yönünü açıklayan birkaç bağımsız paragrafa böldüm.

Makro tanımlarını kullanarak STM32F10x SPL'yi yapılandırma

Kütüphaneyi yapılandırmak için şimdi dikkate alacağımız önceden tanımlanmış makro değerleri kullanılır.
Bir önişlemci yönergesi kullanılarak başlık dosyalarının içinde ayarlanabilirler #tanımlamak veya makro tanımlarının değerlerini anahtar aracılığıyla iletin -D GCC derleyicisi.
Örneğimde ikinci yöntemi kullanıyorum.
Makefile değişkeninde TANIMLAMAK STM32F10x SPL kitaplığını derlemek için gerekli makroları içerir.
Makro tanımı STM32F10X_MD kullanılan mikro denetleyicinin hatta ait olup olmadığını belirtir Orta yoğunluk.
Bu, 64 ila 128 kB arası Flash belleğe sahip mikro denetleyicileri içerir.
Aşağıdaki tabloda farklı mikro denetleyici serileri için makro adları listelenmektedir:

Seri adı Makro Tanım
Düşük yoğunluklu Değer çizgisi STM32F10X_LD_VL Flash bellek kapasitesi 16 - 32 kB ile
Düşük yoğunluklu STM32F10X_LD
Flash bellek kapasitesi 16 - 32 kB ile
Orta yoğunluk Değer çizgisi STM32F10X_MD_VL Flaş - bellek
64 - 128kB
Orta yoğunluk STM32F10X_MD Flash belleğe sahip STM32F101xx, STM32F102xx, STM32F103xx serisinin mikro denetleyicileri 64 - 128 kB
Yüksek yoğunluklu Değer çizgisi STM32F10X_HD_VL hacimli STM32F100xx serisinin mikrokontrolörleri
Flaş - bellek 256 - 512kB
Yüksek yoğunluk STM32F10X_HD hacimli
Flaş bellek 256 - 512kB
XL yoğunluğu STM32F10X_XL
Flaş bellek 512 - 1024 kB
Bağlantı hattı STM32F10X_CL

Mikrodenetleyicinin saat frekansını ayarlamak için system_stm32f10x.c dosyasında makronun açıklamasını gerekli saat frekansı değeriyle kaldırmanız gerekir.

#if tanımlanmışsa (STM32F10X_LD_VL) || (tanımlanmış STM32F10X_MD_VL) || (tanımlanmış STM32F10X_HD_VL) #define SYSCLK_FREQ_24MHz 24000000 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 3600 000 0 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 * / #define SYSCLK_FREQ_72MHz 72000000 #endif

#if tanımlanmışsa (STM32F10X_LD_VL) || (tanımlanmış STM32F10X_MD_VL) || (tanımlanmış STM32F10X_HD_VL)

/* #SYSCLK_FREQ_HSE HSE_VALUE'yu tanımlayın */

#define SYSCLK_FREQ_24MHz 24000000

#başka

/* #SYSCLK_FREQ_HSE HSE_VALUE'yu tanımlayın */

/* #SYSCLK_FREQ_24MHz 24000000'i tanımla */

/* #SYSCLK_FREQ_36MHz 36000000'i tanımla */

/* #SYSCLK_FREQ_48MHz 48000000'i tanımla */

/* #SYSCLK_FREQ_56MHz 56000000'i tanımla */

#define SYSCLK_FREQ_72MHz 72000000

#endif

Kullanım amacı kuvars rezonatör tüm önemli frekanslar için 8 MHz frekansla
25 MHz kuvars rezonatörün kurulmasının gerekli olduğu Bağlantı hattı hariç bir dizi mikro denetleyici.
Eğer kuvars rezonatörleri farklı frekans değerleri ile kullanıyorsanız stm32f10x.h başlık dosyasındaki HSE_VALUE makrosunun değerini değiştirmeniz ve tüm bağımlı fonksiyonları buna göre uyarlamanız gerekir.
USE_STDPERIPH_DRIVER makrosunun amacını tahmin etmek zor değil - STM32F10x standart çevre birimi kitaplığını kullanmak.
USE_FULL_ASSERT – programda hata ayıklamak için ASSERT makrosunu kullanın.

Kütüphanedeasser_param makrosunu kullanma

Tüm STM32F10x SPL kitaplığı işlevleri, bağımsız değişkenlerini kontrol etmek için Assert_param makrosunu kullanır.
Bu makro, sıfıra eşitlik açısından test edilen işlev bağımsız değişkenini içeren bir ifadeyi kontrol eder. İfadenin değeri sıfır ise, bağımsız değişken hata işleyicisi fonksiyonu Assert_failed çağrılır, aksi takdirde (ifade sıfır değilse), bağımsız değişken kontrolü başarılı olur.
Assert_failed fonksiyonunu programınıza uygulamanız gerekir.
Hata mesajını, dosya adını ve hataya neden olan kod satırının numarasını görüntüler.
debug_printf makrosu, standart new_lib kitaplığını veya örneğin Bay Chen'in kitaplığını kullanarak USART aracılığıyla çıktı verebilir.

#define debug_printf xprintf /* printf */ #ifdef USE_FULL_ASSERT voidassert_failed(uint8_t* dosya, uint32_t line) ( debug_printf("Yanlış parametre değeri: %s dosyası %d\r\n satırında", file, (int)line) ; while (1) ( ) )/*asser_failed */ #endif/*USE_FULL_ASSERT*/

#define debug_printf xprintf /* printf */

#ifdef USE_FULL_ASSERT

void iddia_failed (uint8_t * dosyası, uint32_t satırı)

hata ayıklama_printf( "Yanlış parametre değeri: %s dosyası %d\r\n satırında", dosya , (int ) satır ) ;

süre(1)

) /* iddia_başarısız */

#endif/*USE_FULL_ASSERT*/

Kodunuzda uygulanan Assert_failed işlevi yalnızca USE_FULL_ASSERT makrosu bildirildiğinde kullanılır. Aksi takdirde, tüm hata ayıklama kodları kaynaktan çıkarılır. Bu işlevsellik, sürücü kitaplığı ayarları başlık dosyası stm32f10x_conf.h'de uygulanır.

#ifdef USE_FULL_ASSERT #define iddia_param(ifade) ((ifade) ? (void)0: iddia_failed((uint8_t *)__FILE__, __LINE__)) void iddia_failed(uint8_t* dosyası, uint32_t satırı); #else #define iddia_param(ifade) ((void)0) #endif /* USE_FULL_ASSERT */

#ifdef USE_FULL_ASSERT

#define iddia_param(ifade) ((ifade) ? (void)0: iddia_failed((uint8_t *)__FILE__, __LINE__))

void iddia_failed (uint8_t * dosyası, uint32_t satırı) ;

#başka

#define iddia_param(ifade) ((void)0)

#endif /* USE_FULL_ASSERT */

Burada açıklanacak pek bir şey yok. Assert_param kullanımının bir örneğine bakalım.

void set_param(uint8_t * param, uint8_t değer) ( ​​assert_param(param != NULL); *param = değer; )/*set_param*/

void set_param (uint8_t *param, uint8_t değeri)

iddia_param (param != NULL ) ;

* parametre = değer;

) /*set_param*/

İşlev, parametrenin değerini argüman olarak iletilen bir işaretçi aracılığıyla ayarlar. USE_FULL_ASSERT makrosu bildirilmezse satırların
Assert_param(param != NULL) kodda yer almıyor, aksi takdirde parametre bu tanımda kontrol edilir.
İşaretçi tanımlanmamışsa, param != NULL değeri false olur ve USART aracılığıyla dosya adı ve satır numarasını hatayla birlikte çıktılayacak ve ardından döngüye girecek olan Assert_failed işlevi çalıştırılacaktır, böylece değerin değiştirilmesi engellenecektir. bellekte tanımlanmamış bir adrese atanmıştır.
Assert_param makrosunu kodunuzda kullanmanız gerekmez, ancak kütüphane kodunda kullanmanız gerekir.
STM32F10x SPL her yerde kullanılmaktadır.
set_param işlevi, iddia_param kullanılmadan argüman hatası kontrolüyle uygulanabilir.

#define HATA (-1) #define OK (0) int set_param(uint8_t * param, uint8_t değer) ( int r = HATA; if (param == NULL) return r; *param = değer; r = OK; return r ; )/*set_param*/

#define HATA (-1)

#tanımla Tamam (0)

int set_param (uint8_t *param, uint8_t değeri)

int r = HATA;

if (param == NULL )

r'yi döndür;

* parametre = değer;

r = Tamam;

r'yi döndür;

) /*set_param*/

STM32F10x SPL kitaplığında C-Başlangıç ​​dosyası

Başlangıç ​​kodunda, mikro denetleyici başlangıçta başlatılır, yığın yapılandırılır, BSS bölümü sıfırlanır ve ana işlev main() çağrılır.
Başlangıç ​​kodunun STM32F10x SPL kitaplığıyla doğrudan bir ilişkisi yoktur. Ancak bu önyükleme kodunda, programın main() işlevi çağrılmadan önce, CMSIS'in bir parçası olan mikrodenetleyici başlatma işlevi SystemInit() çağrılır.
CMSIS kütüphanesinde kolaylıkla bulunabilir.
Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/TrueSTUDIO dizinine gidin ve gerekli dosyayı kopyalayın. Geriye sadece projenizde kullandığınız mikrodenetleyicinin hangi hatta ait olduğunu bulmak kalıyor.
Bunu yapmak için aşağıdaki tabloya bakın:

Seri adı Dosya adı Tanım
Düşük yoğunluklu Değer çizgisi startup_stma32f10x_ld_vl.s hacimli STM32F100xx serisinin mikrokontrolörleri
Flaş bellek 16 - 32kB
Düşük yoğunluklu startup_stma32f10x_ld.s mikrodenetleyici serisi STM32F101xx, STM32F102xx, STM32F103xx
Flash bellek kapasitesi 16 - 32 kB ile
Orta yoğunluk Değer çizgisi startup_stm32f10x_md_vl.s mikrodenetleyiciler serisi STM32F100xx
Orta yoğunluk startup_stm32f10x_md.s mikrodenetleyici serisi STM32F101xx, STM32F102xx, STM32F103xx
Flash bellek kapasitesi 64 - 128 kB ile
Yüksek yoğunluklu Değer çizgisi startup_stma32f10x_hd_vl.s mikrodenetleyiciler serisi STM32F100xx
Yüksek yoğunluk startup_stma32f10x_hd.s mikrodenetleyici serisi STM32F101xx, STM32F103xx
Flash bellek kapasitesi 256 - 512 kB
XL yoğunluğu startup_stma32f10x_xl.s mikrodenetleyici serisi STM32F101xx, STM32F103xx
Flash bellek kapasitesi 512 - 1024 kB
Bağlantı hattı startup_stm32f10x_cl.s STM32F105xx ve STM32F107xx serisinin mikro denetleyicileri

Başlangıç ​​dosyası, kesme ve istisna vektör işleyicilerinin adlarını içerir, ancak yalnızca sıfırlama vektör işleyicisi uygulanır; burada, main() işlevi çağrılmadan önce tüm ilk başlatma işlemleri gerçekleştirilir.
Diğer tüm istisna işleyicilerin uygulanması, uygulama programcısının sorumluluğundadır. Programınız herhangi bir işleyici kullanmıyorsa bunları kaydetmenize gerek yoktur. Bir istisna meydana gelirse, program kodunu döngüye alan varsayılan işleyici kullanılacaktır.

CMSIS kütüphanesinin bileşimi

Bu yayında daha önce yazıldığı gibi, CMSIS kitaplığı, C dili yapılarının öğelerini kullanarak mikro denetleyici çevre birimlerine erişim sağlar.
Bu kütüphanenin uygulaması iki bölüme ayrılmıştır. İlk bölüm Cortex-M3 çekirdek çevresine erişim sağlar, ikinci bölüm ise çevreye erişim sağlar özel model mikrodenetleyici.
CMSIS standardı Cortex-M3 çekirdekli tüm mikrodenetleyiciler için aynı olduğundan, ilk bölümün uygulaması tüm üreticiler için aynı, ancak ikinci bölümün uygulanması her üretici için farklı olacaktır.
CMSIS çeşitli başlık ve kaynak dosyaları içerir. İlk bölüm dosyaları içerir:

  • core_cm3.h
  • core_cm3.c

CMSIS'in ikinci kısmı C-Startup dosyasının yanı sıra aşağıdaki dosyaları içerir:

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

stm32f10x.h başlık dosyası, stm32f10x mikro denetleyicilerinin çevresel modüllerine erişim için makro tanımları içerir.
system_stm32f10x.h ve system_stm32f10x.c dosyaları mikro denetleyicinin ilk başlatılmasını uygular.

STM32F10x SPL kitaplığının bileşimi ve yapılandırması

Kitaplık, stm32f10x_ ön ekine sahip çevresel modüllerle aynı adı taşıyan kaynak ve başlık dosyalarından oluşur.
Örneğin, USART modülüyle etkileşimin uygulanması stm32f10x_usart.h ve stm32f10x_usart.c dosyalarında bulunur.
Belgelerde açıklanan kitaplık öğelerini adlandırma kuralları ve belirli kodlama kuralları vardır.
Kütüphane, çevresel mikrokontrolör modülleri için sürücülerin uygulanmasını içerir.
Kütüphane elemanlarının adları, çevresel modüller için aşağıdaki kısaltmaları kullanır:

Kısaltma Çevre birimi modülü
ADC analogtan dijitale dönüştürücü
BKP yedekleme kayıtları
OLABİLMEK CAN arayüzü
MSK tüketim denetleyicisi
ÇHS sağlama toplamı hesaplama modülü
DAC dijital-analog dönüştürücü
DBGMCU mikrodenetleyici hata ayıklama
DMA doğrudan bellek erişim denetleyicisi
EXTI harici kesme denetleyicisi
FSMC harici bellek denetleyicisi
FLAŞ Flaş program belleği
GPIO genel amaçlı G/Ç bağlantı noktaları
I2C I2C arayüzü
I2S I2S (Ses) arayüzü
IWDG bağımsız gözlemci zamanlayıcısı
NVIC iç içe kesme denetleyicisi
Güç güç kontrolörü
RCC sıfırlama ve saat denetleyicisi
RTC gerçek zamanlı kontrolör (saat)
SDIO SDIO arayüzü
SPI SPI arayüzü
SistemTick sistem zamanlayıcısı
TİM temel veya gelişmiş zamanlayıcı
USART evrensel seri senkron-asenkron
alıcı-verici
WWDG pencere bekçisi

Bu kısaltmalara dayanarak kütüphanenin yazılım modüllerinin adları oluşturulmuştur. Kütüphanedeki tüm modülleri kullanmak zorunda değilsiniz.
Projede sadece gerekli modüllerin kullanılabilmesi için kütüphanenin yapılandırılması gerekmektedir.
Bu amaçlar doğrultusunda, STM32F10x SPL kitaplığını kullanan her projenin bir stm32f10x_conf.h başlık dosyasına sahip olması gerekir.

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

#include "stm32f10x_gpio.h"

//#include "stm32f10x_i2c.h"

//#"stm32f10x_iwdg.h"yi dahil et

//#"stm32f10x_pwr.h"yi dahil et

#include "stm32f10x_rcc.h"

Gerekli modülü etkinleştirmek için yönergenin açıklamasını kaldırmanız gerekir #katmak karşılık gelen başlık dosyalarıyla birlikte.
Stm32f10x_conf.h başlık dosyası stm32f10x.h'ye dahil edilmiştir, dolayısıyla STM32F10x SPL kitaplığının işlevlerini kullanmak için kaynak kodunuza yalnızca bir stm32f10x.h başlık dosyasını eklemeniz gerekir.

// stm32f10x.h dosyasında #ifdef USE_STDPERIPH_DRIVER #include "stm32f10x_conf.h" #endif

Projenin aynı zamanda USE_STDPERIPH_DRIVER, USE_FULL_ASSERT makrolarını ve kullanılan mikro denetleyicinin serisini belirten bir makroyu da tanımlaması gerektiğini tekrar ediyorum (örneğin, Orta yoğunluk çizgisi için STM32F10X_MD).
Standart kuvars frekans değerini kullanırsanız ve denetleyici maksimum 72 MHz saat frekansında çalışıyorsa, başka hiçbir şeyi değiştirmenize gerek kalmayacaktır.
Makefile'a derlemek için kütüphane dosyalarının bir listesini eklemeniz gerekir.
Örneğin:

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

SRC += stm32f10x_rcc . C

SRC += stm32f10x_gpio . C

STM32F10x SPL kitaplığını kullanma. Çalışma mekanizmaları

Çevresel kütüphaneyi kullanarak programlamaya başlamanın en kolay yolu kütüphaneyle birlikte verilen örneklere bakmaktır. Ancak yine de bu örneklerin kodunu anlamak için kütüphanenin sözdizimi ve kullanımına ilişkin temel bilgiye sahip olmanız gerekir.
Daha önce listelenen çevresel mikrokontrolör modüllerinin tümü başlangıçta devre dışıdır, bunlara saat sinyali sağlanmaz ve elektrik tüketmezler.
Bir çevre birimi modülünü kullanmak için öncelikle ona bir saat sinyali sağlamanız gerekir. Saat sinyali RCC saati ve sıfırlama modülü tarafından sağlanır.
Bu amaçlara yönelik olarak kütüphane aşağıdaki işlevlere sahiptir:

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

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PPPx, ENABLE);

RCC_APB2PeriphClockCmd (RCC_APB2Periph_PPPx, ENABLE) ;

RCC_APB1PeriphClockCmd (RCC_APB1Periph_PPPx, ENABLE) ;

Burada PPP, modül adının adını (örneğin ADC veya USART) belirtir ve x, çevresel modülün numarasıdır.
Öncelikle kullandığınız modülün hangi veri yoluna bağlı olduğunu bulmanız gerekiyor.
Toplamda Cortex-M3 çekirdek mimarisine sahip mikro denetleyicilerin üç veri yolu vardır:
talimat veri yolu, veri yolu ve sistem veri yolu. Talimat veri yolu çekirdeği Flash program belleğine bağlar. Veri ve sistem veri yolları, çekirdek frekansında çalışan bir AHB (ARM Yüksek Hızlı Veri Yolu) veri yolu matrisinde birleştirilir. Ancak AHB veri yolu frekansı bölücüler takılarak azaltılabilir. AHB veri yolu, çekirdek ve DMA modülü gibi yüksek hızlı cihazları birbirine bağlar.
G/Ç cihazları AHB veri yoluna APB1 ve APB2 (ARM Çevresel Veri Yolu) ara veri yolları aracılığıyla bağlanır.
APB2 veri yolunun maksimum çalışma frekansı 72 MHz, APB1 veri yolunun frekansı
36MHz ile sınırlıdır.
Kullandığınız çevre birimi modülünün hangi veri yollarına bağlı olduğunu belgelerden öğrenebilir veya stm32f10x_rcc.h başlık dosyasına bakabilirsiniz.
Bu dosyayı açın ve sırasıyla RCC_AHBPeriph, RCC_APB1Periph ve RCC_APB2Periph değerlerini arayın.

#define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001) #define RCC_AHBPeriph_DMA2 ((uint32_t)0x00000002) #define RCC_AHBPeriph_SRAM ((uint32_t)0x00000004) #define RCC_AHBPeriph_FLITF (( uint32_t) 0x00000010) #define RCC_AHBPeriph_CRC ((uint32_t)0x00000040)

#define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001)

#define RCC_AHBPeriph_DMA2 ((uint32_t)0x00000002)

#define RCC_AHBPeriph_SRAM ((uint32_t)0x00000004)

#define RCC_AHBPeriph_FLITF ((uint32_t)0x00000010)

#define RCC_AHBPeriph_CRC ((uint32_t)0x00000040)

Makroların isimleriyle hangi modüllerin hangi buslara bağlanacağını belirliyoruz. Hangi lastiğin bu üç lastikten birine ait olduğunu belirlemek için sağduyunuzu da kullanabilirsiniz. Örneğin USART modülü bir giriş/çıkış cihazıdır, yani APB veri yollarından birine bağlı demektir. USART oldukça düşük hızlı bir arayüz olduğundan muhtemelen APB1 veriyoluna bağlıdır.

#define RCC_APB1Periph_USART2 ((uint32_t)0x00020000) #define RCC_APB1Periph_USART3 ((uint32_t)0x00040000) #define RCC_APB1Periph_UART4 ((uint32_t)0x00080000) #define RCC_APB1 Periph_UART5 ((uint32_t)0x00100000)

Çevre modülüne bir saat sinyali gönderdikten sonra, başlatma işlevini çağırarak parametrelerini yapılandırabilirsiniz:

PPP_Init(PPP, &PPP_InitStructure);

PPP_Init (PPP ve PPP_InitStructure ) ;

Bir çevresel modülü başlatmak için başlatma fonksiyonuna birçok parametrenin iletilmesi gerektiğinden, bir yapıya yönelik bir işaretçi argüman olarak kullanılır. Başlatma parametreleriyle birlikte yapının kendisi, başlatma işlevini çağırmadan önce bellekte oluşturulmalıdır; yapının elemanlarına gerekli değerler atanmalıdır:

PPP_InitTypeDef PPP_InitStructure = (val1, val2, ..., valN);/* bildirildiğinde yapının başlatılması */

Önce bir yapı oluşturabilir ve ardından gerekli değerleri onun elemanlarına atayabilirsiniz:

PPP_InitTypeDef PPP_InitStructure; PPP_InitStructure.member1 = val1; PPP_InitStructure.member2 = val2; PPP_InitStructure.memberN = valN;

PPP_InitTypeDef PPP_InitStructure ;

PPP_InitStructure . üye1 = değer1;

PPP_InitStructure . üye2 = val2;

PPP_InitStructure . üyeN = valN;

Stm32f10xQuickstart projesinden bir örneğe bakalım:

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

GPIO_InitTypeDef GPIO_InitStructure ;

#ifdef USE_STM32H_103

RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC, ENABLE) ;

GPIO_InitStructure . GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure . GPIO_Speed ​​= GPIO_Speed_50MHz ;

GPIO_InitStructure . GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOC, & GPIO_InitStructure);

GPIO_InitStructure yapısının elemanlarına portun pin numarası, modu ve hızı değeri atanır.
GPIO_Init işlevi çağrılarak GPIOC bağlantı noktasının 12. satırı başlatılır.
GPIO_Init işlevinin ilk argümanı, GPIOC çevre biriminin bellek alanına yönelik bir işaretçidir ve GPIO_TypeDef yapısına yönelik bir işaretçiye dönüştürülür.

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

// stm32f10x.h

#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

#define PERIPH_BASE ((uint32_t)0x40000000)

typedef yapısı

IO uint32_t CRL ;

IO uint32_t CRH;

GÇ uint32_t IDR;

IO uint32_t ODR;

IO uint32_t BSRR ;

IO uint32_t BRR ;

IO uint32_t LCKR;

) GPIO_TypeDef;

GPIO_InitStructure yapısı, başlık dosyasında açıklanan GPIO_InitTypeDef türündedir
stm32f10x_gpio.h:

//stm32f10x_gpio.h typedef struct ( uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode; )GPIO_InitTypeDef; typedef numaralandırma ( GPIO_Speed_10MHz = 1, GPIO_Speed_2MHz, GPIO_Speed_50MHz )GPIOSpeed_TypeDef; typedef numaralandırma ( GPIO_Mode_AIN = 0x0, GPIO_Mode_IN_FLOATING = 0x04, GPIO_Mode_IPD = 0x28, GPIO_Mode_IPU = 0x48, GPIO_Mode_Out_OD = 0x14, GPIO_Mode_Out_PP = 0x10, GPIO_Mode_AF_OD = 0x1C, GPIO_Mode_AF_ PP = 0x18 )GPIOMode_TypeDef;

//stm32f10x_gpio.h

typedef yapısı

uint16_t GPIO_Pin;

GPIOSpeed_TypeDef GPIO_Speed ​​​​;

GPIOMode_TypeDef GPIO_Mode ;

) GPIO_InitTypeDef;

typedef numaralandırma

GPIO_Speed_10MHz = 1,

GPIO_Speed_2MHz,

GPIO_Speed_50MHz

) GPIOSpeed_TypeDef;

typedef numaralandırma

(GPIO_Mode_AIN = 0x0,

GPIO_Mode_IN_FLOATING = 0x04,

GPIO_Mode_IPD = 0x28,

GPIO_Mode_IPU = 0x48,

GPIO_Mode_Out_OD = 0x14,

GPIO_Mode_Out_PP = 0x10,

GPIO_Mode_AF_OD = 0x1C,

GPIO_Mode_AF_PP = 0x18

) GPIOMode_TypeDef;

Gördüğünüz gibi başlatılan yapının veri türleri şu şekilde kullanılabilir: özel türler GPIOSpeed_TypeDef gibi ve çevresel kayıtların başlatılmasının kolaylığı için GPIOMode_TypeDef gibi belirli değerlere sahip veri türleri.
Her GPIO pinini yapılandırmak için 4 bit ayrılmıştır.
Aşağıdaki resim GPIO'nun sıfır bitinin formatını göstermektedir:

Mod – çıkış çalışma modu (giriş/çıkış). Daha doğrusu, bu değerler biraz daha büyüktür; çıkış bağlantı noktası olarak yapılandırılan bağlantı noktalarının, çıkış sinyalinin maksimum frekansı üzerinde bir sınırlaması vardır.

Mod Tanım
00 giriş
01 10 MHz'e kadar çıkış frekansı
10 2 MHz'e kadar çıkış frekansı
11 50 MHz'e kadar çıkış frekansı

CNF – çıkış yapılandırma bitleri. Çalışma moduna bağlıdır:

Pin konfigürasyon kaydının bu yapısıyla, konfigürasyon için tüm bitleri kendiniz ayarlamanın son derece sakıncalı olacağını kabul edin. Bunu GPIO_Init kütüphane fonksiyonunu kullanarak yapmak çok daha kolay olacaktır.
Çevre birimi modülünü başlattıktan sonra PPP_Cmd işlevi kullanılarak etkinleştirilmesi gerekir:

PPP_Cmd(PPP, ETKİNLEŞTİR);

PPP_Cmd(PPP, ETKİNLEŞTİR);

Bu işlev GPIO modülleri için mevcut değildir; başlatmanın ardından GPIO pinlerini hemen kullanabilirsiniz. Kütüphanenin sadece mikrodenetleyici donanımına arayüz sağladığı unutulmamalıdır. Donanım modülünün etkinleştirme/devre dışı bırakma bayrağı yoksa işlev çağrısı PPP_Cmd(PPP, ETKİNLEŞTİR) imkansız.
Çıkış modunda GPIOx pininin durumunu kontrol etmek ve giriş veya çıkış modunda değeri okumak için kütüphane aşağıdaki işlevleri sağlar:

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

void GPIO_SetBits (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) ;

void GPIO_ResetBits (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) ;

uint8_tGPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_tGPIO_Pin) ;

uint16_tGPIO_ReadOutputData(GPIO_TypeDef* GPIOx) ;

uint8_tGPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_tGPIO_Pin) ;

uint16_tGPIO_ReadInputData(GPIO_TypeDef* GPIOx) ;

Çevresel modüllerin geri kalanı aynı şekilde yapılandırılır ve çalışır. Bununla birlikte, belirli donanım modülünün özelliklerine bağlı olarak bazı farklılıklar vardır, bu nedenle öncelikle STM32F10x SPL kitaplığı için seçilen modülün kullanım örneklerini görüntülemenizi önemle tavsiye ederim.

Kesintileri ve istisnaları yönetme

Cortex-M3 çekirdeği iç içe geçmiş bir vektörleştirilmiş kesme denetleyicisi içerir. Denetleyici, işlemci çekirdeği kesintilerine neden olabilecek en fazla 240 kaynağı destekler. Belirli bir mikrodenetleyici modelinde mümkün olan 240 vektörden kaç tanesinin uygulandığı üreticiye bağlıdır. Stm32f10x mikrodenetleyiciler bu vektörlerden en fazla 43 adete sahip olabilir.Bu kesme hatlarına maskelenebilir denir. Ek olarak 15 adet Cortex-M3 çekirdek kesme vektörü ve bir adet harici maskelenemeyen EXTI kesmesi vardır.
Denetleyici, bir işleyici içinde başka bir kesmenin meydana gelebileceği iç içe kesmeleri destekler. Bu bakımdan her kesme kaynağının kendi önceliği vardır. 16 kesme öncelik seviyesi desteklenir.
Cortex-M3 çekirdek kesme vektörleri en yüksek öncelik değerlerine sahiptir.
En yüksek üç kesme düzeyi vektörlere atanır ve değiştirilemez:

Sayı İşleyici Bir öncelik Tanım
1 Reset_Handler -3(en yüksek) Vektörü sıfırla
2 NMI_İşleyicisi -2 Maskelenemeyen kesinti
3 HardFault_Handler -1 Acil koşullar

Diğer tüm kesme vektörlerine 0'dan 15'e kadar öncelik seviyeleri atanabilir.
En yüksek öncelik seviyesi daha düşük bir değere karşılık gelir. Öncelik düzeyi yalnızca tek bir vektöre değil, aynı zamanda bütün bir vektör grubuna da atanabilir. Bu özellik çok sayıda kesme vektörüyle çalışmayı kolaylaştırır.
Öncelik grubunu ayarlamak için STM32F10x SPL kitaplığından bir işlev kullanılır.

Uzun zamandır, hatta çok uzun zamandır yazımıza yeni yazılar gelmemişti o yüzden artık yetişme zamanı 😉 Bugün STM32F4'ü incelemeye başlayacağız. Ve muhtemelen bu kontrolörler için yeni bir proje oluşturarak başlayacağız, ancak dürüst olmak gerekirse bu konuda bir makale yazmak istemedim çünkü yeni proje burada prensip olarak STM32F103 () ile aynı şekilde yaratılmıştır. Ancak yine de STM32F4'te bazı zorluklar ortaya çıkıyor, bu yüzden yine de bu süreci ayrıntılı olarak ele alalım)

Öyleyse Keil'i başlatalım, yeni bir proje oluşturalım - Proje -> Yeni uVision Projesi. Yeni projeyi bir klasöre kaydediyoruz ve ardından kullanılacak mikro denetleyiciyi seçmemiz istenecek. Peki seçelim, STM32F407VG olsun:

Bitti, beliren iletişim kutusunda “Evet” e tıklayın; ilk dosya projemize eklenecektir - startup_stm32f4xx.s. Daha önce olduğu gibi kütüphaneleri kullanacağız CMSIS Ve Standart Çevre Birim Kitaplığı, ancak doğal olarak zaten STM32F4xx kontrolörleri için. Bu yüzden mutlaka bunları indirip gerekli dosyaları hala boş olan projemize eklememiz gerekiyor. Bu arada, farklı insanlardan F4 için bazı "öyle olmayan" kütüphanelerle karşılaştıklarını ve en basit projenin bile bir araya getirilmediğini defalarca duydum. Ben bununla karşılaşmadım, ancak burada benim kullandığım test edilmiş kütüphaneler var:

Böylece indirdik, her şey hazır, artık dosyaları projeye ekliyoruz. Resim neye ihtiyacınız olacağını gösterir:

Evet, hazırlık tamamlandı, şimdi kodumuzu içerecek yeni bir .c dosyası oluşturalım. Hadi gidelim Dosya->Yeni Keil'de boş bir dosya açılır, tıklayın Dosya->Farklı kaydet ve örneğin test.c adı altında kaydedin. Kaydederken dosya uzantısını (.c) belirtmeyi unutmayın. Dosya oluşturuldu, harika ama onu da projemize eklememiz gerekiyor. Aslında bunda karmaşık bir şey yok 😉 Bu dosyaya boş bir test programı yazalım:

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

Neredeyse her şey hazır, geriye kalan tek şey proje ayarlarına bakmak - Proje->Hedef için seçenekler… Birçok sekme içeren bir pencere açılır, burada yalnızca birkaçıyla ilgileniyoruz. Sekmeyi aç C/C++ ve Define alanına şunu yazıyoruz:

Peki, sahada projede yer alan tüm dosyalara kesinlikle yollar eklemeniz gerekir. Bu adımı tamamladıktan sonra F7 (Build) tuşuna basabilirsiniz, proje hatasız ve uyarısız olarak inşa edilecektir. Gördüğünüz gibi karmaşık bir şey yok)

Ama genel olarak ben kişisel olarak işleri biraz farklı yapıyorum. Bu yaklaşımın dezavantajına bakın. Böylece CMSIS ve SPL kütüphanelerini bir yere indirdik, bu klasörlerden dosyalar ekledik, dosyaların yollarını yazdık, her şey yolunda. ANCAK! Yolların tümü mutlak olduğundan, yani bilgisayarınızdaki belirli klasörleri işaret ettiğinden proje başka bir bilgisayarda oluşturulmayacak. Ve başka bir makinede yeni bir proje oluşturmak için adımları yeniden uygulamanız gerekecek. Bu çok büyük bir eksi. Bu nedenle, genellikle yeni bir proje için ayrı bir klasör oluşturuyorum, içinde CMSIS, SPL ve kullanılan diğer kütüphaneler için alt klasörler oluşturuyorum ve her projede ihtiyacım olan tüm dosyaları bu klasörlere koyuyorum. Örnek olarak yeni projemiz için STM32F4_Test klasörünü ve içinde aşağıdaki klasörleri oluşturalım:

Her şeyi CMSIS ve SPL klasörlerine koydum gerekli dosyalar, projeyi oluştururken yazının başında eklediğimiz. Şimdi Keil'i başlatıyoruz, yeni bir proje oluşturuyoruz ve onu Proje alt klasörümüze kaydediyoruz, böylece tüm proje dosyaları tek bir yerde olur ve kaosa neden olmaz)

Proje oluşturuldu, şimdi daha önce olduğu gibi STM32F4_CMSIS ve STM32F4_SPL klasörlerindeki tüm dosyaları projeye ekliyoruz. main() fonksiyonu ile test .c dosyamızı Source klasörüne atıp projeye ekliyoruz. Geriye kalan tek şey ayarları yapılandırmak =) Her şey aynı - tanım alanına şunu yazıyoruz:

USE_STDPERIPH_DRIVER,STM32F4XX



Projeyi birleştiriyoruz - hata yok, uçuş normal! Prensip olarak, sonunda aynı şeyi elde ettik, ancak şimdi proje herhangi bir sorun olmadan hemen başka bir bilgisayara kurulacak ve bu çok kullanışlı ve kullanışlıdır) Kesinlikle tüm proje dosyaları artık yakınlarda, aynı klasörde bulunuyor, ve yollar göreceli hale geldi ve değiştirilmesi gerekmiyor.
Aslında hepsi bu kadar, yakın gelecekte STM32F4'ü programlamak için kesinlikle bir şeyler yapacağız, o yüzden yakında görüşürüz! ;)

Örnek makaleden tam proje -

Standart kütüphanenin sisteme bağlı olduğunu belirttim. Aslında, CMSIS, MK'nin genelleştirilmiş yapısal temsil sistemi ve SPL'nin standart çevre kitaplığıyla bağlantılıdır. Her birine bakalım:

CMSIS
MK'nin çekirdeği ve çevresi ile çalışmayı birleştirmek ve yapılandırmak için bir dizi başlık dosyası ve küçük bir kod kümesidir. Aslında bu dosyalar olmadan MK ile normal şekilde çalışmak imkansızdır. Kütüphaneyi MK için birlikte verilen dokümantasyon sayfasından alabilirsiniz.
Açıklamaya göre bu kütüphane, Cortex ailesinin herhangi bir MK'si ile çalışırken arayüzleri birleştirmek için oluşturuldu. Ancak gerçekte bunun yalnızca tek bir üretici için geçerli olduğu ortaya çıktı; Başka bir şirketin mikro denetleyicisine geçerek, çevre birimlerini neredeyse sıfırdan incelemek zorunda kalıyorsunuz.
Her ne kadar MK'nin işlemci çekirdeğiyle ilgili dosyalar tüm üreticilerden aynı olsa da (sadece aynı işlemci çekirdeği modeline sahip oldukları için - ARM tarafından IP blokları şeklinde sağlanır).
Bu nedenle çekirdeğin yazmaçlar, talimatlar, kesmeler ve yardımcı işlemci birimleri gibi bölümleriyle çalışmak herkes için standarttır.
Çevreye gelince, STM32 ve STM8 (birdenbire) neredeyse benzer ve bu, ST tarafından piyasaya sürülen diğer MK'ler için de kısmen geçerli. Pratik kısımda CMSIS kullanımının ne kadar kolay olduğunu göstereceğim. Ancak bunu kullanmanın zorlukları, insanların belgeleri okuma ve MK tasarımını anlama konusundaki isteksizliğiyle ilişkilidir.

SPL
Standart Çevre Birim Kitaplığı - standart çevre birimi kitaplığı. Adından da anlaşılacağı gibi bu kütüphanenin amacı MK'nin çevresi için bir soyutlama yaratmaktır. Kitaplık, MK çevre birimlerini yapılandırmak ve bunlarla çalışmak için insan tarafından okunabilen sabitlerin bildirildiği başlık dosyalarının yanı sıra çevre birimleriyle işlemler için kitaplığın kendisinde toplanan kaynak kodu dosyalarından oluşur.
SPL, CMSIS üzerinden bir soyutlamadır ve kullanıcıya yalnızca tek bir üreticinin tüm MCU'ları için değil, genel olarak Cortex-Mxx işlemci çekirdeğine sahip tüm MCU'lar için ortak bir arayüz sunar.
Yeni başlayanlar için daha uygun olduğuna inanılıyor çünkü... çevre birimlerinin nasıl çalıştığını düşünmenize izin vermez, ancak kodun kalitesi, yaklaşımın evrenselliği ve arayüzlerin kısıtlaması geliştiriciye belirli kısıtlamalar getirir.
Ayrıca, kütüphanenin işlevselliği, belirli koşullar altında USART (evrensel senkronize-asenkron seri port) gibi bazı bileşenlerin konfigürasyonunu her zaman doğru bir şekilde uygulamanıza izin vermez. Pratik kısımda kütüphanenin bu kısmıyla çalışmayı da anlatacağım.

Herkese selam. Son yazımızda hatırladığınız gibi yazılım paketi STM32 mikrodenetleyicilerle çalışıp ilk programı derledim. Bu yazıda bu kartın mimarisini, mikrodenetleyiciyi ve çalışmak için mevcut kütüphaneleri tanıyacağız.

Aşağıda tahtanın bir resmi var STM32F3 Keşif , burada: 1 — MEMS sensörü. L3GD20 3 eksenli dijital jiroskop. 2 - 3 eksenli dijital doğrusal ivmeölçer ve 3 eksenli dijital jeomanyetik sensör LSM303DLHC içeren bir kutuda MEMS sistemi. 4 – LD1 (PWR) – 3,3V güç kaynağı. 5 – LD2 – kırmızı/yeşil LED. Varsayılan kırmızıdır. Yeşil, ST-LINK/v2 (veya V2-B) ile PC arasındaki iletişim anlamına gelir. ST-LINK/v2-B'nin yanı sıra özel bir ekranım var USB girişi. 6. -LD3/10 (kırmızı), LD4/9 (mavi), LD5/8 (turuncu) ve LD6/7 (yeşil). Son yazımızda LD4 LED'ini yaktık. 7. – İki düğme: özel KULLANICI ve SIFIRLAMA. 8. - Mini-B konnektörlü USB KULLANICI.

9 - USB hata ayıklayıcı/programlayıcı ST-LINK/V2. 1 0. - Mikrodenetleyici STM32F303VCT6. 11. — Harici yüksek frekans jeneratörü 8 MHz. 12. – Burada düşük frekans jeneratörü olması lazım, maalesef lehimlenmemiş. 13. – SWD – arayüz. 14. – Harici veya dahili kontrolörlerin programlanmasını seçmek için kullanılan jumper'lar ilk durumda çıkarılmalıdır. 15 – Jumper JP3 – kontrolörün tüketimini ölçmek amacıyla bir ampermetreyi bağlamak için tasarlanmış bir jumper. Silinirse taşımızın başlamayacağı açıktır. 16. – STM32F103C8T6 üzerinde hata ayıklama kartı bulunmaktadır. 17. — LD3985M33R Düşük voltaj düşüşüne ve gürültü seviyesine sahip regülatör, 150mA, 3,3V.

Şimdi STM32F303VCT6 mikrodenetleyicisinin mimarisine daha yakından bakalım. Onun teknik özellikler: LQFP-100 kasa, ARM Cortex-M4 çekirdek, maksimum çekirdek frekansı 72 MHz, program bellek kapasitesi 256 KB, bellek tipi FLAŞ programları, hacim rasgele erişim belleği SRAM 40 kbayt, RAM 8 kbayt, giriş/çıkış sayısı 87, arayüzler (CAN, I²C, IrDA, LIN, SPI, UART/USART, USB), çevre birimleri (DMA, I2S, POR, PWM, WDT), ADC/DAC 4 *12 bit/2*12bit, besleme gerilimi 2...3,6 V, çalışma sıcaklığı –40...+85 C. Aşağıdaki şekilde 45'i olmak üzere 87 giriş/çıkış portunu gördüğümüz bir pin çıkışı bulunmaktadır. Normal I/O'lar (TC, TTa), 42 5 volt toleranslı I/O'lar (FT, FTf) – 5 V ile uyumludur. (kart üzerinde sağda 5V, solda 3,3V pinler vardır). Her dijital I/O hattı genel bir I/O hattı olarak hizmet verebilir.
hedef veya alternatif işlev. Projeler ilerledikçe yavaş yavaş çevreyi tanıyacağız.

Aşağıdaki blok diyagramı göz önünde bulundurun. Kalp, 72 MHz'e kadar çalışan 32 bitlik ARM Cortex-M4 çekirdeğidir. Mikrodenetleyici içindeki ana programın yürütülmesini izlemek için kullanılabilen yerleşik bir kayan nokta birimi FPU'ya ve bir bellek koruma birimi MPU'ya, yerleşik makro izleme hücrelerine - Gömülü İzleme Makro Hücresi'ne (ETM) sahiptir. Cihaz çalıştığı sürece bu gözlemleri ETM kontakları aracılığıyla sürekli olarak yayınlayabilirler. NVIC (İç içe vektörlü kesme denetleyicisi) – kesme kontrol modülü. TPIU (İzleme Bağlantı Noktası Arayüz Birimi). FLASH bellek içerir – 256 KB, SRAM 40 KB, RAM 8 KB. Çekirdek ile bellek arasında, cihazların doğrudan bağlanmasına olanak tanıyan bir Veri Yolu matrisi bulunur. Ayrıca burada iki tür veri yolu matrisi AHB ve APB görüyoruz; burada ilki daha üretkendir ve yüksek hızlı iletişim için kullanılır dahili bileşenler ve ikincisi çevre birimleri (giriş/çıkış aygıtları) içindir. Kontrol cihazında 4 adet 12 bit ADC (ADC) (5 Mbit/s) ve bir sıcaklık sensörü, 7 karşılaştırıcı (GP Comparator1...7), 4 programlanabilir operasyonel amplifikatör (OpAmp1...4) (PGA (Programlanabilir Kazanç Dizisi) bulunur. )), 2 12 bit DAC kanalı (DAC), RTC (gerçek zamanlı saat), iki izleme zamanlayıcısı - bağımsız ve pencereli (WinWatchdog ve Ind. WDG32K), 17 genel amaçlı ve çok işlevli zamanlayıcı.

Genel anlamda denetleyici mimarisine baktık. Şimdi mevcut yazılım kitaplıklarına bakın. Genel bir bakış yaptıktan sonra aşağıdakileri vurgulayabiliriz: CMSIS, SPL ve HAL. Her birine bir LED'in yanıp sönmesine ilişkin basit bir örnek kullanarak bakalım.

1). CMSIS(Cortex Mikrodenetleyici Yazılım Arayüzü Standardı) - Cortex®-M için standart kütüphane. Cihaz desteği sağlar ve basitleştirir yazılım arayüzleri. CMSIS tutarlı ve basit arayüzlerçekirdek, çevre birimleri ve gerçek zamanlı işletim sistemleri için. Kullanımı program yazmanın profesyonel bir yoludur, çünkü... kayıtlara doğrudan yazmayı içerir ve buna göre veri sayfalarının sürekli okunması ve incelenmesi gerekir. Donanım üreticisinden bağımsız.
CMSIS aşağıdaki bileşenleri içerir:
- CMSIS-CORE: Tutarlı sistem başlatma ve çevre birimi erişimi;
- CMSIS-RTOS: Deterministik Gerçek Zamanlı Yazılım Yürütme yazılım gerçek zamanlı);
- CMSIS-DSP: Dijital sinyal işlemenin hızlı uygulanması dijital işleme sinyaller);
- CMSIS-Sürücü: Ara yazılım ve uygulama kodu için genel çevresel arayüzler (Ara yazılım ve uygulama kodu için genel çevresel arayüzler);
- CMSIS-Pack: Yeniden kullanılabilir yazılım bileşenlerine kolay erişim yazılım bileşenleri);
- CMSIS-SVD: Cihaza ve çevre birimlerine tutarlı görünüm çevresel aygıtlar);
- CMSIS-DAP: Düşük maliyetli değerlendirme donanımına bağlantı. Hata ayıklama yazılımı.

Örneğin bir program yazalım; bir LED'i yakıp söndürelim. Bunun için kayıtları açıklayan belgelere ihtiyacımız var. Benim durumumda RM0316 Referans kılavuzu STM32F303xB/C/D/E, STM32F303x6/8, STM32F328x8, STM32F358xC, STM32F398xE gelişmiş ARM ® tabanlı MCU'ların yanı sıra sorumlu olduğu spesifik bacağın açıklaması DS9118: ARM® tabanlı Cortex®-M4 32b MCU+FPU, 256KB'ye kadar Flash+ 48KB SRAM, 4 ADC, 2 DAC kanalı, 7 comp, 4 PGA, zamanlayıcılar, 2,0-3,6 V. Başlangıç ​​olarak programdaki bağlantı noktasını saatleyeceğiz çünkü Varsayılan olarak her şey devre dışıdır, bu da güç tüketimini azaltır. Referans kılavuzunu açın ve Sıfırlama ve saat kontrolü bölümüne bakın, ardından RCC kayıt haritasına bakın ve IOPEEN'in etkinleştirilmesinden hangi kaydın sorumlu olduğunu görün

Bu kaydın çevre birimlerinin saat ayarının açıklamasına geçelim AHB çevresel saat etkinleştirme kaydı (RCC_AHBENR), burada bu portun 21. bitin altında olduğunu görüyoruz. RCC'yi açın->AHBENR|=(1<<21) . Далее сконфигурируем регистры GPIO. Нас интересует три: GPIOE_MODER и GPIOx_ODR . C помощью них повторим программу с предыдущей статьи, затактируем PE8. Первый отвечает за конфигурацию входа выхода, выбираем 01: General purpose output mode. GPIOE->MODER|=0×10000 . İkincisi ise bacaktaki düşük/yüksek seviyeyi açmak içindir. Program aşağıdadır:

#include "stm32f3xx.h " //Mikrodenetleyici başlık dosyası
imzasız int i;
geçersiz gecikme() (
için (i=0;i<500000;i++);
}
int ana (geçersiz) (
RCC->AHBENR|=(1<<21);
GPIOE->MODER|=0×10000;
iken (1)(
gecikme();
GPIOE->ODR|=0×100;
gecikme();
GPIOE->ODR&=~(0×100);
} }

2). SPL(Standart Çevre Birimleri Kitaplığı)- bu kütüphane ST Electronics'in tüm işlemcilerini birleştirmeyi amaçlamaktadır. Kod taşınabilirliğini geliştirmek için tasarlanmıştır ve öncelikle başlangıç ​​seviyesindeki geliştiricilere yöneliktir. ST, SPL'nin yerine HAL ile uyumlu "düşük katman" adı verilen bir alternatif üzerinde çalışıyor. Düşük Katmanlı (LL) sürücüler, donanıma HAL'den daha yakın, neredeyse hafif, uzman odaklı bir katman sağlamak üzere tasarlanmıştır. HAL'a ek olarak LL API'leri de mevcuttur. Aynı programın SPL'deki bir örneği.

#katmak
#katmak
#katmak
#define LED GPIO_Pin_8
int ana() (
uzun ben;
GPIO_InitTypeDef gpio;
// Mavi LED, E portuna, pin 8'e (AHB veri yolu) bağlanır
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
// E bağlantı noktasını (LED) yapılandır
GPIO_StructInit(&gpio); //bir veri yapısı değişkeni tanımlayıp başlatıyoruz
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_Pin = LED;
GPIO_Init(GPIOE, &gpio);
// Yanıp Sönen LED'ler
iken (1) (
//Açık
GPIO_SetBits(GPIOE, LED);
için (i = 0; ben< 500000; i++);
// Hepsi kapalı
GPIO_ResetBits(GPIOE, LED);
için (i = 0; ben< 500000; i++);
} }

Her fonksiyon teknik dokümantasyonda açıklanmıştır UM1581 Kullanım kılavuzu STM32F30xx/31xx Standart Çevre Birim Kitaplığının Açıklaması. Burada gerekli verileri, yapıları, sıfırlama ve senkronizasyon kontrol işlevlerini içeren ve ayrıca giriş/çıkış bağlantı noktalarını yapılandırmak için üç başlık dosyasını bağlarız.

3). HAL- (Donanım Erişim Düzeyi, Donanım Soyutlama Katmanı)- Geliştirme için başka bir ortak kütüphane. Geçen yazımızda kullandığımız konfigürasyon için CubeMX programı da yayınlandı. Orada ayrıca bu kütüphaneyi kullanarak bir LED'in yanıp sönmesi için bir program yazdık. Aşağıdaki şekilde gördüğümüz gibi küp HAL ve CMSIS sürücülerini üretmektedir. Peki, kullanılan ana dosyaları açıklayalım:
- system_stm32f3x.c ve system_stm32f3x.h- zamanlama sistemini yapılandırmak için minimum işlev seti sağlamak;
— core_cm4.h – çekirdeğin ve çevre birimlerinin kayıtlarına erişim sağlar;
- stm32f3x.h - mikrodenetleyici başlık dosyası;
— startup_system32f3x.s — başlangıç ​​kodu, kesme vektörleri tablosu vb. içerir.

#include "ana.h"
#include "stm32f3xx_hal.h"
void SystemClock_Config(void); /*Saat yapılandırma fonksiyonlarını bildir*/
statik geçersiz MX_GPIO_Init(void); /*G/Ç'yi başlat*/
int ana (geçersiz) (
/*Tüm çevre birimlerinin sıfırlanması, Flash arayüzünü ve Systick'i başlatır.*/
HAL_Init();
/* Sistem saatini yapılandır */
SystemClock_Config();
/* Yapılandırılmış tüm çevre birimlerini başlat */
MX_GPIO_Init();
iken (1) (
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_8); // Bacağın durumunu değiştir
HAL_Delay(100); )
}
geçersiz SystemClock_Config (geçersiz){
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

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

}
/**CPU, AHB ve APB veri yolu saatlerini başlatır */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig (&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){
_Error_Handler(__FILE__, __LINE__);
}
/**Systick kesinti süresini yapılandırın*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Systick'i yapılandırın */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn kesme yapılandırması */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/** Pinleri Analog Giriş Çıkışı EVENT_OUT EXTI olarak yapılandırın */
statik geçersiz MX_GPIO_Init (geçersiz){
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Bağlantı Noktası Saat Etkinleştirme */
__HAL_RCC_GPIOE_CLK_ENABLE();
/*GPIO pin Çıkış Seviyesini yapılandırın */
HAL_GPIO_WritePin (GPIOE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*GPIO pinlerini yapılandırın: PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed ​​= GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}
void _Error_Handler(char * dosyası, int satırı){
iken (1) (
} }
#ifdef USE_FULL_ASSERT

Assert_failed'i geçersiz kılın (uint8_t* dosyası, uint32_t satırı){
}
#endif
Burada, tıpkı önceki örnekte olduğu gibi, dokümantasyondaki her fonksiyonun açıklamasını görebiliriz; örneğin UM1786 Kullanım Kılavuzu STM32F3 HAL ve düşük katmanlı sürücülerin açıklaması.

CMSIS kullanan ilk seçeneğin daha az hantal olduğunu özetleyebiliriz. Her kütüphanenin dokümantasyonu bulunmaktadır. Sonraki projelerde STCube konfigürasyon programını kullanarak HAL ve CMSIS'i kullanacağız ve mümkünse yazmaçları yazılım sarmalayıcılar olmadan doğrudan kullanacağız. Bugün burada duralım. Bir sonraki yazımızda inşaatın temel prensiplerine bakacağız. akıllı ev. Herkese güle güle.




Tepe