راه اندازی واحد LTDC در حالت دو لایه و مکانیزم وقفه

0

راه اندازی واحد LTDC در حالت دو لایه و مکانیزم وقفه

در میکرکنترلرهای سری stm32f7 واحد LTDC دارای دو لایه است که هر کدام می­توانند بصورت مستقل فعال و برنامه ریزی شوند. هنگامی­که لایه­ها با یکدیگر همپوشانی داشته باشند، ترتیب نمایش آن­ها همیشه از یک ثابت پیروی می­کند. بطوریکه که همیشه لایه دو بر روی لایه یک نمایش داده می­شود. همانطور که در بخش قبل بیان شد، LTDC دارای قابلیت Blending است که امکان ترکیب تصویر هر لایه با لایه دیگر و تصویر پس زمینه را فراهم می­کند. در حالت دو لایه ابتدا تصویر لایه اول با تصویر پس زمینه ترکیب شده و نتیجه آن با تصویر دوم ترکیب می­شود. در شکل  1 نحوه ترکیب دو لایه و تصویر پس زمینه نشان داده شده است.

نحوه ترکیب شدن لایه های LTDC
نحوه ترکیب شدن لایه های LTDC

LTDC این امکان را فراهم می آورد که در زمان Runtime مکان و اندازه هر لایه تصویر را تغییر داد.

وقفه های LTDC

LTDC دارای دو وقفه عمومی زیر است:

  • وقفه عمومی LTDC
  • وقفه­ عمومی خطای LTDC

منابع وقفه LTDC در جدول 1 نشان داده شده است. سیگنال­های وقفه دو به دو با یکدیگر AND شده اند. در این پروژه از وقفه Line استفاده شده است. این وقفه هنگامی روی می­دهد که LTDC به خط مشخصی از تصویر برسد.

منابع وقفه واحد LTDC
منابع وقفه واحد LTDC

نحوه تنظیم LTDC در نرم افزار STM32CubeMX

در بخش قبل نحوه تنظیم LTDC در حالت یک لایه نشان داده شد. لذا از تکرار آن در این بخش خوداری شده است. در این بخش نحوه تنظیم آن در حالت دو لایه و با تصویر پس زمینه و وقفه بیان شده است. یادآوری می­شود که در این پروژه از بورد stm32f7discovery استفاده شده است که دارای یک LCD گرافیکی با ابعاد  480×272 پیکسل است.

برای تنظیم LTDC بصورت دو لایه در نرم افزار STM32CubeMX در بخش LTDC سربرگ Layer Settings ابتدا مقدار فیلد Number of Layers را برابر 2 Layer قرار دهید. سپس در قسمت Window Position اندازه و مکان هر لایه را تنظیم کنید. در این پروژه این بخش بصورت شکل زیر تنظیم شده است. در این پروژه کل صفحه نمایشگر به دو قسمت مساوی بین لایه­ها تقسیم شده است.

لازم به ذکر است در اینجا از فرمت پیکس RGB565 استفاده شده است. در صورتی که از فرمت دیگری استفاده می­کنید، این فیلد را با توجه فرمت موردنظر تنظیم نمایید.

نحوه تنظیم اندازه و موقعیت لایه¬های هریک از لایه های LTDC
نحوه تنظیم اندازه و موقعیت لایه های هریک از لایه های LTDC

چگونگی ترکیب لایه­ها با یکدیگر در قسمت Blending تنظیم می­شود. فیلد Alpha constant for blending ضریب ترکیب هر لایه را با لایه­های دیگر و تصویر پس زمینه را مشخص می­کند. مقدار این فیلد عددی بین 0 تا 255 است. در شکل زیر چگونگی تنظیم این بخش که در این پروژه استفاده شده است، نشان داده شده است.

نحوه تنظیم Blending هریک از لایه های LTDC
نحوه تنظیم Blending هریک از لایه های LTDC
  • در بخش Frame Buffer تنظیمات بافر هر لایه انجام می­شود. در شکل  زیر  نحوه تنظیم این بخش نشان داده شده است.

نحوه تنظیم بافر فریم هر لایه
نحوه تنظیم بافر فریم هر لایه

در فیلد Background نیز مقدار تصویر پس زمینه مشخص می­شود. در این پروژه از تصویر کاملا مشکی که مقادیر هر سه فیلد R، G و B آن صفر است استفاده شده است. چگونگی تنظیم این فیلد در شکل  5 نشان داده شده است.

چگونگی تنظیم تصویر پس زمینه هر لایه
چگونگی تنظیم تصویر پس زمینه هر لایه

نحوه فعال نمودن وقفه LTDC در نرم افزار STM32CubeMX

برای فعال نمودن وقفه LTDC تنها کافیست در قسمت LTDC سربرگ NVIC Settings تیک LTDC global interrupt را بزنید و جهت تغییر اولویت وقفه آن در قسمت NVIC اولویت آن تنظیم کنید. با توجه به اینکه در این پروژه فقط یک منبع وقفه وجود دارد لذا از همان مقدار پیشفرض آن استفاده شده است. در شکل 6 چگونگی فعال نمودن این واحد نشان داده شده است.

نحوه فعال نمودن وقفه LTDC در نرم افزار STM32CubeMX
نحوه فعال نمودن وقفه LTDC در نرم افزار STM32CubeMX

بعد از انجام تنظیمات فوق به سربرگ Project Manager رفته و مسیر و نام پروژه را تنظیم کرده و بر روی GENERATE CODE کلیک کرده تا پروژه جدید ایجاد شود.

تبدیل تصویر به فایل C

در بخش قبل نحوه تبدیل تصویر به فایل .h و یا .c با استفاده از نرم افزار lcd_convertor بیان شد. لذا در این قسمت از بیان مجدد آن پرهیز شده است. لازم به ذکر است که حتما فرمت پیکسل که در این نرم افزار انتخاب می­کنید با فرمت پیکسل که در نرم افزار STM32CubeMX انتخاب کرده­اید، مطابقت داشته باشد. در این پروژه از فرمت پیکسل RGB565 استفاده شده است.

نرم افزار پروژه

همانطور که در بخش قبل بیان شد، جهت نماش تصویر ابتدا با در تابع MX_LTDC_Init که نرم افزار STM32CubeMX تولید می­کند، آدرس شروع فریم را تنظیم نمود. برای این منظور کافیست تا دستورات زیر تغییر داد.

pLayerCfg.FBStartAdress = (uint32_t) image_data_pic1;
  pLayerCfg1.FBStartAdress = (uint32_t) image_data_pic2; 

لازم به ذکر است که image_data_pic1 و image_data_pic2 تصاویر موردنظر هستند که با استفاده از نرم افزار lcd_convertor ایجاد شده اند.

سپس برای فعال نمودن وقفه Line باید تابع HAL_LTDC_ProgramLineEvent را فراخوانی نمود. الگوی این تابع بصورت زیر است.

HAL_StatusTypeDef HAL_LTDC_ProgramLineEvent(LTDC_HandleTypeDef *hltdc, uint32_t Line)

در این تابع آرگومان hltdc پورت LTDC و آروگومان Line شماره Line موردنظر را مشخص می­کند.

در وقفه LTDC نیز همانند سایر وقفه­های میکروکنترلر باید تابع Callback متناظر با وقفه آن باید overwrite شود. در این پروژه در روتین وقفه LTDC بصورت زیر است.

void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc)
{
 ReloadFlag 
 

در روتین وقفه فلگ ReloadFlag یک می­شود و در حلقه بی­نهایت برنامه هنگامی که یک فلگ یک شود موقعیت تصویر را جابجا می­کند.

تابع main

تابع main این پروژه بصورت زیر است.

int main(void)
{
  uint32_t index = 0;
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LTDC_Init();

  HAL_LTDC_ProgramLineEvent(&hltdc, 2);

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    for (index = 0; index < 32; index++)
    {
      /* calculate new picture position */
       PicturesPosition(&Xpos1, &Ypos1, &Xpos2, &Ypos2, (index+1));
       
       /* reconfigure the layer1 position  without Reloading*/
       HAL_LTDC_SetWindowPosition_NoReload(&hltdc, Xpos1, Ypos1, 0);
       /* reconfigure the layer2 position  without Reloading*/
       HAL_LTDC_SetWindowPosition_NoReload(&hltdc, Xpos2, Ypos2, 1);
       /*Ask for LTDC reload within next vertical blanking*/
       ReloadFlag = 0;
       HAL_LTDC_Reload(&hltdc,LTDC_RELOAD_VERTICAL_BLANKING);
      HAL_LTDC_ProgramLineEvent(&hltdc, 2);
      while(ReloadFlag == 0)
      {
        /* wait till reload takes effect (in the next vertical blanking period) */
      }
    }
    HAL_Delay(500);
    
    for (index = 0; index < 32; index++)
    {
      /* calculate new picture position */
       PicturesPosition(&Xpos2, &Ypos2, &Xpos1, &Ypos1, (index+1));
       
       /* reconfigure the layer1 position  without Reloading*/
       HAL_LTDC_SetWindowPosition_NoReload(&hltdc, Xpos1, Ypos1, 0);
       /* reconfigure the layer2 position  without Reloading*/
       HAL_LTDC_SetWindowPosition_NoReload(&hltdc, Xpos2, Ypos2, 1);
       /*Ask for LTDC reload within next vertical blanking*/
       ReloadFlag = 0;
       HAL_LTDC_Reload(&hltdc,LTDC_RELOAD_VERTICAL_BLANKING);
       HAL_LTDC_ProgramLineEvent(&hltdc, 2);
      while(ReloadFlag == 0)
      {
        /* wait till reload takes effect (in the next vertical blanking period) */
      }
    }
    HAL_Delay(500);

  }
}
 

در این برنامه از تابع PicturesPosition برای تنظیم موقعیت تصویر استفاده شده است که بدنه آن بصورت زیر است.

static void PicturesPosition(uint32_t* x1, uint32_t* y1, uint32_t* x2, uint32_t* y2, uint32_t index)
{
  /* picture1 position */
  *x1 = index*5;
  *x2 = 240 - index*5;
}
 

از تابع HAL_LTDC_SetWindowPosition_NoReload نیز برای ست کردن موقعیت تصویر بر روی نمایشگر استفاده شده است. الگوی این تابع بصورت زیر است.

HAL_StatusTypeDef HAL_LTDC_SetWindowPosition_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx) 

آروگومان hltdc واحد LTDC موردنظر و X0 و Y0 موقعیت نقطه شروع لایه و LayerIdx شماره لایه را مشخص می­کنند.

خروجی برنامه

خروجی برنامه
خروجی برنامه
Choose your Reaction!
دیدگاه خود را بنویسید

آدرس ایمیل شما منتشر نخواهد شد.

redronic.com