RS 485 Kullanımı

Başlatan vitruvius, 23 Ekim 2014, 00:33:48

vitruvius

Merhaba, ilk defa RS-485 kullanacağım. Forumdaki çoğu konuyu okudum, mantığını anladım ama mod değiştirme olayını yapamadım sanırım. Bunun algoritması nasıl olmalı?

İlk denemem olduğu için çok basit bir "al gülüm ver gülüm" kodu yazdım. İlk olarak A mikrodenetleyicisi butona basıldığında karakter olarak "70" yolluyor. B mikrodenetleyicisi de "70" almışsa "80" yolluyor. Bundan sonra A "80" almışsa "90" yolluyor. B de "90" almışsa "100" oluyor. A "100"ü alınca "Bitti" diyor ve olay bitiyor.

RS-485 kullanmadan rx-tx şeklinde bağlayarak kodu denedim çalıştı. Hatta Bu kadar döngüye girmeden Max487 bağlantılarını yapıp A'yı iletimde, B'yi de alıcı durumunda tutarak bir karakterin iletilip alındığını da gözlemledim. Ama bu döngüye girip mod değiştirme olayını başaramadım.

Bu arada proteus'ta simüle ederken 2sn'de 2000 kadar AVR Usart 0 RX Frame Error uyarısı alıyorum. Muhtemelen bu mod değişikliğindeki çakışmadan olduğunu düşünüyorum.

A için yazdığım kod:
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define F_CPU 8000000UL
#define UART_BAUD_RATE      19200   

#include <util/delay.h>
#include "uart.h"

int main(void)
{	
	DDRD = 0b11111010;	//	PORTD input/output.
	DDRA = 0xF0;
	
	PORTA = 0x00;
	PORTD = 0x00;
	
	unsigned int c;
	unsigned int mode = 0; // Mode 0 = Rx, Mode 1 = Tx
		
	uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
	 
	sei();
	 
    while(1)
    {		 
		c = uart_getc();
		
		if (mode == 0)
		{
			PORTD &= ~_BV(7); // Pin_D7'yi sifir yap. RE ve DE'ye bagli
		}
		
		else if (mode == 1)
		{
			PORTD |= _BV(7); // Pin_D7'yi bir yap. Pin_D7 RE ve DE'ye bagli
		}
		
        if (bit_is_set(PINA,0)) // Button
        {
	        _delay_ms(100);
	        if (bit_is_set(PINA,0))
	        {
		        while (bit_is_set(PINA,0));
				
				mode = 1; // Gondermeden once tx moduna gec
				uart_putc(70);
				mode = 0; // Gonderdikten sonra rx moduna gec
			}
		}		
		
       if (c == 80)
       {
		    mode = 1;
			uart_putc(90);
			mode = 0;
       }
           
       if (c == 100)
       {
		    mode = 1;
			uart_puts("Done!");
			mode = 0;
       }
    }
}


B için yazdığım kod:
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define F_CPU 8000000UL
#define UART_BAUD_RATE      19200  

#include <util/delay.h>
#include "uart.h"

int main(void)
{
	unsigned int c;
	unsigned int mode = 0;
	
	DDRD = 0b11111010;	//	PORTD input/output.
	DDRA = 0xFF;
	
	PORTD = 0x00;
	PORTA = 0x00;
	
	uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
	sei();
	 
    while(1)
    {
        c = uart_getc();		
		
		if (mode == 0)
		{
			PORTD &= ~_BV(7);
		}
		
		else if (mode == 1)
		{
			PORTD |= _BV(7);
		}

		if ( c == 70)
		{
			mode = 1;
			uart_putc(80);
			mode = 0;
		}
			
		if (c == 90)
		{
			mode = 1;
			uart_putc(100);
			mode = 0;
		}
    }
}


Devre şeması:


Teşekkürler.

Kabil ATICI

#1
if ( c == 70)
        {
//buraya biraz gecikme ekle... Karşı taraf kendini toparlayabilsin.
            mode = 1;
            uart_putc(80);
            mode = 0;
        }

hatan şu;
şimdi mode seçme işini main fonksiyon içinde duruyor, ama
mode=1 veya mode=0 yaptığın zaman main fonksiyonu içinde başa dönmedikçe senin mod değişikliğin yerine getirilmez. Ama yukarıdaki gibi bir durumda mode başa dönmeden 2 kez değiştiriyorsun...

void mod_sec(uint8_t modus)
{	if (modus == 0)
	{
		PORTD &= ~_BV(7); // Pin_D7'yi sifir yap. RE ve DE'ye bagli
	}
	
	else 
	{
		PORTD |= _BV(7); // Pin_D7'yi bir yap. Pin_D7 RE ve DE'ye bagli
	}
}

mod değişikliğini bir fonksiyon tanımlayıp
mode = 1;  yerine  mod_sec(1); gibi ifade ile değiştirmen gerekiyor, dolayısı ile
mode=0; yerine mod_sec(0); ile.

sanırım bu max487'de sıkıntı var.
ambar7

vitruvius

#2
Hocam dediklerinizi yapmaya çalıştım ama olmadı ve proteus binlerce kez "B" diye tanımladığım Atmega644P için AVR USART 0 RX Frame Error mesajı veriyor. Yeni kodlar:

A:
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define F_CPU 8000000UL
#define UART_BAUD_RATE      19200   

#include <util/delay.h>
#include "uart.h"

void mod_sec(uint8_t modus)
{	if (modus == 0)
	{
		PORTD &= ~_BV(7); // Pin_D7'yi sifir yap. RE ve DE'ye bagli
	}
	
	else if(modus == 1)
	{
		PORTD |= _BV(7); // Pin_D7'yi bir yap. Pin_D7 RE ve DE'ye bagli
	}
}

int main(void)
{	
	DDRD = 0b11111010;	//	PORTD input/output.
	DDRA = 0xF0;
	
	PORTA = 0x00;
	PORTD = 0x00;
	
	unsigned int c;
		
	uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
	 
	sei();
	 
    while(1)
    {		 
		c = uart_getc();
		
        if (bit_is_set(PINA,0)) // Button
        {
	        _delay_ms(100);
	        if (bit_is_set(PINA,0))
	        {
		        while (bit_is_set(PINA,0));
				
				_delay_ms(10); // Karsi taraf icin gecikme
				mod_sec(1);
				uart_putc(70);
				mod_sec(0);
			}
		}		
		
       if (c == 80)
       {
	       _delay_ms(10); // Karsi taraf icin gecikme
		    mod_sec(1);
			uart_putc(90);
			mod_sec(0);
       }
           
       if (c == 100)
       {
	       _delay_ms(10); // Karsi taraf icin gecikme
		    mod_sec(1);
			uart_puts("Done!");
			mod_sec(0);
       }
    }
}


B:
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define F_CPU 8000000UL
#define UART_BAUD_RATE      19200  

#include <util/delay.h>
#include "uart.h"

void mod_sec(uint8_t modus)
{	if (modus == 0)
	{
		PORTD &= ~_BV(7); // Pin_D7'yi sifir yap. RE ve DE'ye bagli
	}
	
	else if (modus == 1)
	{
		PORTD |= _BV(7); // Pin_D7'yi bir yap. Pin_D7 RE ve DE'ye bagli
	}
}

int main(void)
{
	unsigned int c;
	
	DDRD = 0b11111010;	//	PORTD input/output.
	DDRA = 0xFF;
	
	PORTD = 0x00;
	PORTA = 0x00;
	
	uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
	sei();
	 
    while(1)
    {
        c = uart_getc();		

		if ( c == 70)
		{
			_delay_ms(10); // Karsi taraf icin gecikme
			mod_sec(1);
			uart_putc(80);
			mod_sec(0);
		}
			
		if (c == 90)
		{
			_delay_ms(10); // Karsi taraf icin gecikme
			mod_sec(1);
			uart_putc(100);
			mod_sec(0);
		}
    }
}


Atmel Studio ve proteus dosyalarını da upload ettim, oradan da bakabilirsiniz: http://www.4shared.com/zip/Ec1sxrwjba/Rs_485.html

Bir de max487'de sıkıntı var derken, ne gibi bir sıkıntıdan bahsettiniz?

Teşekkürler.

Kabil ATICI

Aynı programı Atmega16 üzerinden derlemeye çalıştım(sizin işlemcinin adını göremeyince), sanırım kullandığımız derleyiciler farklı olunca bazı yerleri değiştirdi. Hatta uart 'yi kesme ile yapmaya çalıştım. Max487 'yi bağladığım zaman sürekli olarak  işlemciye birşeyler geliyormuş gibi bir durum oluyor. (pull up direnci dahi denedim)
Daha önce Max485 ile gerçek devre üzerinde çalıştım (asm kod ile) hiç bir böyle bir sıkıntı oluşturmamıştı.

Neyse isis'de işin içinden çıkamayınca çalışmayı askıya aldım (başka işim vardı)
ambar7

vitruvius

Hocam devreyi gerçekte kurup denedim ve çalıştı. Ama Proteus'ta neden böyle bir sıkıntı oluyor çözemedim. Yada bu sıkıntı gerçek devrede de bir sorun olduğunun yada olacağının göstergesi midir bilmiyorum. Ama gerçek devrede gönderdiğim her karater için iki tarafta da ledler yakarak bu karakterlerin alındığını gözlemledim. Şimdilik gerçek devre üzerinden ilerleyeceğim, teşekkür ederim.

Kabil ATICI

İsis sihirli değnek değil. Sonuçta bir program ve eksik ve hataları olduğu bir gerçek.
Bir bölümü help dosyasında açıklanmış.

Bu hataların bir bölümü bizden kaynaklanıyor olabilir. (Kopya kullanmanın cezası veya laneti.)
ambar7