logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega32][Atmega8][RS485][c] - błędne wartości danych

boniu747 28 Lip 2009 14:54 4794 7
  • #1 6830766
    boniu747
    Poziom 10  
    Witam
    Mam problem z komunikacją między dwoma uC. Dane są odbierane, jednak nie zgadzają się z wysyłanymi.

    Atmega32 - pełni funkcję Mastera
    
    #define VUART 38400
    #define VUBRR F_CPU/(VUART*16)-1
    #define T0_start 1
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <avr/iom32.h>
    #include <stdlib.h>
    
    
    //Definicje zmiennych
    volatile unsigned char z;
    volatile unsigned int alarm_active=0; 	//aktywność czujek; 1 - wykryty ruch, 0 - brak ruchu
    //void Alarm_Init(int alarm_active);
    
    void TIMER0_Init()
    {
    
      TCNT0 = T0_start;         // wartość początkowa T/C0
      TCCR0 = _BV(CS00)|_BV(CS02); // preskaler 1024
      TIMSK = _BV(TOIE0);        // włącz obsługę przerwań T/C0
    }
    
    SIGNAL (SIG_OVERFLOW0)
    {
      	TCNT0 = T0_start;                // przeładuj timer 0
    	PORTC ^= 0x08;              // przełącz stan LED na PC3
    
    }
    
    //	**********************Funkcje obsługi USART**************************
    
    void USART_Init(uint8_t baud) //inicjalizacja USART
    {
     	//Set baud rate
    	UBRRH = (uint8_t)(baud>>8);
    	UBRRL = (uint8_t)baud;
    	// Enable Receiver and Transmitter
    	UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
    	// Set frame format: 8data, 1 stop bit
    	UCSRC = 0x86; //asynchroniczne, 8-bit, 1-bit stopu
    	PORTD &=~_BV(4); //RS485 - odbior
    	_delay_ms(1);
    } 
    
    
    void USART_Transmit( unsigned char data ) //wyslanie 8 bit
    {
    	//Ustalenie  kierunku transmisji RS485 - nadawanie
    	PORTD |= _BV(4); 
    	_delay_ms(1);
    	// Wait for empty transmit buffer
    	while ( !( UCSRA & (1<<UDRE)) )
    	;
    	// Put data into buffer, sends the data
    	UDR = data;
    	//Ustalenie kierunku transmisji RS485 - odbiór
    	PORTD &=~_BV(4);
    	_delay_ms(1);
    } 
    
    unsigned char UART_odbierz (void)
    {
         /* Wait for data to be received */
       while ( !(UCSRA & (1<<RXC)) )
       ;
       /* Get and return received data from buffer */
       return UDR;
    } 
    
    SIGNAL (SIG_UART_RECV)
    {
    	PORTC ^= 0x10;    //sprawdzenie dioda odbioru
    	z = UART_odbierz();
    	_delay_ms(100);
    	PORTC ^= 0x10;
    
    } 
    
    void Sprawdz_Moduly() //sprawdzenie modulow
    {
    	USART_Transmit(0x01);
    	for (int i=0;i<10;i++){
    		_delay_ms(100);
    		}
    }
    
    //Funkcja glowna
    
    int main(void)
    {
    	//Deklaracja wyjsc i wejsc
    	DDRB=0x0F; 	//PB0-3 będą wyjsciami, PB4-7 będą wejsciami
    	PORTB=0xF0;	// PB4-7 z podciagnieciem do VCC;
    	DDRA=0xFF;	//PA będą wyjsciami
    	DDRC=0xF8;	// 1111 1000 
    	DDRD=0x32;		// 0011 0010
    	PORTD=0xC0;		//PD7 i PD6 z podciagnieciem
    	MCUCSR |= (1<<JTD);
    	MCUCSR |= (1<<JTD); //wylaczenie JTAG
    
    	TIMER0_Init();
    	USART_Init(VUBRR);			//inicjalizacja usart
    	sei();						//wlaczenie przerwan
    
    	while(1) //petla glowna programu
    	{
    
    		Sprawdz_Moduly();
    
    	}
    	
    }
    


    Atmega8 - pełni funkcję modułu
    
    #define VUART 38400
    #define VUBRR F_CPU/(VUART*16)-1
    #define T0_start 1
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <avr/iom8.h>
    #include <stdlib.h>
    
    
    //Definicje zmiennych
    volatile unsigned char z;
    volatile unsigned char adres=0x01; //dla modulu 1
    
    volatile unsigned int alarm_active=0;	//flaga wlaczenia alarmu
    
    //Definicja funkcji
    int sprawdz(void);
    
    
    void USART_Init(uint8_t baud) //inicjalizacja USART
    {
     	//Set baud rate
    	UBRRH = (uint8_t)(baud>>8);
    	UBRRL = (uint8_t)baud;
    
    
    	// Enable Receiver and Transmitter
    	UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
    	// Set frame format: 8data, 1 stop bit
    	UCSRC = 0x86;
    	PORTD &=~_BV(2); //RS485 - odbior
    	_delay_ms(1);
    } 
    
    
    void USART_Transmit( unsigned char data ) //wyslanie 8 bit
    {
    	//Ustalenie  kierunku transmisji RS485 - nadawanie
    	PORTD |= _BV(2); 
    	_delay_ms(1);
    	// Wait for empty transmit buffer
    	while ( !( UCSRA & (1<<UDRE)) )
    	;
    	// Put data into buffer, sends the data
    	UDR = data;
    	//Ustalenie kierunku transmisji RS485 - odbiór
    	PORTD &=~_BV(2);
    	_delay_ms(1);
    } 
    
    
    unsigned char UART_odbierz (void)
    {
         /* Wait for data to be received */
       while ( !(UCSRA & (1<<RXC)) )
       ;
       /* Get and return received data from buffer */
       return UDR;
    } 
    
    
    void TIMER0_Init()
    {
    
      TCNT0 = T0_start;         // wartość początkowa T/C0
      TCCR0 = _BV(CS00)|_BV(CS02); // preskaler 1024
      TIMSK = _BV(TOIE0);        // włącz obsługę przerwań T/C0
    }
    
    SIGNAL (SIG_UART_RECV)
    {
    	PORTD ^= 0x20; //sprawdzenie ledem transmisji
    	z = UART_odbierz();
    	_delay_ms(100);
    	USART_Transmit(0x20);
    	if (z == 0x01 || z ==0x02) 
    	{
    		PORTB ^=0x40; //sprawdzenie ledem poprawnosci transmisji
    	}
    	PORTD ^= 0x20;
    } 
    
    SIGNAL (SIG_OVERFLOW0)
    {
      	TCNT0 = T0_start;                // przeładuj timer 0
    //	PORTB ^=0x40;              // przełącz stan LED na PB6
    }
    
    int sprawdz(void){
    	alarm_active=0;
    	if (PINB & 0x01) alarm_active=1;
    	if (PINB & 0x02) alarm_active=1;
    	if (PINB & 0x04) alarm_active=1;
    	if (PINB & 0x08) alarm_active=1;
    	if (PINB & 0x10) alarm_active=1;
    	if (PINB & 0x20) alarm_active=1;
    
    	if (PINC & 0x01) alarm_active=1;
    	if (PINC & 0x02) alarm_active=1;
    	if (PINC & 0x04) alarm_active=1;
    	if (PINC & 0x08) alarm_active=1;
    	if (PINC & 0x10) alarm_active=1;
    	if (PINC & 0x20) alarm_active=1;
    
    	if (PIND & 0x08) alarm_active=1;
    	if (PIND & 0x10) alarm_active=1;
    	if (PIND & 0x40) alarm_active=1;
    	if (PIND & 0x80) alarm_active=1;
    	return alarm_active;
    }
    
    //Program główny
    
    int main(void)
    {
        /* Zadeklarowanie wyjsc */
    
    	DDRD |= (1<<2)|(1<<5); 	//wyjscie na D2, D5
    	DDRB |= (1<<6)|(1<<7); 	//wyjscie na B6, B7
    	
    	//Zadeklarowanie wejsc
    
    	DDRC = 0x00; 			//wejscia C 0000 0000
    	PORTC = 0x3F;			//z podciagnieciem 0011 1111
    	DDRD &= 0xE6;			//wejscia D3,D4 1110 0110
           PORTD |= 0x18;			//z podciagnieciem
    	DDRB &= 0xC0;			//wejscia B0-B5 1100 0000
    	PORTB |= 0x3F;			//z podciagnieciem
    	DDRD &= 0x3F;			//wejscia D6,D7 0011 1111
    	PORTD |= 0xC0;			//z podciagnieciem
      
    	PORTD ^= _BV(5);
    	MCUCSR |= (1<<JTD);
    	MCUCSR |= (1<<JTD); //wylaczenie JTAG
    
    	TIMER0_Init();
    	USART_Init(VUBRR);
    	sei();
    
        /* Początek nieskończonej pętli */
        while(1)
        {
    		alarm_active=sprawdz();
    		if (alarm_active==0) PORTB |=0x80;
    		else PORTB &= 0x7F; 
    
        }
    	return 0;
    }
    


    Będę dozgonnie wdzięczny za wskazanie błędu, bo nie mam już pomysłów.
    Dodam jeszcze, że prędkość F_CPU jest ustawiona w parametrach projektu 1Mhz dla obu procesorów. Używam wewnętrznego oscylatora w układach.

    Sprawdziłem jeszcze przed chwilą wartość. Atmega8 otrzymuje ciągle 0x00.
  • #2 6830806
    wdogli
    Poziom 18  
    Hej
    Wydaje mi sie że powinieneś jeszcze podać to w programach czyli
    #define F_CPU 1000000UL
  • #3 6830865
    boniu747
    Poziom 10  
    Zrobiłem tak jak radziłeś - niestety bez zmian.
  • #4 6830912
    webmortiz
    Poziom 20  
    widze ze w kodzie uzywasz funkcjonalnosci RS232 a w temacie masz RS485. Jakiego sprzetu uzywasz do konwersji? MAX485, 75176? Moze problem jest sprzetowy? Sam aktualnie mecze sie z RS485, wysylanie ok a odbieranie - smieci. Pokaz schemat moze razem cos wymyslimy.
  • #5 6830927
    markosik20
    Poziom 33  
    Zbyt wcześnie przełączasz na odbiór

    void USART_Transmit( unsigned char data ) //wyslanie 8 bit
    {
       //Ustalenie  kierunku transmisji RS485 - nadawanie
       PORTD |= _BV(4);
       _delay_ms(1);
       // Wait for empty transmit buffer
       while ( !( UCSRA & (1<<UDRE)) )
       ;
       // Put data into buffer, sends the data
       UDR = data;
       //Ustalenie kierunku transmisji RS485 - odbiór
    _delay_ms(1);   
    PORTD &=~_BV(4);
       
    } 

    Przydałoby się jednak użycie przerwań bo takie opóźnienia są czasami zawodne.
  • #6 6830973
    boniu747
    Poziom 10  
    A po jakim czasie powinienem przełączyć na odbiór?
  • #7 6831030
    markosik20
    Poziom 33  
    boniu747 napisał:
    A po jakim czasie powinienem przełączyć na odbiór?

    Jak skończy wysyłać dane :wink:.
  • #8 6831100
    boniu747
    Poziom 10  
    Hehe, no tak ;) Dzięki serdeczne za pomoc.
REKLAMA