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 + LCD. LCD robi tylko standardowe kwadraty.

gorsomir 02 Lut 2009 22:13 2318 5
REKLAMA
  • #1 6094199
    gorsomir
    Poziom 13  
    Witam
    Aż wstyd mi zacząć bo temat niby taki banalny

    Otóż Zbudowałem sobie urządzonko na Atmedze16 z LCD 16x4

    Wszystko ładnie ruszyło oprócz LCD on oprócz standardowych kwadratów nic nie robi
    R/W oczywiście jest do masy wszystkie połączenia są na 100%ok
    LCD po podłączeniu do PC przez LPT rusza bez zająknięcia
    a z Atmegą nie chce

    Program jest napisany w bascomie
    oto listing
    $regfile = "m16def.dat"
    $crystal = 8000000
    Config Lcdmode = Port                                       'Wybieram typ podlaczenia lcd
    Config Lcdbus = 4                                           'LCD podpiety na 4 zyly
    Config Lcd = 16 * 4                                         'Typ LCD
    Config Lcdpin = Pin , Db4 = Pc.5 , Db5 = Pc.4 , Db6 = Pc.3 , Db7 = Pc.2 , E = Pc.6 , Rs = Pc.7       'Jak podpiety LCD
    Cursor Off                                                  'Wylaczam kursor na LCD
    Display On                                                  'Wlaczam LCD
    Cursor Noblink    
    Cls 
    Do
    Lcd "ABC"
    Loop   

    Jest mnie ktoś w stanie nakierować co może być nie tak ?
    Proszę o pomoc i Pozdrawiam
  • REKLAMA
  • #2 6094285
    dawid512
    Poziom 32  
    Wyłącz JTAGA bo jest on standardowo uruchomiony i blokuje niektóre końcówki portu C.
  • REKLAMA
  • #3 6094393
    gorsomir
    Poziom 13  
    Niestety po wyłączeniu JTAGA w Fusebitach LCD nie ruszył ale dzięki za pomoc
  • REKLAMA
  • Pomocny post
    #4 6094675
    dawid512
    Poziom 32  
    Na pewno masz te 8MHz? Po za tym spróbuj wyrzucić to:
    Config Lcdmode = Port
    i to
    Display On   
    oraz zamiast pisać tak: napisz tak:. Śmiem twierdzić że połączenia sprawdzałeś kilka razy oraz sprawdziłeś czy na wszystkich końcówkach portu C pojawia się określony stan(specjalnie wykonany test).
  • REKLAMA
  • #5 6096666
    gorsomir
    Poziom 13  
    Dzięki za pomoc
    Już działa
    Po zmianie programu
    Troche przyznam mnie to zdziwilo bo jak robiłem zawsze coś na tych LCDkach w bascomie to na tamtym kodzie zawsze działało
    Ale jak by nie było to dzięki za pomoc :p
    Pozdrawiam
  • #6 8606631
    danab
    Poziom 10  
    Mój problem trochę zazębia sie z tym wątkiem, dlatego tutaj go opiszę.
    Atmega16 z wyświetlaczem podpiętym do portu C (JTAG wyłączony). Po kompilacji programu, wgraniu programu do procesora i ustawieniu fuse bitów 0xff i 0xc9 na wyświetlaczu LCD w pierwszej linii świecą się tylko prostokąty. Reset procesora niczego nie zmienia.
    LCD podłączony poprawnie, wyświetlacz sprawny, układ montażowy też poprawny (po wgraniu innego programu w tym układzie docelowym program jest wykonywany i wyświetlacz działa poprawnie). Wniosek - źle napisany program (chyba :cry:).
    Program sprawdzany wiele razy, komplilacja wykonywana bez błędów, a mimo to coś nie działa.
    Może ktoś pomoże znaleźć błędy w programie? Załączam listing programu:
    
    #define debug
    
    //MCU ATMega16, 14.7456MHz
    
    /*PIN assignment
    
    LCD display (standard text controller):
    	PC0-3=DB4-7
    	PC4=E
    	PC5=RW
    	PC6=RS 
    	PC7= reserved (for light via NPN transistor - 150mA)
    
    Rotational coder (capacitors 100nF at contacts necessary to prevent spurious edges):
    	PD2 (left)
    	PD3 (right)
    	PB2 (press)
    
    FETs:
    	PD4 charge
    	PD5 weld_power
    	PD6 discharge
    
    ADCs:
    	PA0,1,2 .. potenciometr 0,1,2
    	PA3 ... Vext R divisor 33k+220k
    	PA4 ... Vcap R divisor 33k+220k
    
    LED: 	PB0 via 470R
    
    Triger pedal switch (normally open):   PB1 (using internal pullup, 100nF cap. parallel)
    	
    
    */ 
    #define XTAL 14745600
    #define BAUD 19200
    
    #include "backward.h"
    #include <avr/io.h>
    #include <avr/pgmspace.h>
    #include <avr/eeprom.h>
    #include <avr/interrupt.h>
    #include <setjmp.h>
    #include <avr/sleep.h>
    #include <avr/wdt.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    
    
    #if defined(at90s2313) || defined(at90s8535)
    #else
    #define ATmega
    #endif
    
    #ifdef ATmega
    #define USR UCSRA
    #endif
    
    
    #ifndef MCU
    #define emulate
    #else
    #define AVR_assembler
    #endif
    
    #define itoa10(N,S) itoa(N,S,10)
    #define itoa16(N,S) itoa(N,S,16)
    
    
    void printP (PGM_P string){
            char c;
            c=pgm_read_byte(string);
                       while (c) {
                       loop_until_bit_is_set(USR, UDRE);
                       UDR = c;
                       c=pgm_read_byte(++string);
                       }
                       return;
                     }
    
    
    
    void print (char *string){                                     
                       while (*string) {                                            
                       loop_until_bit_is_set(USR, UDRE);                            
                       UDR = *string++;
                       }                                                            
                       return;                                                      
                     }                                                              
    
    
    
    
    //UART initialize
    #ifdef ATmega
    #define UCR UCSRB
    #define UART_INIT(baud) { \
    UBRRH=0; \
    UBRRL= (XTAL/baud+15)/16-1; \
    UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE); \
    UCSRC=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)|(1<<USBS); }
    #else
    #define UART_INIT(baud) { \
    UBRR = (XTAL/baud+15)/16-1; \
    sbi(UCR, TXEN); \
    sbi(UCR, RXEN); \
    }
    #endif
    
    //UART routines
    volatile uint8_t inuartlen=0;
    volatile uint8_t uartline=0;
    #define MAXUART 64
    volatile char inuart[MAXUART];
    INTERRUPT(SIG_UART_RECV)
    {
    char c=UDR;
    if(uartline) return; //ignore until line is processed
    UDR = c; //echo
    if(c=='\n' || c== '\r' || inuartlen == MAXUART-1) {uartline=1; inuart[inuartlen]=0; inuartlen=0;} 
    else inuart[inuartlen++]=c; 
    }
    
    uint16_t Vset = 120;
    
    
    watchdog(uint8_t onoff)
    {
    if(onoff) {wdt_enable(WDTO_2S); wdt_reset();}
    else {wdt_reset();wdt_disable();}
    }
    
    
    //rotational coder routines
    volatile static uint8_t menustate=0;
    volatile static int8_t menuselect=0;
    
    
    #define N_MENULABEL 1
    typedef char MENULABEL[9];
    static const MENULABEL  menulabel[N_MENULABEL] = {"WELDER"};
    
    
    void process_rotation(uint8_t sense)
    {
    switch (menustate) {
            case 1:
    		if(sense) ++menuselect; else --menuselect;
    		if(menuselect<0) menuselect+=N_MENULABEL;
    		menuselect = menuselect%N_MENULABEL;
                    break;
            case 0:
    		if(sense) ++Vset; else --Vset;
    		if(Vset<10) Vset=10;
    		if(Vset>350) Vset=350;
            default:
    		break;
    }
    }
    
    
    //right:
    //I0:01
    //I1:00
    //I0:10
    //I1:11
    //
    //left:
    //I1:10
    //I0:00
    //I1:01
    //I0:11
    //
    
    volatile static int8_t rotcount=0;
    void rotcoder(uint8_t interrupt, uint8_t pins)
    {
    if(interrupt)
    	{
    	if(pins==0 || pins==3) ++rotcount;
    	else --rotcount;
    	}
    else
    	{
    	if(pins==0 || pins==3) --rotcount;
    	else ++rotcount;
    	}
    if(rotcount==4) {process_rotation(1); rotcount=0;}
    if(rotcount== -4) {process_rotation(0); rotcount=0;}
    }
    
    volatile static uint8_t light=0;
    
    void process_press(uint8_t length)
    {
    switch (menustate) {
    	default:
    		if(length)  //long press
    			{
    			}
    		else	   //short press
    			{ 
    			}
    }
    }
    
    INTERRUPT(SIG_INTERRUPT0)
    {
    rotcoder(0,(PIND>>2)&3);
    }
    
    INTERRUPT(SIG_INTERRUPT1)
    {
    rotcoder(1,(PIND>>2)&3);
    }
    
    volatile static uint8_t timer0x=0;
    
    INTERRUPT(SIG_INTERRUPT2)
    {
    uint16_t tim;
    uint8_t x;
    cbi(GIMSK,INT2);
    cbi(GICR,INT2);
    //toggle the active edge
    if(x=bit_is_set(PINB,PB2))
    	{
    	cbi(MCUCSR,ISC2);
    	tim=timer0x;
    	tim = (tim<<8)|TCNT0;
    	}
    else
    	{
    	sbi(MCUCSR,ISC2);
    	TCNT0=0;
    	timer0x=0;
    	}
    cbi(GIFR,INTF2);
    sbi(GICR,INT2);
    sbi(GIMSK,INT2);
    if(!x) return;
    process_press(tim>3000);
    }
    
    INTERRUPT(SIG_OVERFLOW0)
    {
    ++timer0x;
    }
    
    
    init_rotcoder(void)
    {
    //start timer0
    TCNT0=0;
    TCCR0=CK1024;
    OCR0=0;
    sbi(TIMSK,TOIE0);
    
    //pull-up pins
    cbi(DDRD,PD2); sbi(PORTD,PD2);
    cbi(DDRD,PD3); sbi(PORTD,PD3);
    cbi(DDRB,PB2); sbi(PORTB,PB2);
    
    //and allow edge interrupts on INT0,1,2
    sbi(MCUCR,ISC00); cbi(MCUCR,ISC01);
    sbi(GIMSK,INT0);
    sbi(MCUCR,ISC10); cbi(MCUCR,ISC11);
    sbi(GIMSK,INT1);
    cbi(MCUCSR,ISC2);
    sbi(GIMSK,INT2);
    }
    
    
    //delay routines
    
    void delay_xs(uint16_t xs) //xs takes 4 clocks time
    {
            asm volatile (
            "\n"
            "L_dl1%=:" "\n\t"
            "sbiw %0, 1" "\n\t"
            "brne L_dl1%=" "\n\t"
            : "=&w" (xs)
            );
            return;
    }
    
    void delay_ms(uint16_t ms) //ms takes 1/1000 s
    {
    while(ms--) delay_xs(XTAL/4/1000);
    }
    
    void delay_ms10(uint8_t ms) //ms takes 1/10000 s
    {
    while(ms--) delay_xs(XTAL/4/10000);
    }
    
    void delay_ms100(uint8_t ms) //ms takes 1/100000 s
    {
    while(ms--) delay_xs(XTAL/4/100000);
    }
    
    
    
    //display routines
    
    #define lcd_delay 50
    
    void lcd_w4bit(uint8_t rs, uint8_t x)
    {
    PORTC= 1<<PC4|light
    #if (MCU == atmega8 )
    	; if(rs) sbi(PORTD,PD4); else cbi(PORTD,PD4);
    #else
    	 | rs <<PC6;
    #endif
    delay_xs(lcd_delay);
    PORTC |= x&0x0f;
    delay_xs(lcd_delay);
    cbi(PORTC,PC4);
    delay_xs(lcd_delay);
    sbi(PORTC,PC4);
    delay_xs(lcd_delay);
    }
    
    uint8_t lcd_r4bit(uint8_t rs)
    {
    uint8_t r;
    PORTC= 1<<PC4 | 1<<PC5|light
    #if (MCU == atmega8 )
            ; if(rs) sbi(PORTD,PD4); else cbi(PORTD,PD4);
    #else
             | rs <<PC6;
    #endif
    delay_xs(lcd_delay);
    cbi(PORTC,PC4);
    delay_xs(lcd_delay);
    r=PINC&0x0f;
    cbi(PORTC,PC5);
    delay_xs(lcd_delay);
    return r;
    }
    
    uint8_t lcd_rbyte(uint8_t rs)
    {
    #if (MCU == atmega8 )
    sbi(DDRD,PD4);
    DDRC=0x30;
    #else
    DDRC=0xf0;
    #endif
    delay_xs(lcd_delay);
    return (lcd_r4bit(rs)<<4)|lcd_r4bit(rs);
    #if (MCU == atmega8 )
    sbi(DDRD,PD4);
    DDRC=0x3f;
    #else
    DDRC=0xff;
    #endif
    delay_xs(lcd_delay);
    }
    
    void lcd_init4bit(void)
    {
    #if (MCU == atmega8 )
    sbi(DDRD,PD4);
    DDRC=0x3f;
    #else
    DDRC=0xff;
    #endif
    delay_xs(20000);
    lcd_w4bit(0,3);
    delay_xs(10000);
    lcd_w4bit(0,3);
    delay_xs(500);
    lcd_w4bit(0,3);
    lcd_w4bit(0,2);
    }
    
    void lcd_wbyte(uint8_t rs, uint8_t x)
    {
    lcd_w4bit(rs,x>>4);
    lcd_w4bit(rs,x);
    }
    
    void lcd_clear(void)
    {
    lcd_wbyte(0,0x01);
    delay_xs(30000);
    }
    
    void lcd_init(void)
    {
    lcd_init4bit();
    lcd_wbyte(0,0x28);
    lcd_wbyte(0,0x08);
    lcd_clear();
    lcd_wbyte(0,0x06);
    lcd_wbyte(0,0x0c);
    }
    
    void lcd_print(char *t)
    {
    while(*t) if(*t=='\n') {++t; lcd_wbyte(0,0xc0);} else lcd_wbyte(1,*t++);
    }
    
    
    void lcd_print8(char *t)
    {
    uint8_t l=0;
    while(*t) {lcd_wbyte(1,*t++); ++l;}
    while(l<8) {lcd_wbyte(1,' '); ++l;}
    }
    
    void lcd_cursor(uint8_t r, uint8_t c)
    {
    lcd_wbyte(0,0x80+c+(r<<6));
    }
    
    
    void printx(uint16_t x, char z, char *t)
    {
    strcpy(t,"  .  ");
    t[4]= z;
    t[3]= '0'+x%10; x/=10;
    t[1]= '0'+x%10; x/=10;
    t[0]= '0'+x%10;
    }
    
    void printy(uint16_t x, char z, char *t)
    {
    strcpy(t," .   ");
    t[4]= z;
    t[3]= '0'+x%10; x/=10;
    t[2]= '0'+x%10; x/=10;
    t[0]= '0'+x%10;
    }
    
    uint16_t adcread(uint8_t i)
    {
    ADMUX= i;
    ADCSRA= (1<<ADEN)|(1<<ADIF)|(1<<ADSC)|7;
    loop_until_bit_is_set(ADCSRA,ADIF);
    uint16_t v=ADCL;
    v|= (ADCH<<8);
    return v;
    }
    
    uint16_t voltage(uint8_t i)
    {
    uint32_t tmp= 1176; //calibrated for a given voltage divider resistor tolerance and the fact that the reference voltage is not exactly 5V but depends on the particular stabilizer. High accuracy is not needed anyway
    tmp *= adcread(i);
    tmp /= 3;
    return tmp>>10;
    }
    
    
    int main(void)
    {
    uint16_t pass;
    UART_INIT(BAUD);
    
    //global interrupt activate
    sbi(SREG,7);
    
    //setup inputs and outputs
    sbi(DDRB,PB0); cbi(PORTB,PB0); //led
    cbi(DDRB,PB1); sbi(PORTB,PB1); //trigger
    sbi(DDRD,PD4); cbi(PORTD,PD4); //charge
    sbi(DDRD,PD5); cbi(PORTD,PD5); //weld
    sbi(DDRD,PD6); cbi(PORTD,PD6); //discharge
    
    //write initial message to the display and blink leds
    lcd_init();
    lcd_print("Spot Welder");
    printP(PSTR("Spot Welder Reset!\n"));
    
    delay_ms(500);
    lcd_clear();
    
    //enable rotcoder
    init_rotcoder();
    
    uint16_t Vext, Vcap;
    uint8_t times[3];
    const  uint8_t timemax[3]={200,150,150};
    
    //MAIN LOOP
    while(1)
    {
    ++pass;
    uint8_t i;
    
    //read potentiometers
    for(i=0; i<=2; ++i) 
    	{
    	uint32_t tmp= timemax[i];
    	tmp *= (adcread(i)+1);
    	times[i]= tmp>>10;
    	}
    
    //read Vext and Vcap
    Vext = voltage(3); 
    Vcap = voltage(4); 
    
    //charge/discharge for a while if needed
    cbi(PORTD,PD5);
    cbi(PORTD,PD4); 
    cbi(PORTD,PD6);
    if(Vcap<Vset) sbi(PORTD,PD4); //charge
    if(Vcap>Vset+1) sbi(PORTD,PD6); //discharge
    
    //
    //control display according state set by asynchronous events
    switch (menustate) {
    	case 1: //in menu
    		break;
    	case 0:
    	default:
    		{
    		char text[17];
    		printx(Vext,' ',text);
    		printx(Vset,' ',text+5);
    		printx(Vcap,' ',text+10);
    		lcd_cursor(0,0);
    		lcd_print(text);
    		printy(times[0],' ',text);
                    printx(times[1],' ',text+5);
                    printx(times[2],' ',text+10);
    		lcd_cursor(1,0);
    		lcd_print(text);
    		}
    	break;
    }
    
    //if ready, light the LED and check trigger
    if(abs(Vset-Vcap)<2)
    	{
    	sbi(PORTB,PB0);
    	if(bit_is_clear(PINB,PB1)) 
    		{
    		uint16_t Vcap0 = Vcap;
    		printP(PSTR("FIRE!\n"));
    		if(times[0]) {sbi(PORTD,PD5); delay_ms100(times[0]);}
    		cbi(PORTD,PD5); delay_ms10(times[1]);
    		uint16_t Vcap1 = voltage(4);
    		if(times[2]) {sbi(PORTD,PD5); delay_ms10(times[2]);}
    		cbi(PORTD,PD5);
    		delay_ms(1);
    		Vcap = voltage(4);
    		char text[6];
    		printx(Vcap,' ',text);
    		lcd_clear();
    		lcd_cursor(0,0);
    		lcd_print("Vcap left ");
    		lcd_cursor(0,10);
    		lcd_print(text);
    		printP(PSTR("Vcap remaining: ")); print(text); print("\n");
    		printP(PSTR("Pulse energies: ")); 
    		lcd_cursor(1,0); lcd_print("Puls E ");
    		uint32_t energy = Vcap0*Vcap0 - Vcap1*Vcap1;
    		energy *=94; energy /= 10000; //for 0.94Farad capacitance
    		itoa10((uint16_t)(energy&0xffff),text); print(text);
    		print(" ");
    		lcd_cursor(1,7); lcd_print(text);
    		energy = Vcap1*Vcap1 - Vcap*Vcap;
                    energy *=94; energy /= 10000; //for 0.94Farad capacitance
                    itoa10((uint16_t)(energy&0xffff),text); print(text);
    		print("\n");
    		lcd_cursor(1,11); lcd_print(text);
    		do{} while(bit_is_clear(PINB,PB1)); //wait for release of trigger
    		lcd_clear();
    		}
    	}
    else
    	{
    	cbi(PORTB,PB0);
    	cbi(PORTD,PD5);
    	}
    
    delay_ms(5);
    }//while
    }
    


    Do poprawnej kompilacji potrzebne jeszcze pliki:

    Liczę na pomoc bardziej doświadczonych w programowaniu AVR
REKLAMA