elikkäs loppui muisti kesken pic16f690:sta ja olisi tarvetta lyhentää koodia jonkun verran, koska lisää pitäisi saada vielä aika tavalla jotta projektista saisi jotain irtikin... ehkäpä joku osaisi auttaa hieman selventämään muutamista esimerkeistä mikä loppu pelissä olisi muistin kannalta paras...(joo kokeilemalla selviää, mutta kun en itse omista tuota ohjelmointi palikkaa taikka kunnon kääntäjää vielä...) myös kaipaisin kommenttia ihan tuosta koodista ylipäätään, kritiikki tervetullutta siis. tässä siis tämän hetkinen, yksi monista kohdista missä varmasti olisi parantamisen varaa.... Code: void naytto() { sprintf(str_lcd, " %2d.%2dV", akku / 100, akku % 100); print_xy(0, 1, str_lcd); sprintf(str_lcd, " %2d.%2dV ", vahvari / 100, vahvari % 100); print_xy(0, 10, str_lcd); if(alarivisaato < 3) alarivisaato = alarivisaato + 1; else alarivisaato = 1; if (alarivisaato == 1) { sprintf(str_lcd, " %02d:%02d:%02d ", hour, min, sec); print_xy(1, 0, str_lcd); } if (alarivisaato == 2) { sprintf(str_lcd, "Akku Vahvari"); print_xy(1, 0, str_lcd); } if (alarivisaato == 3){ vahvkoko = (int)EEPROM_READ(0x00); vahvjaannos = (int)EEPROM_READ(0x01); sprintf(str_lcd, " %2d.%2dV ", vahvkoko, vahvjaannos); print_xy(1, 0, str_lcd); } tässä yksi vaihtoehto? Code: void naytto() { sprintf(str_lcd, " %2d.%2dV", akku / 100, akku % 100); print_xy(0, 1, str_lcd); sprintf(str_lcd, " %2d.%2dV ", vahvari / 100, vahvari % 100); print_xy(0, 10, str_lcd); if(alarivisaato < 3) alarivisaato = alarivisaato + 1; else alarivisaato = 1; if (alarivisaato == 1) { sprintf(str_lcd, " %02d:%02d:%02d ", hour, min, sec); } if (alarivisaato == 2) { sprintf(str_lcd, "Akku Vahvari"); } if (alarivisaato == 3){ vahvkoko = (int)EEPROM_READ(0x00); vahvjaannos = (int)EEPROM_READ(0x01); sprintf(str_lcd, " %2d.%2dV ", vahvkoko, vahvjaannos); } print_xy(1, 0, str_lcd); vai olisiko paras tehdä oma funktionsa printtauksen kordinaateille, jotta sitä voisi käyttää kaikkialta?(en kyllä mene takuuseen onnistuuko kordinaattien anto eri funktiossa, kuin siinä missä sanotaan mitä printataan) -> Code: void naytto() { sprintf(str_lcd, " %2d.%2dV %2d.%2dV", akku / 100, akku % 100, vahvari / 100, vahvari % 100); print(); if(alarivisaato < 3) alarivisaato = alarivisaato + 1; else alarivisaato = 1; if (alarivisaato == 1) { sprintf(str_lcd, " %02d:%02d:%02d ", hour, min, sec); } if (alarivisaato == 2) { sprintf(str_lcd, "Akku Vahvari"); } if (alarivisaato == 3){ vahvkoko = (int)EEPROM_READ(0x00); vahvjaannos = (int)EEPROM_READ(0x01); sprintf(str_lcd, " %2d.%2dV ", vahvkoko, vahvjaannos); print(int joku = 1); } void print(){ if(joku == 1) print_xy(1, 0, str_lcd); //printtaus alariville return; else print_xy(0, 1, str_lcd); //printtaus yläriville } mitä tapaa itse suosisitte? nuo 2 esimerkkiä toisista tavoista näpytin nopeasti niin älkää paneutuko pieniin virheisiin niissä jos näettä, idea kuitenkin pitäisi käydä selväksi.
AD on tuskin paras paikka jos kaipaa ohjelmointiapua. Sulla on monta ehtolausetta peräkkäin, joista kuitenkaan vain yksi voi olla tosi, joten kannattasiko käyttää else if:iä tai switch casea? Laita koko koodi näkyviin, koska eipä tuosta paljoa ota selvää.
Switch caseen voisi kyllä nuo siirtää, samaten osan muusta koodista mitkä toteutettu while(asd==x) tällä hetkellä..(jotenkin jäänyt päälle noitten while looppien tekeminen switchin sijaan.) Täytyy myöhemmin laittaa loput koodista jahka pääsen kotia ja saan kirjoitettua pienet dokumentaatiot sinne selventämään asioita.
Switch casesta meinasin mainita, mutta en sitten tiedä viekö koodi yhtään sen vähemmän tilaa niitä käyttämällä. Onko nuo vahvkoko ja vahvjaannos kovin tärkeitä muuttujia? Voisi suoraan pistää printtiin sprintf(str_lcd, " %2d.%2dV ", (int)EEPROM_READ(0x00), (int)EEPROM_READ(0x01) ja jättää muuttujat kokonaan varaamatta. alarivisaato = alarivisaato + 1 vaikuttaa myös aika ikävältä (++). Onko sitten vaikutusta tilantarpeeseen? EOS. Koko koodi pitäisi tosiaan laittaa jakoon, että osaisi mitään tuohon sanoa. Google Drive on ihan näppärä paikka jakaa dokumentteja jos ei jaksa mitään gittiä/tms. väsäillä. E: Se koodihan vie paljon vähemmän tilaa käännettynä kuin selkokielisenä.
väsäilin switch case "version" koodista, mikä on huomattavasti selkeämpi lukea. tosiaan koko jutun juju on lukea akun ja vahvistimen jännitettä autossa, ja sammuttaa pic:iltä lähtö mikä antaa vahvistimelle heräten virran jos jännite tipahtaa liian alas määritetyksi ajaksi.(tietty C-koodin harjoittelu samalla) tila vain loppui ennenkuin sain edes toisen timerin asetettua millä sammuttaisin tuon lähdön. Code: /* * File: jannite.c * Author: Joni * * Created on 7. marraskuuta 2014, 20:11 */ #include <xc.h> #include <htc.h> #include <stdio.h> //CONFIG 16f690 #pragma config FOSC = INTRCCLK // Oscillator Selection (INTOSC oscillator: I/O function on ra4/5) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled) #pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is not MCLR) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config CPD = OFF #pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled) #pragma config IESO=OFF //MUUTA #define RS RC1 #define EN RC0 #define DATABITS PORTB #define MENU RC4 #define ENTER RC5 #define PLUS RC6 #define MIINUS RC7 #define AKKU7 0x9D #define AKKU7GO 0x9F #define VAHV6 0x99 #define VAHV6GO 0x9b void ajansaato(); void tulostus(); void menu(); void remsaadot(); unsigned int msec, sec = 0, min = 15, hour = 8; int scroll = 1; int remscroll = 1; int alarivisaato = 0; char str_lcd[16]; int akku, vahvari; int remoteout = 0; int autorem = 0; int autoremout = 1; int autoremenable = 1; int vahvautorem = 1200; int vahvkoko, vahvjaannos; int alkuasetus; static void interrupt isr(void) //keskeytys { if (T0IF) { TMR0 = 156; T0IF = 0; OPTION_REG = 0x00; if (msec < 10000) msec++; else { msec = 0; sec++; } if (sec > 59) { sec = 0; min++; } if (min > 59) { min = 0; hour++; } if (hour > 23) hour = 0; } } //NÄYTTÖ void delay_ms(int time) { int i, j; for (i = 0; i < time; i++) for (j = 0; j < 100; j++); } void LCD_STROBE(void) { EN = 1; delay_ms(2); EN = 0; } void data(unsigned char c) { RS = 1; delay_ms(1); DATABITS = c; LCD_STROBE(); DATABITS = (c << 4); LCD_STROBE(); } void cmd(unsigned char c) { RS = 0; delay_ms(1); DATABITS = c & 0b11110000; LCD_STROBE(); DATABITS = (c << 4) & 0xF0; LCD_STROBE(); } void lcd_init(void) { delay_ms(15); RS = 0; DATABITS = 0x20; LCD_STROBE(); cmd(0x28); cmd(0x0c); cmd(0x01); cmd(0x06); } void print_xy(int x, int y, const char *q) { if (y == 0) cmd(0xc0 + x); if (y == 1) cmd(0x80 + x); while (*q) { data(*q++); } } void putc_xy(int x, int y, unsigned char c) { if (y == 0) cmd(0xc0 + x); if (y == 1) cmd(0x80 + x); data(c); } //NÄYTTÖ loppu void main() { unsigned int TILA = 1; int mode = 0; // <editor-fold defaultstate="collapsed" desc="porttien alustus"> /* Initial Port Used */ TRISA = 0b00001111; //asetetaan PORTA TRISB = 0x00; //asetetaan PORTB TRISC = 0xFC; //asetetaan PORTC ANSEL = 0x80; ANSELH = 0x00; PORTA = 0b00100000; //portin nollaus PORTB = 0x00; //portin nollaus PORTC = 0x00; //portin nollaus// </editor-fold> /*kellokeskeytys*/ OSCCON = 0x77; OSCTUNE = 0x0F; OPTION_REG = 0x00; TMR0 = 156; T0IE = 1; GIE = 1; //näytön alustus delay_ms(50); lcd_init(); //alku asetukset ensimmäisellä käynnitys kerralla alkuasetus = EEPROM_READ(0x05); if (alkuasetus == 0) { remsaadot(); alkuasetus = 1; EEPROM_WRITE(0x05, alkuasetus); } while (1) { // <editor-fold defaultstate="collapsed" desc="Muunnos"> //analogi muunnosohjelma switch (TILA) { case 1: if (mode == 0) { ADCON0 = AKKU7; delay_ms(2); ADCON0 = AKKU7GO; TILA = 2; } if (mode == 1) { ADCON0 = VAHV6; delay_ms(2); ADCON0 = VAHV6GO; TILA = 2; } break; case 2: if (ADCON0 & 0x02) { TILA = 2; } else { if (mode == 0) akku = (float) (ADRESH * 256 + ADRESL)*1.525; if (mode == 1) vahvari = (float) (ADRESH * 256 + ADRESL)*1.525; TILA = 3; } break; case 3: if (mode == 0) mode = 1; else mode = 0; TILA = 1; break; default:TILA = 1; }// </editor-fold> tulostus(); if (MENU == 0) { menu(); } if (ENTER == 0) { tulostus(); } } } void menu() { sprintf(str_lcd, " enter to set "); print_xy(1, 0, str_lcd); while (1) { switch (scroll) { case 1: sprintf(str_lcd, "<< remote >>"); print_xy(0, 1, str_lcd); if (PLUS == 0 || MIINUS == 0) { scroll = 2; delay_ms(100); } if (ENTER == 0) { remsaadot(); } if (MENU == 0) { return; } break; case 2: sprintf(str_lcd, "<< Clock >>"); print_xy(0, 1, str_lcd); if (PLUS == 0 || MIINUS == 0) { scroll = 1; delay_ms(100); } if (ENTER == 0) { ajansaato(); } if (MENU == 0) { return; } break; } } } void remsaadot() { delay_ms(200); while (1) { switch (remscroll) { case 1: sprintf(str_lcd, "<< remote >"); print_xy(0, 1, str_lcd); if (MIINUS == 0 || PLUS == 0 && remoteout == 1) { remoteout = 0; while (MIINUS == 0 || PLUS == 0); } if (MIINUS == 0 || PLUS == 0 && remoteout == 0) { remoteout = 1; while (MIINUS == 0 || PLUS == 0); } RA5 = remoteout; EEPROM_WRITE(0x03, remoteout); if (remoteout == 0) { sprintf(str_lcd, " rem off "); //print_xy(1, 0, str_lcd); } if (remoteout == 1) { sprintf(str_lcd, " rem on "); //print_xy(1, 0, str_lcd); } if (MENU == 0) { delay_ms(100); return; } if (ENTER == 0) { remscroll = 2; } print_xy(1, 0, str_lcd); break; case 2: sprintf(str_lcd, "< auto remote >"); print_xy(0, 1, str_lcd); if (MIINUS == 0 || PLUS == 0 && autoremout == 1) { autoremout = 0; while (MIINUS == 0 || PLUS == 0); } if (MIINUS == 0 || PLUS == 0 && autoremout == 0) { autoremout = 1; while (MIINUS == 0 || PLUS == 0); } EEPROM_WRITE(0x02, autoremout); if (autoremout == 0) { sprintf(str_lcd, " auto.rem off "); print_xy(1, 0, str_lcd); } if (autoremout == 1) { sprintf(str_lcd, " auto.rem on "); print_xy(1, 0, str_lcd); } if (MENU == 0) { delay_ms(100); return; } if (ENTER == 0) { remscroll = 3; } break; case 3: sprintf(str_lcd, "< auto rem.raja >"); print_xy(0, 1, str_lcd); sprintf(str_lcd, " %2d.%2dV ", vahvautorem / 100, vahvautorem % 100); print_xy(1, 0, str_lcd); if (PLUS == 0 && vahvautorem < 1560) { vahvautorem = vahvautorem + 10; delay_ms(100); while (PLUS == 0); } if (MIINUS == 0 && vahvautorem > 500) { vahvautorem = vahvautorem - 10; delay_ms(100); while (MIINUS == 0); } if (ENTER == 0) { vahvkoko = vahvautorem / 100; vahvjaannos = vahvautorem % 100; EEPROM_WRITE(0x00, vahvkoko); delay_ms(5); EEPROM_WRITE(0x01, vahvjaannos); delay_ms(5); return; } break; } } } void tulostus() { sprintf(str_lcd, " %2d.%2dV %2d.%2dV ", akku / 100, akku % 100, vahvari / 100, vahvari % 100); print_xy(0, 1, str_lcd); if (alarivisaato < 3) alarivisaato++; else alarivisaato = 1; switch (alarivisaato) { case 1: sprintf(str_lcd, " %02d:%02d:%02d ", hour, min, sec); break; case 2: sprintf(str_lcd, "Akku Vahvari"); break; case 3: vahvkoko = (int) EEPROM_READ(0x00); vahvjaannos = (int) EEPROM_READ(0x01); sprintf(str_lcd, " %2d.%2dV ", vahvkoko, vahvjaannos); break; } print_xy(1, 0, str_lcd); } void ajansaato() { delay_ms(100); char str_lcd[16]; unsigned int hourmin = 1; while (hourmin == 1) { print_xy(0, 1, " Aseta tunnit "); sprintf(str_lcd, " %02d:%02d:%02d ", hour, min, sec); print_xy(1, 0, str_lcd); if (PLUS == 0) { hour++; delay_ms(100); } if (MIINUS == 0) { hour--; delay_ms(100); } if (ENTER == 0) { hourmin++; delay_ms(100); } if (MENU == 0) { return; } } while (hourmin == 2) { print_xy(0, 1, " Aseta minuutit "); sprintf(str_lcd, " %02d:%02d:%02d ", hour, min, sec); print_xy(1, 0, str_lcd); if (PLUS == 0) { min++; delay_ms(100); } if (MIINUS == 0) { min--; delay_ms(100); } if (ENTER == 0) { hourmin++; sec = 0; print_xy(0, 1, " onnistui! "); delay_ms(2000); } if (MENU == 0) { return; } } } luultavasti jotain virhettä löytyy, mutta ei paneuduta niihin nyt, ohjelma kuitenkin toimi alkuperäisessä muodossa, mutta siihen ei voinut tilan puutteen takia lisätä enään yhtään mitään. TO-DO -toinen timeri missä muutetaan RA5 tilaa jos tietty ehto täyttyy ja katkaisu asetettu päälle.(kun vain mahtuisi...) -eepromista luku kun laitetaan virrat päälle. E: tosiaan nuo print komennot ottaa pirusti tilaa, pitäisi varmaan kokeilla printin cordinaateille rutiini väsätä mikä poistaisi turhan "print_xy(xxxx)" kirjoituksen joka väliin, kun kuitenkin ohjelman jokainen osa aloittaa printin ylä- tai alarivin alusta.
putc_xy ei ilmeisesti ole missään käytössä? vahvkoko ja vahvjaannos näyttävät olevan turhia muuttujia. esim. vahvkoko = vahvautorem / 100; EEPROM_WRITE(0x00, vahvkoko); voinee korvata EEPROM_WRITE(0x00, vahvautorem / 100); Äkkiseltään sanoisin, että kannattaisi hankkia piiri josta löytyy vähän enemmän tallennustilaa. Tuossa on ilmeisesti huimat 7kB tilaa softalle. E: Kääntäjä voi optimoida koodia jo valmiiksi, eli vaikka se koodi näyttää pitkälle, niin se kääntäjä on tehnyt jo ne optimoinnit itse. Vaikka koodia siis saisikin lyhennettyä tai yleisesti optimoitua, niin softan koko ei välttämättä pienene mihinkään.
put_xy ei tosiaan taida olla käytössä ollenkaan täytenee poistaa pienen lisätilan toivossa. hmmn, totta pystyisin ottamaan suoraan kokonais luvun ja jäännöksen "vahvautorem" muuttujasta ilman tarvetta kahdelle eri muuttujalle, tämä varmaan tuokin jonkun verran tilaa ainakin.(tämä typerä kortti ei siis osaa printata float lukua muuttujasta -> "%f, xxx" , vaan se on pakko tehdä keinotekoisesti ottamalla kokonaisluku ja jäännös...)
Ohjelmoinnissa on useita koulukuntia, mutta ainakin itse kuulun siihen, joka vältää swith-case rakenteita viimeiseen asti. 95% tapauksista switch-case rakenteella tehdään yksinkertaisesta asiasta monimutkainen. Omaan silmään koodissa näkyy olevan todella paljon toistoa eli sitä todennäköisesti voisi yksinertaistaa. Lyhentämällä/yksinkertaistamalla koodia siitä saadaan helpompi lukuista ja se myös mahdollistaa kääntäjän koodin optimoinnin. Ns. if-else shorthand-lauseke on omasta mielestäni erittäin kätevä. esim: if (MIINUS == 0 || PLUS == 0 && remoteout == 1) { remoteout = 0; while (MIINUS == 0 || PLUS == 0); } if (MIINUS == 0 || PLUS == 0 && remoteout == 0) { remoteout = 1; while (MIINUS == 0 || PLUS == 0); } lyhyemmin: if (MIINUS == 0 || PLUS ) { remoteout=remout?0:1; while (MIINUS == 0 || PLUS == 0); } tai if (alarivisaato < 3) alarivisaato++; else alarivisaato = 1; lyhyemmin: alarivisaato=alarivisaat<3?alarivisaato+1:1; On myös syytä miettiä tarviiko tiettyä funktioita kutsua joka välissä: if (PLUS == 0) { hour++; delay_ms(100); } if (MIINUS == 0) { hour--; delay_ms(100); } if (ENTER == 0) { hourmin++; delay_ms(100); } if (MENU == 0) { return; } Vai: if (PLUS == 0) hour++; if (MIINUS == 0) hour--; if (ENTER == 0) hourmin++; if (MENU == 0) return; delay_ms(100); Ja kun oikeasti lähdetään säästämään jokaisesta tavusta, niin kannattaa miettiä tarvitaanko stdio.h kirjastoa. Pelkällä printf-komennolla tulee usen aivan hyvin toimeen.
Vilkaisin koodia nopeasti jo ennen viikkoloppua, mutta kiireiden takia en ehtinyt vastata. Koodin alussa alustat taulukon jonka kooksi asetetaan 16 tavua. char str_lcd[16]; Koodissa talletat sprintf komennolla taulukkoon merkkijonoja joiden pituus on 16 merkkiä eli oletettavasti myöskin 16 tavua. Esimerkiksi: sprintf(str_lcd, "<< remote >>"); Ainkin muutamien standardien mukaan sprintf lisää merkkijonon perään merkkijonon päättymismerkin '\0' joka tässä tapauksessa vuotaisi yli taulukosta. Mikä tarkalleenottaen on saamasi "muistin loppumisen" virheilmoitus? Toimiiko koodi paremmin jos lisäät taulukon koon 17 tavun mittaiseksi tai yli (olettaen että pisimmär merkkijonot mahduvat siihen)? Muutamien lähteiden mukaan ja kuten aiemminkin mainititin sprintf() funktio ja stdio.h kuluttavat melko paljon muistia microcontrollerilta.
Siis ihan ohjelmalle varattu tila tuli täyteen, ei suostunut enään edes kääntäjä kääntämään koodia sen takia.(kaivan sen errorin myöhemmin) hommasin nyt kuitenkin tuon xc8 pro:n lisenssin ja sillä kääntää koodin sen ~35% pienempään tilaan joten mahtuu taas, tuo xc8 free ilmeisesti bloattaa asm koodia jonnin verran, minkä takia se olevinaan ei mahtunut. Jep nuo sprintf käskyt vei tuolla free kääntäjällä ~1.5% muistista per käyttökerta... Näyttö on 16x2 merkkiä max. Toivottavasti nyt vain mahtuisi tuo loppu koodi vielä tuonne jahka saan kirjoitettua kaiken tarvittavan. Anyway, iso kiitos kaikille neuvoista! En tosiaan ole c-koodin kanssa enempää kuin 3kk nyt touhunnut niin kaikki neuvot ovat tervettulleita. Esim. -> remoteout=remout?0:1; tuli ihan uutena tuttavuutena, ja päätyikin käyttöön muutamaan paikkaan kunhan sain sen ensiksi väännettyä kääntäjäni ymmärtämään muotoon -> x=(b==0)?1:0;