برنامه نویسی STM32F4. ایجاد یک پروژه جدید در Keil. STM32F407(STM32F4-DISCOVERY) - رویکرد غیر استاندارد - کتابخانه استاندارد قسمت 1

تا این مرحله، ما از کتابخانه استاندارد هسته - CMSIS استفاده کرده ایم. برای پیکربندی یک پورت در حالت عملیاتی مورد نظر، ما مجبور شدیم برای یافتن رجیستر مسئول یک عملکرد خاص، و همچنین در یک سند بزرگ برای سایر اطلاعات مربوط به این فرآیند جستجو کنیم. وقتی کار با تایمر یا ADC را شروع کنیم، همه چیز دردناک تر و معمول تر می شود. تعداد رجیسترها در آنجا بسیار بیشتر از درگاه های ورودی/خروجی است. پیکربندی دستی زمان زیادی می برد و احتمال اشتباه را افزایش می دهد. بنابراین، بسیاری از مردم ترجیح می دهند با کتابخانه استاندارد محیطی - StdPeriph کار کنند. چه چیزی می دهد؟ ساده است - سطح انتزاع افزایش می‌یابد، نیازی نیست که وارد اسناد شوید و در اکثر موارد به ثبت‌ها فکر کنید. در این کتابخانه تمامی حالت های عملیاتی و پارامترهای محیط MK در قالب ساختار توضیح داده شده است. اکنون، برای پیکربندی یک دستگاه جانبی، فقط باید تابع مقداردهی اولیه دستگاه را با ساختار پر شده فراخوانی کنید.

در زیر تصویری با نمایش شماتیک سطوح انتزاع آورده شده است.

ما با CMSIS (که "نزدیک ترین" به هسته است) کار کردیم تا نشان دهیم میکروکنترلر چگونه کار می کند. مرحله بعدی کتابخانه استاندارد است که اکنون استفاده از آن را یاد خواهیم گرفت. بعد درایورهای دستگاه می آیند. آنها به عنوان فایل های *.c \ *.h درک می شوند که یک رابط نرم افزاری مناسب برای کنترل هر دستگاهی ارائه می دهند. به عنوان مثال در این دوره درایورهای تراشه max7219 و ماژول وای فای esp8266 را در اختیار شما قرار می دهیم.

یک پروژه استاندارد شامل فایل های زیر است:


البته اولاً، اینها فایل های CMSIS هستند که به کتابخانه استاندارد اجازه می دهند با هسته کار کند، قبلاً در مورد آنها صحبت کرده ایم. دوم، فایل های استاندارد کتابخانه. و سوم، فایل های کاربری.

فایل های کتابخانه را می توانید در صفحه اختصاص داده شده به MK هدف (برای ما stm32f10x4) در بخش پیدا کنید. منابع طراحی(در CooCox IDE، این فایل ها از مخزن محیط توسعه دانلود می شوند). هر ابزار جانبی مربوط به دو فایل است - هدر (*.h) و کد منبع (*.c). توضیحات دقیق را می توان در فایل پشتیبانی که در آرشیو کتابخانه موجود در وب سایت موجود است، یافت.

  • stm32f10x_conf.h - فایل پیکربندی کتابخانه. کاربر می تواند ماژول ها را متصل یا جدا کند.
  • stm32f10x_ppp.h - فایل هدر محیطی. به جای ppp می تواند gpio یا adc باشد.
  • stm32f10x_ppp.c - درایور دستگاه جانبی که به زبان C نوشته شده است.
  • stm32f10x_it.h - فایل هدر که شامل تمام کنترل کننده های احتمالی وقفه (نمونه های اولیه آنها) است.
  • stm32f10x_it.c یک فایل کد منبع الگو است که حاوی روال سرویس وقفه (ISR) برای شرایط استثنا در Cortex M3 است. کاربر می تواند ISR های خود را برای وسایل جانبی مورد استفاده اضافه کند.

کتابخانه استاندارد و تجهیزات جانبی در نامگذاری توابع و نشانه گذاری یک قرارداد دارند.

  • PPP مخفف ابزارهای جانبی مانند ADC است.
  • فایل های سیستم، هدر و کد منبع - با stm32f10x_ شروع کنید.
  • ثابت های استفاده شده در یک فایل در آن فایل تعریف شده است. ثابت های استفاده شده در بیش از یک فایل در فایل های هدر تعریف می شوند. تمام ثابت های موجود در کتابخانه محیطی اغلب با حروف UPPER نوشته می شوند.
  • ثبات ها به عنوان ثابت در نظر گرفته می شوند و به آنها حروف بزرگ نیز می گویند.
  • نام توابع خاص محیطی شامل یک مخفف است، مانند USART_SendData() .
  • برای پیکربندی هر دستگاه جانبی، از ساختار PPP_InitTypeDef استفاده می شود که به تابع PPP_Init() منتقل می شود.
  • برای deinitialize (مقدار را روی پیش فرض قرار دهید)، می توانید از تابع PPP_DeInit() استفاده کنید.
  • تابعی که به شما امکان فعال یا غیرفعال کردن وسایل جانبی را می دهد، PPP_Cmd() نامیده می شود.
  • تابع enable/disable وقفه PPP_ITConfig نامیده می شود.

می توانید دوباره لیست کامل را در فایل پشتیبانی کتابخانه مشاهده کنید. حالا بیایید LED چشمک زن را با استفاده از کتابخانه استاندارد محیطی بازنویسی کنیم!

قبل از شروع کار، بیایید به فایل stm32f10x.h نگاه کنیم و خط را پیدا کنیم:

#تعریف USE_STDPERIPH_DRIVER

اگر پروژه را از ابتدا با استفاده از فایل های کتابخانه ای از بایگانی بارگیری شده پیکربندی کنید، باید این خط را از کامنت بردارید. این به شما امکان می دهد از کتابخانه استاندارد استفاده کنید. این تعریف (ماکرو) به پیش پردازنده دستور می دهد که فایل stm32f10x_conf.h را شامل شود:

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

این فایل شامل ماژول است. اگر فقط به موارد خاصی نیاز دارید، بقیه را غیرفعال کنید، این باعث صرفه جویی در زمان در طول کامپایل می شود. همانطور که ممکن است حدس بزنید، ما به ماژول های RTC و GPIO نیاز داریم (اما در آینده به _bkp.h، _flash، _pwr.h، _rtc.h، _spi.h، _tim.h، _usart.h نیز نیاز خواهیم داشت):

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

مانند دفعه قبل، ابتدا باید کلاک پورت B را فعال کنید. این کار توسط تابع اعلام شده در stm32f10x_rcc.h انجام می شود:

Void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph، FunctionalState NewState);

Enum FunctionalState در stm32f10x.h تعریف شده است:

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

بیایید ساختاری را برای تنظیم پایه خود اعلام کنیم (می توانید آن را در فایل stm32f10x_gpio.h پیدا کنید):

GPIO_InitTypeDef LED;

حالا باید آن را پر کنیم. بیایید به محتویات این ساختار نگاه کنیم:

ساختار Typedef ( uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode; ) GPIO_InitTypeDef;

تمام شمارش ها و ثابت های لازم را می توان در همان فایل یافت. سپس تابع init_leds() بازنویسی شده به شکل زیر خواهد بود:

Void led_init() (// فعال کردن ساعت RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)؛ // ساختار را اعلام کنید و آن را پر کنید GPIO_InitTypeDef LED؛ LED.GPIO_Pin = GPIO_Pin_0; = GPIO_Mode_ Out_PP; // راه اندازی پورت GPIO_Init (GPIOB، &LED؛ )

بیایید تابع main() را بازنویسی کنیم:

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

نکته اصلی این است که ترتیب اولیه سازی را احساس کنید: ساعت محیطی را روشن کنید، ساختار را اعلام کنید، ساختار را پر کنید، روش اولیه سازی را فراخوانی کنید. سایر دستگاه های جانبی معمولاً به روشی مشابه پیکربندی می شوند.

برای مدت طولانی، حتی برای مدت بسیار طولانی، هیچ مقاله جدیدی در مورد مقاله ما وجود ندارد، بنابراین وقت آن است که به عقب برگردیم 😉 امروز ما مطالعه STM32F4 را آغاز خواهیم کرد. و احتمالاً ما با ایجاد یک پروژه جدید برای این کنترلرها شروع خواهیم کرد، اگرچه صادقانه بگویم، من نمی خواستم مقاله ای در این مورد بنویسم، زیرا یک پروژه جدید در اینجا، در اصل، به همان روش در حال ایجاد است. همانطور که برای STM32F103 (). اما هنوز هم مشکلاتی با STM32F4 پیش می آید، بنابراین، با این وجود، بیایید این فرآیند را با جزئیات در نظر بگیریم)

بنابراین، بیایید Keil را راه اندازی کنیم، یک پروژه جدید ایجاد کنیم - پروژه -> پروژه uVision جدید.پروژه جدید را در پوشه ای ذخیره می کنیم و سپس از ما خواسته می شود که میکروکنترلر مورد استفاده را انتخاب کنیم. خوب، بیایید انتخاب کنیم، بگذارید STM32F407VG باشد:

انجام شد، در کادر محاوره ای که ظاهر می شود، روی "بله" کلیک کنید و اولین فایل به پروژه ما اضافه می شود - startup_stm32f4xx.s. درست مثل قبل، از کتابخانه ها استفاده خواهیم کرد CMSISو کتابخانه محیطی استاندارد، اما، به طور طبیعی، در حال حاضر برای کنترلرهای STM32F4xx. پس حتما باید آنها را دانلود کنیم و فایل های لازم را به پروژه هنوز خالی خود اضافه کنیم. به هر حال، من بیش از یک بار از افراد مختلف شنیده ام که آنها با کتابخانه های "نه چندان" برای F4 مواجه می شوند و حتی ساده ترین پروژه با هم جمع نمی شود. من خودم با این مورد مواجه نشده ام، با این حال، در اینجا کتابخانه های آزمایش شده ای هستند که خودم از آنها استفاده می کنم:

بنابراین، ما آن را دانلود کردیم، همه چیز آماده است، اکنون فایل ها را به پروژه اضافه می کنیم. تصویر نشان می دهد آنچه شما نیاز دارید:

خوب، آماده سازی کامل است، حالا بیایید یک فایل .c جدید ایجاد کنیم که حاوی کد ما خواهد بود. برویم به فایل->جدید، یک فایل خالی در Keil باز می شود، کلیک کنید File->Save asو برای مثال آن را تحت نام test.c ذخیره کنید. هنگام ذخیره، فراموش نکنید که پسوند فایل (.c) را مشخص کنید. فایل ایجاد شد، عالی است، اما ما همچنین باید آن را به پروژه خود اضافه کنیم. خوب، در واقع، هیچ چیز پیچیده ای در مورد آن وجود ندارد 😉 بیایید یک برنامه آزمایشی خالی در این فایل بنویسیم:

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

تقریباً همه چیز آماده است، تنها چیزی که باقی می ماند این است که به تنظیمات پروژه نگاه کنید - پروژه->گزینه های هدف…پنجره ای با تب های زیادی باز می شود، ما در اینجا فقط به چند مورد علاقه داریم. برگه را باز کنید C/C++و در قسمت Define می نویسیم:

خوب، در زمین شما باید مسیرهایی را به تمام فایل های موجود در پروژه اضافه کنید. پس از انجام این مرحله می توانید F7 (Build) را فشار دهید و پروژه بدون خطا یا اخطار ساخته می شود. همانطور که می بینید، هیچ چیز پیچیده ای نیست)

اما به طور کلی، من شخصاً کارها را کمی متفاوت انجام می دهم. به ضرر این روش نگاه کنید. بنابراین ما کتابخانه های CMSIS و SPL را در جایی دانلود کردیم، فایل ها را از این پوشه ها اضافه کردیم، مسیرهای فایل ها را یادداشت کردیم، همه چیز عالی است. ولی! این پروژه روی رایانه دیگری ساخته نخواهد شد، زیرا مسیرها همه مطلق هستند، یعنی به پوشه های خاصی در رایانه شما اشاره می کنند. و در دستگاه دیگری در واقع باید مراحل ایجاد یک پروژه جدید را دوباره انجام دهید. این یک منفی بزرگ است. بنابراین، من معمولاً یک پوشه جداگانه برای یک پروژه جدید ایجاد می کنم، در آن زیر پوشه هایی برای CMSIS، SPL و سایر کتابخانه های مورد استفاده ایجاد می کنم و تمام فایل هایی را که در هر پروژه خاص نیاز دارم در این پوشه ها قرار می دهم. به عنوان مثال، اجازه دهید پوشه STM32F4_Test را برای پروژه جدید خود و پوشه های زیر در آن ایجاد کنیم:

من تمام فایل های لازم را که هنگام ایجاد پروژه در ابتدای مقاله اضافه کردیم در پوشه های CMSIS و SPL قرار دادم. اکنون Keil را راه‌اندازی می‌کنیم، یک پروژه جدید ایجاد می‌کنیم و آن را در زیر پوشه Project خود ذخیره می‌کنیم تا همه فایل‌های پروژه در یک مکان باشند و باعث هرج و مرج نشوند)

پروژه ایجاد شده است، اکنون مانند قبل، به سادگی تمام فایل های پوشه های STM32F4_CMSIS و STM32F4_SPL را به آن اضافه می کنیم. ما فایل .c تست خود را با تابع main() در پوشه Source قرار می دهیم و آن را نیز به پروژه اضافه می کنیم. تنها چیزی که باقی می ماند این است که تنظیمات را پیکربندی کنید =) همه چیز یکسان است - در قسمت define می نویسیم:

USE_STDPERIPH_DRIVER,STM32F4XX



ما پروژه را مونتاژ می کنیم - هیچ خطایی وجود ندارد، پرواز عادی است! در اصل، در پایان ما همان چیزی را دریافت کردیم، اما اکنون پروژه بلافاصله بدون هیچ مشکلی بر روی هر رایانه دیگری مونتاژ می شود، و این بسیار راحت و مفید است) کاملاً تمام فایل های پروژه اکنون در همان نزدیکی، در همان پوشه قرار دارند. و مسیرها نسبی شده و نیازی به تغییر نیست .
این همه است، در واقع، در آینده نزدیک ما کاری برای برنامه ریزی STM32F4 انجام خواهیم داد، قطعا، پس به زودی شما را می بینیم!;)

پروژه کامل از نمونه مقاله -

در این نشریه، من سعی خواهم کرد بر روی نکات اصلی برای شروع سریع میکروکنترلرهای STM32F10x بر اساس کتابخانه تجهیزات جانبی استاندارد شرکت سازنده STMicroelectronics تمرکز کنم.

مقاله از Eclipse CDT به عنوان محیط توسعه استفاده می کند. از آنجایی که تمرکز اصلی روی کد برنامه خواهد بود، می توانید با خیال راحت تمام دستکاری ها را در Code::Blocks انجام دهید.

ساختار کلی پروژه برای میکروکنترلرهای ARM در مقاله من توضیح داده شده است.

در اینجا به طور خلاصه به شما یادآوری می کنم که برای ساخت یک پروژه برای میکروکنترلرهای ARM (به ویژه STM32F10x) به یک اسکریپت لینکر و یک فایل C-Startup نیاز دارید.

اسکریپت لینکر فایلی است با دستورالعمل هایی برای قرار دادن کد برنامه و داده ها در حافظه میکروکنترلر. می تواند دستور دهد کد برنامه شما در حافظه برنامه فلش یا حافظه داده SRAM بارگذاری شود.

میکروکنترلرها با مقادیر مختلف حافظه برنامه و داده نیاز به اسکریپت های طرح بندی متفاوتی دارند. آنها را می توان از سازنده میکروکنترلر - STMicroelectronics دریافت کرد.
کتابخانه جانبی استاندارد STM32F10x را از بایگانی ARM_Toolchain/Lib/stm32f10x_stdperiph_lib.zip باز کنید.
این شامل پروژه های نمونه برای محیط های توسعه مختلف (IAR EWB، Keil uVision، Atollic True Studio و غیره) است. نزدیکترین آنها برای ما Atollic True Studio است، زیرا این یک تغییر از Eclipse است.
به پوشه Project/StdPeriph_Template/TrueSTUDIO بروید، چندین زیر شاخه در آنجا وجود دارد که نام آنها با نام بردهای توسعه STM3210x-EVAL مطابقت دارد.

ببینید کدام یک از این بردها از همان خط میکروکنترلر شما استفاده می کند. فایل stm32_flash.ld را از دایرکتوری مناسب در پروژه خود کپی کنید.

همچنین می توان یک اسکریپت جهانی ایجاد کرد که در آن فقط مقدار حافظه برنامه و داده مطابق با میکروکنترلر مورد استفاده تغییر می کند.

کد راه اندازی (C-Startup) برای میکروکنترلرهای STM32 را می توان به زبان C یا اسمبلر نوشت.
اگرچه کتابخانه استاندارد محیطی STM32F10x (به اختصار STM32F10x SPL) اغلب به دلیل اشکالاتش مورد انتقاد قرار می گیرد، این ساده ترین راه برای شروع سریع برنامه نویسی STM32 است.
اما شما همیشه می خواهید که نوعی جایگزین وجود داشته باشد. در واقع، تعداد زیادی از آنها وجود دارد، به عنوان مثال، برنامه نویسی به زبان اسمبلی :)

این سخت ترین و بیهوده ترین راه است. راه دوم استفاده از کتابخانه CMSIS است که سینتکسی را برای دسترسی به ساختارهای زبان C برای دسترسی به انواع میکروکنترلرهای جانبی فراهم می کند. ساده ترین و منطقی ترین راه (به نظر من) استفاده از کتابخانه هاست.

اگر قاطعانه با STM32F10x SPL مخالف هستید، جایگزین دیگری مخصوصاً برای شما وجود دارد - کتابخانه libopencm3. در آن، بخش عمده‌ای از نمونه‌ها حول سری اصلی میکروکنترلرهای STM32F10x متمرکز شده‌اند، اما زمان زیادی است که نمونه‌هایی برای سری‌های دیگر (STM32F2xx/4xx) ظاهر شوند. شما همیشه می توانید به پروژه libopencm3 بپیوندید و این روند را تسریع کنید.

استاندارد CMSIS نیز برای استفاده در برنامه های شما اختیاری است.
شما می توانید با صرف مقداری تلاش و زمان برای پیاده سازی سطح HAL (لایه انتزاعی سخت افزار) در زبان برنامه نویسی C، بدون آن کار کنید.

این روش ممکن است در برخی موارد تنها روش موجود باشد. به عنوان مثال، سازمان شما از تراشه های سفارشی مبتنی بر هسته های محاسباتی توسعه یافته توسط ARM و تجهیزات جانبی خاص صنعت استفاده می کند.

یا باید نرم‌افزاری را به زبان C برای میکروکنترلرهایی با هسته ARM9 پیاده‌سازی کنید، که تولیدکنندگان بر روی استفاده از سیستم‌عامل‌های آماده (Linux، QNX، Windows CE) تمرکز می‌کنند، بنابراین کتابخانه‌هایی برای برنامه‌نویسی به زبان C به صورت خالص یا در ترکیب با بیشتر تولیدکنندگان RTOS سبک وزن ممکن است آن را ارائه ندهند.

خوشبختانه، تولیدکنندگان میکروکنترلرهای مبتنی بر هسته Cortex-M3 تعداد زیادی کتابخانه کد را در اختیار توسعه دهندگان قرار می دهند. این موضوع در مورد میکروکنترلرهای STM32 نیز صدق می کند.
بیایید بررسی خود را در مورد کتابخانه STM32F10x SPL ادامه دهیم. ما آن را با استفاده از یک مثال در نظر خواهیم گرفت.
شما می توانید این مثال را باز کنید یا پروژه خود را از ابتدا ایجاد کنید تا کل روند اتفاقی که در حال رخ دادن است را بهتر درک کنید.

برای مورد دوم، مراحل لازم را ذکر می کنم:

  • یک پروژه خالی جدید در Eclipse ایجاد کنید
  • اسکریپت طرح بندی و شروع فایل را در پروژه کپی کنید
  • یک Makefile جدید ایجاد کنید یا یک الگو را کپی کنید
  • هنگام استفاده از Makefile از مثال من به عنوان یک الگو، باید دایرکتوری های src, inc, bin, obj را در داخل پروژه ایجاد کنید و زیر شاخه های Debug و Release را در دایرکتوری bin و obj ایجاد کنید.
  • فایل های منبع و هدر لازم را از کتابخانه های CMSIS و STM32F10x SPL کپی کنید.
  • در صورت استفاده، تغییرات لازم را در قسمت تنظیمات کاربر قالب Makefile اعمال کنید.
  • اهداف جدید «Debug»، «cleanDebug»، «Release»، «cleanRelease»، «Program» را در پنجره «make target» Eclipse ایجاد کنید.
  • هدف "Debug" را راه اندازی کنید و اجرای آن را در پنجره "کنسول" نظارت کنید.

برای درک بهتر مطالب، مقاله را به چندین پاراگراف مستقل تقسیم کردم که هر کدام تنها یک جنبه از کار با کتابخانه STM32F10x SPL را توضیح می‌دهند.

پیکربندی STM32F10x SPL با استفاده از تعاریف ماکرو

برای پیکربندی کتابخانه، از مقادیر ماکرو از پیش تعریف شده استفاده می شود که اکنون آنها را در نظر خواهیم گرفت.
آنها را می توان در داخل فایل های هدر با استفاده از دستورالعمل پیش پردازنده تنظیم کرد #تعريف كردنیا مقادیر تعاریف کلان را از طریق کلید عبور دهید -دیکامپایلر GCC.
در مثالم از روش دوم استفاده می کنم.
در متغیر Makefile تعريف كردنحاوی ماکروهای لازم برای کامپایل کتابخانه STM32F10x SPL است.
تعریف کلان STM32F10X_MDمشخص می کند که آیا میکروکنترلر مورد استفاده متعلق به خط است یا خیر با چگالی متوسط.
این شامل میکروکنترلرهایی با حافظه فلش از 64 تا 128 کیلوبایت است.
در جدول زیر نام ماکروها برای سری های مختلف میکروکنترلرها آمده است:

نام سریال ماکرو شرح
خط ارزش با چگالی کم STM32F10X_LD_VL با ظرفیت حافظه فلش 16 - 32 کیلوبایت
چگالی کم STM32F10X_LD
با ظرفیت حافظه فلش 16 - 32 کیلوبایت
خط مقدار با چگالی متوسط STM32F10X_MD_VL فلش مموری
64 - 128 کیلوبایت
با چگالی متوسط STM32F10X_MD میکروکنترلرهای سری STM32F101xx، STM32F102xx، STM32F103xx با حافظه فلش 64 - 128 کیلوبایت
خط ارزش با چگالی بالا STM32F10X_HD_VL میکروکنترلرهای سری STM32F100xx با حجم
فلش - حافظه 256 - 512 کیلوبایت
تراکم بالا STM32F10X_HD با حجم
حافظه فلش 256 - 512 کیلوبایت
چگالی XL STM32F10X_XL
حافظه فلش 512 - 1024 کیلوبایت
خط اتصال STM32F10X_CL

برای تنظیم فرکانس ساعت میکروکنترلر، باید ماکرو را با مقدار فرکانس ساعت مورد نیاز در فایل system_stm32f10x.c از کامنت خارج کنید.

#اگر تعریف شده است (STM32F10X_LD_VL) || (تعریف شده STM32F10X_MD_VL) || (تعریف STM32F10X_HD_VL) #تعریف SYSCLK_FREQ_24MHz 24000000 #دیگر /* #تعریف SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24K_FREQ_24K/FREQ_240MHz #300000 6MHz 3600 0000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 * / #define SYSCLK_FREQ_72MHz 72000000 #endif

#اگر تعریف شده است (STM32F10X_LD_VL) || (تعریف شده STM32F10X_MD_VL) || (تعریف شده STM32F10X_HD_VL)

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

#define SYSCLK_FREQ_24MHz 24000000

#دیگر

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz 24000000 */

/* #define SYSCLK_FREQ_36MHz 36000000 */

/* #define SYSCLK_FREQ_48MHz 48000000 */

/* #define SYSCLK_FREQ_56MHz 56000000 */

#define SYSCLK_FREQ_72MHz 72000000

#endif

فرض بر این است که از یک تشدید کننده کوارتز با فرکانس 8 مگاهرتز برای همه اصلی استفاده شود
سری میکروکنترلرها به جز خط اتصال که برای آن نیاز به نصب تشدید کننده کوارتز 25 مگاهرتز است.
اگر از تشدید کننده‌های کوارتز با مقادیر فرکانس دیگر استفاده می‌کنید، باید مقدار ماکرو HSE_VALUE را در فایل هدر stm32f10x.h تغییر دهید و همه توابع وابسته را بر این اساس تطبیق دهید.
حدس زدن هدف ماکرو USE_STDPERIPH_DRIVER دشوار نیست - استفاده از کتابخانه استاندارد استاندارد STM32F10x.
USE_FULL_ASSERT – از ماکرو ASSERT برای اشکال زدایی برنامه استفاده کنید.

استفاده از ماکرو assert_param در کتابخانه

همه توابع کتابخانه STM32F10x SPL از ماکرو assert_param برای بررسی آرگومان های خود استفاده می کنند.
این ماکرو عبارتی را بررسی می‌کند که آرگومان تابع را برای برابری صفر آزمایش می‌کند. اگر مقدار عبارت صفر باشد، تابع کنترل کننده خطای آرگومان assert_failed فراخوانی می شود، در غیر این صورت (عبارت صفر نیست)، بررسی آرگومان با موفقیت انجام می شود.
شما باید تابع assert_failed را در برنامه خود پیاده سازی کنید.
پیغام خطا، نام فایل و شماره خط کدی که باعث خطا شده را نمایش می دهد.
ماکرو debug_printf می تواند از طریق USART با استفاده از کتابخانه استاندارد new_lib یا مثلاً کتابخانه آقای چن خروجی بگیرد.

#define debug_printf xprintf /* printf */ #ifdef USE_FULL_ASSERT void assert_failed(uint8_t* file, uint32_t line) (debug_printf("مقدار پارامترهای اشتباه: فایل %s در خط %d\r\n"، فایل، (int)line) ؛ در حالی که (1) ( ) )/* assert_failed */ #endif/*USE_FULL_ASSERT*/

#define debug_printf xprintf /* printf */

#ifdef USE_FULL_ASSERT

void assert_failed (uint8_t * فایل، خط uint32_t)

debug_printf( "مقدار پارامترهای اشتباه: فایل %s در خط %d\r\n", فایل , (int ) line ) ;

در حالی که (1)

) /* assert_failed */

#endif/*USE_FULL_ASSERT*/

تابع assert_failed پیاده‌سازی شده در کد شما تنها زمانی استفاده می‌شود که ماکرو USE_FULL_ASSERT اعلام شده باشد. در غیر این صورت، تمام کدهای اشکال زدایی از منبع حذف می شوند. این قابلیت در فایل هدر تنظیمات کتابخانه درایور stm32f10x_conf.h پیاده سازی شده است.

#ifdef USE_FULL_ASSERT #define assert_param(expr) ((expr) ? (void)0: assert_failed((uint8_t *)__FILE__, __LINE__)) void assert_failed(uint8_t* file, uint32_t line); #else #define assert_param(expr) ((void)0) #endif /* USE_FULL_ASSERT */

#ifdef USE_FULL_ASSERT

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

void assert_failed (uint8_t * فایل , uint32_t line ) ;

#دیگر

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

#endif /* USE_FULL_ASSERT */

اینجا چیز زیادی برای توضیح نیست بیایید به مثالی از استفاده از assert_param نگاه کنیم.

void set_param(uint8_t * param، uint8_t مقدار) (assert_param(param != NULL); *param = value; )/*set_param*/

void set_param (uint8_t * param، uint8_t مقدار)

assert_param (param != NULL ) ;

* param = مقدار ;

) /*set_param*/

تابع مقدار پارامتر را از طریق یک اشاره گر ارسال شده به عنوان آرگومان تنظیم می کند. اگر ماکرو USE_FULL_ASSERT اعلان نشده باشد، می توانیم فرض کنیم که خطوط
assert_param(param != NULL) به سادگی در کد نیست، در غیر این صورت پارامتر در این تعریف بررسی می شود.
اگر اشاره گر تعریف نشده باشد، مقدار param != NULL نادرست خواهد بود و تابع assert_failed اجرا می شود که نام فایل و شماره خط را با خطا از طریق USART خروجی می دهد و سپس حلقه می کند و در نتیجه از بودن مقدار جلوگیری می کند. به یک آدرس تعریف نشده در حافظه اختصاص داده شده است.
اصلاً لازم نیست از ماکرو assert_param در کد خود استفاده کنید، بلکه در کد کتابخانه استفاده کنید
STM32F10x SPL در همه جا استفاده می شود.
تابع set_param را می توان با بررسی خطای آرگومان بدون استفاده از assert_param پیاده سازی کرد.

#define ERROR (-1) #define OK (0) int set_param(uint8_t * param, uint8_t مقدار) (int r = ERROR؛ if (param == NULL) r را برگرداند؛ *param = مقدار؛ r = OK. بازگشت r ;)/*set_param*/

#define ERROR (-1)

#define OK (0)

int set_param (uint8_t * param، uint8_t مقدار)

int r = ERROR ;

اگر (پارام == NULL)

بازگشت r ;

* param = مقدار ;

r = خوب

بازگشت r ;

) /*set_param*/

فایل C-Startup در کتابخانه STM32F10x SPL

در کد شروع، میکروکنترلر در ابتدا مقدار دهی اولیه می شود، پشته پیکربندی می شود، بخش BSS تنظیم مجدد می شود و تابع main () main فراخوانی می شود.
کد شروع هیچ ارتباط مستقیمی با کتابخانه STM32F10x SPL ندارد. اما در این کد بوت، قبل از فراخوانی تابع main() برنامه، تابع مقداردهی اولیه میکروکنترلر SystemInit() فراخوانی می شود که بخشی از CMSIS است.
می توان آن را به راحتی در کتابخانه CMSIS پیدا کرد.
به دایرکتوری Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/TrueSTUDIO بروید و فایل مورد نیاز را کپی کنید. تنها چیزی که باقی می ماند این است که بفهمید میکروکنترلر مورد استفاده در پروژه شما متعلق به کدام خط است.
برای این کار به جدول زیر نگاه کنید:

نام سریال نام فایل شرح
خط ارزش با چگالی کم startup_stm32f10x_ld_vl.s میکروکنترلرهای سری STM32F100xx با حجم
حافظه فلش 16 - 32 کیلوبایت
چگالی کم startup_stm32f10x_ld.s میکروکنترلرهای سری STM32F101xx، STM32F102xx، STM32F103xx
با ظرفیت حافظه فلش 16 - 32 کیلوبایت
خط مقدار با چگالی متوسط startup_stm32f10x_md_vl.s میکروکنترلرهای سری STM32F100xx
با چگالی متوسط startup_stm32f10x_md.s میکروکنترلرهای سری STM32F101xx، STM32F102xx، STM32F103xx
با ظرفیت حافظه فلش 64 - 128 کیلوبایت
خط ارزش با چگالی بالا startup_stm32f10x_hd_vl.s میکروکنترلرهای سری STM32F100xx
تراکم بالا startup_stm32f10x_hd.s میکروکنترلرهای سری STM32F101xx، STM32F103xx
با ظرفیت حافظه فلش 256 - 512 کیلوبایت
چگالی XL startup_stm32f10x_xl.s میکروکنترلرهای سری STM32F101xx، STM32F103xx
با ظرفیت حافظه فلش 512 - 1024 کیلوبایت
خط اتصال startup_stm32f10x_cl.s میکروکنترلرهای سری STM32F105xx و STM32F107xx

فایل راه‌اندازی شامل نام‌های کنترل‌کننده بردار وقفه و استثنا است، اما تنها کنترل‌کننده بردار بازنشانی پیاده‌سازی می‌شود، که قبل از فراخوانی تابع ()main، تمام مقداردهی اولیه انجام می‌شود.
اجرای سایر کنترل کننده های استثنا بر عهده برنامه نویس برنامه است. اگر برنامه شما از هیچ کنترل کننده ای استفاده نمی کند، نیازی به ثبت آنها نیست. اگر یک استثنا رخ دهد، کنترل کننده پیش فرض استفاده خواهد شد - حلقه کردن کد برنامه.

ترکیب کتابخانه CMSIS

همانطور که قبلاً در این نشریه نوشته شد، کتابخانه CMSIS با استفاده از عناصر ساختارهای زبان C، دسترسی به ماژول های جانبی میکروکنترلر را فراهم می کند.
اجرای این کتابخانه به دو قسمت تقسیم می شود. بخش اول دسترسی به حاشیه هسته Cortex-M3 و قسمت دوم - به حاشیه یک مدل میکروکنترلر خاص را فراهم می کند.
از آنجایی که استاندارد CMSIS برای همه میکروکنترلرهای دارای هسته Cortex-M3 یکسان است، اجرای قسمت اول برای همه سازندگان یکسان خواهد بود، اما قسمت دوم برای هر سازنده متفاوت خواهد بود.
CMSIS شامل چندین فایل سربرگ و منبع است. بخش اول شامل فایل های زیر است:

  • هسته_cm3.h
  • core_cm3.c

بخش دوم CMSIS شامل فایل C-Startup و همچنین فایل های زیر است:

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

فایل هدر stm32f10x.h شامل تعاریف ماکرو برای دسترسی به ماژول های جانبی میکروکنترلرهای stm32f10x است.
فایل های system_stm32f10x.h و system_stm32f10x.c اولیه سازی اولیه میکروکنترلر را پیاده سازی می کنند.

ترکیب و پیکربندی کتابخانه STM32F10x SPL

این کتابخانه از فایل‌های منبع و سرصفحه‌های همنام ماژول‌های جانبی با پیشوند stm32f10x_ تشکیل شده است.
به عنوان مثال، اجرای تعامل با ماژول USART در فایل‌های stm32f10x_usart.h و stm32f10x_usart.c موجود است.
قراردادهایی برای نامگذاری عناصر کتابخانه و قوانین رمزگذاری خاصی وجود دارد که در مستندات توضیح داده شده است.
این کتابخانه شامل اجرای درایورهای ماژول های میکروکنترلر محیطی است.
نام عناصر کتابخانه از مخفف های زیر برای ماژول های جانبی استفاده می کند:

مخفف ماژول جانبی
ADC مبدل آنالوگ به دیجیتال
BKP ثبت های پشتیبان
می توان رابط CAN
CEC کنترل کننده مصرف
CRC ماژول محاسبه چک جمع
DAC مبدل دیجیتال به آنالوگ
DBGMCU اشکال زدایی میکروکنترلر
DMA کنترل کننده دسترسی مستقیم به حافظه
EXTI کنترل کننده وقفه خارجی
FSMC کنترلر حافظه خارجی
فلاش حافظه برنامه فلش
GPIO پورت های ورودی/خروجی عمومی
I2C رابط I2C
I2S رابط I2S (صدا).
IWDG تایمر سگ نگهبان مستقل
NVIC کنترل کننده وقفه تو در تو
PWR کنترل کننده قدرت
RCC تنظیم مجدد و کنترل ساعت
RTC کنترلر زمان واقعی (ساعت)
SDIO رابط SDIO
SPI رابط SPI
SysTick تایمر سیستم
TIM تایمر اولیه یا پیشرفته
USART سریال جهانی همزمان-ناهمزمان
فرستنده گیرنده
WWDG نگهبان پنجره

بر اساس این حروف اختصاری، نام ماژول های نرم افزاری کتابخانه شکل می گیرد. شما مجبور نیستید از همه ماژول های موجود در کتابخانه استفاده کنید.
برای استفاده از ماژول های لازم در پروژه، کتابخانه باید پیکربندی شود.
برای این منظور، هر پروژه ای که از کتابخانه STM32F10x SPL استفاده می کند باید یک فایل هدر stm32f10x_conf.h داشته باشد.

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

#include "stm32f10x_gpio.h"

//#include "stm32f10x_i2c.h"

//#include "stm32f10x_iwdg.h"

//#include "stm32f10x_pwr.h"

#include "stm32f10x_rcc.h"

برای فعال کردن ماژول مورد نیاز، باید دستورالعمل را از نظر خارج کنید #عبارتند ازبا فایل های هدر مربوطه
فایل هدر stm32f10x_conf.h در stm32f10x.h موجود است، بنابراین برای استفاده از توابع کتابخانه STM32F10x SPL، فقط باید یک فایل هدر stm32f10x.h را در کد منبع خود قرار دهید.

// در فایل stm32f10x.h #ifdef USE_STDPERIPH_DRIVER #include "stm32f10x_conf.h" #endif

تکرار می کنم که پروژه باید ماکروهای USE_STDPERIPH_DRIVER، USE_FULL_ASSERT و یک ماکرو را نیز تعریف کند که سری میکروکنترلر مورد استفاده را مشخص کند (مثلا STM32F10X_MD برای خط تراکم متوسط).
اگر از مقدار فرکانس استاندارد کوارتز استفاده می کنید و کنترلر با حداکثر فرکانس کلاک 72 مگاهرتز کار می کند، دیگر نیازی به تغییر نخواهید داشت.
برای کامپایل کردن به Makefile باید فهرستی از فایل های کتابخانه اضافه کنید.
مثلا:

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

SRC += stm32f10x_rcc. ج

SRC += stm32f10x_gpio. ج

با استفاده از کتابخانه STM32F10x SPL. مکانیسم های کار

برای شروع برنامه نویسی با استفاده از کتابخانه جانبی، ساده ترین راه این است که به نمونه های ارائه شده با کتابخانه نگاه کنید. اما با این حال، برای درک کد این مثال ها، باید دانش اولیه ای از نحو و استفاده از کتابخانه داشته باشید.
همه ماژول‌های میکروکنترلر محیطی که قبلاً ذکر شده بود، ابتدا غیرفعال می‌شوند، سیگنال ساعت به آنها ارائه نمی‌شود و برق مصرف نمی‌کنند.
برای استفاده از یک ماژول جانبی، ابتدا باید یک سیگنال ساعت به آن ارائه دهید. سیگنال ساعت توسط ماژول ساعت RCC و تنظیم مجدد تامین می شود.
برای این منظور، کتابخانه وظایف زیر را دارد:

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) ;

در اینجا PPP نشان دهنده نام اصطالح ماژول است (به عنوان مثال ADC یا USART)، و x تعداد ماژول محیطی است.
اول از همه، باید دریابید که ماژولی که استفاده می کنید به کدام اتوبوس متصل است.
در مجموع، میکروکنترلرهای با معماری Cortex-M3 دارای سه باس هستند:
گذرگاه دستورالعمل، گذرگاه داده و گذرگاه سیستم. گذرگاه دستورالعمل هسته را به حافظه برنامه فلش متصل می کند. گذرگاه های داده و سیستم در یک ماتریس گذرگاه AHB (ARM Hi-Speed ​​Bus) ترکیب می شوند که در فرکانس هسته کار می کند. با این حال، فرکانس باس AHB را می توان با نصب تقسیم کننده کاهش داد. باس AHB دستگاه های پرسرعت مانند هسته و ماژول DMA را به هم متصل می کند.
دستگاه های I/O از طریق گذرگاه های میانی APB1 و APB2 (ARM Peripheral Bus) به گذرگاه AHB متصل می شوند.
حداکثر فرکانس کاری باس APB2 72 مگاهرتز است، فرکانس باس APB1
محدود به 36 مگاهرتز
می‌توانید دریابید که ماژول جانبی مورد استفاده به کدام یک از گذرگاه‌ها وصل شده است یا در فایل هدر stm32f10x_rcc.h نگاه کنید.
این فایل را باز کنید و مقادیر RCC_AHBPeriph، RCC_APB1Periph و RCC_APB2Periph را به ترتیب جستجو کنید.

#define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001) #define RCC_AHBPeriph_DMA2 ((uint32_t)0x00000002) #تعریف RCC_AHBPeriph_SRAM (000000001) #define RCC_AHBPeriph_DMA2 ((uint32_t) _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)

با نام ماکروها مشخص می کنیم که کدام ماژول ها به کدام اتوبوس ها متصل هستند. همچنین می توانید از عقل سلیم برای تعیین اینکه کدام تایر متعلق به یکی از این سه تایر است استفاده کنید. به عنوان مثال، ماژول USART یک دستگاه ورودی/خروجی است، به این معنی که به یکی از گذرگاه های APB متصل است. USART یک رابط نسبتاً کم سرعت است، بنابراین احتمالاً به گذرگاه APB1 متصل است.

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

پس از ارسال سیگنال ساعت به ماژول جانبی، می توانید پارامترهای آن را با فراخوانی تابع مقداردهی اولیه پیکربندی کنید:

PPP_Init (PPP، &PPP_InitStructure)؛

PPP_Init (PPP، & amp; PPP_InitStructure)؛

از آنجایی که برای مقداردهی اولیه یک ماژول محیطی، پارامترهای زیادی باید به تابع مقداردهی اولیه داده شوند، از یک اشاره گر به یک ساختار به عنوان آرگومان استفاده می شود. خود ساختار با پارامترهای اولیه باید قبل از فراخوانی تابع مقداردهی اولیه در حافظه ایجاد شود؛ عناصر ساختار باید مقادیر لازم را به آنها اختصاص دهند:

PPP_InitTypeDef PPP_InitStructure = (val1, val2, ..., valN)؛/* مقدار دهی اولیه ساختار وقتی که */

ابتدا می توانید یک ساختار ایجاد کنید و سپس مقادیر لازم را به عناصر آن اختصاص دهید:

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

PPP_InitTypeDef PPP_InitStructure ;

PPP_InitStructure. Member1 = val1 ;

PPP_InitStructure. Member2 = val2 ;

PPP_InitStructure. MemberN = valN ;

بیایید به یک مثال از پروژه stm32f10xQuickstart نگاه کنیم:

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 مقدار عدد پین، حالت و سرعت پورت اختصاص داده شده است.
با فراخوانی تابع GPIO_Init، خط 12 پورت GPIOC مقداردهی اولیه می شود.
اولین آرگومان تابع GPIO_Init یک اشاره گر به ناحیه حافظه جانبی GPIOC است که به یک اشاره گر به ساختار GPIO_TypeDef تبدیل شده است.

‎ 00000) typedef struct ( __IO uint32_t CRL؛ __IO uint32_t CRH ؛ __IO uint32_t IDR؛ __IO uint32_t ODR؛ __IO uint32_t BSRR؛ __IO uint32_t BRR؛ __IO uint32_t LCKR؛ ) GPIO_TypeDef؛

// stm32f10x.h

#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)

#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

#define PERIPH_BASE ((uint32_t)0x40000000)

ساختار typedef

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 ;

ساختار GPIO_InitStructure از نوع GPIO_InitTypeDef است که در فایل هدر توضیح داده شده است.
stm32f10x_gpio.h:

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

//stm32f10x_gpio.h

ساختار typedef

uint16_t GPIO_Pin ;

GPIOSpeed_TypeDef GPIO_Speed؛

GPIOMode_TypeDef GPIO_Mode ;

) GPIO_InitTypeDef ;

typedef enum

GPIO_Speed_10MHz = 1،

GPIO_Speed_2MHz،

GPIO_Speed_50MHz

) GPIOSpeed_TypeDef ;

typedef enum

(GPIO_Mode_AIN = 0x0،

GPIO_Mode_IN_FLOATING = 0x04،

GPIO_Mode_IPD = 0x28،

GPIO_Mode_IPU = 0x48،

GPIO_Mode_Out_OD = 0x14،

GPIO_Mode_Out_PP = 0x10،

GPIO_Mode_AF_OD = 0x1C،

GPIO_Mode_AF_PP = 0x18

) GPIOMode_TypeDef ;

همانطور که می بینید، هر دو نوع تعریف شده توسط کاربر، مانند GPIOSpeed_TypeDef، و انواع داده با مقادیر خاص برای راحتی اولیه سازی ثبات های جانبی، مانند GPIOMode_TypeDef، می توانند به عنوان انواع داده های ساختار اولیه استفاده شوند.
4 بیت برای پیکربندی هر پین GPIO اختصاص داده شده است.
تصویر زیر فرمت بیت صفر GPIO را نشان می دهد:

حالت – حالت عملکرد خروجی (ورودی/خروجی). به طور دقیق‌تر، این مقادیر کمی بزرگ‌تر هستند؛ پورت‌هایی که به‌عنوان پورت‌های خروجی پیکربندی شده‌اند محدودیتی در حداکثر فرکانس سیگنال خروجی دارند.

حالت شرح
00 ورود
01 فرکانس خروجی تا 10 مگاهرتز
10 فرکانس خروجی تا 2 مگاهرتز
11 فرکانس خروجی تا 50 مگاهرتز

CNF - بیت های پیکربندی خروجی. بستگی به حالت عملکرد دارد:

موافق باشید که با این ساختار رجیستر پیکربندی پین، تنظیم تمام بیت ها برای پیکربندی خودتان بسیار ناخوشایند خواهد بود. انجام این کار با استفاده از تابع کتابخانه GPIO_Init بسیار ساده تر خواهد بود.
پس از اینکه ماژول جانبی را مقداردهی اولیه کردید، باید با استفاده از تابع PPP_Cmd فعال شود:

PPP_Cmd (PPP، ENABLE)؛

PPP_Cmd (PPP، ENABLE)؛

این تابع برای ماژول های GPIO وجود ندارد؛ پس از مقداردهی اولیه، می توانید بلافاصله از پین های GPIO استفاده کنید. باید به خاطر داشت که کتابخانه فقط یک رابط برای سخت افزار میکروکنترلر فراهم می کند. اگر ماژول سخت‌افزار دارای پرچم فعال/غیرفعال‌سازی نباشد، فراخوانی تابع PPP_Cmd (PPP، ENABLE)غیر ممکن
برای کنترل وضعیت پین GPIOx در حالت خروجی و خواندن مقدار در حالت ورودی یا خروجی، کتابخانه توابع زیر را ارائه می‌کند:

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);

باطل 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) ;

بقیه ماژول های جانبی به همین ترتیب پیکربندی و کار می کنند. با این حال، به دلیل ویژگی های ماژول سخت افزاری خاص، تفاوت هایی وجود دارد، بنابراین اکیداً توصیه می کنم که ابتدا نمونه هایی از استفاده از ماژول انتخاب شده برای کتابخانه STM32F10x SPL را مشاهده کنید.

رسیدگی به وقفه ها و استثناها

هسته Cortex-M3 شامل یک کنترل کننده وقفه برداری تو در تو است. این کنترلر تا 240 منبع را پشتیبانی می کند که می توانند باعث وقفه در هسته پردازنده شوند. اینکه چند بردار از 240 بردار ممکن در یک مدل میکروکنترلر خاص پیاده سازی شود به سازنده بستگی دارد. میکروکنترلرهای Stm32f10x می توانند تا 43 مورد از این بردارها را داشته باشند.این خطوط وقفه قابل پوشش نامیده می شوند. علاوه بر این، 15 بردار وقفه هسته Cortex-M3 و یک وقفه EXTI غیر قابل ماسک خارجی وجود دارد.
کنترلر از وقفه های تو در تو پشتیبانی می کند، جایی که وقفه دیگری می تواند در یک کنترل کننده رخ دهد. در این راستا هر منبع وقفه ای اولویت خاص خود را دارد. 16 سطح اولویت وقفه پشتیبانی می شود.
بردارهای وقفه هسته Cortex-M3 دارای بالاترین مقادیر اولویت هستند.
سه بالاترین سطح وقفه به بردارها اختصاص داده شده و قابل تغییر نیستند:

عدد گرداننده یک اولویت شرح
1 Reset_Handler -3 (بالاترین) بازنشانی بردار
2 NMI_Handler -2 وقفه غیر قابل پوشش
3 HardFault_Handler -1 شرایط اضطراری

تمام بردارهای وقفه دیگر را می توان سطوح اولویت از 0 تا 15 اختصاص داد.
بالاترین سطح اولویت مربوط به مقدار کمتری است. سطح اولویت را می توان نه تنها به یک بردار منفرد، بلکه به کل گروه از بردارها اختصاص داد. این ویژگی کار با تعداد زیادی بردار وقفه را آسان می کند.
برای تنظیم گروه اولویت، تابعی از کتابخانه STM32F10x SPL استفاده می شود.

سلام به همه. همانطور که در مقاله گذشته به یاد دارید، بسته نرم افزاری را برای کار با میکروکنترلرهای STM32 پیکربندی کردیم و اولین برنامه را کامپایل کردیم. در این پست با معماری این برد، میکروکنترلر و کتابخانه های موجود برای کار آشنا می شویم.

در زیر تصویری از تابلو است STM32F3 Discovery ، جایی که: 1 — حسگر MEMS. ژیروسکوپ دیجیتال 3 محوره L3GD20. 2 - سیستم MEMS-in-a-case حاوی شتاب سنج خطی دیجیتال 3 محوره و سنسور ژئومغناطیسی دیجیتال 3 محور LSM303DLHC. 4 – LD1 (PWR) – منبع تغذیه 3.3 ولت. 5 – LD2 – LED قرمز/سبز. پیش فرض قرمز است. سبز به معنای ارتباط بین ST-LINK/v2 (یا V2-B) و رایانه شخصی است. من ST-LINK/v2-B و همچنین نشانگر پورت USB سفارشی دارم. 6. -LD3/10 (قرمز)، LD4/9 (آبی)، LD5/8 (نارنجی) و LD6/7 (سبز). در پست آخر LED LD4 را فلش زدیم. 7. – دو دکمه: کاربر USER و RESET. 8. - USB USER با کانکتور Mini-B.

9 - دیباگر/برنامه نویس USB ST-LINK/V2. 1 0. - میکروکنترلر STM32F303VCT6. 11. - ژنراتور خارجی با فرکانس بالا 8 مگاهرتز. 12. - در اینجا باید یک ژنراتور فرکانس پایین وجود داشته باشد، متأسفانه لحیم نشده است. 13. – SWD – رابط. 14. – جامپرهای انتخاب برنامه نویسی کنترلرهای خارجی یا داخلی، در حالت اول باید حذف شوند. 15 - جامپر JP3 - جامپر طراحی شده برای اتصال آمپرمتر برای اندازه گیری مصرف کنترلر. معلوم است که اگر حذف شود، سنگ ما شروع نمی شود. 16. – STM32F103C8T6 یک برد اشکال زدایی روی آن وجود دارد. 17. — رگولاتور LD3985M33R با افت ولتاژ کم و سطح نویز، 150 میلی آمپر، 3.3 ولت.

حال بیایید نگاهی دقیق تر به معماری میکروکنترلر STM32F303VCT6 بیندازیم. مشخصات فنی آن: کیس LQFP-100، هسته ARM Cortex-M4، حداکثر فرکانس هسته 72 مگاهرتز، ظرفیت حافظه برنامه 256 کیلوبایت، نوع حافظه برنامه FLASH، ظرفیت رم SRAM 40 کیلوبایت، رم 8 کیلوبایت، تعداد ورودی/خروجی ها 87، رابط ها ( CAN، I²C، IrDA، LIN، SPI، UART/USART، USB)، لوازم جانبی (DMA، I2S، POR، PWM، WDT)، ADC/DAC 4*12 بیت/2*12 بیت، ولتاژ تغذیه 2 ... 3.6 V، دمای کاری -40...+85 C. در شکل زیر یک پین اوت وجود دارد که 87 پورت ورودی/خروجی را می بینیم، 45 تای آنها ورودی/خروجی معمولی (TC, TTa)، 42 پورت I/O با تحمل 5 ولت. /Os (FT, FTf) - سازگار با 5 ولت (روی برد پین های 5 ولت در سمت راست و 3.3 ولت در سمت چپ وجود دارد). هر خط ورودی/خروجی دیجیتال می تواند به عنوان یک خط ورودی/خروجی عمومی عمل کند.
مقصد یا تابع جایگزین با پیشرفت پروژه ها به تدریج با حاشیه آشنا خواهیم شد.

بلوک دیاگرام زیر را در نظر بگیرید. قلب یک هسته 32 بیتی ARM Cortex-M4 است که تا 72 مگاهرتز کار می کند. دارای یک واحد ممیز شناور داخلی FPU و یک واحد حفاظت از حافظه MPU، سلول‌های ردیابی ماکرو داخلی - ماکروسل ردیابی جاسازی شده (ETM) که می‌توان از آن برای نظارت بر اجرای برنامه اصلی در داخل میکروکنترلر استفاده کرد. آنها قادرند تا زمانی که دستگاه کار می کند، به طور مداوم این مشاهدات را از طریق کنتاکت های ETM ارسال کنند. NVIC (کنترل کننده وقفه بردار تودرتو) - ماژول کنترل وقفه. TPIU (واحد رابط بندر ردیابی). دارای حافظه فلش – 256 کیلوبایت، SRAM 40 کیلوبایت، رم 8 کیلوبایت. بین هسته و حافظه یک ماتریس Bus قرار دارد که امکان اتصال مستقیم دستگاه ها را فراهم می کند. همچنین در اینجا ما دو نوع ماتریس باس AHB و APB را می بینیم، که در آن اولی سازنده تر است و برای برقراری ارتباط با اجزای داخلی پرسرعت استفاده می شود و دومی برای تجهیزات جانبی (دستگاه های ورودی/خروجی). این کنترلر دارای 4 ADC 12 بیتی (ADC) (5 مگابیت بر ثانیه) و یک سنسور دما، 7 مقایسه کننده (GP Comparator1...7)، 4 تقویت کننده عملیاتی قابل برنامه ریزی (OpAmp1...4) (PGA (آرایه افزایش قابل برنامه ریزی) است. 2 کانال DAC 12 بیتی (DAC)، RTC (ساعت زمان واقعی)، دو تایمر نگهبان - مستقل و پنجره ای (WinWatchdog و Ind. WDG32K)، 17 تایمر عمومی و چند منظوره.

به طور کلی، ما به معماری کنترلر نگاه کردیم. اکنون به کتابخانه های نرم افزار موجود نگاه کنید. پس از بررسی کلی، می توانیم موارد زیر را برجسته کنیم: CMSIS، SPL و HAL. بیایید با استفاده از یک مثال ساده از چشمک زدن یک LED به هر یک نگاه کنیم.

1). CMSIS(استاندارد رابط نرم افزاری میکروکنترلر Cortex) - کتابخانه استاندارد برای Cortex®-M. پشتیبانی دستگاه را فراهم می کند و رابط های نرم افزاری را ساده می کند. CMSIS رابط های سازگار و ساده ای را برای هسته، تجهیزات جانبی آن و سیستم عامل های بلادرنگ فراهم می کند. استفاده از آن روشی حرفه ای برای نوشتن برنامه است، زیرا... مستلزم نوشتن مستقیم به رجیسترها است و بر این اساس، خواندن و مطالعه مداوم برگه های داده ضروری است. مستقل از سازنده سخت افزار.
CMSIS شامل اجزای زیر است:
- CMSIS-CORE: راه اندازی ثابت سیستم و دسترسی محیطی.
- CMSIS-RTOS: اجرای قطعی نرم افزار در زمان واقعی (اجرای قطعی نرم افزار بلادرنگ).
- CMSIS-DSP: اجرای سریع پردازش سیگنال دیجیتال.
- CMSIS-Driver: رابط های جانبی عمومی برای میان افزار و کد برنامه (رابط های جانبی عمومی برای میان افزار و کد برنامه).
- CMSIS-Pack: دسترسی آسان به اجزای نرم افزار قابل استفاده مجدد (دسترسی آسان به اجزای نرم افزار قابل استفاده مجدد).
- CMSIS-SVD: نمای ثابت به دستگاه و لوازم جانبی.
- CMSIS-DAP: اتصال به سخت افزار ارزیابی کم هزینه. نرم افزار رفع اشکال.

به عنوان مثال، بیایید یک برنامه بنویسیم - یک LED چشمک بزنید. برای این کار ما به اسنادی نیاز داریم که رجیسترها را توصیف کنند. در مورد من راهنمای مرجع RM0316 STM32F303xB/C/D/E، STM32F303x6/8، STM32F328x8، STM32F358xC، STM32F398xE پیشرفته مبتنی بر ARM ® MCU، و همچنین شرحی از پایه خاص که مسئول آن است. DS9118: مبتنی بر ARM Cortex®-M4 32b MCU+FPU، تا 256 کیلوبایت فلش + 48 کیلوبایت SRAM، 4 ADC، 2 ch. DAC، 7 comp، 4 PGA، تایمر، 2.0-3.6 V.برای شروع، پورت را در برنامه کلاک می کنیم، زیرا به طور پیش فرض، همه چیز غیرفعال است، که باعث کاهش مصرف انرژی می شود. کتابچه راهنمای مرجع را باز کنید و به بخش Reset and Clock Control نگاه کنید، سپس RCC register map و ببینید چه ثباتی مسئول فعال کردن IOPEEN است.

بیایید به توضیحات مربوط به کلاکینگ تجهیزات جانبی این ثبات برویم ثبت فعال ساعت جانبی AHB (RCC_AHBENR)، جایی که می بینیم این پورت زیر بیت 21 است. آن را روشن کنید RCC->AHBENR|=(1<<21) . Далее сконфигурируем регистры GPIO. Нас интересует три: GPIOE_MODER и GPIOx_ODR . C помощью них повторим программу с предыдущей статьи, затактируем PE8. Первый отвечает за конфигурацию входа выхода, выбираем 01: General purpose output mode. GPIOE->MODER|=0×10000 . مورد دوم برای روشن کردن سطح پایین/بالا روی پا است. در زیر برنامه آمده است:

#include "stm32f3xx.h //فایل هدر میکروکنترلر
بدون امضا int i;
تاخیر خالی () (
برای (i=0;i<500000;i++);
}
int main (خلأ) (
RCC->AHBENR|=(1<<21);
GPIOE->MODER|=0×10000;
در حالی که (1)(
تاخیر انداختن()؛
GPIOE->ODR|=0×100;
تاخیر انداختن()؛
GPIOE->ODR&=~(0×100);
} }

2). SPL(کتابخانه استاندارد لوازم جانبی)- این کتابخانه برای ترکیب تمام پردازنده های ST Electronics در نظر گرفته شده است. طراحی شده برای بهبود قابلیت حمل کد و در درجه اول برای توسعه دهندگان مبتدی طراحی شده است. ST روی جایگزینی برای SPL به نام "لایه پایین" کار می کند که با HAL سازگار است. درایورهای لایه پایین (LL) به گونه ای طراحی شده اند که یک لایه تقریبا سبک وزن و متخصص گرا را ارائه دهند که نسبت به HAL به سخت افزار نزدیک تر است. علاوه بر HAL، API های LL نیز در دسترس هستند. نمونه ای از همین برنامه در SPL.

#عبارتند از
#عبارتند از
#عبارتند از
#define LED GPIO_Pin_8
int main() (
طولانی من;
GPIO_InitTypeDef gpio;
// LED آبی به پورت E، پایه 8 (گذرگاه AHB) متصل است
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE، ENABLE)؛
// پیکربندی پورت E (LED)
GPIO_StructInit(&gpio); //اعلان و مقداردهی اولیه یک متغیر ساختار داده
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_Pin = LED;
GPIO_Init(GPIOE، &gpio);
// LED های چشمک زن
در حالی که (1) (
//بر
GPIO_SetBits (GPIOE، LED)؛
برای (i = 0; i< 500000; i++);
// همه چیز خاموش است
GPIO_ResetBits (GPIOE، LED)؛
برای (i = 0; i< 500000; i++);
} }

هر عملکرد در مستندات فنی توضیح داده شده است راهنمای کاربر UM1581 شرح کتابخانه استاندارد استاندارد STM32F30xx/31xx. در اینجا ما سه فایل هدر را به هم متصل می کنیم که حاوی داده های لازم، ساختارها، تنظیم مجدد و عملکردهای کنترل همگام سازی و همچنین برای پیکربندی پورت های ورودی/خروجی است.

3). HAL- (سطح دسترسی سخت افزار، لایه انتزاعی سخت افزار)- یکی دیگر از کتابخانه های رایج برای توسعه. با آن برنامه CubeMX برای پیکربندی که در مقاله گذشته استفاده کردیم نیز منتشر شد. در آنجا نیز برنامه ای برای چشمک زدن LED با استفاده از این کتابخانه نوشتیم. همانطور که در شکل زیر می بینیم، مکعب درایورهای HAL و CMSIS را تولید می کند. خوب، اجازه دهید فایل های اصلی استفاده شده را شرح دهیم:
- system_stm32f3x.c و system_stm32f3x.h- ارائه حداقل مجموعه ای از توابع برای پیکربندی سیستم زمان بندی؛
- core_cm4.h - دسترسی به رجیسترهای هسته و لوازم جانبی آن را فراهم می کند.
- stm32f3x.h - فایل هدر میکروکنترلر؛
— startup_system32f3x.s — کد راه اندازی، حاوی جدولی از بردارهای وقفه و غیره است.

#شامل "main.h"
#include "stm32f3xx_hal.h"
void SystemClock_Config(void); /*اعلان توابع پیکربندی ساعت*/
static void MX_GPIO_Init(void); /*Initialize I/O*/
int main (خلأ) (
/*تنظیم مجدد تمامی تجهیزات جانبی، رابط Flash و Systick را راه اندازی می کند.*/
HAL_Init();
/* پیکربندی ساعت سیستم */
SystemClock_Config();
/* مقداردهی اولیه تمام تجهیزات جانبی پیکربندی شده */
MX_GPIO_Init();
در حالی که (1) (
HAL_GPIO_TogglePin(GPIOE، GPIO_PIN_8)؛ //وضعیت پا را تغییر دهید
HAL_Delay(100); )
}
void SystemClock_Config (باطل){
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;
اگر (HAL_RCC_OscConfig (&RCC_OscInitStruct) != HAL_OK){

}
/**ساعت های CPU، AHB و APB را راه اندازی می کند */
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;
اگر (HAL_RCC_ClockConfig (&RCC_ClkInitStruct، FLASH_LATENCY_0) != HAL_OK){
_Error_Handler(__FILE__, __LINE__)؛
}
/**زمان وقفه Systick را پیکربندی کنید*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Systick را پیکربندی کنید */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* پیکربندی وقفه SysTick_IRQn */
HAL_NVIC_SetPriority(SysTick_IRQn، 0، 0)؛
}
/** پیکربندی پین ها به عنوان خروجی ورودی آنالوگ EVENT_OUT EXTI */
خالی ثابت MX_GPIO_Init (باطل){
GPIO_InitTypeDef GPIO_InitStruct;
/* ساعت پورت های GPIO فعال شود */
__HAL_RCC_GPIOE_CLK_ENABLE();
/*پیکربندی سطح خروجی پین GPIO */
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 را پیکربندی کنید: 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 *، خط int){
در حالی که (1) (
} }
#ifdef USE_FULL_ASSERT

باطل assert_failed (فایل uint8_t*، خط uint32_t){
}
#endif
در اینجا، دقیقاً مانند مثال قبلی، می‌توانیم برای مثال شرح هر تابع را در مستندات مشاهده کنیم راهنمای کاربر UM1786 شرح درایورهای STM32F3 HAL و لایه پایین.

می‌توانیم خلاصه کنیم که گزینه اول، با استفاده از CMSIS، دست و پا گیر کمتری دارد. برای هر کتابخانه اسنادی وجود دارد. در پروژه های بعدی، ما از HAL و CMSIS با استفاده از برنامه پیکربندی STCube استفاده خواهیم کرد و در صورت امکان، از ثبات ها به طور مستقیم، بدون پوشش های نرم افزاری استفاده خواهیم کرد. بیایید همین امروز توقف کنیم. در مقاله بعدی به اصول اولیه ساخت خانه هوشمند خواهیم پرداخت. خداحافظ همه