יום שבת, 13 בספטמבר 2014

מיקרו בקר הנדסאי אלקטרוניקה ומחשבים כל מה שצריך לדעתד

מיקרו בקר הנדסאי אלקטרוניקה ומחשבים כל מה שצריך לדעת תיכנות פקודות C אסמבלי

מבנה מחשב ספרתי



תפקיד יחידת הקלט הוא לתרגם את השפה שמחוץ למחשב (למשל לחיצה על מספק, עכבר וכו') לשפת המחשב, שהיא שפת אפסים ואחדים.

תפקיד יחידת הפלט הוא לתרגם את שפת המחשב (אפסים ואחדים)לשפה שמחוץ למחשב (תווים על המסך, תמונות, צלילים ועוד) 

יחידת הבקרה מבקרת, שולטת על כל התהליכים שקורים במחשב.

ביחידה האריתמטית לוגית מתבצעות כל הפעולות החשבוניות והלוגיות שמתבצעות במחשב. פעולות חשבוניות הכוונה: חיבור, חיסור, חילוק ושארית ובפעולות לוגיות הכוונה לפעולות: OR, AND, NOT XOR.

זיכרון - הזיכרון הוא יחידת האחסון של המחשב, בזיכרון נכנסים נתונים לפני שהתכנית תרוץ, בזיכרון נשמור נתונים ותוצאות שעבדו במהלך ריצת התכנית ובזיכרון נמצאת התכנית שהמחשב מבצע.




מיקרו בקר



זיכרון התכנית נקרא זיכרון ROM, כלומר זיכרון לקריאה בלבד. בתוך הזיכרון הזה נמצאת התכנית שהבקר מבצע.
זיכרון זה הוא בלתי נדיף, כלומר כאשר מכבים את החשמל התוכן שלו לא יעלם. 
זיכרון RAM הוא זיכרון שניתן גם לכתוב אליו וגם לקרוא ממנו. הוא בדרך כלל שומר נתונים שנכסים לפי איך שהתכנית רצה ותוצאות של שעובדו במהלך ריצת התכנית, הוא גם נקרא זיכרון גישה אקראית.
פסיקה היא הפסקה, הפרעה במהלך ריצת תכנית, מעבר לתכנית שמטפלת במבקש הפסיקה ובסיום תכנית הטיפול חוזרים אל התכנית הקודמת.



תקשורת טורית

ישנם שני סוגי תקשורת:
1. תקשורת מקבילית
2. תקשורת טורית

אנחנו משתמשים בתקשורת כדי לחבר בין שתי נקודות / מערכות.
בתקשורת מקבילית מחברים בין שתי המערכות 8 חוטים ועוד חוט אחד של אדמה (שהוא קו משותף לכל החוטים) בכמה אחת מעבירים בעזרת שמונה חוטים נתון בן 8 ביטים / סיביות.

בתקשורת טורית מחברים בין שתי נקודות / מערכות שני חוטים.
אחד להעביר נתונים ואחד אדמה. כדי להעביר בייט של 8 ביטים, מפרקים את הבייט לסיביות שלו ומשדרים ביט אחרי ביט.

היתרון של התקשורת המקבילית הוא מהירות רבה יותר מזו של הטורית.
החיסרון של התקשורת המקבילית הוא שהוא בעל הרבה יותר חוטים זאת אומרת עולה יותר כסף.

(כמו כן משתמשים בתקשורת טורית באינטרנט)


בתוך המיקרו בקר יש מערכת שיודעת ליצור תקשורת טורית, לכומר יודעת לפרק בייט לביטים ולשדר ביט אחר ביט או לקלוט סדרה של ביטים ולחבר אותם לבייט.


טיימרים / קאונטרים / מונים = בתוך המיקרו בקר יש מעגלי אלקטרוניקה שיודעים לספור.
אם הטיימר סופר פולסים שהמרחק ביניהם ידוע אז אומרים שהוא סופר זמן, טיימר - זמנן (מערכת שסופרת זמן - זמנן)
כאשר קאונטר סופר אירועים מחוץ למיקרו בקר, אומרים שהוא עובד קאונטר.

פורטיo לקלט ופלט:
פורט הוא מעגל אלקטרוני שדרכו מכניסים או מוציאים נתונים מהמחשב.



השוואה בין מיקרו מעבד לבקר

ההבדל העיקרי בין מיקרו מעבד למיקרו בקר הוא ביישום.
במקום שצריך עיבוד מתמטי חזק, גריפה, זיכרון בנפח גדול ומהירות עיבוד גבוהה נשתמש במיקרו מעבד.

במקומות שאינם צריכים עיבוד מתמטי חזק, גרפיקה, זיכרון גדול, או עיבוד מהיר של נתונים, משתמשים במיקרו בקרים.


(מיקרו מעבד בנוי מיחידת בקרה ומיחידה אריתמטית לוגית)

לדוגמה: מחשב אישי צריך הרבה זיכרון, מהירות עיבוד גבוהה, גרפיקה ולכן נשתמש במעבד (מיקרו מעבד).

במערכת אזעקה שבה זיכרון התכנית הוא קילו בטים - אין גרפיקה ומהירות העיבוד איננה איננה קריטית לכן נשתמש בבקרים (מיקרו בקר).

בגלל ההבדל ביישום המעבדים הם בדרך כלל גדולים יותר מהבקרים. יש להם כמות הדקים גדולה בהרבה מהבקרים ומחירם של המעבדים יקר יותר.

מהירות של מעבד היא בג'יגות הרצים, ומהירות של בקרים היא עשרות מגה הרץ.

הרכיבים ממשפחת ה-51


תקשורת טורית
כמות פסיקות
כמות טיימרים / קאונטרים
נפח זיכרון נתונים בבתים
נפח זיכרון בקילו בתים
שם הרכיב
יש
5
2
128
--
8031
יש
6
3
256
--
8032
יש
5
2
128
4k ROM
8051
יש
6
3
256
8k ROM
8052
יש
5
2
128
4k EPROM
8751
יש
6
3
256
8k EPROM
8752
יש+צריבה מקבילית
5
2
128
4k flash
AT89C51
יש+צריבה מקבילית
6
3
216
8k flash
AT89C52
יש+צריבה טוריתISP+
5
2
128
4k flash
AT89S51
יש+SPI
6
3+מערך מונים
256
8k flash
AT89S52
יש+SPI
6
3+מערך מונים
256
12k flash
AT89S53


ISP = In system, programming – צריבה / תיכנות בתוך המערכת

SPI= Serial peripheral interface – ממשק היקפי טורי 





סיבית היא יחידת המידע הקטנה ביותר של המחשב יכול להיות שם או '0' או '1'.
בייט - יחידת מידע שמכילה 8 סיביות
מילה - מכילה 16 סיביות
מילה כפולה - מכילה 32 סיביות


סוגי זיכרונות

1. ROM - READ ONLY MEMORY - זיכרון שאי אפשר לכתוב לתוכו, אלא רק לקרוא ממנו.

(בית חרושת מייצר את הזיכרון עם תוכן מוכן שאי אפשר לשנותו).

2. PROM - programable read only memory  - זיכרון קריאה בלבד שניתן לתכנתו רק פעם אחת בלבד. (זיכרון שאתה קונה מבית החרושת ריק, אתה יכול לצרוב לתוכו / לתכנת / לשנות אות רק פעם אחת בלבד).

3. EPROM - Erasable read only memory - זיכרון לקריאה בלבד שניתן למחיקה ולצריבה מחדש. בעזרת קרינה אולטרה סגולה ניתן למחוק את כל הזיכרון הזה. זה לוקח בערך כעשרים דקות.

4. EEPROM - ניתן למחיקה בצורה אלקטרונית ולצריבה מחדש.

5. FLASH - ניתן למחיקה נקודתית באיזו צורה שרוצים, זיכרון לקריאה בלבד שניתן למחיקה בחלקים.


RAM - Random access memory
גישה אקראי לזיכרון - לפנות לכל תא בזיכרון וניתן למחוק, לשנות, לכתוב, מאבד את כל הנתונים עם איבוד המתח. נמחק בצורה מהירה.



תכנית והרצת תכנית

תכנית היא אוסף של פקודות שהתפקיד שלהם הוא לבצע מטלה כלשהי. (התכנית יושבת בזיכרון ROM)


מבנה יחידת הבקרה

1. program counter - מונה תכניות
2. IR = Instruction register - אוגר הוראה (=פקודה)
3. DRCODER  - מפענח פקודה


הרצת התכנית
בתוך זיכרון התכנית נמצאות פקודות אחת אחרי השנייה.
הרצת התכנית מתבצעת בשלושה שלבים:
א. הבאת הפקודה:
יחידת הבקרה צריכה להביא את הפקודה שנמצאת בזיכרון התכנית ולשמור אותה אצלה בריגיסטר IR.
יחידת הבקרה יודעת מאיזו כתובת להביא את הפקודה על ידי כך שהיא נעזרת ב IR וה- program counter אומר מאיזו כתובת מביאים את הפקודה.
שלב הבאת הפקודה נקרא Fetch ובסיומה הפקודה נמצאת באוגר (=רגיסטר) IR ומונה התכנית מקדם את עצמו באחד כדי להצביע על הפקודה הבאה.
ב. הפקודה שהבאנו היא אוסף של אפסים ואחדים.
יש לפענח את הפקודה כדי להבין מה היא אומרת. את זו עושים בעזרת יחידה שנקראת מפענח הפקודות (DECODER) והיא בדרך כלל אחת היחידות היותר מורכבות במיקרו בקר.
ג. אחרי שיחידת הבקרה מבינה מה אומרת הפקודה היא מבצעת את הפקודה.

לדוגמה
אם הפקודה היא לחבר בין שני מספרים אז יחידת הבקרה מוציאה שרשרת של אותות חשמליים שאומרת ליחידה האריתמטית לוגית לחבר בין שני מספרים שנשלחים אליה, אם הפקודה היית להוציא נתון לפלט כלשהו אז יחידת הבקרה יוצרת שרשרת אותות חשמליים שמוציאה את הנתון הרצון ליחידת הפלט. 

בסיום ביצוע הפקודה חוזרים לסעיף א' שבו מביאים את הפקודה בהאה.

לסיכום הרצה של תכנית היא בעצם אוסף של הסעיפים א', ב' וג' שתיארנו לעיל.





זיכרון הנתונים (RAM)






ארבעת הבנקים



באזור זיכרון הנתונים הפנימי בין הכתובות 0 עד 31 נמצאים ארבעת הבנקים.
בכל בנק יש 8 רגיסטרים מ R0 עד R7.
נניח שעובדים עם תכנית א' ומשתמשים ברגיסטרים R0 עד R7 בבנק 0.
כאשר נעבור לתכנית ב' ונשתמש ברגיסטרים R0 עד R7 בבנק 0 אז התוכן הקודם שלהם יידרס (יימחק), אבל אם ניתן פקודה ונעבור לבנק אחר נוכל להשתמש שוב בריגסטרים R0 עד R7 מבלי שהרגיסטרים R0 עד R7 של הבנק הקודם יידרסו.


16 הבתים המחולקים לסיביות (בית אחד: יחידת זיכרון הבנויה משמונה סיביות
בזיכרון הנתונים הפנימי בין הכתובות 32 עד 47 נמצאים שישה עשר שתים המחולקים לסיביות.
המשתמש יכול לפנות לבית שלמה או לאחד הסיביות באופן פרטי.
הוא יכול להעביר או אפס או אחד ובשלב מאוחר יותר הוא יכול לבדוק מה יש בסיבית. אם יש בסיבית אפס אז הוא יבצע תכנית א', יש יש בסיבית אחד הוא יכל לבצע תכנית אחרת.

הפקודות שעובדים עם סיביות נותנות למתכנת כוח רב.



חיבור זיכרונות חיצוניים למיקרו בקר









͞R͞D͞ - READ קריאה
W͞R͞ - Write כתיבה
P͞S͞E͞N͞ - Program store enable אפשור אחסון תכנית
A - Adress כתובת
D - Data נתון

הזכרונות המתחברים במחשב כמו גם התקני הקלט והפלט מתחברים אל המעבד בעזרת 3 פסים הנקראים:
א. פס כתובות
ב. פס נתונים
ג. פס בקרה

במיקרו בקר ממשפחת ה-51 יש פס כתובות שנקרא ADDRESS BUS.

שיש בו 16 הדקים מ A0 עד A15., סה"כ 16 רגליים. בעזרת הדקים אלה אנחנו יכולים לפנות ל: 65,536 כתובות (שתיים בחזקת שש עשרה).

לכל מחשב ולמיקרו בקר יש פס נתונים (Data Bus).
במיקו בקר ממשפחת ה-51 יש פס נתונים של 8 בתים.
DO...D7
פס הבקרה Control bus הוא פס שעליו יש אותות בקרה.
פס מוגדר קבוצה של קווים המחברים בין היחידות השונות של המחשב ויש להם תפקיד משותף.

ניתן לחבר למיקרו בקר זיכרון נתונים RAM חיצוני בנפח של עד 64K בתים כתובות, בכל כתובת 8 סיביות.
כמות זיכרון התכנית שניתן לחבר למיקרו בקר היא גם 64K בתים,אבל סכום זיכרון התכנית הפנימי ביחד עם זיכרון התכנית החצוני יהיה עד 64K בתים.


כדי לפנות לכל זיכרון (זיכרון תכנית או זיכרון נתונים פנימי או חיצוני) נתנו בתכנה פקודות שונות הפונות לכל זיכרון.
הפקודה MOV פונה לזיכרון הנתונים הפנימי.
הפקודה MOVX פונה אל זיכרון הנתונים החיצוני. 
הפקודה MOVC פונה לזיכרון התכנית (הפנימי והחיצוני).



ארבעה פורטים
בתוך המיקרו בקר יש ארבעה פורטים, מ P0 עד P3.
בכל פורט יש 8 הדקים מאפס עד שבע.
סה"כ 32 הדקים.
פורט הוא מעגל אלקטרוני שדרכו מכניסים או מציגים נתונים מהמעבד (מהמיקרו בקר).

ההדקים של P0 משמשים כחלק הנמוך של הכתובות A0-A7, וגם כהדקי נתונים D0-D6.
P0 נקרא הפורט המרובב והוא יוסבר בהמשך.

P2 משמש כחלק הגובה של פס הכתובות A8-A15.

חלק מההדקים של P3 שהם P3.6 ו p3.7 משמשים כהדקי הקריאה והכתיבה שפונים לזיכרון הנתונים החיצוני.

P1 הוא פורט שמאפשר לנו קלט ופלט כאשר מחברים זיכרונות חיצוניים.

בדרך כלל, ברוב הפרוייקטים אין צורך לחבר זכרונות חיצוניים ואז מקבלים 4 פורטים לקלט ופלט.



הפס המרובב
אמרו ש P0 משמש גם כחלק הנמוך של פס הכתובות וגם כפס הנתונים.
במבט ראשון זה נראה לא הגיוני שעל אותם קווים יהיו גם כתובות וגם נתונים.
באופן מעשי מחלקים כל מחזור של קריאה או כתיבה מהזיכרון החיצוני לשני חלקים:

בחלק הראשון של כל מחזור ההדקים של P0 משמשים כחלק הנמוך של פס הכתובות, ובחלק השני של המחזור, ההדקים משמשים בפס הנתונים.
בצורה כזו חוסכים בהדקים.

כדי לדעת מתי בפס המרובב יש כתובת ומתי יש נתונים קיימת רגל נוספת במיקרו שנקראת ALE.
Address latch enable אפשור נעילת כתובת


בתחילת כל מחזור המעבד מוציא לפס המרובב את הכתובת ובעזרת רגל ה ALE שאתה הוא שם באחד לוגי הוא מודיע שכרגע בפס המרובב כתובת.
לאחר זמן קצר המעבד מוריד את כל רגל ה ALE לאפס ואז הפס המרובב הופך להיות פס הנתנוים.
מכאן שכמות ההדקים שנכנסת היא באחד פחות מהכמות המשותפת.
בדוגמה שלנו הפס המרובב הוא של 8 סיביות וחסכנו שבעה הדקים.
נסביר את זה כך: יש לנו שמונה רגליים ועוד רגל של ה ALE בשביל שנוכל להעביר גם כתובות וגם נתונים: סה"כ 9, במקום 16 רגליים שהם שמונה של כתובת ושמונה של נתונים: שש עשרה פחוח תשע שווה שבע, חסכנו שבעה רגליים.
מה שהיה צריך להיות פחות כמה שיש באמת שווה לכמה חסכנו.



תקציר הפקודות
אנחנו מתחיל לכתוב פקודות ומשימות באמצעות אסמלי.

יש לנו זיכרון נתונים פנימי (RAM) שהמצביעים עליו הם: R1, R2 - (הפקודה היא mov)  בתקציר הפקודות אנחנו נראה Ri כלומר i הוא או אפס או אחד.

אנחנו יכולים להעביר נתון כלשהו רק בין 0 ל 255, משום שבכל תא בזיכרון הנתונים הפנימי (RAM), יש שמונה סיביות:
2^8=256.
בתקציר פקודות זה יהיה מסומן לנו כך data# כלומר data הוא מספר בין 0-255.

יש לנו 128 כתובות באזור הנתונים הפנמי (RAM), בתקציר הפקודות כתובת מסומנת ב: DIRECT והיא מספר בין          0-127.


יש לנו זיכרון נתונים פנימי שהמצביע עליו הוא DPTR, הפקודה היא movx (מהמילה external חיצוני), בזיכרון הנתונים החיצוני יש נפח של 64k, זאת אומרת 16 סיביות, לכן הנתון שמעבירים אליו הוא בין אפס בין 10000H.
2^6 = 64
2k=2^10 = 1024 
64 k 64*1024 = 65,536 = 10000 H.



טבלה שתעזור לכם להתמודד עם פקודות, יש פה הסברים לכל מיני פקודות מייצגות שאם תבינו אותם תוכלו להסביר כל פקודה באסמבלי


הערות
מה עושה הפקודה
הפקודה
A הוא אקומולטור שמשתתף בחישובים.
N הוא מספר בין  0-7
העבר בזיכרון הנתונים הפנימי את התוכן מהרגיסטר "Rn" אל האקומולטור
MOV A,Rn
driect מספר בין 0--127
מעביר כתובת מזיכרון הנתונים הפנימי לאקומטלטר
MOV A,driect
Ri כאשר i  מספר בין 0-1,הרגיסטרים האלה מצביעים על זיכרון הנתונים הפנימי: בתוכו יש כתובת שמצביע על נתון כלשהו.
מעביר את התוכן שהרגיסטר מצביע עליו אל האקומולטור
MOV A,@Ri
יש 256 בתים לכן data 0-255.
מעביר נתון אל זיכרון הנתונים הפנימי אל האקומולטור.
MOV A,#data

מעביר מהאקומולטור לרגיסטר (זיכרון הנתונים הפנימי)
MOV Rn,A

מעביר כתובת לרגיסטר
MOV Rn,direct

מעביר נתון לרגיסטר
MOV Rn,#data
יכול להעביר נתון בכתובות 0-255, כי Ri הוא המצביע של זיכרון הנתונים הפנימי ששם יש 0-255 כתובות
העבר אל האקומולטור נתון מזיכרון הנתונים החיצוני מהכותבת ש Ri מצביע עליה.
MOVX A,@Ri

העבר אל האקומולטור לזיכרון הנתונים החיצוני את מה ש DPTR מצביע עליו.
MOVX A,@DPTR



לולאה באמסבלי

לולאה היא פעולה שחוזרת על עצמה כמה וכמה פעמים עם פרמטר או פרמטרים משתנים משתנים מפעולה חוזרת לפעולה חוזרת.. וככה במקום לכתוב את הפעולה כמה וכמה פעמים עם פרמטרים שונים אז רושמים לולאה אחת שעושה את העבודה. 

תכנית שמשתמשת בעקרון הלולאה כדי לאפס מספר מסוים של בתים.

MOV R0, #50h ; מכניס את הנתון 50 הקסה לתוך הרגיסטר 
MOV R7, #16; מכניס את הנתון 16 הקסה לתוך הרגיסטר
again: MOV @R0, #0 ; יוצר סעיף בשם "שוב" ומכניס לו את הנתון אפס בכתובת שהרגיסטר מצביע עליה
inc R0; מגדיל את הרגיסטר באחד
DJNZ R7. again ; הורד מהרגיסטר אחד, ואם ערכו לא אפס קפוץ לתווית שוב

מ.ע.ה.ה: מה עושה התכנית הבאה: התוכנית ממלאת בלוק של נתונים בזיכרון הנתונים החיצוני ובעצם היא מאפסת את הנתונים בכתובות הבאות: החל מכתובת חמישים הקסה עד הכתובת של שישים ושש הקסה.
R7 נקרא גם מונה לולאה, הוא מראה כמה פעמים יש לחזור על הלולאה (על ידי כך שאם הוא לא מתאפס אחרי הורדה מערכו באחד אז קופצים לתווית again)


כל התוכנית כפי שהיא מתבצעת:

מכניס נתון של חמישים הקסה לתוך R0
מכניס נתון של 16H לתוך R7
יותר תווית בשם again
מכניס את הנתון אפס למה ש R0 מצביע עליו, הוא מצביע על הכתובת 50H בזיכרון הנתונים, לכן בכתובת 50H יש עכשיו אפס
מעלה את R0 באחד כלומר הוא שווה 51
מוריד את R7 באחד כלומר הוא 15, הוא לא שווה אפס אזי חוזרים לתווית again


מכניס את הנתון אפס למה ש R0 מצביע עליו, הוא מצביע על הכתובת 51H בזיכרון הנתונים, לכן בכתובת 51H יש עכשיו אפס
מעלה את R0 באחד כלומר הוא שווה 52
מוריד את R7 באחד כלומר הוא 14, הוא לא שווה אפס אזי חוזרים לתווית again


מכניס את הנתון אפס למה ש R0 מצביע עליו, הוא מצביע על הכתובת 52H בזיכרון הנתונים, לכן בכתובת 52H יש עכשיו אפס
מעלה את R0 באחד כלומר הוא שווה 53
מוריד את R7 באחד כלומר הוא 13, הוא לא שווה אפס אזי חוזרים לתווית again

וכך הלאה





בתוך המיקרו בקר קיים RAM שמורכב בצורה הבאה: 128 בתים המחולקים לארבעה בנקים. בכל בנק 8 רגיסטרים מR0 עד R7 ועוד 16 בתים המחולקים לסיביות ועוד 80 בתים לשימוש כללי.

אזר ה-SFR, הוא אזור הרגיסטרים לתפקידים מיוחדים. (SFR = Special function registers). באזור זה נמצא את port0 עד port3, את רגיטר A שנקרא אקומולטור, רגיסטר B שעוזר בפעולות כפל וחילוק, את ה-DPH ואת ה-DPL שכל אחד מהם בן שמונה סיביות וביחד הם נקראים DPTR, קיצור של DATA POINTER והוא בן שש עשרה סיביות. DPTR הוא רגיסטר שמצביע לזיכרון הנתונים החיצוני (אנחנו משתמשים בו בפקודה של MOVX - איקס מהמילה external חיצוני).
נשאלת השאלה מדוע אנחנו צריכים שש עשרה סיביות למצביע זיכרון הנתונים החיצוני ובאותה נשימה אנחנו צריכים שמונה סיביות בלבד כדי להצביע על זיכרון הנתונים הפנימי? בזיכרון הנתונים הפנימי יש לנו זיכרון של 256 בתים, שבכל בית יש שמונה סיביות, כדי להצביע על כל הבתים אנחנו צריכים מצביע של:  
2^x=256
x=8
בזיכרון הנתונים החיצוני יש זיכרון של 64k, שזה אומר בבינארי:
2^x=65536
x=16

64k=64*2^10=2^6*2^10 = 2^16



עוד תכנית:
MOV DPTR ,#1000H; מכניס אל הרגיסטר שמצביע אל זכרון הנתונים החיצוני את הנתון אלף הקסה
MOV A ,#64H; מכניס לאקומולטור נתון של שישים וארבע הקסה
MOV R7 ,#10H; מכניס נתון של עשר הקסה לתוך הרגיסטר
again: MOVX @DPTR ,A; מכניס את ערך האקומטלטור לתוך ההבית שהרגיסטר מצביע עליה בזיכרון הנתונים החצוני
INC DPTR; מעלה את  ערך הרגיסטר באחד
DJNZ R7 , again; מוריד מערך הרגיסטר אחד ואם הערך אינו אפס הוא עור לתווית שוב

מה עושה התכנית הבאה:

התכנית ממלאת בלוק של נתונים בזיכרון התכנית החיצוני החל מכתובת 1000H ועוד 100FH בנתון 64K.
ה- DPTR הוא רגיסטר שבעזרתו רצים על הכתובות בזיכרון הנתונים החיצוני.
R7 נקרא גם מונה לולאה, הוא מראה כמה פעמים יש לחזור אל התווית again, למעשה הוא קובע את גודל הבלוק.


הסבר פקודה:
MOVC A,@A+DPTR

העבר לאקומולטור נתון מכתובת בזיכרון התכנית הפנימי, מהכתובת שהיא חיבור של האקומולטור וה-DPTR.
להזכירכם המילה C באה מהילה CODE, לכן ניתן להסיק כי הפקודה MOVC מעבירה לזיכרון התוכנית הפנימי, שגודלו הוא 64K.




מה עושה התוכנית הבאה:
בזיכרון התכנית בכתובת 2000H יש 10

בזיכרון התכנית בכתובת 2001H יש 15

בזיכרון התכנית בכתובת 2002H יש 28

בזיכרון התכנית בכתובת 2003H יש 0



MOV DPTR ,#2000H; להכניס את הנתון אלפיים הקסה לרגיסטר
MOV R5 ,#3; להכניס שלוש לרגיסטר
MOV R2 ,#0; להכניס אפס לרגיסטר
again: MOVX A ,@DPTR; יוצר תווית "שוב" ומכניס מזיכרון התכנית החיצוני את הערך של הכתובת שהרגיסטר מצביע עליו
ADD A ,R2; סוכם את התוכן שיש ברגיסטר הימני עם השמאלי ושומר את הסכום ברגיסטר השמאלי
MOV R2 .A; מעביר את מה שיש באקומטלטור לרגיסטר
INC DPTR; מעלה באחד את הערך של הרגיסטר
DJNZ R5 .again; מפחית באחד את הרגיסטר, אם הוא לא אפס עובר לתווית שוב
NOVX @DPTR ,A; האקומטלטור מועבר לתוך מה שהרגיסטר מצביע עליו

פירוט כל התהליך של התכנית
מכניסים נתון של 2000H ל DPTR
מכניסים נתון 3 לתוך R5
מכניסים נתון 0 לתוך R2
תווית של again
מכניסים את מה שהDPTR מצביע עליו, הוא מצביע על כתובת 2000H ושמה יש 10, לכן יש 10 באקומולטור
מוסיפים את התוכן שיש בR2 ל-A  זאת אומרת 10+0 יש בA עכשיו 10.
מכניסים את מה שיש באקומולטור ל-R2, זאת אומרת יש ב R2 עכשיו 10.
מעלה את ה DPTR באחד, לכן הוא מכיל עכשיו 2001H
מפחית מ-R5 אחד, ועכשיו יש ברגיסטר  2, אם זה לא אפס אז קופצים לתווית again



מכניסים את מה שהDPTR מצביע עליו, הוא מצביע על כתובת 2001H ושמה יש 15, לכן יש 15 באקומולטור
מוסיפים את התוכן שיש בR2 ל-A  זאת אומרת 15+10 יש בA עכשיו 25.
מכניסים את מה שיש באקומולטור ל-R2, זאת אומרת יש ב R2 עכשיו 25.
מעלה את ה DPTR באחד, לכן הוא מכיל עכשיו 2002H
מפחית מ-R5 אחד, ועכשיו יש ברגיסטר 1, אם זה לא אפס אז קופצים לתווית again


מכניסים את מה שהDPTR מצביע עליו, הוא מצביע על כתובת 2002H ושמה יש 28H, לכן יש 28 באקומולטור
מוסיפים את התוכן שיש בR2 ל-A  זאת אומרת 28+25 יש בA עכשיו 53.
מכניסים את מה שיש באקומולטור ל-R2, זאת אומרת יש ב R2 עכשיו 53.
מעלה את ה DPTR באחד, לכן הוא מכיל עכשיו 2003H
מפחית מ-R5 אחד, ועכשיו יש ברגיסטר 0, זה שווה אפס לכן ממשיך בתכנית
מכניס את תוכן A לזיכרון הנתונים החיצוני שהDPTR מצביע עליו


התכנית סוכמת את כל הנתונים בזיכרון התכנית החיצוני מהכתובת 2000H עד ל 2002H וכניסה את התוצאה שלה לכתובת 2003H.



מה עושה התכנית הבאה:
נתון זיכרון הנתונים הפנימי:
בכתובת של 50H יש 10
בכתובת של 51H יש 11
בכתובת של 52H יש 12

בכתובת של 60H יש 20
בכתובת של 61H יש 21
בכתובת של 62H יש 22

MOV R0 ,#50H;
MOV R1 ,#60H;
MOV R2 ,#3;
again: MOV A .@R0
XCH A .@R1;
MOV @R0 ,A;
INC R0;
INC R1;
DJNZ R2 , again;



מכניס ל R0 נתון של 50H
מכניס ל R1 נתון של 60H
מכניס ל R2 נתון של 3
יוצר תווית "שוב"
מכניס לאקומולטור את הנתון ש R0 שמכיל 50H מצביע עליו, הנתון הוא 10 .
מחליף בין האקומוטלטור שמכיל 10 לבין הנתון שR1 שמכיל 60H מצביע עליו, והוא 20.
באקומולטור יש עכשיו 20 ובנתון של כתובת 60H בזיכרון התכנית הפנימי יש 10
מכניס את תוכן האקומולטור 20 לתוך מה ש R0 שמכיל 50H מצביע עליו.
מעלה את R0 באחד, עכשיו יש 51H
מעלה את R1 באחד, עכשיו יש 61H
מוריד אחד מ R2, שמכיל עכשיו 2, אם לא אפס קופץ לתווית "שוב"
אכן לא אפס
קופץ לתווית שוב

מכניס לאקומולטור את הנתון ש R0 שמכיל 51H מצביע עליו, הנתון הוא 11 .
מחליף בין האקומוטלטור שמכיל 11 לבין הנתון שR1 שמכיל 61H מצביע עליו, והוא 21.
באקומולטור יש עכשיו 21 ובנתון של כתובת 61H בזיכרון התכנית הפנימי יש 11
מכניס את תוכן האקומולטור 21 לתוך מה ש R0 שמכיל 51H מצביע עליו.
מעלה את R0 באחד, עכשיו יש 52H
מעלה את R1 באחד, עכשיו יש 62H
מוריד אחד מ R2, שמכיל עכשיו 1, אם לא אפס קופץ לתווית "שוב"
אכן לא אפס
קופץ לתווית שוב

וכך הלאה

התכנית מחליפה את הנתונים בין שני בלוקים באזור הנתונים הפנימי.
בלוק אחד מתחיל בכתובת 50H ומסתיים ב52H, הבלוק השני מתחיל בכתובת 60H עד 62H.
הנתון מכתובת 50H מתחלף עם הנתון בכתובת 50H.
הנתון מכתובת 51H מתחלף עם הנתון של 61H
וכך הלאה עד 52H שמחלף עם 62H.
R0 המצביע ל הכתובת בבלוק הראשון
R1 מצביע על הכתובת בבלוק השני
R2 הוא מונה הלולאה והוא קובע עד כמה כתובות יש לבצע את ההחלפה.


XCHD A. @Ri
הפקודה מחליפה את ארבעת הסיביות האחרונות של Ri (כאשר i יכול להיות אפס או אחד, הוא המצביע לזיכרון התכנית הפנימי) עם ארבעת הסיביות הנמוכות של האקומולטור.




עבודה עם מחסנית
כאשר רוצים לשמור נתונים שנצטרך אותם תוך זמן קצר נוהגים לשמור אותם במחסנית.
המחסנית היא אזור של כתובות ב-RAM הנתונים הפנימי.
באזור ה SFR יש רגיסטרים רבים וביניהם נימצא את הרגיסטר SP.
רגיסטר זה מצביע ומראה באיזו כתובת נמצאת כרגע המחסנית.


בעבודה עם מחסנית יש לנו שתי פקודות: 
 PUSH DIRECT
כאשר Direct הוא כתובת בזיכרון הנתונים הפנימי (RAM) הוא מספר 0-255, פקודה שמכניסה את הנתון למחסנית (הוא יהיה עליון, ראשון).
איך זה מתבצע? הפקודה מגדילה את המצביע SP באחד, ולאחריו מכניסה את הנתון בכתובת החדשה של SP.
SP- STACK POINTER = STACK_POINTER
 POP DIRECT- מסיר את הנתון הכי עליון של המחסנית ומעביר אותו לכתובת DIRECT שכתבנו.
איך זה מתבצע?  הנתון ש-SP מצביע עליו עובר לכתובת אשר Direct מציין והמצביע של המחסנית הוא SP יורד באחד.

המחסנית עובדתך על עיקרון LIPO - Last In First Out, כלומר האחרון שנכנס הוא הראשון לצאת.




בכתובת של 60H יש 12
בכתובת של 70H יש 14
בעזרת הפקודות הבאות אנחנו נחליפ ביניהם
push 60H
PUSH 70H
POP 60H
POP 70H

מה שקורה פה בעצם זה שאנחנו מכניסים את הנתון שנמצא בכתובת של 60H בתוך זיכרון התוכנית הפנימי לתוך המחסנית, לאחריו אנחנו מכניסים את הנתון שנימצא בכתובת של 70H בתוך זיכרון התוכנית הפנימי לתוך המחסנית.

אנחנו לוקחים את הנתון העליון במחסנית (כלומר הנתון שנכנס אחרון למחסנית) ומעבירים אותו לכתובת של 60H.
אחר כך אנחנו לוקחים את הנתון העליון במחסנית ושמים אותו בכתובת 70H של זיכרון הנתונים הפנימי.

בעצם ביצענו פה חילוף בין הנתון שיש בכתובת של 60H לבין הנתון שיש בכתובת 70H - כך נבצע חילוף בין שני נתונים שונים בזיכרון התוכנית הפנימי.



רגיסטר PSW
Program status word
מילת מצב תוכנית

הרגיסטר הזה בנוי משמונה סיביות אשר עוזרות לנו לבצע פעולות חשבוניות, הרגיסטר הזה נימצא ליד היחידה האריתמטית לוגית, וכמו שנאמר שם מתבצעות פעולות חשבון לוגיות.

הרגיטר הזה מכיל את שמונה הסיביות הבאות:
CY
AC
F0
RS1
RS2
OV
-
P


רגיסטרים RS1 ו RS2 הם רגיסטרים שנשלטים עלן ידי המתכנת ובעזרתם אנחנו קובעים עם איזה בנק אנחנו עובדים.

בנק
R20
PS1
0
0
0
1
1
0
2
0
1
3
1
1



כאשר מפעילים חשמל ויש RESET הסיביות הללו מקבלות אפס ועובדים עם בנק 0.


דגלים FLAGS

CY בא מהמילה CARRY בעברית נשא

דגל הנשא מקבל אחד כאשר בפעולת החיבור יש נשא מסיבית הMSB (כלומר הסיבית הכי שמאלית) החוצה, או כאשר בפעולת חיסור יש השאלה (BORROW) מבחוץ אל סיבית הMSB, אחרת בדגל הנשא יש אפס.



P - Parity דגל הזוגיות
דגל הזוגיות מראה האם מספר האחדים בתוצאה זוגי או לא זוגי. הזוגיות נבדקת כאן היא זוגיות זוגית.
כלומר כמות האחדים בתוצאה פלו דגל הזוגיות יהיה זוגי.


OV - OVER FLOW
גלישה מעבר
דגל הגלישה מקבל אחד כאשר משתנה היעד איננו מספיק רחב גדי להכיל את התוצאה, אחרת הוא מקבל אפס.
להזכירכם, אם הסיפרה הראשונה (במספר בינארי) הוא אחד אזי מדובר במספר שלילי, אם המספר הראשון אפס אזי המספר חיובי.

(צריך לבדוק דגל הגלישה מקבל אחד כאשר הנשא אל סיבית הMSB שונה מהנשא מסיבית הMSB החוצה.)

F0 - דגל ליישום עדיתי


דגל ה AC  AUXILIARY CARRY - נשא עזר

דגל  הנשא עזר מקבל אחד כאשר יש נשא CARRY מהסיבית מספר שלוש של האקומולטור לסיבית מספר ארבע של האקומולטור, אחרת הוא מקבל אפס.





כאשר המשתמש רוצה לעבוד עם מספרים המיוצגים בקוד BCD - BINARY CODED DECIMAL (כלומר כל ארבע ספרות בינאריות מייצגות סיפרה אחת עשרונית).
אם נוסיף אחרי פעולת החיבור את הפקודה DA A ,   פירושי של DA הוא decimal adjust, אז התוצאה הבינארית שהתקבלה מתוקנת למספר ב BCD.

למשל אם נחבר את הספרות
17H
9H
14H
56H

רגיל אנחנו נקבל את הפתרון: 8A

אם אנחנו נוסיף את הפקודה
DA A אנחנו נקבל:
96H


הוראות אריתמטיות

ADD A , Rn   - בצע פעולת חיבור בין הנתון שבאקומולטור לנתון שברגיסטר, התוצאה חוזרת לאקומולטור והדגלים מושפעים

ADD A ,direct
חבר בין הנתון שבאקומולטור ובין הנתון שבכתובת direct (ב RAM הפנימי). התוצאה מועברת לאקומולטור והדגלים מושפעים.

ADD A , @Ri
חבר בין הנתון שבאקומולטור ובין הנתון בכתובת ש Ri מצביע עליה, התוצאה מוחזרת לאקומולטור והדגלים מושפעים.




ADDC A , Rn
מחבר את התוכן של Rn יחד עם האקומולטור ומחבר גם את מצב הדגל CY (מוסיף אחד אם יש נשא מסיבית ה MSB, אחרת מוסיף אפס)

אם רוצים לחבר את המספר R1 R0  (מספר בעל שש עשרה סיביות, כאשר R1 מכילה את הצד השמאלי של הספרות)
יחד עם R3 ו R2 (כאשר R3 הוא הצד השמאלי של הספרות במספר).
כאשר אנחנו רוצים לשמור את התוצאה ב R5 ו R4  (כאשר R5 הוא הספרות השמאליות של התוצאה).

MOV A,R0
ADD A ,R2
MOV R4 .A
MOV A ,R1
ADDC A ,R3
MOV R5 ,A





SUBB - Subtract Borrow
SUBB A ,R2
חיסור כולל חיסור של דגל ה CY.


בחיסור CY יבדוק האם יש השאלה מבחוץ לסיבית הMSB.
אם רוצים לחסר את המספר R1 R0  (מספר בעל שש עשרה סיביות, כאשר R1 מכילה את הצד השמאלי של הספרות)
יחד עם R3 ו R2 (כאשר R3 הוא הצד השמאלי של הספרות במספר).
כאשר אנחנו רוצים לשמור את התוצאה ב R5 ו R4  (כאשר R5 הוא הספרות השמאליות של התוצאה).


MOV A ,R0
CLR CY
SUBB A ,R2
MOV R4 .A
MOV A ,R1
SUBB A ,R3
MOV R5 ,A







הוראות הפועלות על ביטים (ביט = סיבית)
הוראות על סיבית שקובעים האם יש שם אפס או אחד.

ב S.F.R (special function registers)  a יש כל מיני סיביות שניתן לשלוט בהם באופן ייחודית:
למשל P1.0, P2.0 (שמות של פורטים).

SETB bit - לשים '1' לוגי 
CLR bit - לשים '0' לוגי בביט

bit יכול להיות כל מיני סיביות לשימוש מיוחד כמו פורטים.


מה עושה התכנית הבאה?



again: CLR P1.0
השהייה
SETB P1.0
השהייה
SJMP again

תשובה:
התכנית הבאה תגרום שנורת הלד תהבהב, כמובן שצריך לכתוב השהייה מספיק ארוכה כדי שהעין שלנו תבחין במעבר של הנורה ממצב כבוי למצב דלוק, אנחנו נלמד איך לחשב השהייה.
במצב שבו הלד שלנו בנויה כאשר אנחנו מכניסים לפורט 1.0 אחד לוגי (ששווה לחמש וולט) באמצעות הפקודה SETB, אזי יש לנו חמש וולט בשני הצדדים מה שמבטל אחד את השני וגורם לאי הידלקות של הלד.
כאשר אנחנו מכניסים לפורט 1.0 אפס לוגי (CLR), אז יש לנו חמש וולט בצד אחד, ואפס וולט בצד השני מה שגורם להידקלות הלד.
אנחנו יכולים להבחין בהבדל (לד דלוק שעובר למצב כבוי וממצב כבוי למצב דלוק) רק אם יש לנו השהייה מספיק גדולה.



הכירו את הפקודה CPL (מהמילה Compliment = השלמה, מחמאה. במקרה שלנו השלמה).
הפקודה CPL גם היא עובדת על ביט (סיבית) בודדת.
בסיבית בודדת יכולים להיות שני מצבים: או אפס לוגי או אחד לוגי.
אם בסיבית כרגע יש אחד לוגי - אחרי שימוש בפקודה CPL יהיה בה אפס לוגי.
אם בסיבית כרגע יש אפס לוגי - אחרי שימוש בפקודה CPL יהיה בה אפס לוגי.

CPL הופכת את המצב הנתון של הסיבית למצב ההפוך שלה: מאפס לאחד, מאחד לאפס.

השרטוט לעיל חל גם על התכנית הבאה.
נתונה התכנית הבאה:

again: CPL P1.0
השייה
SJMP again


התכנית הזאת עושה בדיוק את מה שהתכנית שלפניה עושה - רק היא יותר קצרה ויותר חכמה.

אם מצבה של מנורת הלד היה מכובה, כלומר היה בפורט שמחובר אליה 'אחד לוגי' אז אחרי הפקודה CPL מצבה יהיה דלוק.
אם מצבה של מנורת הלד היה דלוק, כלומר היה בפורט שמחובר אליה 'אפס לוגי' אז אחרי הפקודה CPL מצבה יהיה מכובה.



באמצעות דגל ה carry, ניתן לשים בתוכו אליו אפס או אחד לוגי ולהשתמש בו כך:

להעביר את מצב הביט (יכול להיות פורט למשל) אל דגל הקרי
mov c , bit
אם בביט יש אפס לוגי אזי אחרי הפקודה הזאת יהיה אפס לוגי בדגל הנשא (דגל ה-carry)
אם בביט יש אחד לוגי אזי אחרי הפקודה הזאת יהיה אחד לוגי בדגל הנשא.

mov bit ,c
מעביר את המצב של דגל הנשא לביט.
אם היה בדגל הנשא אפס לוגי אז בביט יהיה גם אפס לוגי.
אם היה בדל הנשא אחד לוגי אז בביט יהיה גם אחד לוגי.




כאשר אנחנו סוגרים את S0 (מפסק מספר אפס)  אזי יש אדמה בשני הצדדים.
הדרך הקלה ביותר לזרם לעבור היא לאדמה שנמצאת בצד ימין בשרטוט, כל החמישה וולט יגיעו לאדמה ואף מתח לא יגיע לפורט 1.0, זאת אומרת שיש לנו שם אפס לוגי.

כאשר המספק סגור, אז יש מחלק מתח בין שני שני הנגדים, אחד של עשר אלף אום, והשני של מיליון אום.
מתח נמוך מאוד ייפול על הנגד של העשרה אום, ורוב המתח (בקירוב 5 וולט) ייפול על הנגד של המיליון אום, שיגיע לפורט 1.0, אזי יש לנו שם אחד לוגי.


מה עושה התכנית הבאה?

again: mov c, P1,0
mov P1.1 ,C
SJMP again

התכנית הבאה בודקת מה מצב המפסק ומעבירה את מצב זה לדגל הנשא.

כמו שהסברתי למעלה, כאשר כאשר המפסק סגור יש אפס לוגי בפורט 1.0.
כאשר המפסק פתוח יש אחד לוגי בפורט 1.0.

הפקודה השנייה מעבירה את מצב דגל הנשא לפורט שמחובר ללד.

כאשר נלחץ על הכפתור פורט 1.0 יהיה אפס לוגי,מצב זה יעבור מדגל הנשא לפורט 1.1 שיגרום להידלקות הלד.

אם לא נלחץ על הכפתור והמפסק יהיה פתוח, אז יהיה בפורט אחד לוגי שיעבור לדגל הנשא, שיעביר את מצבו מדגל הנשא אל פורט 1.1 שיגרום לידי כך שהלד יהיה כבוי.

במילים פשוטות יותר כאשר לוחצים על הכפתור האור נדלק, וכאשר המפסק פתוח האור מתכבה.




מה עושה התכנית הבאה:


again: mov c, P1,0
CPL C
mov P1.1 ,C
SJMP again

התכנית עושה את אותו כמו שמוסבר למעלה רק שמצבו של דגל הנשא שמועבר לפורט 1.1 שמחובר ללד יהיה הפוך.

אם נלחץ על הפתור והמפסק יהיה סגור, אז יגיע אפס לוגי לפורט 1.1, הוא יעבור לדגל הנשא, אחרי הפקודה השנייה מצבו של הנשא יתהפך ויהיה אחד לוגי, ואז יגיע אחד לוגי לפורט 1.1 שיגרום לידי כך שלא יהיה אור בלד.

אם לא נלחץ על הכפתור והמספק יהיה פתוח, אז יגיע אחד לוגי לפורט 1.0 שפקודה הראשונה יעביר את מצבו לדגל הנשא, אחר כך יהיה היפוך על מצבו של דגל הנשא, והוא יהיה אפס לוגי, המצב החדש של דגל הנשא יחול על פורט 1.1 (בפקודה השלישית) שיגרום להידלקות של הלד.



פעולות לוגיות

ANL C ,bit
התוצאה תישאר בדגל הנשא
פעולת AND לוגית אומרת את הכלל הבא:
1*1=1
1*0=0
0*1=0
0*0=0
מספיק שיהיה אפס אחד לפחות שהתוצאה תהיה אפס.





כתוב תכנית שתגרום לידי כך שמספיק שרק מפסק אחד יהיה סגור (S1, S0) אזי הלד יילד.


again: mov c , p1.0
ANL C ,P1.1
MOV P1.2 , C
SJMP again

אנחנו זקוקים לאפס לוגי כדי להדליק את נורת הלד, נקבל רק אפס לוגי בשלושת המקרים של פעולת ה AND לוגי (שני המפסקים דלוקים, מפסק אחד דלוק בלבד, מפסק אחד אחר דלוק בלבד) - כאשר אנחנו לוחצים על המפסק אנחנו מקבלים אפס לוגי, לכן התכנית הזאת תעבוד. 
אם לא נלחץ על אף מפסק יהיה אחד לוגי בשני הפורטים, ובפעולת ה AND לוגי נקבל אחד לוגי, מה שעושה את נורת הלד כבויה.


ORL C ,bit
פעולה OR לוגית, מספיק שיש אחד לפחות אז התוצאה תהיה אחת
התוצאה נשמרת בדגל הנשא
1+1=1
0+1=1
1+0=1
0+0=0

על אותה חומרה רשום תכנית שרק כאשר שני המפסקים לחוצים הלד נדלקת.

again: MOV C ,P1.0
ORL C . P1.1
MOV P1.2 ,c
SJMP again

אנחנו צריכים אפס לוגי כדי להדליק את הלד.
כאשר אנחנו עושים פעולת OR לוגית אז רק כאשר שני המפסקים לחוצים אנחנו מקבלים אפס לוגי בשניהם, התוצאה נכנסת לדגל הנשא ומשם מועברת לפורט שמחובר לנורתה הלד - מה שיגרום להידלקות הלד.
בשאר המקרים יתקבל אחד לוגי כתוצאה מפעולת ה OR הלוגי. (מה שלא יגרום להידלקות הלד).




תפקיד נגד ה PULL UP (משיכה למעלה)


תפקיד הנגד של ה-10k הוא לבצע משיכה למעלה.
אם הנגד לא היה אז כאשר המפסק היה פתוח כניסת ה PORT היית מחוברת באוויר.
היות ולפורט יש התנגדות כניסה מאוד גבוהה כל רעש קטן יכול להכניס מצב לוגי אקראי בכניסת הפורט.
לדוגמה אם התנגדות הכניסה היא מיליון אומים (אחד מגה אום) אז רעש של שלוש מיקרו אמפר יכול לגרום למפל מתח של 3V.
כדי למצוא מצב זה שמים נגד שהוא קטן בהרבה מהתנגדות הכניסה של הפורט.
הנגד מחובר אל ה-5V ואז קיים מחלק מתח בינו לבין התנגדות הפורט, והמתח בכניסת הפורט הוא כמעט 5V שזה אחד לוגי.
במילים אחרות הנגד "מושך" את כניסת הפורט למצב גבוה '1' לוגי ולכן הוא נקרא משיכה למעלה.
כאשר המפסק סגור בצד ימין שלו יש אפס שעובר דרך הקצר של המפסק ומגיע לכניסת הפורט כאפס לוגי. 
סדר הגודל של הנגד הוא מקילו אומים בודדים ועז לעשות קילו אומים בודדים.
מצד אחד אם הוא קטן מידי אז כשהמפסק סגור זורם דרכו זרם גדול מידי (חמש חלקי גודל הנגד) ויש בזבוז הספק.
מצד שני אם הוא גדול מיני אז שהמפסק פתוח, יהיה מחלק מתח בין שני נגדים גדולים וייתכן שלא יהיה אחד לוגי בכניסת הפורט.
באופן מעשי נגד של עשרה קילו הוא נגד רצוי וכאשר המפסק נסגר סגור יהיה זרם של חצי מיליאמפר דרכו וכאשר המפסק פתוח יהיה בכניסת הפורט בסביבות ה 4.95V שזה אחד לוגי.

בהרבה מקרים ניתן להשתמש במקום בנגד PULL UP בנגדי PULL DOWN.





מדוע אנחנו משתמשים ב 300 אום כאשר בנגד של הלד?

אם אנחנו רוצים לראות את הלד כאשר אנחנו בתנאי חדר, אנחנו צריכים זרם של 10mA. (הנגד והלד מחוברים בטור לכן הזרם שווה בכל המעגל)
המתח המומלץ להפעלת דיודה הוא: 1.2V עד 1.8V:
1.5v.

5=VR+VLED
5=I*R+VLED
5=10R+1.5
R=(5-1.5)/10=350Ω




חישוב השהייה
לכל מיקרו בקר או מעבד מחברים גביש אשר קובע את תדר העבודה - מהירות העבודה של המיקרו בקר.
הגביש נקרא crystal הוא מעגל תהודה שמורכב מסליל וקבל, במעגלי מיקרו בקרים נהוג לחבר גביש בתדר של עשרות מגה הרץ ואילו במעבדים שבמחשב האישי הגביש הוא בתדר של ג'יגה הרצים.
בתוך המיקרו יש מגבר שביחד עם הגביש יוצרים את המתנגד.
מתנד הוא מעגל שמקבל אנרגיה של מתח ישר (5V של הספק) והוא מוציא אנרגיית חילופין.
אצלינו אנרגיית החילופין היא גל מרובע שנע בין מתחים של אפס עד 5V בתדר הגביש.
גל זה נראה בשרטוט והוא נקרא תדר השעון:

נניח שלמיקרו בקר חיברנו גביש לתדר של 12MHZ.
הגביש מחבר בין הרגליים 18 ו 19 של המיקרו בוקר. (8051).
בין פולס אחד לשני יש מרווח זמן של:
במילים אחרות זמן המחזור הפולסים שיותר המתנד הוא:
T=1/F = 1/12M = 83.33 nano
12 פולסי שעון נקראים מחזור מכונה machine cycle.

בדף תקציר הפקודות רשום ליד כל פקודה כמה בתים הפקודה תופסת ובכמה מחזורי מכונה היא מתבצעת.


בדוגמה שלנו עבור תדר גביש לך 12MHZ זמן המחסור שלנו הוא 83.33 nano ומכאן שמחזור המכונה הוא:
12*8.33 nano = 1 micro sec.

כל מחזור מכונה אחד לוקח זמן של אחד מיקרו.

אם פקודה מסוימת מתבצעת במחזור מכונה אחד, אז לוקח לך אחד מיקרו שנייה כדי להתבצע.
(כלומר מיליונית) שנייה.





נתונה התכנית הבאה:

                                                           cycle
long_delay: mov R7 . #3                     (1)
              ag: mov R6 , #4                     (1)
             aga: DJNZ R6 , aga                (2) 
                     DJNZ R7 , ag                 (2)
                     RET                                (2)


כתוב את כמות מחזורי המכונה כמו שהיא, ואחר כך כביטוי:
1+3(1+4*2+2)+2

הסבר:
פקודה ראשונה מתבצעת רק פעם אחת, לכן אנחנו נכתוב בהתחלה 1.

כאשר יש את הפקודה DJNZ (קפוץ לתווית אם אין אפס ברגיסטר), ואם אין מי שיעלה את הריגסטר (מה שיש בתוכנית) אז הפקודה הזאת תתקיים כמספר התוכן של הרגיסטר: כלומר שלוש פעמים
הפקודה הזאת תתבצע רק שלוש פעמים, אבל הקריאה לתווית תתבצע רק פעמיים בלבד:
פעם ראשונה: מוריד משלוש לשתיים, קורא לתווית.
פעם שנייה: מוריד משתיים לאחד, קורא לתווית.
פעם שלישית מוריד מאחד לאפס, ממשיך הלאה.

הפקודה השנייה תתבצע שלוש פעמים:
פעם אחת היא תתבצע שמריצים את התכנית, ועוד פעמיים כאשר הפקודה ה  DJNZ R7 , ag  קוראת לתווית.
3(1)

הפקודה השלישית תתבצע שלוש פעמים:
פעם אחת היא תתבצע שמריצים את התכנית, ועוד פעמיים כאשר הפקודה ה  DJNZ R7 , ag  קוראת לתווית.
בכל פעם (יש שלוש פעמים) שהרגיסטר R6 מתמלא והפקודה  aga: DJNZ R6 , aga רצה, אזי זה רץ 4 (כמספר הרגיסטר R6) וכל ריצה שווה לשתי מחזורי מכונה: 2*4, כמו שהסברנו התהליך הזה קורא שלוש פעמים:
כלומר  
3(2*4)

פקודה אחרונה מתבצעת רק פעם אחת והיא שווה שתי מחזורי מכונה לכן נכתוב בסוף שתיים
הביטוי:
1+3(1+4*2+2)+2
1+X(1+Y*2+2)+2   
X - התוכן R7
Y - התוכן של R6.




קפיצות jumps

sjmp - קפיצה קצרה
ajmp - קפיצה אבסולוטית
ljmp - קפיצה ארוכה

קפיצה היא מעבר של התכנית לכתובת שאיננה עוקבת לכתובת הנוכחית.
הקפיצה מתבצעת על ידי טעינת מונה התכנית לכתובת הרצויה.
ישנן שלושה סוגי קפיצה:
1. קפיצה קצרה.
2. קפיצה אבסולוטית
3. קפיצה רחוקה.

ההבדל בין הקפיצות הוא טווח הקפיצות.

SJMP
טווח הקפיצה בקפיצה קצרה הוא 127 כתובות קדימה או 128 כתובות אחורה.
הפקודה תופסת שני בתים:
הבית הראשון הוא קוד הפעולה (קוד הפעולה הוא הקוד של ה sjmp עצמו)
והבית השני הוא הטווח של הקפיצה.

(להזכירכם, כאשר יש בסיבית ה MSB אפס הריי שמדובר במספר חיובי, וכאשר יש אחד הריי שמדובר במספר שלילי)

ajmp
טווח הקפיצה הוא פלוס מינוס 2k כתובות.
הפקודה תופסת שני בתים:
בבית הראשון חמש הסיביות הראשונות הם קוד הפעולה, ואילו 3 הסיביות הנותרות באותו בית, ושמונה הסיביות בבית השני בשביל הכתובת שאליה רוצים לקפוץ.
ljmp
קפיצה ארוכה היא לכל כתובת במרחב הזיכרון של המעבד.
הפקודה תופסת 3 בתים, הבית הראשון הוא קוד הפעולה ושני הבתים האחרים הם הכתובת שאליה צריך לקפוץ.



פרוצדורות, רוטינה, סאב רוטינה, תכנית משנה, שיגרה, תת שיגרה

פרוצדורה היא קטע תכנית שקוראים לה מנקודה מסוימת בתכנית.
עוברים לבצע את התכנית הפרוצדורה ובסיום הפרוצדורה מופיעה פקודה RET (מהמילה RETURN) ואז חוזרים אל הפרודה ממנה יצאנו אל הפרוצדורה.
שימוש בפרוצדורה מאפשר חסכון בכתובות של זיכרון, מודולריות טובה יותר של התכנית, זמן ניפוי תכנית קצר יותר, תחזוקה עתידית קצרה יותר.

ACALL כתובת הפרוצדורה
LCALL  כתובת הפרוצדורה

נדגים איך התהליך בתוך המיקרו בקר 8051 מתבצע בעזרת הפקודה LCALL:

נניח שיש לנו בזיכרון התכנית:
כתובה
1000H
תוכן
בית של הפקודה LCALL

כתובה
1001H
תוכן
50H (החלק הראשון של הכתובת שאליה רוצים לקפוץ)

כתובה
1002H
תוכן
00H (החלק השני של הכתובת שאליה רוצים לקפוץ)

כתובה
1003H (כתובת החזרה - הכתובת שאליה נחזור אחרי ביצוע הפרוצדורה בעזרת הפקודה RET)
תוכן
הפקודה כלשהו... 


כתובה
5000H (הכתובת שאליה אנחנו קופצים, תחילת הפרוצדורה)
תוכן
התוכן של הפרוצדורה....



כתובה
5005H
תוכן
הפקודה RET (תגרום לכך שתחזור אל כתובת החזרה)



מה קורה פה בעצם:

PC (PROGRAM COUNTER) =.
 מונה התכנית, הוא זה שמצביע על הפקודה הבאה שאותה צריך המחשב להביא (FETCH פעולת הבאת הפקודה) ולאגור בIR, לפענח (בעזרת decoder - מפענח הפקודה ואז לבצע את הפקודה.
PC=1000H
FETCH
IR = תוכן הפקודה
PC=PC+1=1001H
מתבצע פענוח של הפקודה - המיקרו בקר מבין ששתי הבתים הבאים יהיו הכתובת שממנה הפרוצדורה תתחיל

מביא 50H

PC=PC+1=1002י

מביא 00H

PC=PC+1= 1003H

הכנסת כתובת החזרה למחסנית

sp= מצביע המחסנית

נניח שמצביע המחסנית כרגע הוא
sp=7

הוא מקדם את עצמו באחד
sp=sp+1=8
ומכניס את החלק הנמוך של הPC
03H


הוא מקדם את עצמו באחד
sp=sp+1=9
ומכניס את החלק הגבוה של הPC
10H


הPC נטען לכתובת של הפרוצדורה
PC=5000H



שליפת כתובת החזרה מהמחסנית
מהכתובת שSP מצביע עליה מביאים את הנתון לחלק הגבוה של ה PC
10H
(האחרון שנכנס הוא האחרון שיוצא)
SP=SP-1=8


מהכתובת ש SP מצביע עליה מביאים את הנתון לחלק הנמוךש ל הPC
03H
SP=SP-1=7

PC=1003H





מה עושה התכנית הבאה?

 MOV R0 ,#40H;
MOV R1 ,0;
MOV R2 .#19;
again: CJNE  @R0 .#64H . aga1;
INC R1;
aga1: INC RO;
DJNZ R2 ,again;
END


תזכורת לביצוע הפקודות:
CJNE = Compare jump not equal - השווה וקפוץ אם לא שווה
INC - increament - להגדיל באחד
DJNZ - DECREMENT JUMP NOT ZERO - חסר אחר וקפוץ אם לא אפס, אם אפס תמשיך הלאה

הפקודה עובדת על בלוק נתונים החל מכתובת 40H ועוד 19 כתובות קדימה (עד 52H כולל).
בכל כתובת בודרים האם הנתון הוא 64H.
אם כן מגדילים את המונה R1.
בסיום התכנית R1 מראה כמה פעמים מופיע המספר 64H בבלוק הנתונים הזה.
אם הכנסנו ציונים של 19 תלמידים אז R1 מראה כמה תלמידים קיבלו מאה. (64H=100).
R0 הוא הרגיסטר שבעזרתו רצים על הכתובת בתוך הבלוק. (R0 הוא המצביע של זיכרון התכנית הפנימי RAM).
R1 מונה את כמות המאות.
R2 הוא מונה הלולאה.



פסיקות interrupts

הגדרה, פיקה היא הפסקה, הפרעה במהלך ריצה של תכנית, מעבר לתכנית שמטפלת במבקש הפסיקה ובסיום הטיפול חוזרים לאותה נקודה ממנה יצאנו לתכנית הפסיקה.

ישנם שני סוגי מנהלים:
א. פסיקות - מי שיוזן בטא המנהל
ב. שאילתות

האפשרויות שיש למנהל הפסיקות:
א. לחסום את כולם
ב. לאפשר לכולם
ג. לברור
ד. לתת עדיפות


צורת עבודה נוספת היא שאילתא, או בשפה המקצועית POLLING, בשיטה הזו המיקרו הוא זה שיוזם את הפנייה.
כל פרק זמן מסוים הוא פונה אל ההתקנים המחוברים אליו ובודק האם הם צריכים טיפול.
לעומת זאת בשיטת הפסיקה המיקרו עובד על תכנית כלשהי ואותו התקן שרוצה טיפול הוא זה שיוזם ומבקש טיפול.




רגיסטרים שבעזרתם שולטים על הפסיקות

IE - Interrupt enable
אפשור הפרעה

IP - Interrupt priority
עדיפות פסיקות

TCon - Timers control
בקרת טיימרים


בעזרת ה-IE המתכנת קובע אילו פסיקות מאפשרות ואילו פסיקות חסומות (מי תתקבל ומי לא תתקבל).
בעזרת ה-IP המתכנת קובע שבמידה ומגיעות מספר פסיקות בו זמנית, במי מהן יטפל ראשונה, שנייה וכן הלאה, הוא קובע עדיפות.
רגיסטר ה-TCON מחולק לשניםי:
4 סיביות גבוהות ששולטות על הטיימרים.
4 סיביות נמוכות ששולטות על הפסיקות החיצוניות.



מקורות פסיקה

א. פסיקה חיצונית 0 -  INTO או  EXT0 (שניהם עם גג)

ב. טיימר 0 - TIMER0

ג. פסיקה חיצונית 1 -  INT1 או  EXT1 (שניהם עם גג)

ד. פסיקת טיימר 1 - TIMER1

ה. פסיקת תקשורת אחת - serial, UART

ו. טיימרינג (רק ברכיבים בסיומת 2).


*** משמעותו של הגג:
כאשר יש לנו גג כמו לעיל, זה מצב שנקרא ACTIVE LOW, פעיל בנמוך, זאת אומרת שמצבו הרגיל הוא '1' (אחד לוגי) וכדי להפעיל אותו צריך שהוא יהיה ב- '0' (אפס לוגי).



עדיפות
כתובת הפסיקה
שם
מספר פסיקה
הכי גבוהה
3
EXT0, INT0 בגג
0
0BH
TIMER0
1
13H
EXT1, INT1 בגג
2
1BH
TIMER 1
3
23H
UART, SERIAL
4
הכי נמוכה
2BH
TIMER2
5



תהליך היענות לפסיקה
ה-PC מצביע על הפקודה הבאה.

א. סיום ביצוע הפקודה.

ב. הכנת כתובת החזרה למחסנית:
1. sp=sp+1
2. לכתובת זו נכנס החלק הנמוך של ה - PC לתוך המחסנית
3. sp=sp+1
4. לכתובת זו נכנס החלק הגבוה של ה-PC לתוך המחסנית

ג. ה-PC נטען לכתובת הפסיקה ועוברים לתוכנית הפסיקה.

ד. RETI

ה. שליפת כתובת החזרה מהמחסנית
1. מהכתובת ש PC מצביע עליה מעבירים את החלק הגבוה של ה-PC.
2. sp=sp-1
3. מהכתובת ש PC מצביע עליה מעבירים את החלק הנמוך של ה-PC.
4. sp=sp-1



IE - Interrupt enable רגיסטר אפשור הפסיקות

EX0
ET0
EX1
ET1
ES
ET2
X
EA


יש לשים לב ש EX0  ו- EX1 אמורים להיות עם גג.

EA- משמעותו enable all, אם הוא '0' אז הוא חוסם את כולם, אם הוא '1' אז הוא מאפשר פסיקות לפי מה שרשום בהמשך הרגיסטר.

בעזרת רגיסטר IE המתכנת קובע לאילו פסיקות תהיה היענות ואילו פסיקות יחסמו.
הסיבית EA היא סיבית שבעזרתה המתכנת קובע האם לחום את כל הפסיקות (בעזרת הפקודה CLR A)  או לאפשר פסיקות על ידי אחת בסיבית לפי הרשום בהמשך הרגיסטר.
בכל סיבית שבהמשך אפס חוסם את הפסיקה המתאימה ואחד מאפשר את הפסיקה.


רגיסטר ה-IP

PX0
PT0
PX1
PT1
PS
PT2
X
X


יש לשים לב ש PX0  ו- PX1 אמורים להיות עם גג.

0 - עדיפות נמוכה
1 - עדיפות גבוהה
רשום תכנית (שתי פקודות) שתאפשר את פיקת טיימר 0, פסיקת תקשורת טורית, וסדר העדיפות יהיה קודם תקשורת טורת ואחר כך פסיקת טיימר.

MOV IE ,#10010010b
MOV IP ,#00010000b





רשום שתי פקודות שמאפשרות פסיקות חיצוניות ו timer 1 וסדר העדיפות יהיה timer 1 אחר כך ex0 ורק אחר כך ext1.


MOV IE ,#10101101b
MOV IP ,#00001000b






על פי הטבלה אנחנו רואים ש INT1 ו EXT1 הם בעצם אותו הדבר יש גג, זאת אומרת שכדי להפעיל אותם צריך לשים בהם אפס.
אנחנו גם רואים בטבלה שכתובת הפסיקה של הפסיקה החיצונית 1 היא 13H, לכן נתייחס לזה בתכנית שנכתוב.
יש לשים לב שבין כתובת פסיקה לבין כתובת פסיקה סמוכה לה יש מרווח של שמונה בתים, זאת אומרת שאם אנחנו רוצים תכנית פסיקה ארוכה אנחנו נשתמש בקפיצה כדי שממנה נקפוץ אל התכנית של הפסיקה, כי כאמור אין מספיק מקום לתכנית. במקרה שלנו שמונת בתים יספיקו.








נתונה החומרה הבאה, לחיצה על המספק מדליקה את הלד לדקה, כתוב את התכנית:


ORG 0
SJMP start
ORG 13H
SETB P2.1

השהייה של דקה

CLR P2,1

RETI

ORG100H
START MOV IE, #10000100b
CLR P2.1
SJMP$



TCON

IT0
IE0
IT1
IE1
TR0
TF0
TR1TF1

ארבעת הסיביות הנמוכות של הריגסטר TCON שייכים למערכת הפסיקות החיצוניות.
שתי סיביות שייכות לפסיקה חיצונית 0.
שתי סיביות שייכות לפסיקה חיצונית 1.
הסיבית / הביט IT0 נשלט על ידי המשתמש, ובעזרתו המשתמש קובע האם הפסיקה החיצונית אפס תופעל על ידי רמה או שפה.
כאשר המשתמש שם אפס עובדים עם רמה וכאשר המשתמש שם אחד עובדים עם שפה, כלומר רק כאשר יש ירידה מאחד לאפס.


זאת אומרת כאשר הם עובדים בשפה אחרי ביצוע בקשת הפסיקה בזמן המוגדר הם מתאפסות.







רגיסטר ה- TCON

IT0IE0IT1IE1TR0TF0TR1TF1



IT1

אם שמים '0' עובדים על רמה LEVEL - ניתן לעשות פסיקה בכל עת שהיא. נפעיל בפקודה CLR IT1
אם שמים '1' עובדים על שפה / קצה EDGE - רק שיש מעבר מאחד לאפס ניתן לעשות פסיקה. נפעיל בפקודה: setb IT1




IE1
כאשר אנחנו שמים '0' -  אזי במצב שבו לא אפשרנו פסיקות CLR IE, במידה ומהלך הזמן הזה באה בקשת פסיקה, ולאחר מכן פתחנו את האפשרות לבקשת פסיקה מאוחר יותר - לא נדע על כך - וכאמור לא נטפל בבעיה.

כאשר אנחנו שמים '1' - אזי במצב שבו לא אפשרנו פסיקות CLR IE, במידה ובמהלך הזמן הזה באה בקשת פסיקה, ולאחר מכן פתחנו את האפשרות לבקשת פסיקות: אנחנו נדע שהיית בקשת פסיקה ואנחנו נטפל בה. "המנהל" בודק את הביט הזה, אם יש בו '1' זאת אומרת שמישהו ביקש פסיקה והוא מטפל בו, אם לא אזי מבחינתו לא היית בקשת פסיקה.





הביט IE אפס לוגי או אחד לוגי מתאים לפסיקה חיצונית אפס או אחד בהתאמה.
זהו ביט שעולה ל'1' כאשר יש ירידה מאחד לוגי לאפס לוגי באחד מהדקי הפסיקה החיצונית (להזכירם הפסיקות החיצוניות הם בגג - זאת אומרת הם פעילות בנמוך, זאת אומרת פועלות רק כאשר הן ב '0', זאת אומרת המצב שהן לא פעילות הוא '1').
הביט יתאפס רק כאשר נפנה לכתובת מתאימה בזיכרון התכנית שמתאימה לפסיקה.




תרגיל נוסף בפסיקה



במועדון מפורסם לא מרשים להיכנס יותר ממאה אנשים בו זמנית עקב צו משטרה ומכבה אש למען הבטיחות.
למועדון דלת כניסה אחת ודלת יציאה אחת.
לא ניתן לצאת מהכניסה ולהיפך.
כל פעם שמישהו נכנס המתג s0 נלחץ.
כל פעם שמישהו יוצא המתג S1 נלחץ
רשום תכנית שברגע שיש למעלה ממאה אנשים הזמזם יזמזם.


פתרון

ORG 0
LJMP start 
ORG 3 //  תכנית הפסיקה החיצונית אפס
inc A
CLR C; איפוס דגל הנשא
CJNE A .#100, stam
stam: JC off ; קפוץ לתווית אם יש דגל נשא
// הוא ימשיך את קטע התכנית הבא אם אין דגל נשא
setb p2.5; מפעיל את הזמזם
RETI
off: CLR P2.5
RETI

ORG 13H
DEC A
CLR C
CJNE A ,#100, stam1
stam1: JC off1
setb p2.5
RETI
off1: CLR P2,5
RETI

start: MOV IE ,#10000101b
SET IT0 ; כדי שיספר כל מי שנכנס, לא משנה כמה זמן הוא עומד בכניסה.
CLR P2.5; כיבוי הזמזם
MOV A ,#0
SJMP $
END



אנחנו מנצלים את הפקודה CJNE על מנת לבצע את פעולת החיסור בין A ל100, ולבדוק האם יש דגל נשא או אין, בכל מקרה אנחנו נגיע לתווית stam כי אם 100 שווה נקפוץ ל stam ואם הוא לא שווה הפקודה הבאה היא התווית stam
כאשר יש מספר גדול פחות מספר קטן - אין דגל הקרי, ואז אנחנו נדליק את הזמזם.
כאשר יש מספר קטן פחות מספר גדול - יש דגל נשא, ואז אנחנו נקפוץ 









מונה התכנית הוא ה___, הפקודה נאגרת ב_____

שלבי הבאת הפקודה הם:____________________________________

בזיכרון הנתונים הפנימי יש____ בנקים, מכתובת ___ עד ____ (בעשרוני).

למיקרו פרוסספור יש: ______ ו-________.

במיקרו בקר יש 4 ________ לקלט ופלט.

ברכיבים ________________ אין זיכרון תכנית.

מצביע המחסנית הוא ______, והוא שווה ל____ לאחר פעולת RESET.




תקציר כל הפקודות באסמבלי מיקרו בקר C51 פירוש כל הפקודות נוסחאון בשפת ASM-51 נוסחאון במיקרו בקר 8051

ADD A, Rn
מבצע פעולת חיבור בין רגיסטר Rn ואקומולטור A, כאשר התוצאה נשמרת באקומולטור (A).

ADD A, direct
מוסיף את התוכן שיש בזיכרון הנתונים הפנימי  (direct) שהוא זיכרון RAM לאקומולטור, וכמו כן התוצאה נשמרת באקומולטור

ADD A, @Ri
מבצע פעולת חיבור בין מה שהרגיסטר Ri מצביע עליו עם האקומולטור, התוצאה נשמרת באקומולטור.

ADD A, #data
מבצע פעולת חיבור באופן מיידי בין הנתון (המספר) עם האקומולטור, התוצאה נשמרת באקומולטור.


ADDC A, Rn
מבצע פעולת חיבור בין רגיסטר Rn ואקומולטור A, כאשר התוצאה נשמרת באקומולטור (A), כמו כן דגל הנשא (carry flag) מושפע בהתאם.

ADDC A, #data
מבצע פעולת חיבור באופן מיידי בין הנתון (המספר) עם האקומולטור, התוצאה נשמרת באקומולטור, כמו כן דגל הנשא (carry flag) מושפע בהתאם.


SUBB A, Rn
מבצע פעולת חיסור בין  האקומולטור A לרגיסטר Rn, כאשר התוצאה נשמרת באקומולטור (A).

SUBB A, direct
מחסר את התוכן שיש באקומולטור עם זיכרון הנתונים הפנימי  (direct) שהוא זיכרון RAM, וכמו כן התוצאה נשמרת באקומולטור

SUBB A, @Ri
מבצע פעולת חיסור בין האקומולטור למה שהרגיסטר Ri מצביע עליו, התוצאה נשמרת באקומולטור.

SUBB A, #data
מבצע פעולת חיסור בין האקומולטור לנתון (המספר) באופן מיידי , התוצאה נשמרת באקומולטור.


INC A
מגדיל את ערך האקומולטור באחד.

INC Rn
מגדיל את ערך הרגיסטר Rn באחד

INC direct
מגדיל באחד את הערך שנימצא בכתובת הזיכרון הפנימי RAM

INC @Ri
מגדיל באחד את הערך שהרגיסטר Ri מצביע עליו 



DEC A
מחסיר את ערך האקומולטור באחד.

DEC Rn
מחסיר את ערך הרגיסטר Rn באחד

DEC direct
מחסיר באחד את הערך שנימצא בכתובת הזיכרון הפנימי RAM

DEC@Ri
מחסיר באחד את הערך שהרגיסטר Ri מצביע עליו


INC DPTR
מעלה באחד את DPTR (מצביע זיכרון הנתונים החיצוני)


MUL AB
מכפיל A ב-B, התוצאה נישמרת באקומולטור.

DIC AB
מחלק A ב-B, התוצאה נישמרת באקומולטור

DA A
מתאים את האקומולטור למספר עשרוני


MOVC A,@A+DPTR
העברה של נתונים אשר מתבצעת בזיכרון התוכנית: מעביר את מה שהסכום של DPTR ו-A מצביע עליו לתוך האקומולטור A.

MOVX A,@Ri
מעביר את מה שהרגיסטר Ri מצביע עליו (מצביע בזיכרון התכנית החיצוני) אל האקומולטור.

MOVX A, @DPTR
מעביר את מה ש-DPTR (מצביע בזיכרון הנתונים החיצוני) מצביע עליו לתוך האקומולטור.

MOVX @Ri, A
מעביר את האקומולטור לתוך מה שהרגיסטר Ri מצביע עליו

MOVX @DPTR, A
מעביר את האקומולטור, לתור מה ש-DPTR מצביע עליו (DPTR מצביע של זיכרון הנתונים החיצוני)


PUSH ACC
מעלה את מצביע המחסנית sp באחד, ומכניס למחסנית את האקומולטור. A.

POP ACC
שולף מהמחסנית (מה ש-SP מצביע עליו) את הנתון, מעביר לאקומולטור ומוריד באחד את מצביע המחסנית.


PUSH direct
מעלה את מצביע המחסנית sp באחד, ומכניס למחסנית את מה שיש בכתובת DIRECT בזיכרון הנתונים הפנימי RAM.


POP direct
שולף מהמחסנית (מה ש-SP מצביע עליו) את הנתון, מעביר לנתון בכתובת DIRECT בזיכרון הנתונים הפנימי, ומוריד באחד את מצביע המחסנית.

XCH 
מצבע החלפה בין שניים.

XCHD A, #Ri
מחליף את ארבעת הספרות הנמוכות של האקומולטור עם ארבע ספרות נמוכות של התוכן שהרגיסטר Ri מצביע עליו.


CLR C
שם אפס לוגי בביט C.

CLR bit
שם אפס לוגי בביט.

SETB C
שם אחד לוגי בביט C.

SETB bit
שם אחד לוגי בביט.

CPL C/bit
הופך את מה שנימצא בביט או בביט C, אם היה אפס לוגי אז יהיה אחד לוגי, אם היה אחד לוגי אז יהיה אפס לוגי.

ANL C,bit 
פעלות AND לוגית בין הביט לביט C - התוצאה נישמרת בביט C.

ORL C,bit 
פעלות OR לוגית בין הביט לביט C - התוצאה נישמרת בביט C.


RLC A
מסובב שמאלה את כל הסיביות יחד עם דגל הנשא

RRC A
מסובב ימינה את כל הסיבוית יחד עם דגל הנישא

RR A
מסובב ימינה את האקומולטור

RL A
מסובב שמאלה את האקוטמולטור

SAWP A
מחליף את ארבעת הסיביות הנמוכות עם הגבוהות.

NOP 
פקודת סרק



הדקי הרכיב 89c51 80c51 8051

הדקים 1-8: הדקים של P1. משמשים לקלט או לפלט.
9: רגיל איפוס
10-11 TXD/RXD תקשורת נתונים:
transmit
recive
p3.0
p3.1
12-13 הדקי פסיקה חיסונית 0, פסיקה חיצונית 1. יש להם גג, הם פעילים בנמוך, פועלים באפ לוגי.

14-15 כניסות לטיימר 0 ולטיימר 1.

16-17: קריאה וכתיבה מזיכרון נתונים חיצוני.

18-19 מחברים גביש בין שני ההדקים הללו.

20 - רגל אדמה.

21-28 p2

29 PSEN PROGRAM STORE ENABLE ,
אפשור אחסון תכנית: זוהי רגל הקריאה מזיכרון תכנית חיצוני.

30 - ALE
רגל ה-ALE
adress latch enable
אפשר נעילת כתובת

כדי לחסון ברמות ההדקים שיש למעבד, נוהגים לעשות שיתוף הדקים כלומר הדקים מויימים ישמשו לשני תפקידים.

בכל מחזור פס (קריאה או כתיבה) בחלק הראשון של המחזור משמשים ההדקים 32-39 כחלק הנמוך של פס הכתובוץ, כלומר A0 עד A7.

בחלק הנוסף של המחזור, ההדקים האלה הופכים להיות הדקים של נתונים, מDO עד D7.

ולכן הם גם נקראים AD0 - AD7

רגל ה-ALE אומרת מתי יש בפס המשותף כתובות ומתי בפס המשותף נתונים.
כאשר ברגל ה-ALE יש אחד לוגי, אז בפס המשותף יש כתובות, ולעומת זאת מתי שיש ברגל ה-ALE אפס לוגי אז יש בה נתונים.

לשיתוף כזה של הדקים קוראים: פס מרובב.

וזה נקרא ריבוב פסים.

31: EA
EXTERNAL ADRESS3
בעזרת הרגל הזאת אומרים מיקרו-בקר האם עובדים עם זיכרון התכנית שבתוכו או שכל זיכרון התכנית הוא חיצוני.

אחד לוגי בהדק הזה אומר שזיכרון התכנית הוא פנימי.
אפס לוגי בהדק זה אומר שזיכרון התכנית הוא חיצוני,

32-39: P0

40  - VCC, מתח (או 5V)





מחזור פס

כל פקודה שמתבצעת במיקרו מתבצעת באחד מתוך המחזורים הבאים:
מחזור קריאה.
מחזור כתיבה
מחזור סרק.

מחזור סרק הוא מחזור שבו מתבצעת פעולת פנימית בתוך המיקרו בקר.
למשל העברה של נתון בין הרגיסטרים, הפעלת פורטים מסויימים וכו'.

מחזור קריאה: מחזור קיראה שבו המיקרו בקר קורא נתון מזיכרון שנימצא מחוץ למיקור: במצב כזה שלושת הפים פועלת: פס הכתובות, פס הנתונים ופס הבקרה.


במחזור כתיבה: המיקרו בקר כותב נתון אל הזיכרון החיצוני, שוב יש שימוש בשלושת הפסים. הנתון יוצא מהמיקרו ונכתב אל הזיכרון החיצוני.

סרק
MOV A, #55H

קריאה
MOVX A, @DPTR

כתיבה
MOVX DPTR ,A



TIMERS טיימרים מיקרו בקר 8051

במיקרו בקר שלנו יש טיימר שנקרא up counter, זאת אומרת שהוא סופר למעלה.. למשל: אפס, אחד, שתיים....


בתוך המיקרו יש לנו שני מונים: TIMER 0, ו- TIMER 1.
TH0 - שמונה סיביות
TL0 - שמונה סיביות


TL1 - שמונה סיביות
TH1 - שמונה סיביות



H-high
L-low

TF0 - בקשת פסיקה של טיימר0
TF1 - בקשת פסיקה של טיימר1

כאשר TH0 ו-TL0 מתמלאים, (בהכל יש אחד), זה גורם לך שתהיה בקשת פסיקה של טיימר0.
אותו דבר קורא בטיימר1.


טיימר: זמנן, מערכת שסופרת זמן.

אם מתנד הגביש הוא 12MHZ, נחלק אותו לשתיים עשרה פולסי שעון, 12MHZ חלקי שתיים עשרה: נקבל שכל פולס שעון הוא בתדר של 1MHZ, וזמן המחזור של כל פולס הוא: אחד חלקי אחד מגה הרץ: אחד מיקרו שנייה.




ישנם שני רגיסטרים ששולטים על הטימרים, הם נמצאים ב SFR:

רגיסטר ה-TMOD
הוא נימצא בדף הנוסחאון.
G -C/T - M1 - M0 - G - C/T - M1 - M0

הצד הימני הוא לטיימר 0
הצד השמאלי הוא לטיימר 1

M1 ו-M0 קובעים את אופן העבודה באופן הבא:

M1 M0

אופן עבודה
M0
M1
0
0
0
1
1
0
2
0
1
3
1
1

G - כאשר שמים אפס לוגי הוא מאפשר ספירה

G-  כאשר שמים אחד לוגי לא מאפשר ספירה

C/T - כאשר שמים אפס לוגי עובדים עם טיימר, כאשר שמים אחד לוגי עובדים עם טיימר



מיעון מיידי:
MOV A,#33

מיעון עקיף:
MOV A,@R1

מיעון ישיר:
MOV A,33


בעזרת ה-TMOD קובעים האם הטיימר יעבור כטיימר או כקאונטר, האם לאפשר לו ספטירה ובאיזה אחד מארבע אופני עבודה הוא יעבוד.



רגיסטר ה-TCIN
נימצא אף הוא בדף הנוסחאון.

ארבע סיביות נמוכות שייכות לפסיקות החיצוניות.

ארבע סיביות גבוהות:

TF1 - TR1 - TF0 - TR0

TRO - כאשר יש אפס לוגי הוא עוצר, כאשר יש אחד לוגי הוא רץ


TF0 - הביט עולה לאחד כאשר טיימר 0 ביקש פסיקה.



טיימר 0 באופן 0

באופן 0 המונה עובד כמונה בין 13 סיביות (רק חמש סיביות ב-TH0).
זהו מצב עבודה שנותן תאימות למיקרו בקר מדור קודם שעבד עם 13 סיביות.
כדי שהמונה יספור המפסק שקרוב אליו צריך להיות סגור.
המפסק יהיה סגור אם ביציאת שער AND יש אחד לוגי, כדי לקבל אחד ביציאה.
שתי הכניות של שער ה-AND חייבות להיות באחד לוגי.
הכניסה העליות של שער ה-AND מקבלת אחד בשני מקרים: אחד אם ב-G המתכנת ישים אפס (יש מהפך).
דרך שנייה, ב-G שמים אחד, ואז אחרי המהפך יש אפס, ולכן אם הכניסה הכניסה התחתונה של שער ה-OR תהיה באחד, אז ביציאת שער ה-OR יהיה 2.

הכניסה השנייה של שער ה-AND מחוברת ל -TR0, המתכנת יכול לשלוט האם לשים אחד, או אפס, כאשר הוא שם אפס: מפסיק לספור, כאשר שם אחד הוא סופר.


טיימר 0 באופן 1

טיימר 0 באופן אחד עובד בדיוק כמו באופן אפס, רק שהפעם משתמשים בכל הסיביות.


עבור גביש של 11.0592MHZ מהו קצב הפסיקות באופן כזה:

עושים את תדר הגביש חלקי שתיים עשרה, ואת כל זה מחלקים בשתיים בחזקת מספר הסיביות (שש עשרה).
14.0625 שניות.


טיימר 0 באופן 2

אופן 2 ניקרא גם AUTO RELOAD, טענה אוטמטית.
באופן זה רק הטיימר הנמוך (TL0) הוא זה שסופר. מתאימים את החלק הגבוה (TH0), במספר הרצוי, וכאשר החלק הנמוך מסיים את הספירה ומקבל פולס ספירה נוסף: הוא נותן בקשת פסיקה וגם אומר לTH0 להטעין את TL1 במספר שיש ב-TH0 עצמו.
TL0 מתחיל לספור, TH0 נישאר קבוע (לא מתאפס).



תרגיל דוגמה:
נתונה התכנית הבאה:

MOV TMOD, #20H
MOV IE, #88H -מאפס פסיקת טיימר
MOV TH1, #246
MOV TL1, # 246
SETB TR1
SJMP$ // קופצים במקום עד שיש פסיקה.
ORG 1BH
INC P1
RETI


(יש לזכור כי הוא יגיע ל-9 פולסים ועוד פולס אחד ואז הוא יבקש בקשת פסיקה ויטעים את TL במה שיש ב-TH)

צייר את צורת הגלים בפורט 1.

אם תדר הגביש ייקטן פי 2, אזי התדר של מה שייצא ייקטן פי 2.

בעצם בנינו מחולל תדר בקלי קלות.

p1.0 01010101

p1.1 001100110011

p1.2 0000111100001111

וכך הלאה.



שפת C51


עד כה כתבו כל מיני תכניות בשפת אמסלי, היה נחמד והיה טוב, אבל אסמבלי היא שפה שעבר זמנה, והגיעה הזמן לעבור לשפה האמיתית: שפת C. השפה שבאה האחרי השפה C, שהיא שפה שיותר מקורבת לבנים האדם.


הגדרת משתנים:
int - מספר שלם
char - תו
float - שברים
string - מחרוזת


אופרטורים:
+ חיבור
- חיסור
/ חילוק ללא שארית
% חילוק שהתוצאה שלו היא רק השארית
* כפל
&& פעולת "וגם" לוגית (כאשר '1' או כל המספרים האחרים למעט 0 הם אמת, ואפס בלבד זה שקר)
|| פעולת 'או' לוגית בין שני סיביות ('1' או כל מספר אחר שהוא ל 0 הוא אמת, ואפס הוא שקר)

| פעולת אנד לוגית בין שני מספרים בינאריים. (בין שני בתים המכילים סיביות)
& פעולת 'וגם' לוגית בין שני מספרים בינאריים. (בין שני בתים המכילים סיביות)



בכל סוף משפט בשפת C חייב להיות ; (נקודה פסיק), על מנת שהקומפיילר יבדיל בין פקודה לפקודה


אנחנו מתחילים כל כתיבת תוכנית בתוך פונקציית void כלומר לא מחזירה ערך:

void main()
{
כל התכנית הראשית, בעצם התכנית שנכתוב
}





פקודות 

פקודת תנאי if

מבנה:
if(תנאי)
{
אוסף פקודות
}

else

{
אוסף פקודות
}


אופן פעולה:
התנאי נבדק פעם אחת בלבד. אם התנאי מתקיים הוא מבצע את אוסף הפקודות אחרי ה-if.
אם התנאי לא מתקיים הוא מבצע את אוסף הפקודות אחרי ה- else.



פקודת while

מבנה:
while(תנאי)
{
אוסף הפקודות
}


אופן פעולה:
כל עוד התנאי מתקיים כאשר נכנסים אל ה-while ואחרי סיום כל הפקודות: אוסף הפקודות ימשיך לרוץ



פקודת do-while

אופן פעולה: הפקודה קודם כל עושה את אוסף הפקודות, ורק אחר כך בודקת האם.
(בשונה מ while שקודם בודקת את התנאי ורק אחר כך מבצעת את הפקודות אם התנאי מתקיים או לא)




לולאת for

מבנה:

for( x; y; z )
{
אוסף פקודות
}

אופן פעולה:

x - אוסף פקודות ראשון חד פעמי
y - תנאי שנבדק אחרי כל z, ובכניסה ללואה.
z - אוסף פקודות אחרון שמתבצע כל סוף ביצוע אוסף פקודות

הפקודות של x מתבצעות
אוסף הפקודות מתבצע
הפקודות של z מתבצעות
התנאי y נבדק אם הוא מתקיים ממשיכים באוסף הפקודות.... אם התנאי לא מתקיים יוצאים מהלולאה.



switch and case

מבנה:
switch(ביטוי)
{
case _____;
אוסף פקודות
break;

case _____;
אוסף פקודות
break;
.
.
.
.

deafult;
אוסף פקודות
}


פונקציית פלט קלט במסך LCD 
על מנת שנוכל לזמן את הפונקצייה הזאת אנו נצטרך לכתוב את זה בתחילת התכנית.

#include <stdio.h>
h - header כותר
stdio = starndart inpur output


אנחנו צריכים לשמור על תחביר תקין על מנת שנוכל לזמן את הפוקנציה
syntax = תחביר


פלט
printf("ייכתב כאן כל התוכן שנכתוב למעט תווים מיוחדים שנזכיר למטה", y);

y - כאן ייכתבו ביטויים
תווים מיוחדים
\n
גורם לירידת שורה

\t
נשאר באותה שורה אבל התוכן שייכתב אחרי הפקודה הזאת יזוז קצת ימינה

\r
תו אחד אחורה


%d - decimal  מספר עשרוני
%f - float מספר לא שלם
%h - hexa מספר הקסה-דצימלי
%c - code  ערך אסקי של הכתב
%o - octaly ערך שלם אוקטלי


למשל:

int x, y;
y=4;
x=5;

printf("x+y=%d+%d=%d",x,y,x+y);

מה שנקבל על הצג:

x+y=5+4=9



קלט


על מנת לקלוט מהמשתמש נצטרך לשמור גם על תחביר תקין:

scanf("%x",&משתנה)
x- טיפוס הערך שאותו אנחנו רוצים לקלוט,
למשל:
%d... כמו לעיל
התוכן בין הגרשיים זה מה שאותו

&ביטוי
המשתנה שאליו נקלוט את הקלט

דוגמה:

int x, y;
printf("Please, enter two numbers:");

scanf(/n %d, x);
scanf(/n %d, y);


printf("x+y=%d+%d=%d",x,y,x+y);




התכנית שלעיל קולטת שני משתנים מהמשתמש תוך כדי הוראה נימוסית אשר מבקשת בצורה יפה מהמשתמש לקלוט שני מספרים, ולאחר מכן מבצעת פעולת חיבור ומציגה את התרגיל והתוצאה בצורה יפה למשתמש.



קטע תכנית:

#include <stdio.h>
void main()
{
int x, y;
char my_choice;
printf("Please, enter two numbers:");

printf("the first number:/n ");
scanf( %d, x);
printf("the second number:/n :");
scanf( %d, y);

printf("/n what to make between the two numbers?);
printf("/n  for add press +");
printf("/n  for subtraction press +");
printf("/n  for multiply press +");
printf("/n  for division press + /n");


scanf(" %c. &my_choise) 
swtich(my_choise)
{
case '+'
printf("/nx+y=%d+%d=%d",x,y,x+y);
break;


case '-'
printf("/nx-y=%d-%d=%d",x,y,x-y);
break;


case '*'
printf("/nx*y=%d*%d=%d",x,y,x*y);
break;



case '/'
printf("/nx/y=%d/%d=%d",x,y,x/y);
break;

deafult()
printf("it is a wrong key");
break;
}

}



התכנית שלעיל מבקשת מהשתמש לקלוט שני מספרים, ומציגה לו ארבע פעולות בין שני המספרים: חיבור, חיסור, כפל וחילוק.
המשתמש בוחר את הפעולה שהוא רוצה על פי ההקשה שלו, ובהתאם למה שהוא הקיש.
הפעולה שהוא בחר מוצגת לו על המסך, וכמו כן הפיתרון.



תכנית שמבצעת עצרת שפת C הסבר


int i, num, result;
printf("\n Please enter a number:");
scanf("%d", &num)
*********************8
for(i=2, result; i<=num; i++)
result=result*i;

print("\n the Azeret of %d=%d",num,result);








רשום תכנית שתקלוט מהשמשתמש ציונים של תלמידי הכיתה במקצוע המיקרו.
התכנית תספור את כמות הנכשלים, את כמות התלמידים שציונים מעל 90 ואת ממוצע הציונים בכיתה, בכיתה יש 20 תלמידים.


int agv, grade, best_grades, bad_grades,stu;
avg=0;
best_grades=0;
bad_grades=0;


for(stu=1; stu<=20;i++)
{
printf("Please enter the grade of the students number: %d \n" , stu)
scanf("%d", &grade)

avg+=avg;

if(grade>90)
best_grades++;

if(grade<55)
 bad_grades++;

}

printf("\n the avg is: %f", (float) avg/stu)
print("\n the number of the good students is: %d , best_grades);
printf("\n the number of the bad students is: %d" , bad_grades);





קלוט מספר מהמשתמש ומצא לו את המספר השלם הכי קרוב לשורש של המספר הנ"ל.


int number,i ;

printf("please enter number \n")
scanf("%d", &number)

for (i=0; i*i <=number; i++)
{
}

if( i*i - number > number-(i-1)*(i-1))
printf("\n the number is: %d", i-1)

else
printf("\n the number is: %d", i)





תרגול בשפת C51 ובשפת הסף אמסבלי



כתוב תוכנית בשפת הסף ובשפת C51 אשר תקבל בלוק של נתונים בזיכרון הנתונים הפנימי) ותסכום את המספרים שגדולים מארבע, בבלוקים 100H עד 300H
*בשפת אסמבלי אין צורך לבדוק שהנתונים לא חרגו מהמקסימום (256)

נחשב כמה בלוקי נתונים יש בין הכתובות 200 הקסה עד 300 הקסה , בעזרת המחשבון:
300H-200H= 100H = 100 decimal

char tavle_of_datas[100]
for ( i=0 ; i < 100; i++)  // מילוי בלוק הנתונים במערך
tavle_of_data[i] 0x


for ( i=0 ; i < 100; i++)
{
if (tavle_of_data[i] > 4)
sum = sum + number_data
}

data at 0x600h = sum;



mov R2, #0  // סוכם לנו את כל המספרים הגדולים מארבע
mov DPTR, #100H
again:
CLR C
MOV R0 ,@DPTR

CJNE R0, #4, CHK // בודק האם המספר שווה ארבע, אם הוא לא שוה אז הוא ממשיך בבדיקה, אחרת בודק מספר הבא
SJMP another_number

CHK:
MOV A, @DPTR
SUBB A, #4
ANL A.#80H // בודק האם תוצאת החיסור היא חיוביות או שלילית
CJNE A. #80H, another_number// השווה, קפוץ אם שמונים הקסה, כלומר שלילי
// אם הגענו לפה סימן שהמספר הוא מספר שגדול מארבע
MOV A,#0
ADD A, R0

mov R7. A //מעביר את מה שיש באקומולטור לרגיסטר

mov A, R2 // מעביר את מה שיש ברגיסטר אר שתיים שהוא הסוכם שלנו, לאקומולטור
mov A, R7

mov R2, A

another_number:

INC DPTR
CJNE DPTR, #300H , again // קופץ לתווית "שוב" כל עוד המצביע לא שווה שלוש מאות הקסה


כתוב תכנית בשפת הסף או בשפת c51 אשר תוסיף את כל המספרים הזוגיים מהנתון שבכתובת 99H ותחסר את כל המספרים החיוביים מהנתון שבכתובת 99H.

הערה: הנח כי כל המספרים חיוביים ואינם שווים אפס.

if(tavla[i] %2 ==0) // אם המספר זוגי
0x100= 0x100+tavla[i];
else
0x100= 0x100-tavla[i];


LJMP START

ORG 03H
ljmp aa


ORG 200
START:
mov IE, #81H
MOV R1, #50H
SJMP $

aa:

// השהייה על מנת להתגבר על ידי ניטור מגעים
mov r5,#100
dd: mov r4,#100
djnz r4, $
djnz R5, dd


mov A, p1

mov R7 , A

ANL A, #1
JZ hibbor//קפוץ אם יש אפס, כלומר חיובי

//חיסור
mov A, p1
mov R4, A
mov A, @R1

CLR C
SUBB A, R4
mov @R1 , A
RETI

hibbor:
mov A, p1
ADD A, @R1
mov @R1 , A


RETI

END




4 מספרים עוקבים הם מספרים מדהימים, כתוב תכנית שתבדוק האם בלוק הנתונים החל מכתובת: 80H ועד שש עשרה בתים קדימה, כולו מורכב ממספרים מדהימים.

for (i=0; i<16; i=i+3)
while (flag)
{
if (tavla[i+3]-1==tavla[i+2] && tavla[i+2]-1==tavla[i+1] && tavla[i+1]-1==tavla[i])

}
flag=0;

if (flag)
p1_0=0;

else
P1_0=1;




כתוב תכנית בשפת הסף של המיקרו בקר 8051 שתבדוק מישהו המספר הגדול ביותר (המקסימלי) בבלוק הכתובות: 100H עד 130H בזיכרון הנתונים החיצוני. התכנית תאחסן בזיכרון הנתונים בכתובת 60H בזיכרון הנתונים הפנימי.

פתרון תשובה:

mov dptr , #100h  // מצביע בזיכרון הנתונים החיצוני
mov r1, #48 // מונה לולאה
movx A, @dptr
mov R7, A // ברגיסטר הזה יאוחסן המספר המקסימלי

again:
movx A, @dptr
mov R3, A
mov A, R7

CLR C
SUBB A, R3
ANL A, #80H // אם באקומולטור יהיה אפס: אין יותר גדול מהמקסימום
JNZ switch_max  // אם באקומולטור יש מספר שהוא לא אפס: זאת אומרת שיש יותר גדול מהמקסימום
inc dptr // אם הגענו לפה אין מספר גדול מהמקסימום, לכן לבדוק את הבא
djnz r1 , again
SJMP SOF
switch_max: // אם הגענו לפה צריך להחליף את המקסימום, כי יש יותר גדול ממנו
movx A, @dptr
mov r7, A

inc dptr
djnz r1 , again
SJMP SOF

SOF:
MOV A, R7
MOV 60H, A
SJMP $

end





כתוב תכנית בשפת הסף של המיקרו 51 אשר תחבר בין הניבל הנמוך והניבל הגבוהה של הנתון בכתובת 4010H בזיכרון הנתונים הפנימי, ותשמור אותו באקומולטור.

MOV dptr,#400h
movx A, @dptr
mov R4, A // save it

ANL A, #11110000b // high nibble

mov r5, #4 // counter of loop
aga: rr a
djnz R5, aga
MOV R5, A // ONE NUMBER

MOV A, R4
ANL A, #00001111b  // SECOND NUMBER

ADD A, R5

sjmp $
end


כתוב תכנית בשפת הסף של המיקרו 8051 שבהתחלה תדליק נורת אחת. ברגע שנלחץ על כפתור הנורות תרוצנה ימינה, ברגע שנלחץ על כפתור אחר הנורות תרוצנה שמאלה. הנח כי הנוריות נלדקות בנמוך ('0').

*על מנת לראות את האורות רצים בעין, אנו צריכים לשים השהיות. לא חובה לשים בתכנית זו השהייה.

LJMP START
org 03h
mov r4,#1
setb c
reti

org 13h
mov r4,#1
clr c
reti


ORG 200
start:

MOV IE, #10000101B
MOV A, #11101111b
mov p1,#11101111b
mov r4,#0
cjne R4, #1 , $



iinterrupt1:
again1:
RR A
jnc iinterrupt2
MOV P1, A
SJMP again1
RETI


iinterrupt2:
again2:
RL A
jc iinterrupt1
MOV P1, A
SJMP again2
RETI

END



אותה תכנית עם הסברים

LJMP START
org 03h  // פסיקה חיצונית שנייה
mov r4,#1
setb c // כך ממן ריצת נוריות ימינה
reti

org 13h  // פסיקה חיצונית שנייה
mov r4,#1
clr c  // שם אפס לוגי בדגל הקרי, כך מסמן ריצת נוריות שמאלה
reti


ORG 200
start: // התכנית הראשית שממנה המיקרו בקר מתחיל לרוץ

MOV IE, #10000101B  // מאפשר שתי פסיקות חיצוניות
MOV A, #11101111b
mov p1,#11101111b
mov r4,#0
cjne R4, #1 , $   // ממשיץ לקפוץ במקום עד שיש פסיקה



iinterrupt1:
again1:
RR A
jnc iinterrupt2  // בודק האם מישהו לחץ על פסיקה שנייה באמצעות דגל הקרי
MOV P1, A
SJMP again1
RETI


iinterrupt2:
again2:
RL A  // מריץ את נורות הלדים שמאלה
jc iinterrupt1  // בודק האם מישהו לחץ על פיקה ראשונה באמצעות דגל הקרי
MOV P1, A
SJMP again2
RETI

END




כתוב תכנית בשפת הסף של המיקרו 8051 אשר בודקת האם הרכיב הלוגי, מסוג שער AND תקין . שני הכניסות שלו הם בפורטים: p1.1 ו- p1.2, היציאה שלו היא בפורט p1.3.
אם הרכיב הלוגי תקין נורת הלד בפורט p1,4 תידלק. (היא פועלת בגבוה, דרוש אחד לוגי על מנת להדליק אותה)

LJMP START

org 200
start:

CLR P1.4

CLR P1.1 //0
CLR P1.2 //0
jb p1.3 ,bed

//0
SETB P1.2 //1
jb p1.3 ,bed

SETB P1.1 //1
//1
jnb p1.3 ,bed

//1
CLR P1.2 //0
jb p1.3 ,bed

SETB P1.4
SJMP $

BED:
SJMP $




END


כתוב את אותה תכנית בדיוק בשפת c51


# include <regx51.h>

void main()
{


int x=0;

if (x<4)
{
P1_0 = 1 ;
}
}






אין תגובות:

הוסף רשומת תגובה