در قسمت قبلی درباره راهاندازی واحد ADC و گرفتن اطلاعات توسط DMA صحبت کردیم و در این قیمت میخواهیم دربارهی استفاده از DMA برای ارسال اطلاعات از حافظه توسط واحد USART صحبت کنیم. همانطور که میدانید استفاده از DMA برای انتقال اطلاعات بین وسایل جانبی میکروکنترلر (Peripheral) و حافظه موجب تسریع عملکرد میکروکنترلر خواهد شد. در این بخش مثل بخش قبلی میخواهیم از DMA برای ارتباط بین وسایل جانبی و حافظه استفاده کنیم. اما این بار برای ارسال اطلاعات از حافظه به واحد USART. با سیسوگ همراه باشید.
مرحله اول) ایجاد پروژه در محیط STM32CubeMX
همانند قبل مراحل ایجاد پروژه را طی میکنیم و تنظیم دیباگ و کلاک را انجام میدهیم. سپس در منوی Connectivity، واحد USART1 را انتخاب کرده و پس از تنظیم پارامترهای این واحد مانند بخش قبلی، از تب DMA Setting کلید Add را میزنیم. از منوی کشویی Select، USART1_TX را انتخاب میکنیم. این بار DMA را در حالت Normal mode و جهت انتقال اطلاعات را Memory to peripheral انتخاب میکنیم. اکنون به تب Project Manger رفته و بقیه تنظیمات را مثل گذشته انجام میدهیم و در آخر GENERATE CODE را زده تا به محیط برنامهنویسی وارد شویم.
تنظیم DMA
مرحله دوم) نوشتن کد پروژه
در این بخش نیز مثل قبل ابتدا باید به تنظیم واحد DMA بپردازیم. چون از واحد USART تنها برای ارسال اطلاعات استفاده میکنیم نیاز به نوشتن کد برای تنظیم آن وجود ندارد و با تنظیماتی که در محیط CubeMX انجام دادیم کدهای موردنیازی برای این واحد، در پروژه ما ایجادشده است.
قبل از هر چیز متغیرهای مورداستفاده را به کد اضافه میکنیم:
1 2 | uint8_t message1[] = "\r\n Hey! This is a test message\r\n"; uint8_t ARRAYSIZE = sizeof(message1); |
سپس درون int main (بعد از SystemClock_Config) و یا در بدنه تابع MX_DMA_Init، کد زیر را اضافه میکنیم :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_4, (uint32_t)message1, LL_USART_DMA_GetRegAddr(USART1), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, ARRAYSIZE); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4); LL_USART_EnableDMAReq_TX(USART1); |
در آخرین خط، اجازه درخواست ارسال اطلاعات به DMA داده میشود. در این پروژه نیازی به نوشتن هیچ کدی در حلقه while(1) نیست و با تنظیماتی که انجام دادیم واحد DMA اطلاعات نوشتهشده در حافظه را از طریق USART ارسال خواهد کرد. نتیجه اجرا را میتوانیم در ترمینال پورت سریال مشاهده کنیم:
در بخش بعدی در مورد واحد SPI و نحوه ارسال اطلاعات توسط آن، صحبت خواهیم کرد.
با سلام. من خاستم از dma برای حالت rx در usart استفاده کنم ولی موفق نشدم . آیا نکته ای وجود داره
سلام دوست عزیز. برای دریافت اطلاعات از rx رابط USART به وسیله DMA اگر اندازه داده دریافتی رو بدونید، میتونید با قرار دادن یک حلقه و درخواست دادن به اندازه تعداد بایت های کلمه ، اطلاعات رو دریافت کنید. در خصوص گرفتن اطلاعات در حالتی که اندازه داده مشخص نیست، یک مقاله جدا لازمه که احتمالا در آینده مینویسم.
سلام بازم ممنون از اطلاعاتی که به اشتراک میزارید . اگه من در حالت ارسال circular رو انتخاب نکنم . بعد هر وقت خاستم با dma ارسال کنم همون نوشتن خط اخری تو برنامه بالا کافیه ؟ ممنون
سلام، خواهش میکنم. خوشحالم که آموزشهارو دنبال میکنید. توی این آموزش ابهامی وجود داشت که برطرف شد. توی این قسمت بر خلاف قسمت قبلی DMA روی حالت Normal تنظیم میشه نه Circular و برای همین نوشته شده بود که سایر پارامترها تغییر نمیکنند. حالا میرسیم به سوال شما. اگر DMA روی Normal mode تنظیم شده باشد، برای ارسال مجدد اطلاعات باید دستور آخر و دستور قبل از آن، یعنی دو دستور فعال سازی و اجازه درخواست DMA رو دوباره بنویسیم. و اگر بخواهیم اطلاعات ارسالی رو عوض کنیم و پیام دیگری بفرستیم، هر چهار دستور باید مجددا نوشته شوند و این بار آدرس و اندازه پیام جدید رو مشخص کنیم. امیدوارم با این توضیحات جواب سوال شما رو به طور کامل داده باشم.
سلام ممنون بله ابهام برطرف شد . فقط جهت اطلاع اینکه چه اینتراپت فعال باشه چه غیره فعال در حالت normal برای استفاده مجدد از دستورات بالا باید پرچم اتمام ارسال حتما پاک بشه . در غیره این صورت ارسالی صورت نمیگیرد. من با stm32f205rbt تست کردم.همچنین در این میکرو کنترلر خط سوم دستورات بالا به این صورت تغییر کرد
ll_dma_enablestream(dma2,ll_dma_stream_0);