PİC16f628a serial haberlesme sorunu

Başlatan redmen, 01 Kasım 2023, 09:40:20

redmen

Selamunaleykum hayırlı günler bir proje üzerinde çalışıyorum.Normal şartlar da çalışan işimi gören bir yazılımım mevcut kendi yazdığım,ancak bu yazılıma serial port üzerinden çalışan C# ile yapılmış bir arayüz yapıp kolay yoldan proğramlamak istedim ancak veri aktarımda sorun yaşıyorum bilgi verirseniz sevinirim.
'****************************************************************
'*  Name    : PC STEEP MOTOR                                    *
'*  Author  : [DESIGN BY FATİH AYDOĞDU]                         *
'*  Notice  : Copyright (c) 2011 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 10.10.2011                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
@ DEVICE pic16f628A                      'DENETLEYİCİ 16f628A                                
@ DEVICE pic16f628A, WDT_ON              'BEKÇİ KÖPEĞİ AÇIK
@ DEVICE pic16f628A, PWRT_ON             'GERİLİMDENGELENİNCE 1 KEZ RESET AT
@ DEVICE pic16f628A, PROTECT_OFF         'KOD KORUMA KAPALI
@ DEVICE pic16f628A, MCLR_OFF            'MCLR PİNİ KULLANILMAYACAK
@ DEVICE pic16f628A, INTRC_OSC_NOCLKOUT  'DAHİLİ OSİLATÖRÜ KULLAN
@ DEVICE Pic16f628A, BOD_OFF             'GERİLİM DALGALANMASI RESET KAPALI
INCLUDE "MODEDEFS.BAS"
'*****************************************************************
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
    DEFINE HSER_SPBRG 25  ' 9600 Baud @ 4MHz, 0,16%
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    DEFINE HSER_BAUD 9600 ' BaudRate 9600
    DEFINE OSC 4 
'******************************************************************
TRISA=%00000000                             'A PORTU ÇIKIŞ
TRISB=%00000010                             'B PORTUNUN 2.BİTİ GİRİŞ
PORTB=0:PORTA=0                             'A VE B PORTLARI SIFIRLANDI
CMCON=7                                     'COMPARATÖR İPTAL
'******************************************************************
VERI  VAR WORD[7]
VER1 VAR WORD[7]              
FREKANS VAR WORD[7]
RCA     VAR  BYTE                           'RCA  ADINDA 8 BİTLİK DEĞİŞKEN TANIMLANDI
SYMBOL GIE  =INTCON.7                       'BUTÜN İNTERRUPTLAR AÇILDI
SYMBOL PEIE =INTCON.6                       'USARTR INTERRUPT AÇILDI
SYMBOL RCIE =PIE1.5                         'USART ALMA AÇILIYOR
SYMBOL RCIF =PIR1.5                         'USART INTERRUPT OLUŞTU BBAYRAĞI

'*******************************************************************
RCIE=1
PEIE=1
GIE=1
RCIF=0
INTCON=%11000000
ON INTERRUPT GOTO INT

NERE:

pause 250               
FREKANS1:
pause 2000
serout PORTA.1,T9600,["*"]
PAUSE 2000          
serout PORTA.1,T9600,[FREKANS,13,10] 
PAUSE 2000 
goto nere

DISABLE
INT:
    GIE=0
    HSERIN [VER1]
    FREKANS=VER1
    HSEROUT [FREKANS] 
    RCA=RCREG
    RCIF=0
    GIE=1
    Resume
    enable
    'END      
Bu üzerinde uğraştığım..
@ DEVICE pic16F628A                                                   
@ DEVICE pic16F628A, WDT_OFF              
@ DEVICE pic16F628A, PWRT_ON 
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT              
@ DEVICE pic16F628A, PROTECT_ON         
@ DEVICE pic16F628A, MCLR_off 'MCLR pini kullanılıyor.
        
include "modedefs.bas"
DEFINE HSER_RCSTA 90h 
DEFINE HSER_TXSTA 24h 
DEFINE HSER_SPBRG 25 
DEFINE HSER_CLROERR 1 
VERI var WORD         
TRISB=%11011111
TRISA=%11000000        
CMCON=7                 
OPTION_REG=7           
PORTB=0        
PORTA=0
PAUSE 100
IF PORTA.7=1 THEN GOTO FREKANS2
pause 250               
FREKANS1:
pause 2000
serout PORTA.1,T9600,["*"]
PAUSE 2000          
serout PORTA.1,T9600,["AT+DMOSETGROUP=0,173.9750,173.9750,0012,0,0000",13,10] 
PAUSE 2000 
SEROUT PORTA.1,T9600, ["AT+DMOSETVOLUME=5",13,10] 
PAUSE 1000
GOTO DEVAM
FREKANS2:
pause 2000
serout PORTA.1,T9600,["*"]
PAUSE 2000          
serout PORTA.1,T9600,["AT+DMOSETGROUP=0,136.1000,136.1000,0012,0,0000",13,10] 
PAUSE 2000 
SEROUT PORTA.1,T9600, ["AT+DMOSETVOLUME=4",13,10] 
PAUSE 1000 
GOTO DEVAM  
              
 DEVAM:
  SAYI VAR BYTE 
  STD var  PORTB.0    '1 STD  8870
  E1  var  PORTB.4    'Q1 du 8870
  E2  var  PORTB.3    'Q2 du 8870
  E3  var  PORTB.2    'Q3 du 8870
  E4  var  PORTB.1   'Q4 du 8870
 
  SIFRE_1 var PORTB.5      ' 
  PORTA.0=1
  
  
  b1 VAR BYTE
  b2 VAR BYTE
  b3 VAR BYTE
  b1=0
  b2=0
  b3=0
      
  c1  var BYTE   '1° code DTMF
  c2  var BYTE   '2° code DTMF
  c3  var BYTE   '3° code DTMF
  c4  var BYTE   '4° code DTMF
  Q1  var BIT
  Q2  var BIT
  Q3  var BIT
  Q4  var BIT
 
BASLA:
DTMF1:      
            BUTTON STD,1,255,0,b1,1,DECODER1	
            PAUSE 20
    		BUTTON STD,0,255,0,b2,1,RAZ          
           	GOTO DTMF1
DECODER1:	
            Q1=E1		
    		Q2=E2
    		Q3=E3
    		Q4=E4
     		c1 =  Q1 + 2*Q2 + 4*Q3 +  8*Q4 	
            GOTO DTMF2
           
DTMF2: 	
            b3=0
            WHILE b3<75	
    		BUTTON STD,1,255,0,b1,1,DECODER2	
       	    PAUSE 20
        	b3=b3+1
            WEND
            GOTO DTMF1
DECODER2:	
            Q1=E1		
    		Q2=E2
    		Q3=E3
    		Q4=E4
     		c2 =  Q1 + 2*Q2 + 4*Q3 +  8*Q4 	
      	    GOTO DTMF3
        
DTMF3: 	
            b3=0
            WHILE b3<75	
    		BUTTON STD,1,255,0,b1,1,DECODER3	
         	PAUSE 20
	        b3=b3+1
            WEND
            GOTO DTMF1
DECODER3:	
            Q1=E1		
    		Q2=E2
    		Q3=E3
    		Q4=E4
     		c3 =  Q1 + 2*Q2 + 4*Q3 +  8*Q4 	
            GOTO SIFRE
              
RAZ:  
	  
        	Q1=0
        	Q2=0
	 	    Q3=0
            Q4=0
       	    GOTO DTMF1
            END
SIFRE:	
           PAUSE 10	
  	       IF c1=3 AND c2=9 AND c3=8 THEN 
           SIFRE_1=1
           PORTA.0=0  
           ENDIF
           IF c1=7 AND c2=8 AND c3=5 THEN 
           SIFRE_1=1
           PORTA.0=0 
           ENDIF
           IF c1=1 AND c2=4 AND c3=9 THEN
           SIFRE_1=1
           PORTA.0=0     
           ENDIF
           IF c1=5 AND c2=6 AND c3=4 THEN 
           SIFRE_1=1
           PORTA.0=0  
           ENDIF
           IF c1=7 AND c2=10 AND c3=5 THEN
           SIFRE_1=1
           PORTA.0=0      
           ENDIF
           IF c1=2 AND c2=5 AND c3=7 THEN 
           SIFRE_1=1
           PORTA.0=0  
           ENDIF
           IF c1=8 AND c2=2 AND c3=6 THEN
           SIFRE_1=1
           PORTA.0=0     
           ENDIF
           IF c1=12 AND c2=10 THEN  
           SIFRE_1=0
           PORTA.0=1  
           ENDIF
            
          c1=0	
          c2=0
          c3=0
   	      c4=0
          GOTO DTMF1     
      
Bu da normal olarka kullandığım.

aRci

Merhaba;
simulasyondaki portu uygulamaya bağlamak için sanırım sanalport programı kullanmak gerekiyordu bende ihtiyaç duymuştum ve o şekilde çözdüğümü hatırlıyorum tabi en kolayı küçük bir devre yapıp doğrudan test etmek

redmen

Merhaba evet sanal port kullanılıyor lakin sorun yaşadım bende bir max232 li bir de uart modülü kullanarak iki modülü fiziksel olarak birleştirip gerçek deneme olanığı sağladım.sorunsuz çalışıyor.

ete

Ortada bir sorun varmıdır yokmudur anlayamadım. Birinci mesaj sorun var diyor son mesaj sorunsuz çalışıyor diyor. Farklı şeyler için kullanılmış sözler olabilir.
Kodları incelediğimde gördüğüm kusurlu yerleri aşağıda veriyorum.
Birinci kod'da,
NERE ile GOTO NERE satırları arasında yer alan PAUSE'ler haberleşme senkronunu bozacak niteliktedirler.

Basic de bir kural vardır. İşlenmekte olan BASIC komutu bitirilmeden kesme oluşsa bile kesme alt programına program gitmez. Komutun bitirilmesini bekler.
PAUSE 2000 yaklaşık 2000 ms yada 2 sn lik bir gecikme yaratan komuttur. Bu şu demektir bu komutun bitirilme süresi 2000 ms dir. Bu komut işlenirken USART portuna bilgi geldiği algılanır ise program Kesme etiketine gidemeyeceği için o gelen bilgi kaçırılacak demektir.
Bu durumda yeni kuralı söyleyeyim. Bir programda Kesme kullanıyorsunuz kesinlikle pause komutunu kullanmayınız. Yada gecikmeyi çok küçük (us) dilimlere bölerek uygulayın. İlla gecikme yaratacaksanız aşağıdaki gibi yapın. Süre yetmez ise daha fazla PAUSEUS 5 ekleyebilirsiniz.
FOR W=0 TO 10000
  PAUSEUS 5
  PAUSEUS 5
  PAUSEUS 5
NEXT
Bu komutlarda size epeyce bir gecikme yaratacaktır. Ancak USART'a bilgi gelir ise en fazla 5us gecikme ile program Kesme etiketine gidecektir.

İkinci programda basic sayı limitlerini aşan değerler yer alıyor. Bu değerler komut formatına bakılırsa String şeklinde yollanıyor (çift tırnak arasında yer aldığı için) ise sorun olmaz. Mesela 136.1000 bir rakammıdır yoksa karektermidir Rakam ise Basic bunu yollayamaz. Çünki WORD tipi değişken değeri aşılmış oluyor. Bu ikincide de bol keseden Pause kullanılmış ama gönderen tarafta Pause kullanımı sorun yaratmaz. Alıcı taraf için ise büyük sorun.

Ete

redmen

Ete hocam öncelikle cevabınız için teşekkür ederim,sorun var birinci yazılım için sorun yok ise ikinci program içindi,birinci program arayüzle kullanmak için programın sadece bir bölümü,burada serial haberleşme yaparak arayüz üzerinden değer değişikliği yapmaya çalışıyorum gömülü sistemler de olduğu gibi,ikinci program ise mevcut kart üzerinde kullandığım arayüz programı olmaksızın kullandığım sorun yaşamadığım istediğimi yapan bir program,ben birinci bölümü ikinci program üzerine ekliyerek serial haberleşme yapmaya çalışıyorum,verdiğiniz bilgilere dikkat edip tekrardan üzerinde çalışacağım.arayüzden string bir ifade yada karekter grubu yolluyorum,pic ilk kareterden sonrasını almıyor onu çözmeye çalışıyorum.yoksa bu değişkenlerin eproma kaydı sonra geri çağrılması sonra komut satırına eklenmesi onlar ile sorun yaşıyacağımı sanmıyorum.

enes

#5
VER1 VAR WORD[7] 

VER1 WORD tıpı tanımlama yapmıssın

DISABLE
INT:
    GIE=0
    HSERIN [VER1]
    FREKANS=VER1

usart haberlesme kesme rutınınde bu sekılde word tıpı degısken alımı yapamazsın.
alınacak verı byte tıpınde olmalı

once bi isaretcı data ayarla sonrasınde bir dongu kurarak dıger verılerı pespese almaya calıs.

C#  bilmiyorum... VB orneklerı ıstersen verebilirim

redmen

#6
 Teşekkür ederim kardeşim,ben elektronik konusun da çok iyiyim ama proğram işimi geliştirme gereksinimi pek duymamıştım universiteden sonra,genel de karşılaştırma,sinyal takip gibi,pic programları üzerinde çalıştım,lakin şimdi artık iş tamamen plc yada pic üzerinden dönüyor. Uuart ve serial habesleşme üzerinde pek çalışmadım,o yüzden biraz deneme yanılma yolu ile ilerliyorum,örnek programlar atarsanız sevinirim,

ete

Birinci programdaki Pause ler o program için hiç bir sorun yaratmaz. Program çalışır. Asıl sorun karşıdaki Alıcıda oluşur.
Bu sorun biz senkron uyuşmazlığı diyoruz.
Örnekle açıklayayım.
- Oda da oturuyorsun
- Kapı çaldı ve sen o anda ne yapıyorsan bırakıp gidip kapıyı açıyorsun . Ne geldi ise alıyorsun.
  Burada sen kapı ile senkron çalıştın. Bir yerde kapının çalmasını bekliyordun.

Şimdi aynı örneği farklı şekilde işleyelim.

- Oda da oturuyorsun birden tuvalet ihtiyacı duydun ve oraya girdin. (Pause 2000 başladı)
- O anda kapı çaldı ama sen kapıya gidemiyorsun çünki meşgulsün. (Pause sürüyor)
- Kapıdaki adam kapının açılmadığını görüp geri gitti.
- Sen Tuvaletten çıktın (pause bitti) kapıya koştun açtın ama kimseyi göremedin.
Ne oldu gelen kimse onu kaçırdın.
Olay tamamen buna benzer şekilde gelişir.
Alıcı ile verici senkron içinde olmaz ise veri alışverişi olmaz. Verici ne zaman isterse bilgi yollayabilir. Ama Alıcı o veriyi sürekli beklemelidir. İşte Pause ler bu sürekli bekleme işini bozan unsurlardır. Her ne kadar Kesme kullansanız da Pause var ise Pause süresi sona ermeden program kesme etiketine gidemez.
BU açıklamaya göre yeniden düşün istersen.

İkinci programdaki yollama verisinin her bir karekterini bir diziye atarsan ve dizi yollama formatını kullanırsan bu sorunu aşarsın gibi geliyor bana.
Her bir karekter tek bir byte gibi düşünülmelidir. Ancak bu şekilde yapılabilir sanırım.

hserout [STR ArrayVar{\n}]' Send string of n characters
Alırken de benzer şekilde hserin [STR ArrayVar{\n}]' Send string of n characters

Ete

redmen

Hocam pauseler kısmını düzelttim,orda sorun yok,zaten o aslında başka bir programı takip etmesi içindi,onun için biraz karıştı,mesala dtmf sinyali ile cihaz açıldığında, dışardan gelecek bir pulse ile sayma işlemi de yaptırıp  kapatma sinyali gelmez ise 7 dk  için de sistemin resetlemesi içindi,ama şu işi çözünce ona bir düzenleme getireceğim,c# arayüzünde aslında iki şey denedim,ikisin de de istediğimi gönderebiliyorum mesala birisin de FREKANS ="AT+DMOSETGROUP=0,173.9750,"+sayi2+"0,0012,0,0000"; bu şekilde yaparak serial port üzerinden string bir ifade olarak gönderebiliyorum ancak bu pic için zor durum olduğu için onun yerine bu satırı pic içerisine yazıp arada ki c# üzerinden sayı2 değişkenlerini gönderip eproma kayıt edip,sonra epromdan çağırıp pic içerisinde komut satırında birleştirip serilport üzerinden SA818 Modülüne göndermek istiyorum işin aslı bu,tabi bu veri akışını istediğim gibi sağlarsam dtmf şifrelerini de değişkenler vasıtası ile eproma yazmayı düşünüyorum,aynı anda bir çok işlemi pic,e yaptırmaya çalışıyorum belki de ama olursa güzel olacak kanatindeyim.

redmen

#9
C# üzerinden bu şekilde bir veri gönderimi yapıyorum ve 16f628a
veriler sıra ile ver1 ver2 ver3 şeklinde bilgi işareti ile gönderiliyor

enes

zaman bılgısı gondermek ve almak ıcın su sekılde yapıyorum

PC arayuzden :

SerialPort1.Write("ABC" + Chr(Now.Hour) + Chr(Now.Minute) + Chr(Now.Second) + Chr(Now.DayOfWeek) + Chr(Now.Month) + Chr(Now.Day) + Chr(yıl-2000))

pic tarafından data alım :

HSERIN [WAIT("ABC"),SAAT,DAK,SN,GUN,AY,DAY,YIL]

seklınde oluyor.

ama senın gonderdıgın verıler 255 uzerı oldugu ıcın  pc tarafında verıyı bytlarına ayırıp tek tek gondermeyı dene. PıC tarafında da ayrılmıs parcaları bırlestır ve kullan...

redmen

Teşekkür ederim kardeşim,bu yöntemi de deneyeceğim inşallah.

redmen

Öncelikle herkese ilgisinden ve verdikleri bilgilerden dolayı teşekkür ederim.belki birilerinin fikri olur yada takıldığı bir nokta olursa güzel bir örnek oldu,tabi ki proğram üzerinde henüz işim bitmedi ama serial haberleşme eproma kaydetme,epromdan okuma,okunan bilgiyi serout komutu ile dışarı aktarma bölümünü buraya yazıyorum.
@ DEVICE pic16f628A                      'DENETLEYİCİ 16f628A                                
@ DEVICE pic16f628A, WDT_ON              'BEKÇİ KÖPEĞİ AÇIK
@ DEVICE pic16f628A, PWRT_ON             'GERİLİMDENGELENİNCE 1 KEZ RESET AT
@ DEVICE pic16f628A, PROTECT_OFF         'KOD KORUMA KAPALI
@ DEVICE pic16f628A, MCLR_OFF            'MCLR PİNİ KULLANILMAYACAK
@ DEVICE pic16f628A, INTRC_OSC_NOCLKOUT  'DAHİLİ OSİLATÖRÜ KULLAN
@ DEVICE Pic16f628A, BOD_OFF             'GERİLİM DALGALANMASI RESET KAPALI
INCLUDE "MODEDEFS.BAS"
'*****************************************************************
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
    DEFINE HSER_SPBRG 25  ' 9600 Baud @ 4MHz, 0,16%
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    DEFINE HSER_BAUD 9600 ' BaudRate 9600
    DEFINE OSC 4 
'******************************************************************
TRISA=%00000000                             'A PORTU ÇIKIŞ
TRISB=%00000010                             'B PORTUNUN 2.BİTİ GİRİŞ
PORTB=0:PORTA=0                             'A VE B PORTLARI SIFIRLANDI
CMCON=7                                     'COMPARATÖR İPTAL
'******************************************************************

VER1 VAR BYTE
VERI  VAR byte[7]
FRE VAR WORD     
TOPLAM VAR BYTE[7]
RCA     VAR byte                           'RCA  ADINDA 8 BİTLİK DEĞİŞKEN TANIMLANDI
SYMBOL GIE  =INTCON.7                       'BUTÜN İNTERRUPTLAR AÇILDI
SYMBOL PEIE =INTCON.6                       'USARTR INTERRUPT AÇILDI
SYMBOL RCIE =PIE1.5                         'USART ALMA AÇILIYOR
SYMBOL RCIF =PIR1.5                         'USART INTERRUPT OLUŞTU BBAYRAĞI

'*******************************************************************
RCIE=1
PEIE=1
GIE=1
RCIF=0
INTCON=%11000000
ON INTERRUPT GOTO INT

NERE:

pause 2               
FREKANS1:
pause  2
serout PORTA.1,T9600,["*"]
PAUSE 2
READ 0,VERI[0],VERI[1]
READ 2,VERI[2],VERI[3] 
READ 4,VERI[4],VERI[5]
READ 6,VERI[6],VERI[7]
serout PORTA.1,T9600,["AT+DMOSETGROUP=0,173.9750,",VERI[0],VERI[1],VERI[2],VERI[3],VERI[4],VERI[5],VERI[6],VERI[7],"0,0012,0,0013",13,10] 
PAUSE 2 

DISABLE
INT:
    GIE=0
    HSERIN 100,NERE,[WAIT("VER1"),VERI[0],VERI[1],VERI[2],VERI[3],VERI[4],VERI[5],VERI[6],VERI[7]]
    VER1=VERI
    WRITE 0,VERI[0],VERI[1]
    WRITE 2,VERI[2],VERI[3]
    WRITE 4,VERI[4],VERI[5]
    WRITE 6,VERI[6],VERI[7]
    HSEROUT [VERI[0],VERI[1],VERI[2],VERI[3],VERI[4],VERI[5],VERI[6],VERI[7]]
    RCA=RCREG
    RCIF=0
    GIE=1
    Resume
    enable
    goto nere
    END 

ve konu ile ilgili iki adet resim yolluyorum,ilk resim ısıs çalıştığında epromda ki verinin serout üzerinden aktarılması,ikinci resim ise arayüzden gelen verinin eproma alınıp serout üzerinden aktarılmasıdır.




aRci

paylaşım için teşekkürler ben size pc programını soracağım bunun ile ilgili detay verebilirmisiniz eğer ticari değilse ve hatta bir konu açıp yeni başlayanlar için kısam örnekler verebilirmisiniz.

redmen

Aslın da ticari lakin çokta önemli değil,Visual studio ile hazırlanmış bir arayüz,kullanımı kolay ve kodlar anlaşılır,işimiz tamamlanınca paylaşım da bulunuruz inşallah.saklayacak bir şey değil yani.

Powered by EzPortal