elektronist kitaplık

Tanju Taşçılar, 3 Mayıs 2002
doc uC003-030502

Yazılımla RS232...

Günümüzde yaygın olarak kullanılan ve mikroişlemciler tarafından işlenmesi oldukça kolay olan seri haberleşme tiplerinin başında gelenlerden biri RS232'dir. RS232 asenkron tipte bir seri haberleşmedir. Yani bitlerin belirlenmesinde bir referans işareti olan saat işareti bulunmamaktadır. Bunun yerine bitlerin zamanlaması kullanılmaktadır. Bu da böyle bir seri haberleşmenin zamanlamasını ön plana çıkarmaktadır.

Standart RS232'de haberleşme bir start biti ile başlar, genellikle 8 data bitinin ardından bir veya iki stop biti ile sona erer. Data bitlerinin sayısı 5 ile 9 arası seçilebilir. Ayrıca stop biti öncesi parite biti kullanılabilir. Parite biti iletişimdeki hataları azaltmak için kullanılabilir. Kullanımı seçimliktir. Hiç parite biti kullanılmayacağı gibi kullanılan parite bitinin anlamına göre even, odd, mark ve space olarak adlandırılan özelliklerde olabilir. Bu durumda birçok kombinasyon olabilmesine karşın genellikle 8N1 şeklinde belirtilen, paritesiz 8 data biti ve bir stop biti şeklindeki kombinasyon kullanılmaktadır. Ayrıca RS232 yalnızca protokol standardı değil aynı zamanda elektriksel özelliklerin de belirtildiği bir standarttır. Ancak burada elektriksel standartları ile ilgilenmeyeceğiz. Ayrıca eğer kendi sistemimizin içinde bu tür bir iletişim şeklini kullanıyorsak yukarda belirtilenlere de uymak zorunda değiliz. Mesela 16 data biti olan bir protokol de kullanabiliriz. Aslında burada inceleyeceğimiz örnek NRZ formatında bir seri iletişimi esas olarak işlemektedir. NRZ formatı seri iletişimde kullanılan formatlardan biridir. Data ve işaret için kullanılan lojik seviyeler bu formatta sabittir. Yani genel kullanımıyla burada 0 olan bit lojik 0, 1 olan bit lojik 1 seviyesinde olmaktadır.

Bu incelemede 8N1 formatını kullanacağız. Bu formatın işaret şekli aşağıda görülmektedir.

Bu şekilde de görüldüğü gibi, sinyal olmadığı durumda data hattı lojik 1 seviyesindedir. İletişim 0 olan start biti ile başlar. 8 adet data bitinden sonra 1 olan stop biti gelir.

Asankron olan RS232 iletişiminde zamanlama ile işlem yapılmaktadır. Bu durumda temel olarak alınan zaman bir bit zamanına karşılık gelen zamandır. RS232'oe standart olarak 120 Baud'dan başlayan ve 115000'e kadar giden bit zamanlamaları kullanılmaktadır. Burada en çok kullanılan 9600 Baud değerini kullanacağız. 9600 Baud'da bir bit zamanı 1/9600 saniye yani yaklaşık 104 mikrosaniyedir. Pic kullanılan sistemlerde çok büyük bir çoğunlukla 4 MHz'lik bir kristal ve dolayısı ile 1 mikrosaniyelik komut zamanı kullanılmaktadır. Biz de bunu temel alacağız. Değişik parametreler için isteyen kendi değişikliklerini yapabilir.

Zamanlamanın önemli olduğu bu sistemde gerekli doğruluğu tutturabilmek için işlemcinin iletişim boyunca başka işlerle rahatsız edilmemesi gerekmektedir. Bu konuda işleyeceğimiz biçiminde herhangi bir interrupt kullanılmayacağı için işlemci iletişim boyunca yalnızca bu işle ilgilenecektir. Aslında böyle bir durumda gerçek zamanlı bir işletim sisteminden söz edemeyeceğiz. Dolayısı ile yazacağımız program bu şekilde olacaktır. Eğer gerçek zamanlı görevler yapacaksak bu tür bir programlamayı kullanmamız uygun değildir. Bu durumda ya interrupt kullanmak veya zaman dilimlemesi sistemini kullanarak çok katı program yazmamız gerekmektedir.

Zamanlama olayını bir de dışardan gelecek olan bilginin de asenkron olacağını düşünerek gözönünde bulundurmamız gerekmektedir. Yani işlemcimiz başka bir iş yaparken dışardan bilgi gelmeye başlarsa ve biz yeterince hızlı olarak bunu değerlendiremezsek gelen bilgiyi kaçırırız. Bu ilave durum da program şeklimizi etkileyecektir. Genellikle bu bizi dışardan bir bilgi bekleyen ve bu bilgiye karşılık bir işlem yapan ve sonunda da bir cevap veren sistemlerle sınırlı bırakacaktır.

Teknik olarak gönderme rutinini inceleyelim. Böyle bir rutinde bir bit zamanı olan 104 mikrosaniye süresince 0 olan start biti ile başlarız. Bu bitin bitiminde ilk bit olan Bit0 için gerekli lojik seviyede yine bit zamanı kadar bekler ardından diğer data bitleri için aynı işlemi yaptıktan sonra stop biti için 1 değerini bir bit zamanı kadar tutar ve rutinimizi sona erdiririz. Bu rutinde her değişiklik bitlerin başlangıç anına denk gelmektedir.

;***SCI_Write

	MOVWF	S_Reg
	MOVLW	.8
	MOVWF	S_Counter

	BCF	Tx		;Start bit
	GOTO	$+1
	GOTO	$+1
	GOTO	$+1
	GOTO	$+1
	CALL	S_Delay
Wr_Loop				;Send data bits
	BTFSS	S_Reg,LSB
	BCF	Tx
	BTFSC	S_Reg,LSB
	BSF	Tx
	RRF	S_Reg,F
	NOP
	CALL	S_Delay
	DECFSZ	S_Counter,F
	GOTO	Wr_Loop

	BSF	Tx		;Stop bit
	CALL	S_Delay

;---SCI_Write
      

Programda mümkün olduğu kadar basit bir şekil kullanabilmek için tek bir gecikme rutini kullanılıyor. Bu durumda da bazı yerlerde uyum sağlamak için zaman dolguları kullanılmakta. Öncelikle göndereceğimiz data S_Reg adlı seri işlem registerine yüklenmekte. Bitlerin sayısı olan 8 de S_Counter adlı sayaca yüklenmekte. Zaman dolguları ile birlikte S_Delay rutini ile bir bit zamanı geçirilmekte. Bu aynı zamanda start bitini bitirmekte. Sıra 8 adet data bitine gelmekte. S_Reg'deki 0'ncı bit dikkate alınarak gönderme çıkışı olan Tx'in değeri belirlenmekte. S_Reg sağa kaydırılarak yeni bit yerine gelmekte ve bu işlem 8 defa tekrarlanmakta. Her seferinde bir bit zamanı sonunda işlem bitmekte. 8 data biti tamamlanınca değeri 1 olan stop biti Tx'e yerleştirilmekte ve yine bir bit zamanı beklenmektedir. Bunun sonunda işlem tamamlanmaktadır.

;***SCI_Read

	MOVLW	.8		
	MOVWF	S_Counter
Rx_Start
	CLRWDT
	BTFSC	Rx
	GOTO	Rx_Start
	MOVLW	.10
	GOTO	$+1
	CALL	S_Delay_Half
	BTFSC	Rx		;? True start bit
	GOTO	Rx_Start	;No, false start bit
Rx_Loop
	CALL	S_Delay
	GOTO	$+1
	CLRC
	RRF	S_Reg,F
	BTFSC	Rx
	BSF	S_Reg,MSB
	DECFSZ	S_Counter,F
	GOTO	Rx_Loop
	MOVLW	.23
	CALL	S_Delay_Half	;For stop bit
	
	BTFSS	Rx
	GOTO	Main_Loop	;Receive error

;---SCI_Read
    

Gönderme rutini ise alma rutininden biraz değişiklik içermekte. Gönderirken gerekli işareti oluşturmakta iken bu sefer bu işaretten bilgiyi oluşturacağız. Hazırlık için S_Counter'e alınacak olan bit sayısı 8'i yükleriz. Bu durumda öncelikle işaret başlangıcını algılamamız gerekmektedir. Data yokken sinyal hattında lojik 1 bulunmaktadır. Biz lojik 0'ın gelmesini bekleyeceğiz. Start bitinin başlaması ile lojik 0 algılanır. Bu durumda sinyalden gerekli bilgiyi oluşturmak için en kolay yöntem belli zaman aralıkları ile örnekleme yapmak olacaktır. Bunun için de gönderilen bitlerin ortalarına rastlayan zamanlar örnekleme noktaları olarak kullanılır. Ancak burada öncelikle yarım bit zamanı bekleyerek start bitinin doğruluğunu denememiz gerekir. Zaman dolguları ile S_Delay_Half rutini sonrası yarım bit zamanı sonrasına gelmiş oluruz. Burada hatta hala 0 olup olmadığına bakarız. Eğer 0 ise işlemin normal olduğunu düşünerek diğer bitleri almaya devam ederiz. Yok değil ise yine başa döner yeni bir başlangız bekleriz.

Bu noktada tam start bitinin ortasında bulunmaktayız ve ilk data bitinin ortasına kadar gitmek için bir bit zamanı bekleriz. Daha sonra S_Reg registerini sağa kaydırarak yeni bit için yer açarız. Bu durumda yeni bit MSB yani 7. bit olacaktır. Rx'in değerine göre bu biti değiştiririz. Bu işleme 8 data biti de bitene dek devam ederiz. 8 data biti bittikten sonra bilgimiz gelen sinyalden yeniden oluşturulmuştur. Bu durumda bir bit zamanı daha bekler ve stop bitinin 1 olup olmadığını kontrol ederiz. Eğer herşey normal ise işlem tamamlanmıştır.

Aşağıda 12c508 için yazılmış olan programın tamamı yer almaktadır. Son derece basit olan bu programda bir bayt bilgi alınmakta ve alınan bilgi geri yollanmaktadır. Bu çok basit işlemci ile çok basit bir programdır.

  Title "Mikrosis Elektronik Tutorial - SW_RS232"
  Subtitle "Revision 1.0 - Jan 2002"
;**********************************************************
; By Tanju TASCILAR
; (c)Mikrosis Elektronik
;**********************************************************
  Processor 12C509
  Include "P12C509.INC"
  Errorlevel 1,-207

  __CONFIG _XT_OSC&_WDT_ON&_CP_OFF&_MCLRE_OFF ; Set up config bits
  __IDLOCS 0F000			   ; Set up ID locations 0F000

; I/O pin naming

  #Define Tx		GPIO,4	;SCI Tx
  #Define Rx		GPIO,3	;SCI Rx

;RAM Area *************************************************
;Bank 0
  CBlock        0C
    S_Reg		;Serial work register
    S_Counter
    c_1			;Counter
  EndC

  #Define Out_Bit	S_Reg,MSB

; DDR values **********************************************
  GPIO_DDR	EQU	B'00101000'

; Port reset values ***************************************
  GPIO_RST	EQU	B'00010001'     ;GPIO reset value

; Control words *******************************************
  Option_RST	EQU	B'01000000'	;OPTION reset value

MSB     EQU     .7
LSB     EQU     .0

;**********************************************************
; Main
;**********************************************************
	MOVWF	OSCCAL		;Optional
	CALL    Init_All
	GOTO	Main_Loop

;**********************************************************
; Serial work delay
;**********************************************************
S_Delay
	CLRWDT
	MOVLW	.22
S_Delay_Half
	MOVWF	c_1
	NOP
S_D_Loop
	NOP
	DECFSZ	c_1,F
	GOTO	S_D_Loop
	RETURN
;**********************************************************
; Init All
;**********************************************************
Init_All
	MOVLW	GPIO_RST
	MOVWF	GPIO
	MOVLW	GPIO_DDR
	TRIS	GPIO
	MOVLW	Option_RST
	OPTION
	RETURN
;**********************************************************
; Main Loop
;**********************************************************
Main_Loop

;***SCI_Read

	MOVLW	.8		
	MOVWF	S_Counter
Rx_Start
	CLRWDT
	BTFSC	Rx
	GOTO	Rx_Start
	MOVLW	.10
	GOTO	$+1
	CALL	S_Delay_Half
	BTFSC	Rx		;? True start bit
	GOTO	Rx_Start		;No, false start bit
Rx_Loop
	CALL	S_Delay
	GOTO	$+1
	CLRC
	RRF	S_Reg,F
	BTFSC	Rx
	BSF	S_Reg,MSB
	DECFSZ	S_Counter,F
	GOTO	Rx_Loop
	MOVLW	.23
	CALL	S_Delay_Half	;For stop bit
	
	BTFSS	Rx
	GOTO	Main_Loop		;Receive error

;---SCI_Read

;***SCI_Write

	MOVWF	S_Reg
	MOVLW	.8
	MOVWF	S_Counter

	BCF	Tx		;Start bit
	GOTO	$+1
	GOTO	$+1
	GOTO	$+1
	GOTO	$+1
	CALL	S_Delay
Wr_Loop				;Send data bits
	BTFSS	S_Reg,LSB
	BCF	Tx
	BTFSC	S_Reg,LSB
	BSF	Tx
	RRF	S_Reg,F
	NOP
	CALL	S_Delay
	DECFSZ	S_Counter,F
	GOTO	Wr_Loop

	BSF	Tx		;Stop bit
	CALL	S_Delay

;---SCI_Write

	GOTO	Main_Loop

        END    
        

sw_rs232.asm kaynak kodu.

Copyright © Mikrosis Elektronik 2002 - info@elektronist.com