در بخش قبلی واحد SPI را راهاندازی کردیم و با جزییات آن تا حدودی آشنا شدیم. در این بخش میخواهیم به کمک این واحد، یک LCD سریال (Nokia 5110) را راهاندازی کنیم. در تصویر زیر نمونه LCD موردنظر و ترتیب پایههای آن نشان داده شده است.
برای اطلاع از نحوه صحیح اتصال پایههای LCD به میکروکنترلر و تنظیم اولیه آن باید به دیتاشیت دستگاه مراجعه کنیم. طبق شکل نشان داده شده و اطلاعات موجود در دیتاشیت Nokia 5110 ، پایههای Gnd و CE باید به پایه Gnd میکرو وصل شوند. پایههای Vcc و BL نیز به 5v یا 3.3v میکرو متصل میشوند. پایههای Reset و DC به ترتیب به A3 و A4 (که باید در پروژه بهعنوان پین خروجی تعریف کنیم) و همچنین پایههای CLK و DIN به ترتیب به A5 و A7 متصل میشوند.
برای شروع کار همانند گذشته پروژه را در Cube MX ایجاد میکنیم و تنظیمات دیباگ و کلاک را انجام میدهیم. واحد SPI را نیز مانند بخش قبل تنظیم میکنیم. پایههای A3 و A4 نیز باید بهعنوان خروجی تعریف شوند. بقیه تنظیمات را مثل قبل انجام میدهیم، کد پروژه را ایجاد میکنیم و وارد محیط KEIL میشویم.
نوشتن کد پروژه
در ابتدا، تابع send_SPI که در بخش قبل نوشتیم را در این پروژه نیز تعریف میکنیم و آن را بهصورت زیر تغییر میدهیم:
1 2 3 4 5 6 7 8 9 | void send_SPI(uint8_t data) { while(!LL_SPI_IsActiveFlag_TXE(SPI1)); LL_SPI_TransmitData8(SPI1, data); if(LL_SPI_IsActiveFlag_RXNE(SPI1)) {} } |
مانند قبل، واحد SPI را فعال میکنیم (قبل از حلقه while(1)) :
1 | LL_SPI_Enable(SPI1); |
حالا باید با توجه به توضیحات دیتاشیت، LCD Nokia را راهاندازی کنیم. بدین منظور، باید ابتدا از طریق پایه A3 که به Reset LCD متصل است، یک ریست اولیه انجام دهیم، سپس از طریق پایه A4، LCD به حالت کدهای دستوری ببریم و 4 دستور مربوط به تنظیم نمایشگر را بفرستیم و در آخر دوباره LCD را به حالت داده برگردانیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 | ////configure LCD : LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_3); LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_3); LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_4); //LCD Command Mode send_SPI(0x21); //LCD extended commands send_SPI(0xb0); //Set LCD Vop (Contranst) send_SPI(0x04); //Set temp coeffifiecnt send_SPI(0x14); //LCD bias model 1:40 send_SPI(0x20); //LCD basic commands send_SPI(0x40); //set Y addr send_SPI(0x80); //set X addr send_SPI(0x0c); //Going to normal state LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4); //LCD Data Mode |
همانطور که در توضیحات دستورات نوشته شده، اولین دستور مربوط به تنظیم اولیه LCD است که مشخص میکند که در حالت توان پایین باشد یا نه، و همچنین حرکت افقی یا عمودی موقعیت نوشتن را تعیین میکند (بدینصورت که 0x20 اطلاعات را افقی و 0x22 اطلاعات را عمودی نمایش میدهد). دستور دوم نیز تعیین میکند که نمایشگر در چه حالتی نمایش دهد. دستور سوم و چهارم نیز برای تعیین موقعیت اولیهی نوشتن هستند.
اکنون میتوانیم اطلاعات دلخواهمان را روی LCD Nokia نمایش دهیم. بهعنوانمثال میخواهیم پیکسل یا خانههای صفحهنمایش را بهصورت یکی در میان سیاهوسفید کنیم، با نوشتن کد زیر در حلقه while(1)، خانهها یکی در میان خاموش و روشن میشوند و جای آنها عوض میشود.
1 2 3 4 5 6 7 8 9 10 11 12 | for(int i=0;i<6*84;i++) { send_SPI(0xFF); send_SPI(0x00); } LL_mDelay(250); for(int i=0;i<6*84;i++) { send_SPI(0x00); send_SPI(0xFF); } LL_mDelay(250); |
مقدار تعریفشده برای تکرار حلقههای for، یعنی 6 X 84 تعداد پیکسلهای LCD را مشخص میکند که 6 ردیف و 84 ستون هستند. اگر اتصالات و تنظیمات گفته شده به درستی انجام شده باشد، میبینیم که تصویر موردنظر رو نمایشگر ظاهر میشود.
نمایش یک عکس دلخواه روی LCD
بدین منظور باید عکس موردنظرمان را به ابعاد 6 در 84 (6 ردیف و 84 ستون) درآوریم. سپس آن را فرمت سیاهوسفید یا Grayscale درآوریم و به یک آرایه 8 بیتی با اندازه 6 X 84 در آوریم که هر درایه یک پیکسل را مشخص میکند. حالا میتوانیم این آرایه را در کد بهعنوان یک ثابت تعریف کنیم و در تابع اصلی، به کمک send_SPI به نمایش در آوریم:
1 2 3 4 5 6 | uint8_t image[504] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00, ... ,0x00,0xff,0xff,0xff,0x00,0xff } for(int i=0;i<84*6;i++) { send_SPI(image[i]); } |
باید توجه کرد که آرایه تولید شده و نحوه نمایش اطلاعات از نظر افقی یا عمودی بودن تطابق داشته باشند.
در بخش بعدی در مورد نحوه استفاده از فونت برای نوشتن روی LCD Nokia صحبت خواهیم کرد.
سلام و خسته نباشید
به نظر شما چرا lcd راه اندازی نمیشه ؟؟حتی کارهای زیر رو هم انجام دادم
spi رو عوض کردم از شماره 2 استفاده کردم
کابل ها کانکتورها چک شدن
lcd با اردینو تست کردم ، روشن میشه
تنها تفاوت اینه با cubeide انجام دادم.
مشکل رو بعد از کلی کلنجار رفتن پیدا کردیم. دستورات بالا ال سی دی ما ور روشن نکرد ،باید اول به درستی، طبق دیتاشیت راه اندازی بشه(یه چندتا دستور بیشتر از اون 4تا لازم هست که باید اضافه بشه) و اینکه حدودا یه زمان 60 الی 70 میلی ثانیه برای پایه ریست در لحظه راه اندازی باید در نظر گرفت.بعد از این کارها ال سی دی داده های بالا رو نشون داد.
LL_GPIO_TogglePin(GPIO_Port_1, Pin_1);
LL_mDelay(1);
چرا وقتی کد بالا را تو حلقه while مینویسم به جای اینکه هر 1 میلی ثانیه تاگل کنه هر 2 میلی ثانیه تاگل میکنه؟
سلام، چک کنید که آیا فقط همین دستورات توی حلقه while نوشته شده، و اینکه فرکانس کلاکتون رو چه عددی تنظیم شده. برای اینکه به مقدار دقیق برای زمان بندی برسید بهتره که از تایمر استفاده کنید. توی مقالههای قبلی و بخش تایمر در این مورد صحبت شده.
سلام ممنون و عالی بود
سلام دوست عزیز. خوشحالم که آموزشهارو دنبال میکنی.