דילר בינגו על מיקרו-בקר
Microcontroller Bingo Dealer — קוד C משובץ על בקר KEIL MCBSTR9
בפרויקט זה כתבנו קטע קוד בשפת C המדמה דילר במשחק בינגו. תחילה תופיע הודעת פתיחה עם שם המשחק והוראות להמשך. השחקנים מתבקשים להפעיל את המשחק על ידי לחיצה על הכפתור הראשון, וכעת יתחילו להיות מוצגים על המסך בזה אחר זה קלפים שונים המדמים "שליפה" מתוך חפיסת קלפים רגילה.
01 רקע לבחירה
הרעיון נולד ממשחק בינגו משפחתי: בכל סבב, מי שתורו להיות הדילר "הפסיד" את ההשתתפות במשחק — במקום להתרכז בשליפה המהירה של הקלף שהוכרז, הוא היה עסוק בהכרזה על הקלפים ובסידורם. כדי שיהיה לכולם נוח, קל וכיף יותר לשחק, החלטתי לבנות דילר אוטומטי שיבצע את העבודה הזו.
בחרנו בפרויקט זה מכיוון שהוא משלב אתגר של כתיבת קוד ותכנון לוגיקה לשימוש בכפתורים ובפוטנציומטר לבקרת מהירות ריצת נוריות LED — תוך שימוש בבקר KEIL ו-LCD לצורך אינטראקציה עם המשתמש.
02 מהלך המשחק
את מהירות ה"שליפה" ניתן לשנות על ידי הזזת הפוטנציומטר. את המשחק ניתן להשהות ולהפעיל בשנית על ידי לחיצה על כפתור ההפעלה (הראשון).
הכפתור השני מסמן ניצחון — ברגע שנלחץ תופיע הודעה מתאימה ומיד בזה אחר זה יוצגו הקלפים "שנשלפו" עד כה על מנת לוודא ניצחון. בסיום ריצת הקלפים תופיע הודעה על המסך, ולתחילת משחק חדש ניתן ללחוץ על הכפתור השלישי. בכל זמן המשחק ישנו חיווי ויזואלי בצורת נורות ה-LED שרצות או מהבהבות בהתאם לשלבים במשחק.
03 רקע תיאורטי
בקרים (Microcontrollers) הם יחידות חישוביות זעירות הכוללות מעבד, זיכרון ואמצעי קלט/פלט, ומשמשים במגוון רחב של יישומים. הבקר איתו עבדנו הוא בקר של חברת KEIL מסוג MCBSTR9, המהווה אחד מהבקרים הנפוצים המשמשים ללמידה ולפיתוח בפרויקטים קטנים. באמצעות שימוש בכפתורים ובפוטנציומטר באמצעות קריאה אנלוגית, ניתן לשלוט במשתנים בתוכנית בזמן אמת, כמו מהירות ריצת הנוריות ומשך זמן ההשהיה בפרויקט זה.
בנוסף לכך, השימוש ב-ADC (Analog-to-Digital Converter) מאפשר לבקר לקרוא ערכים אנלוגיים מהפוטנציומטר ולהמיר אותם לערכים דיגיטליים שהבקר יכול לעבד. זה מאפשר לנו לקבל ערך מתמשך מהפוטנציומטר ולהשתמש בו לשליטה על פונקציות שונות בקוד לבחירתנו.
ה-LCD (Liquid Crystal Display) משמש להצגת מידע למשתמש בזמן אמת. בפרויקט זה ה-LCD משמש להצגת הודעות פתיחה, קלפים ומצב המשחק. הנוריות (LEDs) משמשות לצורך מתן פידבק ויזואלי למשתמש — הן מופעלות הן בצורת הבהוב והן בצורת ריצוד בחלקים מסוימים של הקוד, כאשר מהירות הריצה שלהן משתנה בהתאם לערך הפוטנציומטר.
04 תרשים זרימה
להלן תרשים הזרימה של התוכנית — מאתחול המערכת, דרך קריאת הפוטנציומטר וערבוב החפיסה, ועד הלולאה הראשית המטפלת בהצגת הקלפים, בהשהיה ובמצב הניצחון.
תרשים זרימה מילולי
- Start
- Initialize System
- Read Potentiometer Value
- Set LED Run Speed based on Potentiometer Value
- Display Opening Messages on LCD
- Wait for Start Button Press
- Main Loop — Read Potentiometer Value and Update Speed → Change LED State → Display Cards on LCD → Check Button Press for Pause or Win
- If Pause Button Pressed, Update State to Paused
- If Win Button Pressed, Enter Win State → Display Win Message → End Game
- Else, Continue Main Loop
05 הקוד
התוכנית נכתבה בשפת C עבור בקר ה-MCBSTR9. קריאת הפוטנציומטר מתבצעת דרך ה-ADC בפונקציית measure(), המחזירה ערך 10-ביט (0x03FF) המשמש לקביעת זמני ההשהיה; הנוריות מהבהבות דרך blink_leds().
float measure(void) {
ADC->CR &= 0xFF7F;
ADC->CR = 0x0002;
ADC->CR |= 0x0001;
delay_ms(100);
while ((ADC->CR & 0x8000) == 0);
return (ADC->DR0 & 0x03FF);
}
void blink_leds(int times, unsigned int delay) {
int i;
for (i = 0; i < times; i++) {
LED = 0xFF;
delay_ms(delay);
LED = 0x00;
delay_ms(delay);
}
} חפיסת 52 הקלפים מיוצגת כמערך אינדקסים ומעורבבת באלגוריתם Fisher–Yates; הצבע והערך של כל קלף נגזרים מהאינדקס (cardIndex % 13 לערך, cardIndex / 13 לצבע).
void shuffle(int *deck, int size) {
int i, j, temp;
for (i = size - 1; i > 0; i--) {
j = rand() % (i + 1);
temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
} בלולאה הראשית הנוריות "רצות" הלוך ושוב באמצעות הזזת ביט (n << 1 / n >> 1) עם היפוך כיוון בקצוות (0x80, 0x01), ובכל מחזור נשלף הקלף הבא מהחפיסה ומוצג ב-LCD. הלולאה ממשיכה ומטפלת בכפתורי ההשהיה (SW1) והניצחון (SW2).
while (running) {
vmax = measure();
LED = n;
delay_ms((unsigned int)vmax);
if (direction == 1) {
n = n << 1;
if (n == 0x80) {
direction = -1;
}
} else {
n = n >> 1;
if (n == 0x01) {
direction = 1;
}
}
set_cursor(0, 1);
if (!paused) {
cardIndex = deck[displayedIndex];
displayedCards[displayedIndex++] = cardIndex;
if (displayedIndex >= 52) {
displayedIndex = 0;
}
sprintf(buffer, "%s of %s", values[cardIndex % 13], suits[cardIndex / 13]);
lcd_print((const unsigned char*)buffer);
delay_ms(1500);
lcd_clear();
}
} 06 המשך הפיתוח
כרגע ההכרזות מוצגות על צג LCD קטן בלבד. השלב הבא בתכנון הוא הוספת רמקול עם צ'יפ MP3 וטעינת קבצי קול שיכריזו בקול על הקלפים ועל הניצחון — כך שהמשחק יהיה נגיש וקל יותר לשימוש גם למבוגרים.