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

Przetwornik ADC dziwny wynik

INTOUCH 20 Kwi 2011 16:23 1405 5
REKLAMA
  • #1 9421882
    INTOUCH
    Poziom 30  
    Witam.
    Napisałem w C kod do przetwarzania ADC.
    Niestety mam dziwy 6 cyfrowy wynik na wyświetlaczu.
    Najciekawsze jest to że zmienia mi się pierwsza i ostatnia cyfra np:
    844448 zmienia się na
    944449 i tak w kółko

    Poniżej jest kod
    
    void ADCinit();
    void ADCinit()
    {
    //ADMUX =0b00000000;
    ///*
    SET_BIT(ADMUX, REFS1)//WYKORZYSTANIE WEWNĘTRZNEGO NAPIĘCIA REFERENCYJNEGO
    SET_BIT(ADMUX, REFS0)
    
    CLR_BIT(ADMUX, ADLAR);// DLA PRZETWORNIKA 10 BIT
    
    CLR_BIT(ADMUX, MUX3);//Ustawienia kanału -Kanał 0
    CLR_BIT(ADMUX, MUX2);//do pomiaru wartości bedzie wykorzystywany wyłącznie kanał zero
    CLR_BIT(ADMUX, MUX1);
    CLR_BIT(ADMUX, MUX0);
    //*/
    CLR_BIT(SFIOR, ADTS2);//TRYB FRE RUNNING
    CLR_BIT(SFIOR, ADTS2);//przetwornik pracuje w trybie, w którym ciągle obywa się próbkowanie, przetwarzanie i zapisywanie wyniku
    CLR_BIT(SFIOR, ADTS2);
    
    CLR_BIT(ADCSRA, ADPS2);//USTALENIE PRESKALERA
    CLR_BIT(ADCSRA, ADPS1);
    CLR_BIT(ADCSRA, ADPS0);
    
    SET_BIT(ADCSRA, ADATE);//AUTOWYZWALANIE
    SET_BIT(ADCSRA, ADIE);// UAKTYWANIENIE PRZERWAŃ
    SET_BIT(ADCSRA, ADEN);// WŁĄCZENIE PRZETWORNIKA
    SET_BIT(ADCSRA, ADSC);// ROZPOCZĘCIE KONWERSJI(PRZETWARZANIA)
    
    
    }
    
    
    volatile int pomiar1=0;
    volatile int pomiar2=0;
    volatile int pomiar3=0;
    volatile int pomiar4=0;
    volatile int pomiar5=0;
    volatile int pomiar=0;
    char *zmieena5;
    //*Obsługa przerwania ADC//
    SIGNAL(SIG_ADC)
    {
    pomiar1=(ADCL|(ADCH<<8));//*5;//dla max 1024*5= 5120
    pomiar=(pomiar1+pomiar2+pomiar3+pomiar4+pomiar5)/5;
    pomiar5=pomiar4;
    pomiar4=pomiar3;
    pomiar3=pomiar2;
    pomiar2=pomiar1;
    
    _delay_ms(200);
    LCD_Clear();
    itoa(pomiar1,zmieena5,10);
    
    LCD_WriteText(zmieena5);
    
    
    
    }
    
  • REKLAMA
  • #2 9422211
    tmf
    VIP Zasłużony dla elektroda
    Te program to dobry przykład jak nie należy pisać:
    1. pomiar1=(ADCL|(ADCH<<8)); - nie gwarantuje poprawnej kolejności dostępu do rejestru ADC. Użyj po prostu ADC bez kombinowania, albo rozdziel to na dwie linie.
    2. SIGNAL nie powinno być już używane.
    3. delay i obsługa LCD w przerwaniu? Koszmar.
    4. Najważniejsze zmienna5 jest wskaźnikiem na typ char, nie przydzielasz jej pamięci, a więc działanie itoa jest losowe bo nadpisuje obszary pamięci nie przydzielone zmiennej zmienna5.
  • REKLAMA
  • #3 9422226
    janbernat
    Poziom 38  
    To nie wynik dziwny- to obsługa przerwania jest dziwna.
    Co tam robi_delay() i osługa wyświetlacza?
    Uśrednianie też należy wstawić do głównej pętli- chyba że pomiary są na tyle rzadko że zdąży się to zrobić.
    Ale to trzeba obliczyć.
  • REKLAMA
  • #4 9423126
    INTOUCH
    Poziom 30  
    Opóźnienie i wyświetlenie dałem po to żeby mieć podgląd do tego co się dzieje na przetworniku ADC.
    To jest program testowy.
    Rozumiem że według panów przetwornik ADC działa poprawnie, tylko nie poprawnie jest wyświetlany wynik.
    Interesuje mnie głównie to jak wypluć wartość zawartą w rejestrze ADC na ekran LCD.
  • REKLAMA
  • #6 9424994
    INTOUCH
    Poziom 30  
    Program źle napisany ale działa.
    Temat do zamknięcia.
    
    #define F_CPU	16000000UL	//16MHz zegar procesora
    #include <avr/io.h>
    #include <util/delay.h>
    #include <string.h>
    #include <stdlib.h>
    #include <avr\interrupt.h>
    
    
    /*********************************************************/
    //*Definicje makr zmieniająćych stany bitów w rejestrach*//
    #define        SET_BIT(r,x)        r|=_BV(x);//USTAW BIT W REJESTRZE
    #define        CLR_BIT(r,x)        r&=~_BV(x);//WYCZYŚĆ BIT W REJESTRZE
    #define        TOG_BIT(r,x)        r^=_BV(x); ///ZMIEŃ STAN BITU W REJESTRZE
    /*********************************************************/
    
    /****************************************/
    //*Obsługa wyświetlacza Hitachi HD44780*//
    #define LCD_RS_DIR		DDRC			//
    #define LCD_RS_PORT 	PORTC			//
    #define LCD_RS			(1 << PC3)		//definicja bitu portu dla lini RS
    
    #define LCD_E_DIR		DDRC			//
    #define LCD_E_PORT		PORTC			//
    #define LCD_E			(1 << PC2)		//definicja bitu portu dla lini E
    
    #define LCD_DB4_DIR		DDRC			//
    #define LCD_DB4_PORT	PORTC			//
    #define LCD_DB4			(1 << PC4)		//
    
    #define LCD_DB5_DIR		DDRC			//
    #define LCD_DB5_PORT	PORTC			//
    #define LCD_DB5			(1 << PC5)		//
    
    #define LCD_DB6_DIR		DDRC			//
    #define LCD_DB6_PORT	PORTC			//
    #define LCD_DB6			(1 << PC6)		//
    
    #define LCD_DB7_DIR		DDRC			//
    #define LCD_DB7_PORT	PORTC			//
    #define LCD_DB7			(1 << PC7)		//
    
    //-------------------------------------------------------------------------------------------------
    //
    // Instrukcje kontrolera Hitachi HD44780
    //
    //-------------------------------------------------------------------------------------------------
    
    #define HD44780_CLEAR					0x01		//wyczyszczenie wyświetlacza//1,64ms
    
    #define HD44780_HOME					0x02		//ustawienie kursora na pozycji pierwszego znaku w pierwszej lini//1,64ms
    
    #define HD44780_ENTRY_MODE				0x04		//określenie trybu pracy kursora/okna wyświetlacza//40us
    	#define HD44780_EM_SHIFT_CURSOR		0			//po zapisaniu znaku do wyświetlacza kursor zmienia położenie
    	#define HD44780_EM_SHIFT_DISPLAY	1			//po zapisaniu znaku do wyświetlacza kursor nie zmienia położenia
    	#define HD44780_EM_DECREMENT		0			//kursor lub okno wyświetlacza przesuwa się w lewo (dekrementacja adresu znaku)
    	#define HD44780_EM_INCREMENT		2			//kursor lub okno wyświetlacza przesuwa się w prawo (inkrementacja adresu znaku)
    
    #define HD44780_DISPLAY_ONOFF			0x08		//Ustawia tryb wyświeltacza (włączenia/wyłączenia)//40us
    	#define HD44780_DISPLAY_OFF			0			//wyłączenie wyświetlacza
    	#define HD44780_DISPLAY_ON			4			//włączenie wyświetlacza
    	#define HD44780_CURSOR_OFF			0			//wyłączenie kursora
    	#define HD44780_CURSOR_ON			2			//włączenie kursora
    	#define HD44780_CURSOR_NOBLINK		0			//wyłączenie migania kursora
    	#define HD44780_CURSOR_BLINK		1			//włączenie migania kursora
    
    #define HD44780_DISPLAY_CURSOR_SHIFT	0x10		//przesunięcie kursora i wyświetlenie tekstu//40us
    	#define HD44780_SHIFT_CURSOR		0			//przesuwany jest kursor
    	#define HD44780_SHIFT_DISPLAY		8			//przesuwana jest zawartość okna
    	#define HD44780_SHIFT_LEFT			0			//kierunek przesuwu w lewo
    	#define HD44780_SHIFT_RIGHT			4			//kierunek przesuwu w prawo
    
    #define HD44780_FUNCTION_SET			0x20		//konfiguracja wyświetlacza//40us
    	#define HD44780_FONT5x7				0			//matryca znaków 5*7 punktów
    	#define HD44780_FONT5x10			4			//matryca znaków 5*10 punktów
    	#define HD44780_ONE_LINE			0			//wyświetlacz jednowierszowy
    	#define HD44780_TWO_LINE			8			//wyświetlacz dwuwierszowy
    	#define HD44780_4_BIT				0			//interfejs 4-bitowy
    	#define HD44780_8_BIT				16			//interfejs 8-bitowy
    
    #define HD44780_CGRAM_SET				0x40		//ustawia adres pamięci generatora znaków. 
    													//AAA - 3-bitowy adres znaku, 
    													//LLL - 3-bitowy numer linii składającej się 
    													//na graficzne odwzorowanie znaku.
    
    #define HD44780_DDRAM_SET				0x80		//ustawia adres pamięci wyświetlacza, 
    													//pod który nastąpi zapis (bądź odczyt) danych 
    													//operacją Data write lub Data read.
    
    //-------------------------------------------------------------------------------------------------
    //
    // Deklaracje funkcji
    //
    //-------------------------------------------------------------------------------------------------
    
    void LCD_WriteCommand(unsigned char);				//wczytaj instrukcje
    void LCD_WriteData(unsigned char);					//wczytaj dane
    void LCD_WriteText(char *);							//wczytaj text
    void LCD_GoTo(unsigned char, unsigned char);
    void LCD_Clear(void);								//czyść wyświetlacz
    void LCD_Home(void);								//powrót kursora na początek
    void LCD_Initalize(void);							//inicjalizacja wyświetlacza
    
    //--------------------------------------------------------------------------------------------------
    // Funkcja wystawiająca półbajt na magistralę danych
    //
    void _LCD_OutNibble(unsigned char nibbleToWrite)
    {
    if(nibbleToWrite & 0x01)
    	LCD_DB4_PORT |= LCD_DB4;
    else
    	LCD_DB4_PORT  &= ~LCD_DB4;
    
    if(nibbleToWrite & 0x02)
    	LCD_DB5_PORT |= LCD_DB5;
    else
    	LCD_DB5_PORT  &= ~LCD_DB5;
    
    if(nibbleToWrite & 0x04)
    	LCD_DB6_PORT |= LCD_DB6;
    else
    	LCD_DB6_PORT  &= ~LCD_DB6;
    
    if(nibbleToWrite & 0x08)
    	LCD_DB7_PORT |= LCD_DB7;
    else
    	LCD_DB7_PORT  &= ~LCD_DB7;
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu bajtu do wyświetacza (bez rozróżnienia instrukcja/dane).
    //
    //-------------------------------------------------------------------------------------------------
    void _LCD_Write(unsigned char dataToWrite)
    {
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite >> 4);
    LCD_E_PORT &= ~LCD_E;
    LCD_E_PORT |= LCD_E;
    _LCD_OutNibble(dataToWrite);
    LCD_E_PORT &= ~LCD_E;
    _delay_us(50);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu rozkazu do wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteCommand(unsigned char commandToWrite)
    {
    LCD_RS_PORT &= ~LCD_RS;
    _LCD_Write(commandToWrite);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja zapisu danych do pamięci wyświetlacza
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteData(unsigned char dataToWrite)
    {
    LCD_RS_PORT |= LCD_RS;
    _LCD_Write(dataToWrite);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja wyświetlenia napisu na wyswietlaczu.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_WriteText(char * text)
    {
    while(*text)
      LCD_WriteData(*text++);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja ustawienia współrzędnych ekranowych
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_GoTo(unsigned char x, unsigned char y)
    {
    LCD_WriteCommand(HD44780_DDRAM_SET | (x + (0x40 * y)));
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja czyszczenia ekranu wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Clear(void)
    {
    LCD_WriteCommand(HD44780_CLEAR);
    _delay_ms(2);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja przywrócenia początkowych współrzędnych wyświetlacza.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Home(void)
    {
    LCD_WriteCommand(HD44780_HOME);
    _delay_ms(30);
    }
    //-------------------------------------------------------------------------------------------------
    //
    // Procedura inicjalizacji kontrolera HD44780.
    //
    //-------------------------------------------------------------------------------------------------
    void LCD_Initalize(void)
    {
    unsigned char i;
    LCD_DB4_DIR |= LCD_DB4; // Konfiguracja kierunku pracy wyprowadzeń
    LCD_DB5_DIR |= LCD_DB5; //
    LCD_DB6_DIR |= LCD_DB6; //
    LCD_DB7_DIR |= LCD_DB7; //
    LCD_E_DIR 	|= LCD_E;   //
    LCD_RS_DIR 	|= LCD_RS;  //
    _delay_ms(15); // oczekiwanie na ustalibizowanie się napiecia zasilajacego
    LCD_RS_PORT &= ~LCD_RS; // wyzerowanie linii RS
    LCD_E_PORT &= ~LCD_E;  // wyzerowanie linii E
    
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      LCD_E_PORT |= LCD_E; //  E = 1
      _LCD_OutNibble(0x03); // tryb 8-bitowy
      LCD_E_PORT &= ~LCD_E; // E = 0
      _delay_ms(5); // czekaj 5ms
      }
    
    LCD_E_PORT |= LCD_E; // E = 1
    _LCD_OutNibble(0x02); // tryb 4-bitowy
    LCD_E_PORT &= ~LCD_E; // E = 0
    
    _delay_ms(1); // czekaj 1ms 
    LCD_WriteCommand(HD44780_FUNCTION_SET | HD44780_FONT5x7 | HD44780_TWO_LINE | HD44780_4_BIT); // interfejs 4-bity, 2-linie, znak 5x7
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF); // wyłączenie wyswietlacza
    LCD_WriteCommand(HD44780_CLEAR); // czyszczenie zawartosći pamieci DDRAM
    _delay_ms(2);
    LCD_WriteCommand(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);// inkrementaja adresu i przesuwanie kursora
    LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK); // włącz LCD, bez kursora i mrugania
    }
    /****************************************/
    
    /************************************/
    //*Obsługa klawiatury -8 przycisków*//
    
    
    #define KLAWIATURA		DDRB	//PORTB PRZEZNACZONY NA OBSŁUGĘ KLAWIATURY
    #define S0				1	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S0"
    #define S1				2	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S1"
    #define S2				4	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S2"
    #define S3				8	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S3"
    #define S4				16	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S4"
    #define S5				32	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S5"
    #define S6				64	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S6"
    #define S7				128	//DEFINICJA STANU WYSOKIEGO PRZYCISKU "S7"
    //-------------------------------------------------------------------------------------------------
    //
    // Funkcja incjująca klawiaturę
    //
    //-------------------------------------------------------------------------------------------------
    
    
    
    
    
    /*************************************************************************************************************/
    /********************************************PRZETWORNIK ADC**************************************************/
    
    #define TESTPOM 1024
    #define ADC_RUN SET_BIT(ADCSRA, ADIE)// UAKTYWANIENIE PRZERWAŃ
    #define ADC_STOP CLR_BIT(ADCSRA, ADIE)// DEAKTYWACJA PRZERWAŃ
    //*
    void ADCinit();
    /*
    void ADCinit(void)
    {
    ADMUX= 0b11000000;
    ADCSRA = 0b11101111;
    } 
    */
    void ADCinit()
    {
    DDRA=0x00;
    //ADMUX =0b00000000;
    ///*
    CLR_BIT(ADMUX, REFS1)//WYKORZYSTANIE WEWNĘTRZNEGO NAPIĘCIA REFERENCYJNEGO
    CLR_BIT(ADMUX, REFS0)
    
    CLR_BIT(ADMUX, ADLAR);// DLA PRZETWORNIKA 10 BIT
    
    CLR_BIT(ADMUX, MUX3);//Ustawienia kanału -Kanał 0
    CLR_BIT(ADMUX, MUX2);//do pomiaru wartości bedzie wykorzystywany wyłącznie kanał zero
    CLR_BIT(ADMUX, MUX1);
    CLR_BIT(ADMUX, MUX0);
    //*/
    
    CLR_BIT(SFIOR, ADTS2);//TRYB FRE RUNNING
    CLR_BIT(SFIOR, ADTS1);//przetwornik pracuje w trybie, w którym ciągle obywa się próbkowanie, przetwarzanie i zapisywanie wyniku
    CLR_BIT(SFIOR, ADTS0);
    
    SET_BIT(ADCSRA, ADPS2);//USTALENIE PRESKALERA
    SET_BIT(ADCSRA, ADPS1);
    SET_BIT(ADCSRA, ADPS0);
    
    SET_BIT(ADCSRA, ADATE);//AUTOWYZWALANIE
    SET_BIT(ADCSRA, ADIE);// UAKTYWANIENIE PRZERWAŃ
    SET_BIT(ADCSRA, ADEN);// WŁĄCZENIE PRZETWORNIKA
    SET_BIT(ADCSRA, ADSC);// ROZPOCZĘCIE KONWERSJI(PRZETWARZANIA)
    //*/
    }
    
    
    
    volatile int pomiar1=0;
    
    char zmieena5[11];
    //char* zmieena5="";
    
    //*Obsługa przerwania ADC//
    ISR(SIG_ADC)
    {
    pomiar1=(ADC);
    
    _delay_ms(200);
    
    LCD_Clear();
    itoa(pomiar1,zmieena5,10);
    
    LCD_WriteText(zmieena5);
    
    
    
    }
    
    
    
    
    int main (void)
    {
    ADCinit();
    KLAWIATURA=0x00;
    
    
    LCD_Initalize();
    _delay_ms(20); // czekaj 20ms 
    sei();
    
    
    
    while (1) {
    
    
       
    
    }
    
    return 0;
    }
    
    
    
REKLAMA