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

AT90Can128 problem z przerwaniem

p_kacper 03 Wrz 2009 07:48 1197 1
REKLAMA
  • #1 6974276
    p_kacper
    Poziom 11  
    Witam,
    piszę program do układu wykorzystującego żyroskopowy czujnik przyspieszenia (Adis 16355). Mam problem z niestartowaniem programu- mikrokontroler rozpoczyna pracę, jednak po wykonaniu
    sei();

    resetuje się i rozpoczyna pracę od początku.
    Dzieje się tak jednak tylko wtedy, gdy przed sei(); wykonuję zerowanie();. Jeśli zablokuję zerowanie(). wszystko jest ok- przerwania działają z częstotliwością jaką sobie policzyłem (1ms).
    Proszę kogoś bardziej bystrego o analizę kodu i pomoc.
    Z góry dziękuje, Przemek.

    
    [b]//plik config[/b]
    #include "config.h"
    
    void SPI_MasterInit(void)
    {
    /* Set MOSI and SCK output, all others input */
    DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1 << DD_SS) | (1<< DD_RESET) | (1<<DDB0);
    /* Enable SPI, Master, set clock rate fck/16= 1Mb/s */
    SPCR = (1<<SPE)|(1<<MSTR) |(1<<SPR0) | (1<<CPHA) | (1<<CPOL) | (1<<SPIE);
    //SPSR =(1<<SPI2X); //preskaler pomnożony przez 2
    }
    
    void SPI_Transmit(char cData)
    {
    /* Start transmission */
    SPDR = cData;
    /* Wait for transmission complete */
    while(!(SPSR & (1<<SPIF)));
    }
    
    unsigned char SPI_Receive(void)
    {
    /* Wait for reception complete */
    while(!(SPSR & (1<<SPIF)));
    /* Return data register */
    return SPDR;
    }
    
    unsigned char SPI_WriteRead(char cData)
    {
    /* Start transmission */
    SPDR = cData;
    /* Wait for transmission complete */
    while(!(SPSR & (1<<SPIF)));
    /* Return data register */
    return SPDR;
    }
    
    
    
    
    [b]//plik main[/b]
    #include "config.h"
    
    #define BUT PINE & _BV(5)
    #define LED_ON PORTE&= ~(1<<PB4) // zapal diode
    #define LED_OFF PORTE|= (1<<PB4) // zgas diode
    
    #define XAcclAdr 0x0b
    #define YAcclAdr 0x0d
    #define ZAcclAdr 0x0f
    
    #define XGyroAdr 0x05
    #define YGyroAdr 0x07
    #define ZGyroAdr 0x09
    
    
    volatile signed int	 liczT0=0,
    			predkosc=0,
    			 data=0;
    volatile unsigned int	u2data=0, droga=0, i=0, I=0;	
    			
    
    
    
    
    
    signed int u2_to_dec( unsigned int u2, unsigned char len )
    {
    unsigned char i=len;
    unsigned int potega=1;
    
    
    	if( u2 & _BV(len-1))
    	{
    
    		while(i>0)
    			{
    				potega=potega*2;
    				i--;
    			}
    
    		return u2-potega;//u2-2^(len);
    	}else
    	{
    		return u2;
    	}
    
    }
    
    
    signed int dec_to_u2(signed int dec, unsigned char len )
    {
    unsigned char i=len;
    unsigned int potega=1;
    
    
    	if( dec<0)
    	{
    
    		while(i>0)
    			{
    				potega=potega*2;
    				i--;
    			}
    
    		return dec+potega;//u2-2^(len);
    	}
    	
    	else
    	{
    		return dec;
    	}
    
    }
    
    
    
    signed int offset(unsigned char adr)
    {
    unsigned char i=0;
    signed int suma=0;
    
    	for(i=10 ; i!= 0 ; i--)
    	{
    		data= read_register(adr) & 0x3FFF;
    		data= u2_to_dec(data,14);
    		suma= suma + data;
    		waitms(1);
    	}
    
    
    	return suma/10;
    
    }
    
    void zerowanie(unsigned char adr, unsigned char lsb_off_adr)
    {
            write_command(lsb_off_adr, 0);
            write_command(lsb_off_adr + 1, 0);
    
    	data=-offset(adr);
    	u2data= dec_to_u2(data,12);
    	write_command(lsb_off_adr + 1, u2data>>8);
            write_command(lsb_off_adr,u2data & 0b11111111);
    return;
    }
    
    
    void Timer0_init()
    {
    	OCR0A=250; 						//przy presk. 64 wyzwala przerw. co 1ms
    
    	TIMSK0 = TIMSK0 | 1<<OCIE0A; 	//zezwolenie lokalne na przerwania od porównania Timera0
    	TCCR0A |= 1<<CS00 | 1<<CS01 | 1<<COM0A1; 	//preskaler na 64 (daje f= 250kHz)
    }
    
    
    
    
    SIGNAL(TIMER0_COMP_vect)
    {
    
    //kod obsługi przerwania
    			
    return;
    }
    
    
    int main()
    {
    signed int temp=0;
    unsigned int test=0;
    unsigned char data1,data2;
    
    	CS_UP;	
    	RESET_UP;
    //	waitms(5);
    	RESET_DOWN;
    //	waitms(5);
    
    	SPI_MasterInit();
    	USART0_Init(103);	
    	Timer0_init();	
    	
    [b]zerowanie(0x0a, 0x20);
    sei();[/b]
    		while(1)
    		{
                     }
    
    }[/b]


    Aha- jeszcze jeden plik źródłowy z pozostałymi procedurami:
    
    #include "config.h"
    void write_command( unsigned char adr_cmd, unsigned char cmd )
    {
    	CS_DOWN;   // chip select na stan niski
    	waitms(1); //_delay_us(1);
    
    	SPI_Transmit(128 + adr_cmd); // transmisja starszego bajtu to adis163
    	SPI_Transmit(cmd); // transmisja mlodszego bajtu do adis1635x
    
    	CS_UP;     // chip select na stan wysoki
    	waitms(1); //_delay_us(1);
    	
    }
    
    
    
    
    
    unsigned int	read_register(unsigned char adr)
    {
    	unsigned int temp=0;
    	unsigned char	msb_byte=0, lsb_byte=0;
    	
    	adr = adr & 0b00111111;	
    
    	CS_DOWN;
    	waitms(1);  //_delay_us(0.1);
    
    	SPI_Transmit(adr);
    	SPI_Transmit(adr);
    
    	CS_UP;
    	waitms(1); //_delay_us(40);
    	CS_DOWN;
    
    	msb_byte = SPI_WriteRead(adr);
    	lsb_byte = SPI_WriteRead(adr);
    	CS_UP;
    
    	temp = (unsigned int)(msb_byte<<8);
    	temp = temp | lsb_byte;
    
    	
    //send_number_dec(msb_byte & 0b1111111);       
    //send_number_dec(lsb_byte);
    
    	return temp;
    	
    }
    
    
    void	read_registers()
    {
    	unsigned int temp=0;
    	unsigned char	msb_byte=0, lsb_byte=0, i=0;
    
    	CS_DOWN;
    	waitms(1); //_delay_us(0.1);
    
    	SPI_Transmit(0x05);
    	SPI_Transmit(0x05);
    	CS_UP;
    
    while (i<11)
    {
    	waitms(1); //_delay_us(40);
    	CS_DOWN;
    
    	msb_byte = SPI_WriteRead(0x07 + i);
    	lsb_byte = SPI_WriteRead(0x07 + i);
    	CS_UP;
    
    	switch(i)
    		{		
    
    			case 0:
    				XGyroData = (unsigned int)(msb_byte<<8);
    				XGyroData = ZAcclData | lsb_byte;
    			break;
    			
    			case 2:
    				YGyroData = (unsigned int)(msb_byte<<8);
    				YGyroData = YGyroData | lsb_byte;
    			break;
    			
    			case 4:
    				ZGyroData = (unsigned int)(msb_byte<<8);
    				ZGyroData = ZGyroData | lsb_byte;
    			break;
    			
    			case 6:
    				XAcclData = (unsigned int)(msb_byte<<8);
    				XAcclData = XAcclData | lsb_byte;
    			break;
    
    			case 8:
    				YAcclData = (unsigned int)(msb_byte<<8);
    				YAcclData = YAcclData | lsb_byte;
    			break;
    
    			case 10:
    				ZAcclData = (unsigned int)(msb_byte<<8);
    				ZAcclData = ZAcclData | lsb_byte;
    			break;
    
    		}
    	i=i+2;
    }
    }  
    
    
    
    
    unsigned int	XAccl()
    {
    	return read_register(0x0B) & 0x3FFF;
    
    }
    
    unsigned int	YAccl()
    {
    	return read_register(0x0D) & 0x3FFF;
    
    }
    
    unsigned int	ZAccl()
    {
    	return read_register(0x0F) & 0x3FFF;
    
    }
    
    unsigned int	XGyro()
    {
    	return read_register(0x05) & 0x3FFF;
    
    }
    
    unsigned int	YGyro()
    {
    	return read_register(0x07) & 0x3FFF;
    
    }
    
    unsigned int	ZGyro()
    {
    	return read_register(0x09) & 0x3FFF;
    
    }
    
    
    
    void adis1635x_conf()
    {
    	
    
    }
  • REKLAMA
  • #2 6977283
    p_kacper
    Poziom 11  
    Temat zamknięty, problem rozwiązany.
    Bruździły przerwania od SPI. Wystarczyło w inicjalizacji usunąć część kodu ustawiającą bit włączający przerwania od SPI. Praktycznie używam tego interfejsu pierwszy raz więc nie zagłębiałem się czemu tak się działo. Możliwe, że skądś się brało przerwanie na SPI, a nie było procedury obsługi, przez co program nie wracał do momentu, w którym przerwanie zostało wywołane no i po jakimś czasie RESET :/

    Najważniejsze, że już działa. Pozdrawiam!
REKLAMA