Behöver nybörjarhjälp att programmera i C

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
DJNZ
Inlägg: 16
Blev medlem: 19 augusti 2012, 20:15:41
Ort: Götene

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av DJNZ »

Eftersom du använder MikroC Pro så finns det en del exempel på LIBstock

tex
http://www.libstock.com/projects/view/5 ... t-displays

Kanske du hittar något användbart där.

Det var bara ett tips

//
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Magnus_K »

Tack för tipset DJNZ. Ska kika på detta lite under kvällen.

Ja, nu har jag skrivit lite pseudokod. Eller i alla fall tror mig gjort.

Den första interrupten startar SPI_klockan och när adc_data har fyllts så stänger den av klockan. Har inte bestämt ännu med vilken frekvens detta ska göras men förhållandevis ofta.

Den andra interrupten gör just skrivningen till displayerna enligt (förhoppningsvis) era tips.
Sitter just nu och försöker kladda ner flödet på just att "stycka av" adc_data till 1000, 100, 10, och en-tal.

Ser det allt för bedrövligt ut, tankemässigt alltså?

(Nu kanske ni förstår vilken låg nivå jag ligger på angående programmeringen...)

Kod: Markera allt

unsigned short adc_data;
bool adc_flag;

void interrupt1(TIMER0FLAG == 1) {                    // Vet inte hur ofta den ska läsa datan från ADC:n
                                                      // men denna timer ställs in efter det kravet

              adc_data &= 0xffff
              Starta SPI_klocka
              
              if(SPI_BUFFER är full !& adc_flag) {         //Det ska även maskas av med mera i dessa metoder
                        Flytta dom 8 bitarna till adc_data MSB
                        }
              if{SPI_BUFFER är full && adc_flag) {
                        Flytta dom 8 bitarna till adc_data LSB
                        Stäng av SPI_klocka
                        }
     
void interrupt2(TIMER1FLAG == 1) {                             // Denna timer snurrar med 400 Hz så varje
                                                               // siffra (4 st) uppdateras med 100 Hz
              Släck segment
              Läs porten och maska av (AND:a med 0)
              Skicka värdet till LAT
              Räkna upp vilken display som ska laddas nästa gång
              Om >3 så nolla
              Tänd nya segment

}

void main() {

     while(1) {}
}
Användarvisningsbild
hanzibal
EF Sponsor
Inlägg: 2499
Blev medlem: 7 september 2010, 20:54:58
Ort: Malmö/Lund

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av hanzibal »

Denna pseudokod (?) är för mig svårläst pga märklig formatering (kanske för att jag läser på en telefon) men rekommenderar att du, för ökad läsbarhet, väntar med att blanda in LCD mm tills du fått rätt på grundfunktionaliteten.

Jag tycker generellt att du "överplanerar" och ägnar för mycket tid att tänka igenom saker i förväg - du ställer frågor om saker för tidigt och alla olika svar du får, hur korrekta de än är, förvirrar ibland mer än vad de förklarar eftersom de ofta väcker nya frågor hos dig - frågor som du själv kunnat besvara senare, vis av erfarenheten av att först ha försökt.

Sätt igång och implementera på riktigt nu och återkom med reella problem när du verkligen kört fast istället.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Magnus_K »

Jo det har du nog rätt i hanzibal. Det blir tyvärr lite för djupa tankar ibland.
Ska se om jag får till något vettigt.

Angående formateringen vet jag inte. I mina ögon ser det överskådligt ut med antagligen är det för att jag är författaren. Ni som kan det här, ser säkert bara runskrift.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Magnus_K »

Vart är det lämpligt att lägga själva uträkningen för vilken siffra som ska visa vad?

Just nu ser det ut som följer:

- Interrupt 1 skickar klockpuls till ADC:n och samlar svaret i en variabel.
- Interrupt 2 gör själva sifferbytet. Vid varje interrupt så uppdaterar den en av siffrorna dvs när 4 st interrupter skett så har alla 4 siffror uppdaterats.

Frågan gäller alltså vart det är lämpligt att lägga uträkningen där jag delar ner ADC-datan i delar och tilldelar ett nummer till respektive siffra.
Är det feltänk att man låter while-loopen göra detta om och om igen och när interrupt 2 sker så är det redan klart vilken siffra den ska visa på respektive position.
Spontant så känns det som att lägga denna uträkning i interrupten så kommer ta en massa tid, vilket man inte vill att den ska göra.

Förstår någon vad jag menar? Känns lite rörigt.
Användarvisningsbild
Icecap
Inlägg: 26610
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Icecap »

Interrupten som växlar vilken siffra som visas ska ENBART sköta den bit!
Den ska ha 4 bytes reserverat (en per siffra, det var väl 4?) och i de bytes ska de färdiga bitmönster vara, ingen dekodning eller annat som ska utföras av ISR'n!

När du sedan har ett värde att skriva ut gör du det via en rutin i mainloop. Den rutin lägger rätt siffermönster i rätt byte av de 4 så att scanningen bara ska tugga på och ingen stör den.

Om du har en interrupt som anger att A/D-omvandlaren är klar är mitt sätt att dels läsa värdet till en variabel, starta om A/D-omvandlaren (om det behövs) och sedan sätta en flagga som betyder att det finns ett värde att omvandla.

I mainloop kollas flaggan, är den aktiv hoppas rutinen som behandlar det värde inte över.

Rutinen omvandlar värdet som beskrivit ovan.
Sedan nollas flaggan.
Klart.
Om du vill starta A/D-omvandlaren här går det såklart bra.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Magnus_K »

Japp, det var 4 st LED-siffror.
Klart som korvspad Icecap!

Tack!

Förstår inte hur ni håller reda på allt. Är uppe i nästan 150 rader kod och är alldeles snurrig av allt.
Användarvisningsbild
Icecap
Inlägg: 26610
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Icecap »

Och du tror att vi håller reda på allt? Jag sitter just och grejer ett projekt där jag använder samma buffer till att skicka data i till en funktion som skriver ut i en buffer och skickar med radio. Tyvärr är det samma buffer så det skiter sig rejält... Men jag hittade det och löser det...

EDIT: Har löst det och nu fungerar den del.
Er uppe på 1400+ rader kod - och det är "bara" en trådlös varningsskylt som i grunden bara kan skicka en "slå på nu i såhär lång tid" från sändaren till mottagaren.

Sedan tillkommer alla rutiner i egna filer, seriell kommunikation (3 st UART) med interruptstyrd buffring på alla samtidig (3* 220 rader), kryptering av kommunikationen, systeminitieringen (220 rader + 630 rader) och lite andra småsaker, så som en kommandotolk av typen klartext. ("set intensity 100", "get unit name", set unit name skitsystem norr" osv.)
Senast redigerad av Icecap 9 december 2014, 19:03:13, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43231
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av sodjan »

> Är uppe i nästan 150 rader kod och är alldeles snurrig av allt.

Det handlar bara om att hantera hela applikationen i lämpliga
bitar i taget. Om du börjar få 100 eller fler rader i main()
eller i en enstaka funktion som ett enda block, så kan det
vara dags att bryta upp det i fler funktioner. Varje funktion
ska inte vara större än att den enkelt kan överblickas och
både förstås och testas. Sedan (när man håller på med
koden "ovanför") så behöver man inte tänka mer på det.

Och vad är "för mycket kod på ett ställe"? Tja, det kan
väl vara då man får den känsla som du uttrycker... :-)

Aplikationerna som vi underhåller "på jobbet" har 10-tusentals
rader totalt med alla under/sub rutiner och det är kod skriven
under en 30+ års period i 6-7 olika språk. Man kan så klart
inte hålla allt i huvudet utan får ha tydliga gränssnitt mot
de olika rutinerna och lita på att det fungerar... :-)

Men "bara" 150 rader för en komplett applikation är
inte speciellt mycket...
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Magnus_K »

Försöker verkligen hålla mig till att göra en funktion, testa, lägga undan. Ny funktion, testa och lägga undan. Det är nog en fråga om rutin och kunskap också. Jobbar på det!

Nu till ett par mer programmeringsspecifika frågor:

För att omvandla 12-bitars ADC-datan till en spänningsnivå så tänkte jag göra som följer. Men vad händer när det blir decimaler? Finns det något annat sätt?
Jag försöker alltså få värdet att istället för att bara ge "5" så ska det ge "5000" och sen placerar jag decimalen manuellt på displayen.

Kod: Markera allt

total_voltage = adc_data * 4,8823;
Här nedan vill jag sedan dela ner total_voltage för att skickas vidare till "scannern".

Kod: Markera allt

unsigned short voltage[3];

                    voltage[3] = total_voltage % 1000;
                    total_voltage /= 1000;
                    voltage[2] = total_voltage % 100;
                    total_voltage /= 100;
                    voltage[1] = total_voltage % 10;
                    total_voltage /= 10;
                    voltage[0] = total_voltage % 1;

Det som alltså är klart sedan tidigare är att tex en 2:a har en färdig byte som heter NUMBER[2], en 5:a heter NUMBER[5] osv.

Vad använder jag för funktion för att utföra ta värdet från ett voltage-element och placera detta inom [] på NUMBER?
Skit vad svårt det här var att förklara... Nytt försök:
Hur skriver jag för att få elementsiffran i NUMBER att matcha värdet i voltage-elementet

Fungerar något i stil med:

Kod: Markera allt

NUMBER[voltage[1]];
Användarvisningsbild
Icecap
Inlägg: 26610
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Icecap »

Ett sätt är att använda flyttal. Det kostar exekveringshastighet och programminne - men det går.

Ett annat är att räkna lite:

unsigned long Work;
Work = ADC_Value;
Work *= 48823;
Nu är Work rätt skalad fast 10000000 är 1,0000V.

Man kan ju i samma veva skala det hela lite ner, kanske till en unsigned short:
Work /= 10000;
Då är 1000 = 1,000V

Internt går det alldeles utmärkt att räkna så men vid visningstillfällen ska du peta in komma på rätt position.

Varför har du bara 3 platser för scannaren? Var det inte 4 siffror?

Men för att göra om det till synbara tal måste du i grunden ha två rutiner:
En som plockar ut rätt siffra - och det har vi ju varit igenom redan.
Och en som slår upp i en tabell för att omvandla siffra till binärt mönster att visa.

För att göra det lätt för mig i sin tid gjorde jag mycket jobb som gjorde att det blev litet jobb om jag skulle ändra något.

Kod: Markera allt

#define Seg_A 0x01
#define Seg_B 0x02
#define Seg_C 0x04
#define Seg_D 0x08
#define Seg_E 0x10
#define Seg_F 0x20
#define SEG_F 0x40
#define DP      0x80

const BYTE Pattern[] = {
  Seg_A + Seg_B + Seg_C + Seg_D + Seg_E + Seg_F, // '0'
  Seg_A + Seg_B, // '1'
osv osv...
  }

BYTE Get_Pattern(BYTE Digit)
  {
  return(Pattern[Digit]);
  }
på detta vis kunde jag skriva koden och sedan rita mönsterkortet, skulle jag ändra vilken portpinne som gick var passar tabellen fortfarande, det är bara definitionerna som ska ändras, sedan är tabellen som sådan OK.

Man kan såklart baka ihop dessa funktioner.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Magnus_K »

Ni ska verkligen ha en klapp på axel och under granen för att ni står ut med mig :tumupp:

Jag har gjort omvandligen precis som du visade överst i ditt inlägg Icecap men jag får inte ordning på min interrupt. Den som scannar de 4 LED-siffrorna.
Interrupten har en frekvens av 500 Hz och eftersom den uppdaterar en LED-siffra i taget så hamnar varje siffra på ca 150 Hz vilket borde räcka.

Det största problemet jag har med detta är att alla 4 siffror visar samma siffra hela tiden. Har aldrig lyckats få dom att visa olika.
Ser någon vart jag tänkt fel i interrupten nedan?

Det är ju mer kod "runt om" men jag försökte skala ner det till enbart det nödvändiga för frågan. Om någon mer del behövs så postar jag gärna den också.

Kod: Markera allt

const int DIGIT[4] = {
      0b00000010,
      0b00000100,
      0b00001000,
      0b00010000
};

const int NUMBER[10] = {
      0b11000000,    //0
      0b11111001,    //1
      0b10100100,    //2
      0b10110000,    //3
      0b10011001,    //4
      0b10010010,    //5
      0b10000010,    //6
      0b11111000,    //7
      0b10000000,    //8
      0b10010000     //9
};

void interrupt(void) {

     if(INTCON.TMR0IF) {
     
              LATA &= (PORTA & 0x00);             // Släck anod
              LATD &= (PORTD & 0x00);             // Släck segmenten
              i++;                                // Räkna upp vilken display som ska laddas nästa gång
              if(i == 4) {i = 0;};                // Om >3 så nolla
              j = voltage[i];                     // Tilldela j siffran som ska visas på nästa LED
              LATD |= NUMBER[j];                  // Aktivera rätt segment
              LATA |= DIGIT[i];                   // Tänd ny anod

              Counter++;                          // Öka räknaren som vid 3 triggar ny ADC-läsning
              INTCON.TMR0IF = 0;                  // Nolla overflow flaggan
              }
}
Användarvisningsbild
adent
Inlägg: 4232
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av adent »

Du har bara glömt öka i inne i interruptet? EDIT: Nej det gör du ju Annars hade du bara haft en siffra lysande :) Jag är blind...

Hmmm, och du har stoppat in olika saker i voltage[] ?

Sen är det ett ; för mycket här: "if(i == 4) {i = 0;}; // Om >3 så nolla"

MVH: Mikael
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av Magnus_K »

Det hade du rätt i adent! Konstigt att inte det gav något fel när jag kompilerade.
Tog bort den sista ";" men gjorde tyvärr ingen skillnad.

voltage[] arrayen har 4 element och jag ger dessa induviduella värden enligt rutinen jag postat tre inlägg upp.
(enda skillnaden är att jag dividerar med 10 mellan varje modulus, tankevurpa)

Först fick jag bara nollor på displayen och trodde det var rätt visat men bara jag som inte lyckas få ADC-datan rätt konverterad.
Senare visade det sig att displayen bläddrar till ibland till "1111", "4444" eller "0.0.0.0." så då misstänkte jag att det är något i denna interrupt som felar. Ser bara inte vad...

EDIT: Hmm, kom på det nu när jag skrev det. Jag har inte definerat någonstans hur ett decimaltecken ska skrivas ut, tänkte vänta med det, men ändå visas alla fyra ibland.
Ytterligare ett tecken på att jag inte skriver till porten riktigt... eller felkopplat! Återkommer om detta!
Användarvisningsbild
adent
Inlägg: 4232
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Behöver nybörjarhjälp att programmera i C

Inlägg av adent »

Som nån pepekade:

unsigned short voltage[3];

3 ska vara 4.

Har du provat att ändra:

Kod: Markera allt

                  voltage[3] = total_voltage % 1000;
                    total_voltage /= 1000;
                    voltage[2] = total_voltage % 100;
                    total_voltage /= 100;
                    voltage[1] = total_voltage % 10;
                    total_voltage /= 10;
                    voltage[0] = total_voltage % 1;
till:

Kod: Markera allt

          voltage[3] =1;
                    voltage[2] = 2;
                    voltage[1] = 3;
                    voltage[0] = 4;
?

MVH: Mikael
Skriv svar