PIC BASIC PRO Öğreniyoruz soru cevapları

Başlatan aster, 19 Mayıs 2005, 17:33:33

ete

Aslında programın tamamını görmeden sürekli burada tartışıyor ve akıl veriyoruz ama yanlış yapıyoruz sanırım.
O nedenle programı buraya koyarsan daha uygun olacak herhalde. Amacın nedir onuda açıklarsan sevinirim.
Normal şartlarda duty değerinin 100'ü aşmaması gerekmezmi o zaman yazdığın;

'IF DUTY_A=255 THEN DUTY_A=99
'IF DUTY_B=255 THEN DUTY_B=99
'IF DUTY_C=255 THEN DUTY_C=99
komutlar tümden yanlış oluyor. Ama aşıyor ise o zaman o kararsızlığın 255 dolaylarında gözükmesi gerekirdi.
Anlayacağın programın tamamını görmek lazım artık.
Ben olsam şöyle yazardım.

'IF DUTY_A=100 THEN DUTY_A=1
'IF DUTY_B=100 THEN DUTY_B=1
'IF DUTY_C=100 THEN DUTY_C=1
Çünki bildiğim kadarı ile yalnızca artırma tuşları var. O halde eksiltme olmayacağına göre butona bastıkça artacak. Nereye kadar?, 100 oluncaya kadar 100 olunca yeniden 1 den başlatmak en mantıklısı olurdu.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

emrah

hocam artırmada var azaltmada var toplam 6 adet tuş var. programım şu şekilde;

kesme programı sizin derslerde verdiginiz program hocam.




TRISA=0
TRISB=%11111111
TRISC=0
TRISD=0
TRISE=0

porta=0
portb=0
portc=0
portd=0
porte=0



DEFINE LCD_DREG PORTD 'LCD data port
DEFINE LCD_DBIT 4 'LCD data starting bit 0 or 4
DEFINE LCD_RSREG PORTD 'LCD register select port
DEFINE LCD_RSBIT 3 'LCD register select bit
DEFINE LCD_EREG PORTD 'LCD enable port
DEFINE LCD_EBIT 2 'LCD enable bit
DEFINE LCD_LINES 2 'Number lines on LCD


DEFINE OSC 20

@ DEVICE pic16F877                                                   
@ DEVICE pic16F877, WDT_OFF                 
@ DEVICE pic16F877, PWRT_ON                
@ DEVICE pic16F877, PROTECT_OFF         
@ DEVICE pic16F877, HS_OSC

ON INTERRUPT GoTo KESME   
OPTION_REG=%10001000      
INTCON=%10100000

ADCON1=7

DUTY_A VAR BYTE
DUTY_B VAR BYTE
DUTY_C VAR BYTE
LEDA VAR BYTE
LEDB VAR BYTE
LEDC VAR BYTE
I VAR WORD
X VAR BYTE

PAUSE 100
LCDOUT $FE,1

   DUTY_A=1
   DUTY_B=1
   DUTY_C=1



BASLA:

'LCDOUT $FE,$80,"R =",DEC3 DUTY_A
'LCDOUT $FE,$88,"G =",DEC3 DUTY_B
'LCDOUT $FE,$C0,"B =",DEC3 DUTY_C

DUTY_A=DUTY_A+PORTB.0
DUTY_A=DUTY_A-PORTB.1

DUTY_B=DUTY_B+PORTB.2
DUTY_B=DUTY_B-PORTB.3

DUTY_C=DUTY_C+PORTB.4
DUTY_C=DUTY_C-PORTB.5

FOR I=0 TO 1000

'FOR X=0 TO 2

'NEXT X

NEXT I
I=0



IF DUTY_A=100 THEN DUTY_A=1
IF DUTY_B=100 THEN DUTY_B=1
IF DUTY_C=100 THEN DUTY_C=1

IF DUTY_A=255 THEN DUTY_A=99
IF DUTY_B=255 THEN DUTY_B=99
IF DUTY_C=255 THEN DUTY_C=99

GOTO BASLA







DISABLE
KESME:
      LEDA=LEDA+1
      IF (PORTC.1=1 AND LEDA=DUTY_A) OR (PORTC.1=0 AND LEDA=100-DUTY_A) THEN
         PORTC.1=1-PORTC.1
         LEDA=0
      ENDIF
             
     
      LEDB=LEDB+1
      IF (PORTC.2=1 AND LEDB=DUTY_B) OR (PORTC.2=0 AND LEDB=100-DUTY_B) THEN
         PORTC.2=1-PORTC.2
         LEDB=0
      ENDIF
     
      LEDC=LEDC+1
       IF (PORTC.3=1 AND LEDC=DUTY_C) OR (PORTC.3=0 AND LEDC=100-DUTY_C) THEN
         PORTC.3=1-PORTC.3
         LEDC=0     
      ENDIF
         
      TMR0=230
      INTCON.2=0       
      RESUME
      ENABLE
     
END





bu yaptıgım sürücüye baska picten bilgi gelcek zaten, benm düşümcem buton yerine diger picin pinlerini buton yerine baglayarak picten sinyal göndermekti.  seri data göndermeyi  bu işin içine soksamda , bekleme , butonlar ve 1-99 arası if şartlarını kaldırıp duty degerlerine seri data göndererek değiştirsem yapılabilirmi?   yani pwm için yazdıgım programın ana menusune  SERIN komutu kullanabilirmiyimki? bu komut data geldiginde çalısıyor gelmediğinde data beklemesi yapıyor. bu bekleme kesmeyi etkilermi

yazacagım komut şu;

DISABLE

SERIN Pin,Mode,{Timeout,Label,}{[Qual...],}

ENABLE

kullanılabilirmi?

emrah

seri iletişimi denedim fakat olmadı. bu şekilde yapılamazmı?


pwm sinyali ürettigim pic 16f877 ve 20 mhz de çalısıyor.
ana menusunde şu programı kullandım

BASLA:

DISABLE
SerIn2 PORTC.7,1200,[DUTY_A,DUTY_B,DUTY_C]
ENABLE

GOTO BASLA


bilgiyi gönderdigim pic ise 4 mhz ile calısan 16f628a ;

programı;

BASLA:

A=30
B=40
C=55

    IF PORTB.1=1 THEN
    SEROUT2 PORTB.0,1200, [A,B,C] 
    ENDIF
   
    GOTO BASLA

ete

#363
O şekilde senkron tutmayacağı için çalışmaz. En iyisi USART kesmesi kullanmaktır.
Şimdilik Seri iletişimi bir kenara koy istersen Ona sonra bakarız.
Aşağıdaki kodu bir denermisin devrende;
BASLA:

DUTY_A=DUTY_A+PORTB.0
DUTY_A=DUTY_A-PORTB.1

DUTY_B=DUTY_B+PORTB.2
DUTY_B=DUTY_B-PORTB.3

DUTY_C=DUTY_C+PORTB.4
DUTY_C=DUTY_C-PORTB.5

FOR I=0 TO 15:NEXT I

GOTO BASLA

DISABLE
KESME:
      FOR X=0 TO 255
      IF x<=DUTY_A THEN 
         PORTC.1=1
      ELSE
         PORTC.1=0
      ENDIF      

      IF x<=DUTY_b THEN 
         PORTC.2=1
      ELSE
         PORTC.2=0
      ENDIF 
      
      IF x<=DUTY_c THEN 
         PORTC.3=1
      ELSE
         PORTC.3=0
      ENDIF       
      NEXT

      INTCON.2=0       
      RESUME
      ENABLE
     
END


Tuşların çalışma süresi hızlı gelirse döngü miktarını  15 den 20 ye  hatta 16 -17 -18 şeklinde artırırsan daha hassas sonuç elde edersin.
Bu şekilde PWM frekansı yaklaşık 550 Khz dolayına yükselecek. Bu ise kesinlikle kırpışma falan olmamasını sağlaması lazım.
Ancak parlaklıkla ilgili sorun çıkabilir . Olursa frekansı düşürmek gerekecek O zamanda Kesme içindeki döngü arasına ;
Pauseus 5 gibi bir komut koyman yeterli olacaktır.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

emrah

tek kelimeyle harika... tam istedigm gibi oldu hocam cok teşekkür ederim. 

pwm sürücü kısmını 16f628A ile yapacagımdan,  USART kesmesi bu picte yok diye biliyorum?


yapacagım saat devresinde 16f877a kullanacagım. ledleri sürebilmek içinde 16f628A kullanacagım. eger bu ikisi arasında seri iletişimi yapamazsam butonların girişine, 16f877 den 6 adet pic cıkartıp 16f628 pin girişlerine baglayacagım, buda hem sıkıntılı hem gereksiz olur dıye dusunuyorum. USART ı bu şekilde kullanmak mumkunmu hocam? daha önce de USART ile hiç ilgilenmedim

ete

Harika olduğuna sevindim. Daha da harika olabilir unutma.
Mevcut program çok kısa aralıkle kesme yaratıyor. Kesme süresini her 4 küsur ms de bir seviyesine çıkartırsan sonuç dahada harika olacaktır.
Bu ise sana USART üzerinden bilgi alma imkanı da sağlayacaktır.

Kesme süresi değişikliği için yalnızca option registerinin değerini değiştirmen yeterli olacaktır. Registere aşağıdaki değeri verirsen yaklaşık her 4,1 ms de bir kesme oluşacaktır.
OPTION_REG=%10000011  şeklinde .
Bu durumda buton kontrolü hızlanacak. Bu nedenle döngü sayısını 50 ye çıkart bence.
Ayrıca kesme kısmında pauseus kullanmış isen onuda sil.

Bu program ile dışarıdan seri bilgide almak istiyorsan USART kesemsini açman ve Kesme kısmında ufak bir ayarlama yapman gerekecek.
Öncelikle belirteyim 16F628 ve 628A da USART portu vardır kesme oluşturabilirsin.

USART kesmesini aktif etmek için sırası ile;
- INTCON.6 biti "1" yapılacak
- PIE1.5 biti "1" yapılacaktır.

Kesme Kısmında ise iki adet ayrı kesme kaynağı oluştuğu için ayrım yapmak zorundasın. Bunun için oluşan kesmenin hangisi olduğunu anlaman ve ona göre işlem yapman gerekiyor. Burada temel veri kesme bayraklarıdır.
Şayet TMR0 bayrağı set edilmiş ise TMR0 kesmesi oluşmuştur. O halde şu anda ne yapılıyorsa aynı işleri yapıp kesmeden çıkması gerekir.
Şayet USART kesmesi oluşmuş ise PIR1.5 biti set ediliecektir. Bu durumda USART dan gelen bilgiler alınmalıdır. Bu kesme bayrağı direk sıfırlanmaz. Ancak RCREG registerini okursan yada bir başka değişkene aktarırsan bayrak otomatik sıfırlanacaktır.
Şimdi Kesme kısmını bu açıklamalara göre düzenleyelim;
DISABLE
KESME:
IF PIR1.5=1 then VERIAL
 FOR X=0 TO 255
      IF x<=DUTY_A THEN 
         PORTC.1=1
      ELSE
         PORTC.1=0
      ENDIF      

      IF x<=DUTY_b THEN 
         PORTC.2=1
      ELSE
         PORTC.2=0
      ENDIF 
      
      IF x<=DUTY_c THEN 
         PORTC.3=1
      ELSE
         PORTC.3=0
      ENDIF   
'      pauseus 5    
      NEXT
      INTCON.2=0       
      GOTO CIK

VERIAL:
HESERIN 3,CIK, [WAIT("GS"),DUTY_A,DUTY_B,DUTY_C]
TEMP=RCREG

CIK:
       RESUME
       ENABLE


20 Mhz de çalıştığına göre sorunsuzca 9600 baud da haberleşme yapabilirsin.
628 den bilgi yollarken
HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]

HSEROUT ["G","S",DUTY_A,DUTY_B,DUTY_C]  şeklinde yollaman gerekiyor.
Ayrıca her iki programın başına ;
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 129 ' 9600 Baud @ 20MHz, 0,16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

komutlarını eklemeyi de unutma.
Hepsi bu kadar.

Ete

Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

emrah

hocam dediginiz OPTION_REG=%10000011  değişikligini yaptım donguyü 50 de denedim ve 200 de denedim butonlar çok hızlı renk değişimide hızlı oluyor?

ete

Döngüyü 255'e kadar çıkartabilirsin.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

emrah

255 degerinde ilk programa gore hızlı. hocam haberlesmeyı yapablrsem buna gerek kalmayacak.


programda regester ayarları şöyle yapılı, fakat PIE1 regesterinide burayamı ekleyecegim?

ON INTERRUPT GoTo KESME   
OPTION_REG=%10000011      
INTCON=%11100000
PIE1.5=1   ----------------    şeklindemi?


bilgiyi 877 den gönderecegim HSER kullandıgım zaman portc.7 pininden alacagım demi?

ete

Evet. Aynen öyle.  PortC de TX yazılı olan pinden gönderme yapacak diğerinde RX yazılı pinden gelen bilgiyi alacaksın.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

emrah

hocam anlatılan herseyi yaptım yada yaptım sanıyorum . kafam allak bullak oldu. zahmet olmazsa gönderdigm linkteki dosyalar bir göz atarsanız nerede hatam var. simulasyonda denedim ama veri gitmiyor.

http://www.dosya.tc/server9/bLoIe5/RGB_full.rar.html

emrah

628 için yazılan programda WDT on konumunda hocam!

ete

Sorun 628 de RX pinini giriş olarak ayarlamamak. Ancak sistemin kuruluş biçiminide sevdiğimi söyleyemem.
Bu nedenle programları biraz değiştirdim.

Önce 877'yi vereyim;
TRISA=0
TRISB=%11111111
TRISC=%11000000
TRISD=0
TRISE=0

porta=0
portb=0
portc=0
portd=0
porte=0


DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 129 ' 9600 Baud @ 20MHz, 0,16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

DEFINE LCD_DREG PORTD 'LCD data port 
DEFINE LCD_DBIT 4 'LCD data starting bit 0 or 4 
DEFINE LCD_RSREG PORTD 'LCD register select port 
DEFINE LCD_RSBIT 3 'LCD register select bit 
DEFINE LCD_EREG PORTD 'LCD enable port 
DEFINE LCD_EBIT 2 'LCD enable bit 
DEFINE LCD_LINES 2 'Number lines on LCD

DEFINE OSC 20

@ DEVICE pic16F877                                                   
@ DEVICE pic16F877, WDT_OFF              	
@ DEVICE pic16F877, PWRT_ON             	
@ DEVICE pic16F877, PROTECT_OFF         
@ DEVICE pic16F877, HS_OSC

ADCON1=7

DUTY_A VAR BYTE
DUTY_B VAR BYTE
DUTY_C VAR BYTE
LEDA VAR BYTE
LEDB VAR BYTE
LEDC VAR BYTE
I VAR WORD
TOP VAR WORD
X VAR BYTE

PAUSE 100
LCDOUT $FE,1

   DUTY_A=1
   DUTY_B=1
   DUTY_C=1
 


BASLA:

LCDOUT $FE,$80,"R =",DEC3 DUTY_A
LCDOUT $FE,$88,"G =",DEC3 DUTY_B
LCDOUT $FE,$C0,"B =",DEC3 DUTY_C



DUTY_A=DUTY_A+PORTB.0
DUTY_A=DUTY_A-PORTB.1 

DUTY_B=DUTY_B+PORTB.2 
DUTY_B=DUTY_B-PORTB.3 

DUTY_C=DUTY_C+PORTB.4 
DUTY_C=DUTY_C-PORTB.5 

I=DUTY_A+DUTY_B+DUTY_C

IF I=TOP THEN BASLA

HSEROUT [REP$AA\5,REP$00\5,REP$FF\5]

HSEROUT ["G","S",DUTY_A,DUTY_B,DUTY_C]

TOP=I

GOTO BASLA
      
END


Şimdi de 628'i vereyim;
PORTA=0
PORTB=0     
TRISB=%00000010         
TRISA=%00000000  
'-----------------------------------------------------------------
@ DEVICE pic16F628A                      'işlemci 16F628                                
@ DEVICE pic16F628A, WDT_ON              'Watch Dog timer açık
@ DEVICE pic16F628A, PWRT_ON             'Power on timer açık
@ DEVICE pic16F628A, PROTECT_OFF         'Kod Protek kapalı
@ DEVICE pic16F628A, MCLR_off            'MCLR pini kullanılMIYOR.
@ DEVICE pic16F628A, HS_OSC
'-----------------------------------------------------------------
DEFINE OSC 20

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 129 ' 9600 Baud @ 20MHz, 0,16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

ON INTERRUPT GoTo KESME   
 	
INTCON=%11000000
PIE1.5=1

CMCON=7  

'ADCON1=7

DUTY_A VAR BYTE
DUTY_B VAR BYTE
DUTY_C VAR BYTE
LEDA VAR BYTE
LEDB VAR BYTE
LEDC VAR BYTE

TEMP var byte

I VAR BYTE
X VAR BYTE

PAUSE 200
LCDOUT $FE,1

   DUTY_A=1
   DUTY_B=1
   DUTY_C=1
 


BASLA:

FOR X=0 TO 255
      IF x<=DUTY_A THEN 
         PORTA.1=1
      ELSE
         PORTA.1=0
      ENDIF      

      IF x<=DUTY_b THEN 
         PORTA.0=1
      ELSE
         PORTA.0=0
      ENDIF 
      
      IF x<=DUTY_c THEN 
         PORTA.2=1
      ELSE
         PORTA.2=0
      ENDIF   
   
      NEXT

'FOR I=0 TO 10:NEXT I

GOTO BASLA

DISABLE
KESME:

HSERIN 3,CIK, [WAIT("GS"),DUTY_A,DUTY_B,DUTY_C]
TEMP=RCREG

CIK:
       RESUME
       ENABLE


Dene bakalım. Artık bu yazışmaya bir son veriyorum. Gerisini kendin halletmeye bak . Zaten her şey çalışıyor. Belki ufak tefek süre ayarlamaları gerekebilir onlarıda yaparsın.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

emrah

Tamam hocam çalışıyor. herşey için teşekkür ederim....

emrah

merhaba hocam;

12f675 picini ilk defa kullanacagım, pici denemek için söyle bir program birleştirdim.

@	device  pic12F675, intrc_osc_noclkout, wdt_off, pwrt_on, mclr_off, protect_off	

DEFINE OSCCAL_1K 1 
DEFINE ADC_BITS 4
DEFINE ADC_SAMPLEUS 50
DEGER VAR BYTE
DEGER2 VAR BYTE
CMCON=7
ANSEL=%00110001
TRISIO=1




BASLA:
PAUSE 1500
ADCIN 0,DEGER
DEVAM:
PAUSE 1000
ADCIN 0,DEGER2
IF DEGER2<DEGER THEN HIGH GPIO.1
GOTO DEVAM
END



fakat bu programda GP5 portu sürekli 1 konumuda kalıyor.

bu picle esas yapacagım iş 1 adet onolog girşi ve 5 adet röle kontrolü olacak hocam. yardımlarınızı bekliyorum