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

ATmega16 i problem z wyswietlaniem danych na LCD :(

Top Gun 13 Cze 2007 23:16 1420 1
REKLAMA
  • #1 3982153
    Top Gun
    Poziom 20  
    Posty: 556
    Pomógł: 2
    Ocena: 26
    Ponizej przedstawiam swoj kod:
    
    #include <avr/io.h>
    #define F_CPU 16000000UL
    #include <util/delay.h>
    #include <avr/interrupt.h>
    //#include <avr/iom16.h>
    #include "lcd.h"
    #include "usart.h"
    
    
    #define Timer2_start TCNT2 = 0x63; TCCR2 = 0x07;  //0x63 - poczatkowa 99, preskaler 1024 0x07
    #define Timer2_stop TCCR2 = 0;
    unsigned short int sekunda=0, napiecie, temperatura, zadana, int_byte[3];	//0-65535
    unsigned char tekstA[3], tekstB[4], tekstC[3], histereza=0, x=0, Bufor;
    unsigned char byte[4], y;
    
    int read_adc(void)
    {
    	ADMUX=0xC0;			//VRef = 2,56V - ADC0 jako input
    	ADCSRA = 0x87; // zezwolenie na konwersje, preskaler 128
    	ADCSRA |= 1<<ADSC; //start pojedynczej konwersji 
    	while(bit_is_set(ADCSRA,ADSC)){}; 
    	return ADCW; 
    }
    
    unsigned char glowne(void)
    {
    	napiecie = read_adc();
    	itoa(napiecie, tekstB, 10);
    	temperatura = 0.38*napiecie+2.2;
    	if(temperatura>=zadana) PORTB = 0x02;
    	if(temperatura<(zadana-histereza)) PORTB = 0x00;
    	itoa(temperatura, tekstA, 10);
    	lcd_xy(0,2);
    	if(temperatura>99) write_text(tekstA);
    	if(temperatura>9 & temperatura <100)
    	{
    		write_text(tekstA);
    		lcd_xy(0,4);
    		write_char(' ');
    	}
    	if(temperatura<10)
    	{
    		char i;
    		write_text(tekstA);
    		for(i=3; i<5; i++)
    		{
    			lcd_xy(0,i);
    			write_char(' ');
    		}
    	}
    	lcd_xy(1,0);
    	if(napiecie>999) write_text(tekstB);
    	if(napiecie>99 & napiecie<1000)
    	{
    		write_text(tekstB);
    		lcd_xy(1,3);
    		write_char(' ');
    	}
    	if(napiecie>9 & napiecie<100)
    	{
    		char i;
    		write_text(tekstB);
    		for(i=2; i<4; i++)
    		{
    			lcd_xy(1,i);
    			write_char(' ');
    		}
    	}
    	if(napiecie<10)
    	{
    		char i;
    		write_text(tekstB);
    		for(i=1; i<4; i++)
    		{
    			lcd_xy(1,i);
    			write_char(' ');
    		}
    	}
    	asm("nop");
    	return temperatura;
    }
    
    ISR(TIMER0_OVF_vect)
    { 
    	TCNT2 = 0x63;
    	sekunda++;
    	if(sekunda==100)
    	{
    		Timer2_stop;
    		sekunda=0;
    		USART_Transmit(glowne());//temperatura);
    		Timer2_start;
    	}
    }
    
    ISR(SIG_UART_RECV) 
    { 
    	Bufor = UDR; 
    	if (x<3)
    	{
    		byte[x] = Bufor;
    		x++;
    	}
    	byte[3] = 0;
    	if(x>2)
    	{
    		zadana = atoi(byte);
    		x = 0;
    		lcd_xy(0,10);
    		itoa(zadana, tekstC, 10);
    		write_text(tekstC);
    	}
    }
    
    int main(void)		// program główny
    {
    	// konfiguracja portów we/wy
    	DDRA = 0b11111110;	//PortA0 jako wejscie napiecia mierzonego
    	DDRB = 0x02;		//Nozka T1 jako wyjscie
    	DDRC = 0xFF;
    	DDRD = 0b11001110;  //PORTD0 oraz 4,5 jako wejście 
    	_delay_ms (5);
    	lcd_init();			//inicjalizacja LCD
    	USART_Init(MYUBRR);
    	zadana = 280;
    	histereza=3;
    	lcd_xy(0,0);
    	write_text("B=");
    	lcd_xy(0,5);
    	write_text("C");
    	lcd_xy(0,8);
    	write_text("Z=");
    	lcd_xy(0,13);
    	write_text("C");
    	lcd_xy(1,8);
    	write_text("H=3");
    	sei();				//globalne zezwolenie na przerwania
    	TIMSK = 0x40;			//wlaczamy przerwanie T2
    	Timer2_start;
    	lcd_xy(0,10);
    	itoa(zadana, tekstC, 10);
    	write_text(tekstC);
    	for(;;)						//petla nieskończona
    	{
    	}
    	return 0;
    }
    

    lcd.h
    
    // Definicje dotyczace LCD 
    #define LCD PORTC 				//port z LCD
    #define RS 0                     // wybor rejestru 
    #define RW 2                     // 1 - odczyt; 0 - zapis 
    #define E 3                      // sygnal zezwalajacy (enable) 
    #define SET_E LCD |= _BV(E) 
    #define CLR_E LCD &= ~_BV(E) 
    #define SET_RS LCD |= _BV(RS) 
    #define CLR_RS LCD &= ~_BV(RS) 
    #define SET_RW LCD |= _BV(RW) 
    #define CLR_RW LCD &= ~_BV(RW) 
    //#define DDRLCD DDRC             // port z podlaczanym LCD 
    //#define PINLCD PINC             // port z podlaczanym LCD 
    // Wykorzystujemy tylko cztery linie przesylowe D4-D7 portu PORTLCD 
    // pcodedura zapisu bajtu do wyświetlacza LCD
    // bez rozróżnienia instrukcja/dana
    
    void write_to_lcd(char x)
    {
    	SET_E; // ustaw na E stan wysoki
    	LCD = ((LCD & 0x0F) | (x & 0xF0)); // zapis pierwszej połówki bajtu
    	CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    	asm("nop");
    	SET_E; // ustaw na E stan wysoki
    	LCD = ((LCD & 0x0F) | ((x & 0x0F) << 4)); // zapis drugiej połowki bajtu
    	CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    	_delay_ms(1); // czekaj 1ms
    }
    
    // ***************** procedura zapisu instrukcji do wyświetlacza LCD
    void write_command(char x)
    {
    	CLR_RS; // niski stan na RS -> zapis instrukcji
    	write_to_lcd(x); // zapis do LCD
    }
    
    //***************** procedura zapisu danej do wyświetlacza LCD
    void write_char(char x)
    {
    	SET_RS; // wysoki stan na RS -> zapis danej
    	write_to_lcd(x); // zapis do LCD
    }
    
    // ***************** procedura zapisu tekstu do wyświetlacza LCD
    void write_text(char * s)
    {
    	while(*s) // do napotkania 0
    	{
    		write_char(*s); // zapisz znak wskazywany przez s na LCD
    		s++; // zwiększ s (przygotuj nastepny znak)
    	}
    }
    
    // ***************** procedura inicjalizacji wyświetlacza LCD
    void lcd_init(void)
    {
    	_delay_ms(50); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    	CLR_RW;
    	CLR_E; // E = 0
    	CLR_RS; // RS = 0
    	char i; // zmienna licznikowa
    	for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
    	{
    		SET_E; // E = 1
    		LCD &= 0x30; //
    		CLR_E; // E = 0
    		_delay_ms(5); // czekaj 5ms
    	}
    	SET_E; // E = 1
    	LCD &= 0x20; //
    	CLR_E; // E = 0
    	_delay_ms(1); // czekaj 1ms
    	write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    	write_command(0x08); // wyłącz LCD, kursor i miganie
    	write_command(0x01); // czyść LCD
    	write_command(0x06); // bez przesuwania w prawo
    	write_command(0x0C); // włącz LCD, bez kursora i mrugania
    }
    
    // ***************** procedura ustawiania pozycji kursora
    void lcd_xy(unsigned char w, unsigned char k)
    {
    	write_command((w*0x40+k) | 0x80); 
    }
    

    usart.h
    
    #define FOSC 16000000UL
    #define BAUD 19200UL
    #define MYUBRR (FOSC/(16*BAUD))-1
    unsigned char data[2], i;
    
    void USART_Init( unsigned int ubrr )
    {
    	UBRRH = (unsigned char)(ubrr>>8);	// Set baud rate
    	UBRRL = (unsigned char)ubrr;
    	UCSRA = 0x00;		//
    	UCSRB = 0b11011000;	//(1 << RXCIE) | (1<<RXEN) | (1<<TXEN);
    	UCSRC = 0b10000110;					// Set frame format: 8data, 1stop bit, parity=none
    }
    
    void USART_Transmit(unsigned int dana) 
    {
    	if(dana>255)
    	{
    		data[0] = 255;
    		data[1] = dana-255;
    	}
    	else
    	{
    		data[0] = 0;
    		data[1] = dana;
    	}
    	for(i=0; i<2; i++)
    	{
    		while (!(UCSRA & (1<<UDRE)));	//Czekaj na pusty bufor transmisji
    		UDR = data[i];					// Put data into buffer, sends the data
    	}
    }
    
    

    Problem jest taki: po odpaleniu urzadzenia pokazuja sie napisy, ktore sa w funkcji main() i one nigdy nie znikaja. Problemem jest to, ze w funkcji glowne() robi sie pomiar i co sekunde ten pomiar ma sie wyswietlac. No i ten pomiar sie wyswietla na ulamek sekundy po czym znika. Metoda prob i bledow okazalo sie, ze wylaczenie wysylania temperatury na usart USART_Transmit() powoduje zaprzestania znikania tych danych. Zmienialem polozenie tej funkcji, zmienilem Timer2 na 0, nawet wyrzucilem timer i zostawilem tylko opoznienie na delay - nic nie pomoglo. Czy ktos moglby mi podpowiedziec gdzie jest, zapewne glupi, blad? Niedlugo musze prace oddac na obrone ...
  • REKLAMA
  • #2 4001983
    Top Gun
    Poziom 20  
    Posty: 556
    Pomógł: 2
    Ocena: 26
    Poradzilem sobie sam :P
REKLAMA