آموزش اتصال نمایشگر نوکیا 5110 به برد آردوینو

قبل از دوران تلفنهای لمسی رنگی، نمایشگرهای کوچک سیاه و سفید روی گوشیهای کلاسیکی مانند نوکیا 3310 و 5110 مرسوم بودند. با ورود به دنیای ساخت و سازِ DIY، همین نمایشگرهای کوچک حدود 1.5 اینچی به خاطر اندازه کوچک، قیمت کم، مصرف توان پایین و قابلیت نمایش متن و تصاویر بیتمپ بین سازندگان محبوب شدند.
مروری بر سختافزار
کنترلر LCD PCD8544
هسته این ماژول را یک کنترلر تکتراشه CMOS با مصرف پایین از فیلیپس به نام PCD8544 تشکیل میدهد. این کنترلر از یک رابط سریال شبیه SPI برای برقراری ارتباط با میکروکنترلرها استفاده میکند و برای راهاندازی نمایشگر گرافیکی با رزولوشن 84×48 پیکسل طراحی شده است.
تأمین ولتاژ و تولید بایاس داخلی LCD در این کنترلر باعث کاهش مصرف توان میشود؛ در حالت عادی LCD حدود 6 تا 7 mA مصرف دارد.
طبق دیتا شیت، این چیپ در بازه ولتاژ عملیاتی 2.7V تا 3.3V کار میکند و سطوح سیگنال آن 3V است. بنابراین در صورت اتصال به میکروکنترلری با سطح منطقی 5V مثل آردوینو، لازم است از تبدیل سطح منطقی استفاده شود.
نور پسزمینه (Backlight)
نمایشگر دارای نور پسزمینه است که در چهار رنگ متفاوت عرضه میشود: قرمز، سبز، آبی و سفید. نور پسزمینه از چهار LED تشکیل شده که در اطراف لبهٔ نمایشگر لحیم شدهاند. برای تغییر رنگ نور پسزمینه، نمایشگر را از برد جدا کنید (گیرههای فلزی پشت برد را فشار دهید) و LEDهای اطراف لبه را جایگزین کنید.
نقشه حافظه LCD نوکیا 5110
کنترلر PCD8544 دارای 504 بایت حافظهٔ Graphic Display Data RAM (GDDRAM) است که الگوی نمایش را در خود نگه میدارد. این ناحیهٔ حافظه به 6 بانک (از 0 تا 5) تقسیم شده است؛ هر بانک شامل 84 ستون/سگمنت (از 0 تا 83) است و هر ستون میتواند 8 بیت داده (از 0 تا 7) ذخیره کند. بنابراین محتوای کلی حافظه برابر است با:
6 banks × 84 segments × 8 bits = 4032 bits = 504 bytes
هر بیت نمایانگر یک پیکسل صفحه است که میتواند به صورت برنامهای روشن یا خاموش شود.

مشخصات فنی
مشخصات مهم نمایشگر به شرح زیر است:
| تکنولوژی نمایش | Dot Matrix LCD |
| رابط با MCU | SPI |
| اندازه صفحه | 1.5 Inch Across |
| رزولوشن | 84×48 pixels |
| ولتاژ عملیاتی | 2.7V – 3.3V |
| جریان عملیاتی | 50mA max |
| زاویه دید | 180° |
پین اوت ماژول نمایشگر نوکیا 5110
پینهای ماژول به صورت زیر تعریف میشوند:

RST — پین ریست (active low). با کشیدن این پین به سطح پایین میتوان نمایشگر را ریست کرد. اتصال آن به ریست آردوینو باعث ریست خودکار نمایشگر میشود.
CE (Chip Enable) — برای انتخاب یکی از ماژولهایی که روی یک باس SPI مشترک قرار دارند استفاده میشود. این پین نیز active low است.
D/C (Data/Command) — برای تمایز میان دادهها و دستورات کنترلر (مثلاً تنظیم مکاننما، پاک کردن صفحه و غیره) کاربرد دارد.
DIN — پین داده سریال (MOSI).
CLK — پین کلاک سریال (SCLK).
VCC — تغذیهٔ ماژول؛ باید به 3.3V متصل شود.
BL — کنترل نور پسزمینه. با اتصال به یک پین PWM آردوینو یا از طریق پتانسیومتر میتوان روشنایی را تنظیم کرد.
GND — زمین مدار.
سیمکشی ماژول نوکیا 5110 به آردوینو
اتصالات نسبتاً سادهاند: پینهای کلاک (CLK)، داده (DIN)، D/C، CE و RST را به پینهای مشخص آردوینو وصل کنید. توجه داشته باشید که حداکثر ولتاژ ورودی برای LCD برابر 3.6V است، بنابراین اتصال مستقیم به آردوینو 5V مجاز نیست و باید تبدیل سطح انجام شود.
یکی از سادهترین روشهای تبدیل سطح، قرار دادن مقاومت سری در خطوط داده است. به عنوان مثال میتوانید مقاومتهای 10K در مسیر CLK، DIN، D/C و RST و یک مقاومت 1K در مسیر CE قرار دهید.
پین BL را از طریق یک مقاومت محدودکنندهٔ جریان 330Ω به 3.3V متصل کنید. اگر میخواهید روشنایی را کنترل کنید، میتوانید BL را به یک پین PWM آردوینو متصل کنید یا از یک پتانسیومتر استفاده کنید.
جدول اتصال پینها به صورت زیر است:
| Nokia 5110 LCD | Arduino | توضیحات | |
|---|---|---|---|
| VCC | 5V | – | |
| GND | GND | – | |
| RST | 3 | via 10KΩ | |
| CE | 4 | via 1KΩ | |
| D/C | 5 | via 10KΩ | |
| DIN | 6 | via 10KΩ | |
| CLK | 7 | via 10KΩ | |
| BL | 5V | via 330Ω |
نمودار سیمکشی در ادامه نشان داده شده است.

نصب کتابخانهها
درایورهای کنترلر PCD8544 منعطف اما نسبتاً پیچیدهاند و کار با آنها مستلزم دانستن جزئیات آدرسدهی حافظه است. برای سادهسازی، از کتابخانهٔ Adafruit PCD8544 Nokia 5110 LCD استفاده میکنیم که پیچیدگیهای کنترلر را مخفی میکند و کنترل نمایشگر را با چند دستور ساده ممکن میسازد. علاوه بر آن برای رسم اشکال گرافیکی باید کتابخانهٔ Adafruit GFX را نیز نصب کنید. همچنین کتابخانهٔ Adafruit BusIO بهصورت داخلی توسط کتابخانهٔ PCD8544 استفاده میشود، پس آن را نیز نصب کنید.
مراحل نصب در محیط Arduino IDE: منوی Sketch > Include Library > Manage Libraries… را باز کنید، سپس در کتابخانهها جستجو نموده و به ترتیب کتابخانههای Adafruit PCD8544، Adafruit GFX و Adafruit BusIO را نصب کنید.




مثال آردوینو 1 — نمایش متن
اسکچ زیر قابلیتهای زیر را نشان میدهد:
- نمایش متن ساده
- نمایش متن معکوس (inverted)
- نمایش اعداد
- نمایش اعداد در مبناهای مختلف (HEX, DEC)
- نمایش نمادهای ASCII
- چرخش متن
اسکچ پایه را اجرا کنید تا با نحوهٔ کار نمایشگر آشنا شوید.
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Declare LCD object for software SPI
// Adafruit_PCD8544(CLK,DIN,D/C,CE,RST);
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
int rotatetext = 1;
void setup() {
Serial.begin(9600);
//Initialize Display
display.begin();
// you can change the contrast around to adapt the display for the best viewing!
display.setContrast(57);
// Clear the buffer.
display.clearDisplay();
// Display Text
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(0,0);
display.println("Hello world!");
display.display();
delay(2000);
display.clearDisplay();
// Display Inverted Text
display.setTextColor(WHITE, BLACK); // 'inverted' text
display.setCursor(0,0);
display.println("Hello world!");
display.display();
delay(2000);
display.clearDisplay();
// Scaling Font Size
display.setTextColor(BLACK);
display.setCursor(0,0);
display.setTextSize(2);
display.println("Hello!");
display.display();
delay(2000);
display.clearDisplay();
// Display Numbers
display.setTextSize(1);
display.setCursor(0,0);
display.println(123456789);
display.display();
delay(2000);
display.clearDisplay();
// Specifying Base For Numbers
display.setCursor(0,0);
display.print("0x"); display.print(0xFF, HEX);
display.print("(HEX) = ");
display.print(0xFF, DEC);
display.println("(DEC)");
display.display();
delay(2000);
display.clearDisplay();
// Display ASCII Characters
display.setCursor(0,0);
display.setTextSize(2);
display.write(3);
display.display();
delay(2000);
display.clearDisplay();
// Text Rotation
while(1)
{
display.clearDisplay();
display.setRotation(rotatetext); // rotate 90 degrees counter clockwise, can also use values of 2 and 3 to go further.
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(0,0);
display.println("Text Rotation");
display.display();
delay(1000);
display.clearDisplay();
rotatetext++;
}
}
void loop() {
}
خروجی نمونهٔ این اسکچ به صورت زیر است.

توضیح کد
اسکچ با وارد کردن سه کتابخانه آغاز میشود: SPI.h، Adafruit_GFX.h و Adafruit_PCD8544.h. سپس یک شیء از کلاس Adafruit_PCD8544 ساخته میشود که پنج شمارهٔ پین آردوینو را به عنوان آرگومان میگیرد و به پینهای CLK، DIN، D/C، CE و RST نمایشگر متصل میکند. متغیر rotatetext برای دوران محتویات نمایشگر استفاده میشود.
#include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_PCD8544.h>
در تابع setup ابتدا نمایشگر با متد begin() مقداردهی اولیه میشود. سپس با setContrast(value) میتوان کنتراست را تنظیم کرد که مقدار 0 تا 100 میپذیرد؛ معمولاً مقادیر بین 50 تا 60 نتایج خوبی میدهند. بعد با clearDisplay() بافر صفحه پاک میشود.
//Initialize Display display.begin(); // you can change the contrast around to adapt the display for the best viewing! display.setContrast(57); // Clear the buffer. display.clearDisplay();
نمایش متن ساده (Hello World)

// Display Text
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(0,0);
display.println("Hello world!");
display.display();
delay(2000);
display.clearDisplay(); برای نمایش متن ابتدا اندازه فونت با setTextSize() مشخص میشود (اعداد غیرمنفی، از 1 به بالا). سپس رنگ فونت با setTextColor() تعیین میشود؛ مقدار BLACK برای متن تیره و WHITE برای متن روشن استفاده میشود.
قبل از چاپ متن باید مکاننما با setCursor(X,Y) تنظیم شود؛ مبدا (0,0) در گوشهٔ بالا-چپ صفحه است، محور X به سمت راست و محور Y به سمت پایین بزرگتر میشوند.
برای چاپ متن میتوان از print() یا println() استفاده کرد؛ println() پس از چاپ مکاننما را به خط بعد میبرد. در نهایت با display() محتویات بافر به حافظهٔ داخلی کنترلر منتقل و روی LCD نمایش داده میشود.
نمایش متن معکوس (Inverted)

// Display Inverted Text
display.setTextColor(WHITE, BLACK);
display.setCursor(0,0);
display.println("Hello world!");
display.display();
delay(2000);
display.clearDisplay(); برای نمایش متن معکوس از فرم دو آرگومانی setTextColor(FontColor, BackgroundColor) استفاده میکنیم. این کار با استفادهٔ جیانگذاری تابع (function overloading) ممکن شده است؛ به طور نمونه setTextColor(BLACK, WHITE) متن سیاه روی پسزمینهٔ سفید را تولید میکند.
مقیاسبندی اندازه فونت

// Scaling Font Size
display.setTextColor(BLACK);
display.setCursor(0,0);
display.setTextSize(2);
display.println("Hello!");
display.display();
delay(2000);
display.clearDisplay(); فرمتی که فونت را میسازد مبتنی بر نسبت 5×7 است: مقدار 1 متن را در اندازهٔ 5×7 پیکسل برای هر کاراکتر رسم میکند، مقدار 2 تبدیل به 10×14 پیکسل و به همین ترتیب ادامه مییابد.
نمایش اعداد

// Display Numbers display.setTextSize(1); display.setCursor(0,0); display.println(123456789); display.display(); delay(2000); display.clearDisplay();
متدهای print() و println() پیادهسازیهایی دارند که 32-bit unsigned int را میپذیرند؛ در نتیجه بازهٔ نمایش اعداد صحیح از 0 تا 4,294,967,295 است.
مشخص کردن مبنای نمایش اعداد

// Specifying Base For Numbers
display.setCursor(0,0);
display.print("0x"); display.print(0xFF, HEX);
display.print("(HEX) = ");
display.print(0xFF, DEC);
display.println("(DEC)");
display.display();
delay(2000);
display.clearDisplay(); هر دو تابع print() و println() پارامتر اختیاری دومی دارند که مبنای نمایش را مشخص میکند: BIN، OCT، DEC و HEX. برای اعداد ممیز شناور، این پارامتر تعداد اعشار را مشخص میکند. چند مثال:
- print(78, BIN) → “1001110”
- print(78, OCT) → “116”
- print(78, DEC) → “78”
- print(78, HEX) → “4E”
- println(1.23456, 0) → “1”
- println(1.23456, 2) → “1.23”
- println(1.23456, 4) → “1.2346”
نمایش نمادهای ASCII

// Display ASCII Characters display.setCursor(0,0); display.setTextSize(2); display.write(3); display.display(); delay(2000); display.clearDisplay();
تفاوت بین print()/println() و write() این است که اولی متن خوانا برای انسان (ASCII) میفرستند، در حالی که write() دادهٔ باینری میفرستد. با write(3) میتوان مثلاً یک نماد قلب را روی نمایشگر رسم کرد.
چرخش متن

// Text Rotation
while(1)
{
display.clearDisplay();
display.setRotation(rotatetext);
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(0,0);
display.println("Text Rotation");
display.display();
delay(1000);
display.clearDisplay();
rotatetext++;
} با setRotation() میتوان محتوای نمایشگر را چرخاند. پارامتر این تابع یک عدد غیرمنفی است که چهار جهت چرخش را مشخص میکند؛ افزایش عدد باعث چرخش 90 درجهای محتوا در جهت پادساعتگرد میشود:
- 0 — جهت پیشفرض (landscape)
- 1 — چرخش 90 درجه به راست
- 2 — وارونه (upside down)
- 3 — چرخش 90 درجه به چپ
مثال آردوینو 2 — رسم اشکال پایه
در این اسکچ نحوهٔ رسم شکلهایی مثل مستطیل، دایره و مثلث نمایش داده شده است. بیشتر تنظیمات اولیه مشابه مثال قبلی است. در ادامه اسکچ کامل آورده شده و سپس بخشهای مربوط به رسم اشکال تشریح میشوند.
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Declare LCD object for software SPI
// Adafruit_PCD8544(CLK,DIN,D/C,CE,RST);
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
void setup() {
Serial.begin(9600);
//Initialize Display
display.begin();
// you can change the contrast around to adapt the display for the best viewing!
display.setContrast(57);
// Clear the buffer.
display.clearDisplay();
// Draw Rectangle
display.drawRect(0, 0, 60, 40, BLACK);
display.display();
delay(2000);
display.clearDisplay();
//Draw Filled Rectangle
display.fillRect(0, 0, 60, 40, BLACK);
display.display();
delay(2000);
display.clearDisplay();
//Draw Round Rectangle
display.drawRoundRect(0, 0, 60, 40, 8, BLACK);
display.display();
delay(2000);
display.clearDisplay();
//Draw Filled Round Rectangle
display.fillRoundRect(0, 0, 60, 40, 8, BLACK);
display.display();
delay(2000);
display.clearDisplay();
//Draw Circle
display.drawCircle(20, 20, 20, BLACK);
display.display();
delay(2000);
display.clearDisplay();
//Draw Filled Circle
display.fillCircle(20, 20, 20, BLACK);
display.display();
delay(2000);
display.clearDisplay();
//Draw Triangle
display.drawTriangle(20, 0, 0, 40, 40, 40, BLACK);
display.display();
delay(2000);
display.clearDisplay();
//Draw Filled Triangle
display.fillTriangle(20, 0, 0, 40, 40, 40, BLACK);
display.display();
delay(2000);
display.clearDisplay();
}
void loop() {
}
خروجی نمونهٔ این اسکچ را مشاهده کنید.

رسم مستطیل


// Draw Rectangle display.drawRect(0, 0, 60, 40, BLACK); display.display(); delay(2000); display.clearDisplay(); //Draw Filled Rectangledisplay.fillRect(0, 0, 60, 40, BLACK); display.display(); delay(2000); display.clearDisplay();
تابع drawRect(x, y, w, h, color) یک مستطیل توخالی با ضخامت 1 پیکسل رسم میکند که پارامترها به ترتیب X و Y مبدا، عرض، ارتفاع و رنگ هستند. برای رسم مستطیل پرشده از fillRect() استفاده کنید.
رسم مستطیل با گوشههای گرد


//Draw Round Rectangle display.drawRoundRect(0, 0, 60, 40, 8, BLACK); display.display(); delay(2000); display.clearDisplay(); //Draw Filled Round Rectangledisplay.fillRoundRect(0, 0, 60, 40, 8, BLACK); display.display(); delay(2000); display.clearDisplay();
تابع drawRoundRect() همان پارامترهای drawRect() را میگیرد بهعلاوهٔ یک پارامتر اضافی برای شعاع گرد شدن گوشهها. تابع متناظر fillRoundRect() برای رسم پرشده استفاده میشود.
رسم دایره


//Draw Circle display.drawCircle(20, 20, 20, BLACK); display.display(); delay(2000); display.clearDisplay(); //Draw Filled Circledisplay.fillCircle(20, 20, 20, BLACK); display.display(); delay(2000); display.clearDisplay();
برای رسم دایره از drawCircle(x0, y0, r, color) استفاده کنید؛ این تابع یک دایرهٔ توخالی با ضخامت 1 پیکسل رسم میکند. fillCircle() نمونهٔ پرشدهٔ آن است.
رسم مثلث


//Draw Triangle display.drawTriangle(20, 0, 0, 40, 40, 40, BLACK); display.display(); delay(2000); display.clearDisplay(); //Draw Filled Triangledisplay.fillTriangle(20, 0, 0, 40, 40, 40, BLACK); display.display(); delay(2000); display.clearDisplay();
تابع drawTriangle(x0, y0, x1, y1, x2, y2, color) سه مختصات رأسها را میگیرد: رأس بالا (x0,y0)، رأس چپ (x1,y1) و رأس راست (x2,y2). تابع مرجع fillTriangle() برای رسم مثلث پرشده به کار میرود.
مثال آردوینو 3 — نمایش بیتمپ
نمایش تصاویر بیتمپ برای لوگوها، آیکونها یا اسپرایتها مفید است. در این مثال یک تصویر مونوروم 84×48 (آرایهٔ بایت) در حافظهٔ برنامه ذخیره و با drawBitmap() نمایش داده میشود.
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
// Declare LCD object for software SPI
// Adafruit_PCD8544(CLK,DIN,D/C,CE,RST);
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
// 'Marilyn Monroe 84x48', 84x48px
const unsigned char MarilynMonroe [] PROGMEM = {
0x00, 0x00, 0x00, 0x7f, 0x00, 0x02, 0xfe, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x00,
0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1f, 0xe1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
0x00, 0x00, 0x0f, 0xf1, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xd8, 0xe0,
/* ... ادامهٔ آرایه تا تکمیل 84x48 بایت ... */
};
void setup() {
Serial.begin(9600);
//Initialize Display
display.begin();
// you can change the contrast around to adapt the display for the best viewing!
display.setContrast(57);
// Clear the buffer.
display.clearDisplay();
// Display bitmap
display.drawBitmap(0, 0, MarilynMonroe, 84, 48, BLACK);
display.display();
// Invert Display
//display.invertDisplay(1);
}
void loop() {
}
تابع drawBitmap(x, y, bitmapArray, w, h, color) برای نمایش آرایهٔ بیتمپ استفاده میشود. آرگومانها به ترتیب X و Y گوشهٔ بالا-چپ، آرایه بایت مونوروم، عرض و ارتفاع تصویر به پیکسل و رنگ هستند. برای تصویر 84×48، X و Y معمولاً صفر تنظیم میشوند.

تهیهٔ تصویر 84×48 و تبدیل به آرایه
رزولوشن نمایشگر 84×48 است؛ پس تصاویر بزرگتر به درستی نمایش داده نمیشوند. برای تهیهٔ تصویر مناسب ابتدا بوم (canvas) را در برنامهٔ گرافیکی دلخواه (مثلاً MS Paint، Photoshop یا Inkscape) روی 84×48 پیکسل تنظیم کنید و تصویر را ذخیره کنید.


برای تبدیل تصویر به آرایهٔ بایت که PCD8544 بفهمد، دو راه وجود دارد: ابزار آنلاین image2cpp یا نرمافزار آفلاین LCD Assistant.
تبدیل آنلاین با image2cpp
ابزار image2cpp قابلیتهایی مثل تبدیل همزمان چند تصویر، مقیاسبندی (Stretch/Scale to fit/Original)، تنظیم آستانهٔ روشنایی برای تبدیل به سیاه/سفید، ترازبندی مجدد و معکوس کردن رنگها را دارد. آستانهٔ روشنایی تعیین میکند پیکسلهایی که بالاتر از مقدار آستانهاند سفید و پائینتر سیاه شوند. در مثال از مقدار 171 برای آستانه استفاده شده تا جزئیات مناسبی حاصل شود.



پس از تنظیم، فرمت خروجی را روی Arduino Code قرار داده و دکمهٔ Generate code را بزنید تا آرایهٔ بایت به صورت آمادهٔ درج در کد تولید شود. اگر تصویر روی نمایشگر اعوجاج داشت، تغییر حالت Draw Mode معمولاً مشکل را برطرف میکند.


تبدیل آفلاین با LCD Assistant
نرمافزار ویندوزی LCD Assistant هم فایل بیتمپ را به آرایه تبدیل میکند. ابتدا تصویر را به صورت 1-bit مونوروم 84×48 ذخیره کنید (در MS Paint گزینهٔ Monochrome Bitmap). این روش معایبی دارد؛ مثلاً آستانهٔ روشنایی ثابت و برابر 50% است و قابل تنظیم نیست.


بعد از باز کردن فایل در LCD Assistant، از منوی File گزینهٔ Save output را انتخاب کرده و خروجی را به صورت یک فایل متنی ذخیره کنید. توجه داشته باشید گزینهٔ Byte Orientation در تولید آرایه تأثیر دارد؛ در صورت اعوجاج، حالتهای مختلف این تنظیم را امتحان کنید.


پس از ایجاد آرایه، آن را در کد خود کپی کنید، نام مناسبی به آرایه بدهید و در drawBitmap() از آن استفاده کنید.











