قسم الميكروكنترولر والروبوت ودوائر الاتصال بالحاسب الالي قسم المتحكمات الـ microcontroller و المعالجات microprocessor و التحكم الرقمي بالكمبيوتر CNC والانظمة الآلية والروبوت Robots

   

ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 10-08-2018, 09:15 AM المشاركة 105   
افتراضي




كود اسيمبلى لقراءة وحدة I2C :
الوحدة تحتاج ثلاثة برامج فرعية Sub واحد لقراءة بايت و تستخدمه لأى عدد وهو يتطلب تحديد عنوان البدء لذا نضع رابع لتحديد البدء.
إذن هنا نبدأ بالتعريفات و يجب ملاحظة أنها قد تتشارك مع كثير من التعريفات المطلوبة لباقى الكود وليست بالضرورة تتخصص لقراءة وحدات I2C .أول تعريف قد يكون مفيدا لكثير من المبرمجين و يوفر كثير من الوقت و الكود. تعريف HW_Err حيث يخصص خانة من الذاكرة باسم أعطال المكونات وهى تستطيع أن تحوى بيانات 8 أجهزة و بتعليمه وضع صفر يكون الكل بخير و يلى ذلك تعريف كل بت منهم باسم أخر كقولنا مثلا
MemErr = HW_ERR.0
ADCErr=HW_ERR.1
الخ ثم SETB تعرف أن هذه القطعة لا تعمل و من ثم لاحقا لديك الأمر JB لتضع رسالة خطأ مناسبة للمستخدم. لو تركت هذا للمترجم سيخصص بايت كاملة لكل بت منهم أى 8 بايت.

كود:

; Definitions

;HW_Err		EQU	20h
Dev_Add		EQU	21h
ByteCount	EQU	22h
BitCount	EQU	23h
PgAddress	EQU	24H		
AckDel		EQU	25h
DelTime1	EQU	26h
DelTime2	EQU	27h

SDA		EQU	P0.2		; Mem
SCL		EQU	P0.3
يلى ذلك تعريف Dev_Add أى عنوان القطعة و يمكنك تخصيص مكان فى الذاكرة كما هو مكتوب أو تكتفى بأن تضعه فى المراكم A و تنفذ ما شئت فقط لا تنسى أن تغير التعريف أو التعريف و الكود حسب المترجم لديك.
تعريف ByteCount فقط ليذكرك كم بايت كتبت من الصفحة Page لو ستكتب صفحة كل مرة. تعريف BitCount يمكنك حقيقة استبداله بأى متغير متاح لديك فالفكرة أن البايت بها 8 بت و انت تحتاج لعدهم وهنا للتوضيح فقط خصص لها مكان فى الذاكرة لكن يمكنك استخدام مسجل من 0 إلى 7 أو أى خانة تسميها Count تعد بها كل الدورات الموجودة فى البرنامج.
PgAddress أيضا مجرد خانة لتحفظ فيها أين تريد بدء الكتابة داخل الوحدة.
AckDel لو تستخدم قطع كثيرة متنوعة على ذات الخط قد يختلف زمن انتظار الرد ACKNOWLEDGE من طراز لآخر وقد تحتاج أن تجعل الزمن متباين و إلا يمكنك استخدام رقم ثابت و نستغنى عنه.
DelTime1,2 خانتان لعد زمن تأخير سواء قليل حتى اكثر من 256 أو اكثر حتى اكثر من 65536 بهما معا و يمكنك دمجهما مع أى خانات مخصصة لما يسمى Scratch Pad أو كشكول المسودة حيث تحسب أشياء وقتية.
SDA,SCL مطلوبان للنظام.
كود:

Mem_Init:				;  RESET ATMEL memory, a dummy write
;	MOV	HW_ERR,#0		; Clear all errors
	ACALL	MemStart		; the 24C01 reply erroneously IF uP is reset, and needs write cycle
	MOV	A,Dev_Add		; Device address 1010,page 000 and write bit
	ACALL	WriteMemByte
	ACALL	SendPgAdd
	ACALL	MemStop
	ACALL	Wait_10ms
	RET
	
CalcMemAdd:			; Calculates Page Address by PageNu in A * 8
	MOV	B,#8
	MUL	AB
	MOV	PgAddress,A
	RET
الكود التالى خاص بالذاكرة 24C01 من إنتاج أتميل فقط حيث بعد ريسيت قد لا تستجيب كما يجب لذا يجب تهيئتها باستخدام دورة كتابة كاذبة بطلب كود البدء MemStart ثم نضع العنوان 1010000 و بت كتابة ثم نرسل الأمر و نختار صفحة مثلا صفر و نرسله و نرسل نبضة إيقاف MemStop و ننتظر 10 مللى ثانية.
الكود التالى يمكنك الاستغناء عنه فقط احسب العنوان كما تشاء و حسب ما لديك من عتاد.
كود:

MemStart:			; Send start code, ret w/ SCL,SDA low
	SETB	SDA
	NOP
	SETB	SCL
	ACALL	Wait_9
	CLR	SDA		; Start 
	ACALL	Wait_9
	CLR	SCL		; ready for clock
	ACALL	Wait_9
	RET
يلى ذلك كود إرسال نبضة البدء حيث يجب أن يكون SDA,SCA=1 ثم بعد ذلك ينتقل SDA للصفر. النبضة Clock يجب أن تكون صاعدة لذا و حال SDA=صفر ننقل SCL = صفر فى انتظار النبضة. السبب فى هذا أنك لو أردت قراءة 100 بايت مثلا لن تحتاج Start أخرى مادام العنوان متتالى و تحتاجه فقط عند تغيير العنوان.
يلى ذلك إرسال نبضة MemClk و إرسال توقف MemStop
كود:

MemClk:
	ACALL	Wait_9
	SETB	SCL
	ACALL	Wait_9
	CLR	SCL
	ACALL	Wait_9
	RET
	
MemStop:
	CLR	SCL		; just in case , prepare for stop
	NOP
	CLR	SDA		; Ready for stop
	NOP
	SETB	SCL	; Command mode
	ACALL	Wait_9
	SETB	SDA	    ; Stop
	ACALL	Wait_9
	CLR	SCL		; End of Command mode
	RET
إرسال نبضة MemClk يبدأ بوضع SCL=1 ثم إعطاء الوقت الكافى ثم إعادته للصفر و أيضا إعطاء الوقت الكافى و إرسال توقف MemStop رغم أننا مفترض أن نأتى و SCL=صفر ولكن احتياطيا نجعله بصفر ثم وقت ثم SDA=صفر و انتظار وهنا نجعل SCL=1 ليترجم الطرف الآخر كأمر و ننتظر ثم نضع SDA=1 كأمر بالتوقف ثم ننتظر و أخيرا نضغ SCL = صفر حتى لا يترجم مزيد من الأوامر.
أول ما نحتاجه هو كتابة بايت لتحديد البداية وهذا موضوعنا القادم إن شاء الله

اعلانات

ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 11-08-2018, 09:14 AM المشاركة 106   
افتراضي



أول ما نحتاجه هو كتابة بايت لتحديد البداية و كما ذكرنا فنعد 8 بت فى خانة أو مسجل أو ما تريد تسميته BitCount ولو لديك متغير باسم Cntr مثلا تعد به كل ما تحتاجه فلا بأس ثم تستخدم الأمر RLC A وهو Rotate Left through Carry وهو ببساطة يزيح كل البتات فى المراكم A يسارا خطوة واحدة و البت 7 تذهب إلى C و ما كان فى C يذهب إلى بت صفر فى A و السبب أننا لا نستطيع نقل بت من المنافذ أو الذاكرة إلا لخانة C و منها فقط. لذا طبيعى أن تكون الخطوة التالية هى MOV SDA,C حيث تنقل البت إلى طرف SDA . نستخدم Left لكى ننقل البت العليا أولا كشروط نظام I2C و مقابلها RRC وهى لليمين. بعد ذلك نطلب الأمر MemClk لإعطاء نبضة ثم ننقص عدد البت واحد و نقفز لنكرر باقى 8 بت وهنا لا نعطى بدء Start ولا توقف Stop فقد نحتاج إرسال بايت جديدة.
الآن لدينا بت قادمة من القطعة تقول ACK و قد اعتمدت حقيقة طريقتين مختلفتين فيما نفذت من برامج:
الأولى أن افحصها مرة واحدة فى البدء أثناء التهيئة فإن لم تأتى أعطى رسالة خطأ و أتوقف و إن كانت موجودة فهى بخير و أفترض سلامتها طوال وقت التشغيل مكتفيا بإعطاء نبضة لترد بنبضة ACK ولا أقرأها ولا أفحصها و هذا أوفر قليلا فى الكود و السرعة و يناسب الأجهزة التى تغلق و يعاد تشغيلها كثيرا لكنه لا يناسب الخدمة الشاقة حيث تعمل 24 ساعة وبدون رقابة فقد تعطل و يظل الجهاز يعمل على خطأ بلا توقف و ليست ذاكرة فقط ولكنها قد تكون ساعة وقت حقيقى أو مقياس حرارة أو غيره وهنا وجب أن التزم بالكتاب كما يقولون و أختبرها آخر كل بايت لأتأكد من وجودها بخير.

كود:

WriteMemByte:			; Writes 8 bit in A to mem and reads ack then back, no Stop
	MOV	BitCount,#8
	WMB00:
	RLC	A			; MSD first
	MOV	SDA,C		; put data, setup delay in MemClk
	ACALL	MemClk		; clock it 3 wait loops in clk
	DJNZ	BitCount,WMB00
	ACALL	ReadEEAck
	RET


ReadEEAck:
	ACALL	Wait_9
	SETB	SDA		; make it input
	ACALL	Wait_9	
	SETB	SCL		; Start Clk
	MOV	AckDel,#0
	RAloop:
	JNB		SDA,EndAck
	ACALL	Wait_9
	DJNZ	AckDel,RAloop
;	CLR	ERRLED
	EndAck:
	CLR	SCL			; end clk
	NOP
	SETB	SDA		; Make it input again
	ACALL	Wait_9
	RET
هذا كود قراءة نبضة "اعلم" وهى أن تقول القطعة "تمام أو علم و جارى التنفيذ" و هذه إحدى الطرق و لو لديك مؤقت خالى يمكنك استخدامه فى انتظارها و الفكرة ننتظر قليلا لاستيعاب ما سبق ثم SDA=1 و تنتظر الاستيعاب و SCL=1 ثم تنشئ دورة من 256 لفه و تفحص لو SDA = صفر إذن وصلت المعلومة فنقفز خارج الدورة و إلا نكرر فإن نفذ العد يمكنك أن ترفع علما بحدوث خطأ أو عطل و تسجله فى بايت الأخطاء و تنير ليد أيضا أو تكتب رسالة الخ.
لو خرجت من الدورة مبكرا يعنى أنها سليمة و يمكنك استئناف العمل.
الآن لنكتب فى القطعة نحتاج أن نرسل لها أمر كتابه يشمل عنوان تعريف القطعة (أى واحدة هى المعنية بهذا التخاطب) ثم عنوان الكتابة الفعلى داخلها ثم ترسل بعدها ما نريد كتابته من بيانات . هذا الكود يمكنك أن تستخدمه منفصلا أو غالبا من خلال الكتابة المتعددة.

كود:

SendPgAdd:				; send start Mem page adress from location PgAddress, no stop 
	ACALL	MemStart		; send start command
	MOV	A,#10100000b		; Device address 1010,page 000 and write (0) bit 
	ACALL	WriteMemByte
	MOV	A,PgAddress		; Get EE address
	ACALL	WriteMemByte
	RET
هذا الكود لإرسال المطلوب فنبدأ بنبضة بدء Start ثم عنوان القطعة وهو هنا ثابت لكنك تستطيع تعرف خانة باسم Dev_Add تضع فيها عنوان أى قطعة تود محادثتها و تغير هذه الخطوة إلى MOV A,Dev_Add ثم تطلب كود WriteMemByte السابق شرحه لإرساله للقطعة ثم تضع فى A العنوان ألذى تود الكتابة عنده ثم تطلب الكود مرة أخرى لإرساله ثم نعود أيضا بدون Stop .
الآن هذا الكود يمكننا كتابة صفحة كاملة من 8 بايت بتحديد 8 بايت كما فى القراءة و لكن احذر يجب أن تكون فى عداد آخر لذا سميت الأول عداد البت و الثانى عداد البايت لأن كل بايت ستستخدم عداد البت ذاتيا لعد 8 بت.
الآن بعد تجهيز عداد 8 بت ترسل باستخدام الكود السابق عنوان القطعة ثم عنوان الكتابة و نعود هنا بدون Stop . و الآن ستكون قد جهزت الثمانية بايت فى مجموعة من 8 خانات متتالية فى أى مكان فى الذاكرة تختاره مثلا 41 أو ما شئت أفضل البدء برأس العد مثل 40 فيكون من 40 إلى 47 و هنا أضع 40 فى المسجل R0 و المسجلان R0,R1 بهما خاصية أنك تستطيع استخدام محتوى أي منهما كعنوان لذا نضع 40 وهى تشير لأول بايت و من ثم فالأمر MOV A,*R0 تجعله يأخذ خانة الذاكرة المشار إليها بالمسجل R0 فالعلامة * هذه تعنى "غير مباشر" أى المحتوى عنوان البيان و ليس البيان ذاته. أخذنا أول بايت فى A ثم نطلب كود WriteMemByte السابق شرحه لإرساله للقطعة ثم نزود R0 بواحد فيحتوى 41 و يشير للبايت الثانية ثم ننقص العداد بواحد و نقفز لو لا يساوى صفر للتكرار.
أعلم أنك تقول أن هنا خطوات زائدة فبدلا من إنقاص عداد فضلا عن استخدامه أصلا كان من الممكن مقارنة R0 بنهاية العنوان 47 وهذا صحيح 100% عندما تتعامل مع قطعة واحدة لا تحتاج تجهيز أكثر من مصفوفة بيانات واحدة لكن لو لديك ذاكرتين لنوعين من البيانات أو حتى صفحتين مختلفتين أو ذاكرة مع ساعة أو وظيفة أخرى فستختلط الأمور.
بعد إكمال الصفحة نرسل Stop و نتوقف 10 مللى ثانية لضمان الكتابة و لو لديك شيء ما أفضل من دورة إضاعة الوقت كتحديث للشاشة أو قراءة ADC أو غيره فالأفضل قضاء الوقت فيما هو مفيد فلا يؤثر ذلك على القطعة طالما المتحكم بعيدا عن أوامر I2C.
كود:
     

Write2Mem:	; Writes 8 memory locations to EEprom add in PgAddress from RAM in R0
	MOV	ByteCount,#8		; loop counter, 8 bytes
	ACALL	SendPgAdd		; start adress and ack
	W2m:
	MOV	A,*R0			; get byte
	ACALL	WriteMemByte
	INC	R0			; Point 2 next
	ACALL	Wait_9	
	DJNZ	ByteCount,W2m
	ACALL	Wait_9
	ACALL	MemStop
	ACALL	Wait_10ms		; Write wait time
	RET	 

لا جدوى من الكتابة ما لم نستطيع القراءة وهو موضوعنا القادم إن شاء الله

اعلانات اضافية ( قم بتسجيل الدخول لاخفائها )

ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 12-08-2018, 08:27 AM المشاركة 107   
افتراضي




الآن كتبنا و نريد أن نقرأ و يمكننا أن نقرأ بايت واحدة أو أى عدد من البيتات بلا حد أقصى فلووصلت لنهاية القطعة سيعود المؤشر للصفر ليبدأ من أول الذاكرة مرة أخرى . نحتاج إرسال عنوان هذه القطعة مع أمر قراءة . ولقراءة عدد من البايت سنحتاج قراءة العدد كله ماعدا الأخيرة و نرسل بعد كل منهم Ack للقطعة و إلا لن تستجيب. ثم تقرأ الأخيرة و يرسل بعدها Stop و هكذا الكود حيث نضع فى عداد للبايت العدد ناقص واحد وهنا نريد قراءة 8 فنضع 7 و يمكنك استخدام متغير باسم ByteNu و تطرح منه واحد أو تضع فى ByteCount عدد البايت و تبدأ الكود بالأمر DEC ByteCount ثم تنتظر و تطلب كود SendPgAdd السابق لإرسال العنوان للقطعة و عنوان الكتابة و هكذا حددت العنوان ثم ترسل STOP ثم عنوان القطعة و تكتب بايت مع أمر قراءة و هنا نبدأ الدورة.
كود:

ReadMem:	; Read 8 memory locations from EEprom Address in PgAddress to RAM address in R0
	MOV	ByteCount,#7		; loop counter, send only 7 bytes with ack, then one with stop
	ACALL	Wait_9
	ACALL	SendPgAdd		; send start command,PgAddress,no stop
	ACALL	MemStop		; Send stop to read sequentially at current location
	ACALL	Wait_9
	ACALL	MemStart		; send start command
	MOV	A,#10100001b		; Device address 1010,page 000 and Read bit
	ACALL	WriteMemByte
	NxtRead:
	ACALL	ReadMemByte	; result in A
	ACALL	SendEEAck
	MOV	*R0,A
	INC	R0
	DJNZ	ByteCount,NxtRead
	ACALL	ReadMemByte	; read the 8th
	MOV	*R0,A	
	ACALL	MemStop
	RET
طبعا يجب أن نضع فى R0 أو R1 عنوان الذاكرة حيث نريد أن نبدأ حفظ ما نقرأ ثم نطلب كود قراءة بايت التالى شرحة ثم نرسل نبضة ACK كما سيلى شرحة فنجد نتيجة القراءة فى المراكم A و من ثم نحفظه فى العنوان المشار إليه بالمسجل المختار سواء R0 أو R1 ثم ننقص عد البايت و ننتقل لو لا = صفر لنكرر القراءة و عندما ينتهى العد نقرأ الأخيرة ثم نحفظها ثم نرسل STOP و نعود.
الآن كيف نقرأ بايت واحدة؟
طبعا عدد البت =8 ثم ننشئ دورة من ننتظر ثم نرسل نبضة برفع SCL =1 و الانتظار ثم ننقل الرد من طرف SDA إلى C لأنه لا غيره يمكن النقل منه و إليه. ثم ننفذ الأمر RLC أى Rotate Left with Carry لنضعه فى البت صفر و التى باستمرار الإزاحة ستصبح فى النهاية رقم 7 ثم ننهى النبضة بخفض SCL ثم ننقص العد واحد ونكرر لنهاية 8 بت ثم ننتظر و نعود دون نبضة توقف Stop لنتمكن من قراءة التالية إن أردنا.
كود:

ReadMemByte:			; Reads 8 bit from mem to A, neither Ack nor stop pulse
	MOV	BitCount,#8
	RMB00:
	ACALL	Wait_9
	SETB	SCL		; send clock
	ACALL	Wait_9
	MOV	C,SDA		; Get data, MSD first
	RLC	A			; MSD first
	CLR	SCL		; clock end
	DJNZ	BitCount,RMB00
	ACALL	Wait_9
	RET

SendEEAck:		; Send ACK code, ret w/ SCL low			
	CLR	SDA
	ACALL	Wait_9
	ACALL	MemClk
	SETB	SDA		; make it input again
	ACALL	Wait_9
	RET
طبعا بعد استقبال 8 بت لابد هنا من أن ترسل ACK للقطعة لتستقبل البايت التالية وهى بتصفير SDA و الانتظار ثم نطلب كود إرسال نبضة ثم نضع SDA=1 ليصبح دخول للمتحكم مرة أخرى و ننتظر ثم نعود
لم يبقى سوى دورات التأخير أو قضاء الوقت أو الانتظار وهى إما مجموعة من NOP وهى تستهلك دورة أو دورات من العد باستخدام مسجل أو خانة ذاكرة
كود:
	

; Delay routines at 11.059Mhz Xstal has 1.085 uS per cycle, clk rate = 0.92 MHz=920KHz
;  --------------------------------------------------------
' time:		9 cyc.	(incl. ACALL/RET)=9.765 uSec 
' stack:	2		(incl. ACALL/RET)=4
Wait_9:	
		NOP
		NOP
		NOP
		NOP
		NOP
		RET		

;  ---------------------------------------------------------------
; destroys: 	Nothing
;  time:		9326 cyc.	(incl. ACALL/RET)=10.11871 ms
; stack: 4		(incl. ACALL/RET)=4
Wait_10ms:	
		MOV	DelTime1,#20
	_W10ms:	MOV	DelTime2,#231
			DJNZ	DelTime2,$
		DJNZ	DelTime1, _W10ms
		RET
القراءة و الكتابة فى ذاكرة المتحكم سهلة نوعا ما بكود الأسيمبلى و لذا سنستخدم المتحكم AT89S5283 ذو 2 ك ذاكرة داخلية EEPROM فيمكن الكتابة و القراءة فيها.
الآن نحتاج عرض البيانات على الشاشة وهو موضوعنا القادم إن شاء الله.



ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 13-08-2018, 08:22 AM المشاركة 108   
افتراضي



الشاشة LCD ما هى و كيف تبرمج لها:
الشاشات نوعين نوع رسومية و هى خارج نطاق هذا الشرح لأنها تعتمد برامج متخصصة لمعالجة الرسوم و معظم اللغات العالية توفر دعم لها لكنها أكثر ملائمة للمتحكمات من نوع AVR لحاجتها لذاكرة كبيرة نوعا ما.
النوع الثانى نصية حيث تكتب على صف أو صفين أو أربعة صفوف و فى كل صف 16 حرف و ظهرت أنواع بها 20 حرف لكنها تعتمد ذات المتحكم ألذى يوائم بين الشاشة و الدوائر التى نصممها لذا نجد الشاشة ذات 16×1 مكونه من سطرين الأول يكتب فى الثمان أحرف اليسرى بعنوان من صفر إلى 8 و سطر ثان يكتب فى الأحرف الثمان اليمنى بعنوان يبدأ من 40 هيكسا إلى 48 هيكسا و الشاشة ذات 16×2 تحتوى أيضا سطرين السطر الأول للكتابة فى الستة عشر حرف العليا بعنوان من صفر إلى 15 أى صفر إلى F هيكسا و السطر الثانى للكتابة فى الستة عشر حرف السفلى بعنوان من 40 هيكسا و حتى 4F هيكسا و الشاشة ذات 16×4 أيضا سطرين لكن الستة عشر الأولى كما سبق من صفر إلى 15 أى صفر إلى F هيكسا و السطر الثانى للكتابة فى الستة عشر حرف السفلى بعنوان من 40 هيكسا و حتى 4F هيكسا أما الستة عشر الثالثة فهى امتداد الستة عشر الأولى أى بعنوان من 16 إلى 31 او 10_Hex إلى 1F_hex و الأخيرة امتداد الثانى أى من 50_HEX إلى 5F_HEX وهذه هامة لأنك لو تريد جعل الكتابة متحركة فهكذا ستبدو أى ما فى السطر الثالث سينتقل للأول و ما فى الثانى للرابع.
الشاشات ذات الأرقام أعلى من 16 فهى بذات الترتيب إلا أن الستة عشر تصبح 20 أو اكثر.
الآن ذكرنا أن للشاشة متحكم وفى الحقيقة أكثر من واحد بحسب عدد الصفوف من الأحرف و لو نظرت فى ظهرها ستجد لطعة سوداء هى ذاك المتحكم. لا يهمنا كثيرا ما هو ولكن يهمنا كيف يتصرف لنتواءم معه
عند توصيل التيار يبدأ فى التهيئة و يحتاج 50 مللى ثانية لإنهائها لذا لا تتعامل مع الشاشة خلال هذا الوقت ، و الأفضل أن تكتب الكود لينهى بعض أو كل مهامه الأخرى أولا من تهيئه المنافذ و الأجهزة الأخرى المحيطة و إن شئت فهناك وسيلة لتعرف إن كانت قد أتمت تهيئتها أم لا لكنه سيكلفك مخرج من مخارج المتحكم لذا عادة ما أقدر الوقت ثم أعطل المتحكم باقى هذا الوقت فلو حاولت التعامل معها قد لا يعمل ولا تكتب إطلاقا لأنها ببساطة لم تتلقى منك أمر التشغيل.
الآن بعد هذه الفترة تصبح مهيأة ذاتيا للعمل على النسق الآتى
عرض البيانات 8 بت
المعروض سطر واحد و الثانى مخفى
مساحة الحرف 5×8 نقطة وهى ذات العدد الكامل من الأحرف حيث النمط الآخر 5×11 لا يحتوى إلا عدد محدود جدا من الأحرف.
الشاشة مطفأة و ربما هذا لتقليل الاستهلاك و السبب غير مذكور فى الداتاشيت.
المؤشر مطفأ وهو خط يكون أسفل الحرف ألذى ستتم كتابته تاليا
الوميض مطفأ وهو المؤشر إما ثابت أو يظهر و يختفى "يومض"
تزايد بواحد وهو بعد الكتابة يزيد رقم المؤشر بواحد ليشير للحرف التالى وهو يمكن أن يكون سالب 1 ليشير للحرف السابق.
بلا إزاحة و هذه الإزاحة تحرك الكتابة بدلا من أن يتحرك المؤشر

الآن أول شيء أن نكمل التهيئة. نلاحظ أن التهيئة تخيرنا ما بين استخدام 8 بت بما فيها من سرعة و خطوات أقل على حساب عدد الخطوط أو 4 بت توفر 4 خطوط لكن ضعف الوقت و ضعف الكود وهذا خيارك أنت. الآن ربما تريد تحويل الشاشة لنظام 4 بت ، معنى هذا أن الأوامر كلها يجب أن تكون على 4 بت فقط و هنا سيكون التعامل مع الأربعة بت العليا فقط بينما الأربعة السفلى أصفار و تدخل الأمر على مرتين وهذا سبب البطء.
كيف تتعامل معها؟ الأمر بسيط ، ضع ما تشاء على مجموعة البيانات و اختار بطرف R/S ما تريد. لو R/S=0 فستترجم الشاشة ما وضعت على مجموعة البيانات كأمر للتنفيذ و إن كان R/S = واحد ستعتبره حرف يجب كتابته و هذا فور تحريك الطرف E من صفر إلى 1 و إعادته للصفر مرة أخرى . هذا يتيح لك توصيل أكثر من شاشة معا و تضع ما تشاء على ذات البيانات المشتركة و تضع R/S للمجموعة كلها و المعنية فقط تصدر لها الأمر E .
الآن ماذا نضع؟ هذا الجدول يبين كافة الأوامر المتاحة و يلى شرحها حيث "-” تعنى لا يهم و الواحد مثل الصفر لا أثر له. أيضا الجدول به عديد من الأوامر ، ما يحدد هو أين يقع أول 1 فى الآمر فدوما الأعلى أصفار.


الأمر 1 هو أطولهم تنفيذا حيث يمحو الشاشة بكتابة مسافة بيضاء (20h) فى كل الخانات و يصفر العداد و يبدأ من أول خانة
الأمر 1X يعود للأول لكن مع الإبقاء على محتوى الشاشة لذا فهو أسرع
الأمر فى الخانة الثالثة فالبت صفر باسم S تحدد هل سيتم إزاحة الشاشة لو =1 أما لو = صفر فلا تزاح الشاشة ويزاح المؤشر. و البت التالية رقم 1 باسم I/D لو = 1 تحدد زيادة المؤشر بواحد فتكون الإزاحة لليسار أو لو هى = صفر تحدد نقص المؤشر بواحد فتكون الإزاحة لليمين.
الأمر فى الخانة الرابعة البت صفر باسم B =0 المؤشر لا يومض ولو =1 المؤشر يومض، و البت 1 باسم C المؤشر Cursor لو = 1 يظهر المؤشر ولو = صفر يختفى المؤشر دون التأثير على الكتابة. البت 2 باسم D أو Display لو = 1 تشغل الشاشة و لو= صفر تطفئ الشاشة .
الأمر فى الخانة الخامسة بعد أن اكمل الأوامر الخاصة بالتهيئة أصبح الآن فى الشكليات و ذلك حتى يكون المستخدم قد أتم التعديلات الأساسية لو أراد أن يعمل بنظام 4 بت الخ. البت صفر وواحد لا أثر لهما و البت 2 باسم R/L أى Right/Left وهى تحدد اتجاه الحركة يمين أم يسار ثم البت 3 باسم S/C أى Screen/Cursor فلو =1 الشاشة تتحرك ولو بصفر فالشاشة ثابتة و المؤشر يتحرك. المقصود بالشاشة طبعا هو الكتابة.
الأمر فى الخانة السادسة البت 2 باسم F أى Font لتحديد 5*8 أم 5*11 ثم البت 3 باسم N أى Number لو = 1 تعنى سطرين ولو = صفر تعنى سطر واحد (فى الشاشة 16*1 تكون 8 حرف أو 16 و الشاشة 4*16 تكون خط 1،3 أم الأربعة) و البت رقم 4 باسم D أى Data Line لو =1 فالتعامل مع 8 بت ولو = صفر تكون 4 بت.

المرة القادمة بإذن الله نكمل


ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 14-08-2018, 08:39 AM المشاركة 109   
افتراضي



باقى الكود
قبل أن نكمل الأكواد يجب أن نعلم نقطة حول تركيب الشاشة فبها نوعين من الذاكرة CG أى Character Generator منها ROM قراءة فقط حيث تتولى توليد أكواد الحروف المطبوعة على الشاشة و منها RAM تحتوى 64*8 خانة للمستخدم يستخدمها كذاكرة عشوائية أو يضع فيها حتى ثمانية أحرف خاصة يود طباعتها. أيضا بها نوع قابل للقراءة و الكتابة تسمى DD أى Display Data و التى تحتوى المعروض فعليا الآن على الشاشة و من المفيد أن نعلم ماذا تعرض الشاشات مقابل كل كود من صفر و حتى FF

و لهذا فائدة كبيرة حيث يمكنك طباعة علامة درجة الحرارة باستخدام الكود 0FDh أو علامة الأوم أو ميكرو و النسبة التقريبية و أكواد العملات وعلامة القسمة و الجذر التربيعى الخ.
الأمر يمكنك من تحديد العنوان فى ذاكرة توليد الأحرف لتكتب فيها أو تقرأ منها، هناك بضع خانات يمكنك الكتابة فيها لتشكل أحرفك الخاصة.
الأمر الثامن يمكنك من وضع العنوان للخانة التى تريد الكتابة عليها فيمكنك مثلا أن تكتب أول الشاشة رقمين ثم تنتقل لمنتصف الشاشة بدلا من كتابة عدد من المسافات البيضاء و هناك تكتب الوحدات المطلوبة.
الأمر العاشر هو كتابة بايت لأى من الذاكرتين السابقتين بفرض أنك قد حددت العنوان سابقا. لو عنوان CG ستحفظ حيث حددت أما لو DD ستترجم لحرف يعرض على الشاشة.
الأمرين التاسع و الحادى عشر للقراءة من الشاشة و ذلك بفرض أنك وظفت الطرف المسمى R/W فى الشاشة وهو رقم 5 من أطراف الشاشة. الأمر التاسع لمعرفة هل الشاشة أنهت ما تقوم به و تنتظر جديد فتعلمه من البت 7 و الباقى هو العنوان الحالى. الأمر الحادى عشر للقراءة من الذاكرة CG للأغراض السابقة.
الآن الأطراف بالترتيب للشاشة ووظائفها هى:
1 – أرضى للشاشة لزوم التشغيل مع الطرف رقم 2 يغذى من +5 فولت للتشغيل.
3- طرف Vo للتغذية و التباين و تقترح الشركة توصيله بمقاومة تحدد الفولت قدرها 5 ك وهى للتباين و تغير خانات الشاشة من بيضاء بدون كتابة إلى سوداء بلا تفاصيل مرورا بالوضع الصحيح حيث تكون القراءة واضحة. شخصيا استبدلتها بمقاومة 100 أوم فى كل الشاشات الخضراء بلا مشاكل أما الزرقاء فقد تحتاج تعديل طفيف.
4 – R/S وهى تحكم فى ما تفعل الشاشة بالبيانات ، لو =1 تكتبها على الشاشة و لو = صفر تنفذها كأمر
5 – طرف R/W حيث يمكنك من القراءة و الكتابة للشاشة ولو لا تستخدم خاصية القراءة أوصلها بالأرضى لتكون على وضع الكتابة دوما.
6- طرف E اختصار Enable وهو يفعل الشاشة لكى تنفذ المطلوب
7 : 14 البيانات حيث 7 هى D0 و الطرف 14 هو D7
15 طرف موجب لإضاءة خلفية الشاشة بمجموعة من LEDs والطرف 16 هو السالب أو الأرضى و يمكنك التوصيل المباشر ب+5 فولت و أرضى أو من خلال مقاومة لتقليل الإضاءة أو التحكم فيها PWM أو تضع مفتاح لتوفير الطاقة لأجهزة البطارية فعلى أى حال لو ضبطت التباين على طرف 3 جيدا ستكون الشاشة مقروءة بدون إضاءة الخلفية. التيار يختلف بحسب حجم الشاشة و الطراز، ارجع للداتاشيت.

كود التهيئة موضوعنا القادم بإذن الله



ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 15-08-2018, 10:27 AM المشاركة 110   
افتراضي



خطوات التهيئة :
أربعة خطوات لتهيئة الشاشة.ا
الأولى لا تحتاجها لو ستستخدم نصف الشاشة فقط لكن لجعلها تظهر سطرين يجب وضع 1 مكان N و ستكرر اختيار 8 بت لترسل
00111000

الثانية ضرورة لكون الشاشة مطفئه و يجب تفعيلها بهذا الأمر و لو تريد إظهار المؤشر أضف 1 ولو يومض أضف 1
00001100 الشاشة فقط
00001110 المؤشر ظاهر و ثابت
00001111 المؤشر ظاهر و يومض.
يلى ذلك محو الشاشة و العودة للعنوان صفر بالأمر "1”
و أخيرا هل تريد تحريك الشاشة أم المؤشر و غالبا لو تريد حركة المؤشر من اليسار لليمين فلا حاجة لهذا الأمر

الكود:
طبعا تسمى الطرف RS لأى منفذ و طرف و تسمى Ena لأى منفذ و طرف و تسمية Ena بدلا من E فقط مجرد إضافة توضيح خاصة لكود كبير و به متغيرات عديدة فضلا عن أن بعض المترجمات يشترط أن الاسم على الأقل ثلاثة أحرف.
نلاحظ أن كل خطوة لها زمن تحتاجه الشاشة لكى تنفذ هذا الأمر و بديهى أنه لا علاقة له بتردد الكريستال فلا رابط بينهما.
كود:
CLR RS MOV LCD_Data,#00111000b Setb Ena NOP CLR Ena MOV LCD_Data,#00001100b Setb Ena NOP CLR Ena MOV LCD_Data,#1 Setb Ena NOP CLR Ena MOV LCD_Data,#00000110b Setb Ena NOP CLR Ena Setb RS
فقط 18 خطوة بعضها قد لا يكون ضروريا ، أما لو تريد التهيئة لأربعة بت فالأمر معقد و سأشرحه هنا لا بهدف أن تستخدمه و لكن لتعلم كم تضحى من السرعة و الكود مقابل 4 بت توفرها وهذا موضوعنا القادم بإذن الله


ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 16-08-2018, 09:00 AM المشاركة 111   
افتراضي




التعامل بنسق4 بت

قد تبدو المسألة سهلة أن نضع 4 بت الأعلى على 4 بت من الحافلة حيث تكون أطراف الشاشة لكن مهلا لنأخذ الأمر الأول سنضع القيمة 0010 على أربعة بت.
أى أربعة بت؟ سأفترض الحسنى و أن المصمم قد وضعهم إما من صفر إلى 3 أو من 4 إلى 7 ، حسنا أى منفذ؟
فى بيك تجد منفذ 5 طرف أو سته طرف وهذا ملائم لهذه القضية لكن فى أتميل كل المنافذ 8 طرف.
بسيطة أضع القيمة و الباقى أصفار.. ولكن هذا الباقى متصل بشيء ما و قد لا يريد أن يكون صفرا الآن!!
أصبحنا فى مشكلة ، يجب قراءة المنفذ و التعديل عليه ثم إعادة كتابته ثانيا.
هذا أمر صعب لكن قد يهون قليلا من المعاناة لو وضعنا RS,E معا على ذات المنفذ و من ثم يتبقى طرفين للتعامل معهما
خطوات التعامل مع 4 بت هى أن سنستخدم الأطراف الأربعة العليا من الشاشة DB4 : DB7 و الباقى يمكن توصيلهم بالأرضى. الآن تحدد R/S ثم تضع النصف العلوى من البيان أولا على الشاشة و نبضة على طرف E ثم تضع النصف السفلى من البيان و نبضة E ثم تنتظر وقت تنفيذ الأمر أو الانتهاء من الكتابة.
لذا فى التهيئة لا توجد مشاكل فى وضع القيمة حسب الجدول ثم تفعيلها ووضع الثانية و تفعيلها ثم الانتظار لكن المشكلة عندما تحتاج أن تكتب حرفا و ليكن "A” وهو هيكسا 14 و المشكلة أنك لا تعرف أصلا أنه الحرف كذا و لذلك نحتاج قراءة المنفذ و نلغى منه 4 بت المخصصة للشاشة ثم نضيف الجزء الأعلى من A وهو واحد ثم نعيده على المنفذ و نبضة E ثم نضع الجزء الأدنى وهو 4 و نضعه على المنفذ طبعا سنحتاج الأمر Swap ألذي يبدل النصفين معا (لا حاجة لإعادة قراءة المنفذ)، هذه قصة طويلة .
أتميل وضعت كود مخصص لهذا الأمر وهى XCHD واختصار Exchange Digit و تعرضنا سابقا لمثيلة XCH و كانت تستبدل محتوى A بمحتوى أى مكان و الآن هذه تعتبر أى مسجل من R0:R7 حامل للعنوان المطلوب و تستبدل الأربعة الدنيا بالأربعة الدنيا ثم نعيده للمنفذ مرة أخرى . كان الخيار بين أمرين أن يستخدم مع الأربعة الدنيا فقط و ترسل مباشرة للمنفذ أو ترسل لذاكرة و بإضافة أمر Swap تكتب فى ألأربعة العليا.
لذا و كما فى كل الطرز ذاكرة المنافذ تشارك الذاكرة العادية ذات العنوان و كيفية الكتابة مباشرة أو غير مباشرة تحدد أيها ، فقد اختير الحل الثانى ليكون هذا الأمر غير مباشر ليكتب فى الذاكرة و إن شئت بأمر Swap تنقلها للأربعة البت العليا.

هل خطر على بالك للحظة أن تستخدم المنفذ P0:P3 يوفر فى الكود عن استخدامك P4:P7؟ لقد أثبتها لك بالكود هنا لكن لو لم تظهر معك فى المترجم فهو قد اعتمد الحل الأسهل الأكثر كلفة .
وهنا أيضا لا يفوتنى ذكر الرائع المسمى الأردوينو و ألذى يتعامل مع البت ولا يتعامل مع منفذ كامل و لإدخال بايت كاملة كم أمر ستحتاج، ما لم تعتمد نظام تسلسلى. و ألذى لن يوفر لك أى كود أو وقت.
هذا كود للكتابة فى الشاشة بنظام 4 بت. سنحتاج خانة مؤقته أو متغير إن شئت نسميه Temp و يمكنك استخدام أى خانة أخرى سبق تخصيصها كما ذكرنا كمسودة. أول أمر يضع عنوانها فى المسجل R0 ثم نضع نسخة من المنفذ LCD_Data فى Temp وهذا حتى تتجنب أى تعديل فى الأربعة بت الغير مستخدمة للشاشة و قد تكون موظفه لغيرها ، ثم تضع ما تريد إرساله للشاشة Chr2prn فى A ثم تبدل نصفيه لإرسال النصف العلوى أولا ثم بالأمر XCHD تستبدل الأربعة بت الأدنى فى A بالأربعة الأدنى فى العنوان المشار إليه فى المسجل R0 وهو هنا Temp ثم تعيد Temp للمنفذ
كود:


MOV	R0,#temp
MOV	temp,LCD_data		; To preserve the other 4 bits
MOV	A,Chr2prn	; Put in temporary location
Swap	A		; Put the High nibble as low nibble
Xchd	A,*R0 		; replace a with temporary
MOV	Lcd_DATA,temp
SETB	Ena
NOP
CLR		Ena			; Clock it
Swap	A		; get back the low nibble
XCHD	A,*R0 		; replace a with temporary
MOV	Lcd_DATA,temp
Setb	Ena
NOP
CLR		Ena			; Clock it

ثم نبضه تفعيل وهى Ena=1 ثم صفر و نكرر بتبديل A لنستعيد الأربعة الأخرى و نكرر. و بعد إرسال الدفعتين أى 8 بت تنتظر تنفيذ هذا الأمر أى أن الشاشة لا تعامل كل نصف على حدة.

طبعا للسهولة نستخدم 8 بت و من ثم يكون لدينا بضع دوال بسيطة و تكون التهيئة كاملة موضوعنا القادم إن شاء الله



ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 17-08-2018, 09:26 AM المشاركة 112   
افتراضي




لتهيئة الشاشة نحتاج بضع تعريفات وهى أى منفذ تستخدمه و أى بت تكون RS و أى بت تكون Ena و تكتب الثوابت التالية لتحديد السطر ألذى تود الكتابة فيه لكن أذكرك أن فى الشاشة 16×1 الثمانية اليسرى هى سطر رقم 1 بعنوان صفر و الثمانية اليمنى هى سطر رقم 2 بعنوان 40 هيكسا و أى كتابة بيتهما لن تظهر إلا فى حال إزاحة الشاشة لليسار سيختفى الحرف الأيسر و يدخل بدلا منه ما هو فى خانة 8 وهكذا وهذه هى التهيئة كاملة بالتعريفات لنسق 8 بت .
بعد التهيئة سنحتاج دوما للكتابة فى الشاشة و إصدار أوامر لها لذا سيكون من الأفيد لو نجعل التفعيل و تحديد أمر أو كتابة فى كود مستقل لذا سنعدل التهيئة السابقة و نستغل وظيفتين إحداهما Do_LCD لتنفيذ أمر و الأخرى Writ_LCD لكتابة حرف و تصبح التهيئة
كود:

Line1		EQU	$0		; 00h :0fh
Line2		EQU	$40		; 40H :4FH
Line3		EQU	$10		; 10H :1FH
Line4		EQU	$50		; 50H :5FH 

INCLUDE 89s8253.MC
RS		EQU	p3.0
ENA		EQU	p3.1
LCD_Data	EQU	p2
Chr2prn		EQU	12h
Temp		EQU	13h

MOV		LCD_Data,#00111000b
ACALL	Do_Lcd
MOV		LCD_Data,#00001100b
ACALL	Do_Lcd
MOV		LCD_Data,#1
ACALL	Do_Lcd
MOV		LCD_Data,#00000110b
ACALL	Do_Lcd
الآن لتنفيذ أمر سنضعه على المنفذ ثم نستخدم الكود Do_LCD حيث نحدد RS = صفر ليكون أمر ثم ننتظر و نرفع ENA =1 ثم ننتظر و نعيده مرة أخرى و نطلب كود انتظار تمام التنفيذ طبقا للجدول السابق و لكتابة حرف سنضعه أيضا على المنفذ و نستخدم الكود Writ_LCD حيث نجعل RS=1 ليكون كتابة و نفعل ENA و لمزيد من الاختصار يمكنك جعل كل منهما فقط تضع قيمة RS ثم تنتقل لكود يسمى CLOCK مثلا يحتوى باقى الكود لتطابقه.
كود:

Do_LCD:				; writes a Command   to LCD 
	CLR	LCD_RS		; Command Reg
	NOP				; 5 ns delay
	SETB	LCD_Ena		;
	NOP				; DELAY > 175 ns
	CLR	LCD_Ena
	LCALL Wait_50		; Wait Execution time	43 us
	RET

Writ_LCD:				; writes a character to LCD * current location
	SETB	LCD_RS		; Data Reg
	NOP
	SETB	LCD_Ena		
	NOP			
	CLR	LCD_Ena
	LCALL Wait_50		; Wait Execution time 43uS
	RET
كثيرا ما تحتاج للتعامل مع سطرا كاملا من 16 حرف حيث تكتب فى جزء منه قيمة ما ثم تترك مسافة و تكتب الوحدات أو تنسق السطر كما تشاء لذا ستحتاج فى التعريفات أن تضيف 16 خانة متسلسلة و بدورة تكتب 16 حرف مرة واحدة

كود:

Disp1	EQU	$10		; LCD line text, LCD address in B reg, next 16 location till 5F
Disp2	EQU	$11
Disp3	EQU	$12
Disp4	EQU	$13
Disp5	EQU	$14
Disp6	EQU	$15
Disp7	EQU	$16
Disp8	EQU	$17
Disp9	EQU	$18
Disp10	EQU	$19
Disp11	EQU	$1A
Disp12	EQU	$1B
Disp13	EQU	$1C
Disp14	EQU	$1D
Disp15	EQU	$1E
Disp16	EQU	$1F

Wait_50:
	MOV	Del1,#47	; 1 cycle
		DJNZ	Del1,$	
	RET		
دورة التأخير المطلوبة بالطبع بحسب الكريستال المستخدمة ولو بطيئة تستغنى عن كثير من NOP المستخدمة
هكذا راجعنا أساسيات الدائرة و نبدأ المرة القادمة بإذن الله التصميم بعائلة C51 و التى لا تحتوى كثير مما ذكرنا وتحايلنا لذلك




الساعة معتمدة بتوقيت جرينتش +3 الساعة الآن: 06:59 AM
موقع القرية الالكترونية غير مسؤول عن أي اتفاق تجاري أو تعاوني بين الأعضاء
فعلى كل شخص تحمل مسئولية نفسه إتجاه مايقوم به من بيع وشراء وإتفاق وأعطاء معلومات موقعه
التعليقات المنشورة لا تعبر عن رأي موقع القرية الالكترونية ولايتحمل الموقع أي مسؤولية قانونية حيال ذلك (ويتحمل كاتبها مسؤولية النشر)