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

[AVR STUDIO] Dziwne zachowanie programu

kult 01 Lis 2010 20:04 1358 5
  • #1 8690372
    kult
    Poziom 16  
    Witam!
    Piszę program do obslugi przetwornika A/C ADS1256. Jednak już teraz widzę, że program wykonuje się nie tak jak zostal napisany.

    Kod:
    
    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>
    #include "ads1256.h"
    
    #define F_CPU 8000000UL
    #define RS_BAUD 19200UL
    #define RS_UBRR F_CPU / 16 / RS_BAUD - 1
    
    #define DD_MOSI    PINB5
    #define DD_MISO    PINB6
    #define DD_SCK     PINB7
    #define DD_SS      PINB4
    #define DDR_SPI    DDRB
    #define PIN_SPI    PINC
    
    typedef struct {
    	uint8_t pream[4];		//preambula
    	uint8_t command;	 	//komenda
    	uint8_t data2;			//dane -najstarszy bajt
    	uint8_t data1;
    	uint8_t data0;			//dane - najmlodszy bajt
    	uint8_t crc8;			//suma kontrolna
    } Packet;
    
    void uart_init(uint16_t ubrr);
    void uart_putc(uint8_t data);
    uint8_t uart_getc(void);
    uint8_t crc8(Packet _p);
    void send_packet(Packet _p);
    unsigned char SPI_SendByte(unsigned char data);
    
    uint8_t crc8(Packet _p)
    {
    	uint8_t crc = 0;
    	crc = _p.command ^ _p.data2;
    	crc += crc ^ _p.data1;
    	crc += crc ^ _p.data0;
    	return(crc);
    }
    
    void send_packet(Packet _p)
    {
    	_p.pream[0]='U'; _p.pream[1]='A'; _p.pream[2]='R'; _p.pream[3]='T';
    	_p.crc8 = crc8(_p);
    	uart_putc(_p.pream[0]);
    	uart_putc(_p.pream[1]);
    	uart_putc(_p.pream[2]);
    	uart_putc(_p.pream[3]);
    	uart_putc(_p.data2);
    	uart_putc(_p.data1);
    	uart_putc(_p.data0);
    	uart_putc(_p.crc8);
    }
    
    unsigned char SPI_SendByte(unsigned char data)
    {
    		SPDR = data;
     		while(!(SPSR & (1<<SPIF)));
    		return(SPDR);
    }
    
    
    void uart_putc(uint8_t data)
    {
    	while (!(UCSRA & (1 << UDRE)));
    	UDR = data;
    }
    
    
    uint8_t uart_getc(void)
    {
    	while(!(UCSRA & (1 << RXC)));
    	return UDR;
    }
    
    void uart_init(uint16_t ubrr)
    {
    	UBRRH = (uint8_t)(ubrr >> 8);
    	UBRRL = (uint8_t)ubrr;
    	UCSRB = (1 << RXEN) | (1 << TXEN);
    	// 8 bitów danych, 1 bit stopu, brak parzystos'ci
    	UCSRC = (1 << UCSZ0) | (1 << UCSZ1);
    }
    
    
    
    int main(void)
    {
    	uint8_t c;
    	Packet pakiet;
    	DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
    	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPHA);
    	
    	uart_init(RS_BAUD);
    	ADS1256_DevOpen(&SPI_SendByte);
    	while(1)
    	{
    		c = uart_getc();
    		uart_putc(c);
    		
    		pakiet.command = ADS1256_CMD_RREG;
    		pakiet.data2 = ADS1256_MUX;
    		pakiet.data0 = ADS1256_ReadReg(ADS1256_MUX);
    		send_packet(pakiet);
    	}
    	return 0;
    }
    

    W funkcji main widać nieskończoną pętlę while(1). Widać, że program powinien czekać na odebranie znaku z UARTa, jednak wcale tego nie robi, tylko nadaje dziwne wartości (wykonuje się funkcja send_packet).
    W debuggerze program najpierw wykonuje
    
    pakiet.command = ADS1256_CMD_RREG;
    pakiet.data2 = ADS1256_MUX;
    

    a następnie skacze do
    
    c = uart_getc();
    


    o co tu chodzi? Czy móglby mi ktoś wyjaśnić, co robię źle?
  • #2 8690479
    Andrzej__S
    Poziom 28  
    Deklarujesz zmienną c, przypisujesz jej wartość zwracaną przez funkcję uart_getc(), ale nigdzie później nie używasz tej zmiennej. W wyniku optymalizacji instrukcja c=uart_getc(); może być nawet całkowicie pominięta.
  • #3 8690610
    kult
    Poziom 16  
    dzięki za odpowiedź, ale po dodaniu instrukcji wysylającej znak po odebraniu (echo) nic się nie zmienilo.
  • #4 8691046
    Andrzej__S
    Poziom 28  
    Po czym wnioskujesz, że program nie działa prawidłowo? Sprawdzasz go na sprzęcie czy tylko w symulatorze? W zasadzie kolejność wykonania instrukcji, które wymieniłeś, nie ma większego znaczenia, dlatego że np. przypisanie wartości pakiet.command=ADS1256_CMD_RREG; nie zależy w żaden sposób od wyniku c=uart_getc();. Czasami kompilator w takim przypadku zmienia kolejność, jeśli tak mu pasuje. Podejrzewam, że gdybyś napisał przykładowo w takiej kolejności:
    
       c=uart_getc();
       pakiet.command=c;
    

    to wtedy c=uart_getc(); wykona się przed pakiet.command=c;. Chociaż z drugiej strony też to może zostać zoptymalizowane do czegoś takiego:
    
       pakiet.command=uart_getc();
    

    i zmienna c w ogóle nie zostanie utworzona.
  • Pomocny post
    #5 8692070
    Konto nie istnieje
    Konto nie istnieje  
  • #6 8694749
    kult
    Poziom 16  
    Dzieki _marek
REKLAMA