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

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
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 »

Nej, det är inte varje gång samma funktioner ska köras ihop.

Jag tror du har lösningen i ditt exempel. Att jag tar mina 5 funktioner (eller hur många det blir) och sammanställer dessa i alla de olika kombinationer jag vill ha och där efter kan jag köra det case som passar.

Jag hade en gnutta förhoppning om att det fanns något "smart" sätt att genom denna enda variabel kunna välja ut flera case, tex att nyttja en array eller något men jag snubblade nog när jag tänkte igen.

Tack för detta Icecap, nu vet jag hur jag ska gå vidare!
Användarvisningsbild
Jan Almqvist
Inlägg: 1581
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

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

Inlägg av Jan Almqvist »

"Många case blir det..."

Varför inte använda en variabel där varje bit anger vad som ska göras?

Exempel:

Kod: Markera allt


#define OP_A  0x01
#define OP_B  0x02
#define OP_C  0x04
#define OP_D  0x08
#define OP_E  0x10

void min_function(const int op)
{

  if (OP_A & op)
  {
     funcion_A();
  }

  if (OP_B & op)
  {
     funcion_B();
  }

   ...

  if (OP_E & op)
  {
     funcion_E();
  }

}

johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

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

Inlägg av johano »

Edit: bolltvåa på den..

Du kan använda en bitmask istället, typ såhär nånting:

Kod: Markera allt

enum { temp=1, voltage=2, power=4, some=8, someother=16, current=32 };


void process(int x)
{
    if(x & temp)
        TempFunc();
        
    if(x & voltage)
        VoltageFunc();
        
    if(x & power)
        PowerFunc();

    if(x & some)
        SomeFunc();

    if(x & someother)
        SomeotherFunc();

    if(x & current)
        CurrentFunc();
}


int main()
{
    int x = temp | voltage | someother;

    process(x);

    x = power | current | some;

    process(x);
    
    
    return 0;
}
/johan
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 »

@Jan Almqvist och johano:
Jag tror jag får avvakta lite och se hur jag ska ha övriga "systemet". Det här var lite svårare än jag trodde men onekligen har ni också bra lösningar.

För övrigt har jag implemeterat de ändring ni föreslagit (hoppas jag) och istället för att skapa egna variabeltyper som du föreslog hummel så valde jag att gå på adent's spår och inkludera stdint.h istället. Det är nog lika bra att jag försöker hålla någon slags standard.
Men jag förstår vad du säger hummel. Det är ju också fler än en gång man råkat göra en "Search'n'Replace" och klantat till något. Följer man ditt tips så har man ju nästa lika snabbt döpt om alla variabler till den nya kompilatorn.
Nackdelen med att göra den här omdöpningen är att MikroC's IDE inte längre känner igen variabeltyperna och färglägger/bold:ar längre. Enligt deras forum så kanske denna "feature" kommer så småningom, alltså att lägga till nya keywords/reserved words.

För den som är intresserad så ser det ut så här nu (fortfarande med lite väl onödiga kommentarer):

Kod: Markera allt

#include "stdint.h"

void init() {
     OSCCON = 0b11111000;        //x4 PLL and 32MHz
     //OSCCON = 0b01011000;      // 1 MHz
     
     OPTION_REG = 0b00000101;    //1:64 prescaler

     ANSELA = 0;
     ANSELB = 0;
     ANSELD = 0;
     ANSELE = 0;

     CM1CON0 = 0;
     CM2CON0 = 0;
     CM3CON0 = 0;
     CM4CON0 = 0;
     
     OPA1CON = 0;
     OPA2CON = 0;
     OPA3CON = 0;
     
     PSMC1CON.B7 = 0;
     PSMC2CON.B7 = 0;
     PSMC3CON.B7 = 0;
     PSMC4CON.B7 = 0;
     
     INTCON.GIE = 1;
     INTCON.PEIE = 1;
     INTCON.TMR0IE = 1;

     SSP1CON = 0b00101010;        //Clock idle low, start SPI-module and use ADD-reg to calculate clock
     SSP1ADD = 0b00000100;        //Slow SPI-clock to 1,6MHz

     TRISD = 0;
     LATD = 0;
     TRISA = 0;
     LATA = 0;
     TRISE = 0;
     LATE = 0;

     TRISC.B3 = 0;
     TRISC.B4 = 1;
     TRISC.B5 = 0;
     
     LATA.B5 = 1;                // Hold ADC SS high for stby-mode
     LATE.B0 = 0;                // Debug LED, start black
     LATE.B1 = 0;                // Debug LED, start black
     

}

uint16_t adc_data;
uint16_t temp_adc_data = 0;
uint8_t Counter = 0;
uint8_t new_value = 0;
uint8_t a = 0;
uint8_t b = 0;
uint8_t voltage[4];
uint32_t total_voltage;
uint8_t adc_flag = 0;
uint8_t i;
uint8_t j;


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

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


void main() {

     init();
     
     while(1) {

              if(new_value){                             // Varje gång ett nytt ADC-värde är satt
                                                         // så ska denna rutin köras
                    total_voltage = 0;                   // Nolla variablen
                    total_voltage = adc_data;            // Överför ADC-värdet
                    
                    total_voltage *= 12207;              // Omvandla ADC-värdet till spänningsnivå
                    total_voltage /= 10000;              // Skala ner detta så tex 1V blir 1000
                    
                    voltage[3] = total_voltage / 1000;
                    voltage[2] = (total_voltage / 100) % 10;
                    voltage[1] = (total_voltage / 10) % 10;
                    voltage[0] = (total_voltage) % 10;
                    new_value = 0;
                    }
               if(Counter >= 60) {                                // När ISR:en scannat 60 ggr så är det dags att
                                                                  // hämta nytt ADC-värde
                                                                      
                          SSP1BUF = 0;                            // Nolla buffern
                          temp_adc_data = 0;                      // Nolla temp-variablen
                          LATA.B5 = 0;                            // Chip Select, aktivera ADC:n

                          while(!SSP1STAT.B0) {}                  // Om buffern är full så:
                          temp_adc_data = SSP1BUF;                // Flytta buffern till variablen
                          SSP1BUF = 0;                            // Nolla bufferm
                          temp_adc_data <<= 8;                    // Skifta dessa 8 bitar uppåt
                          
                          while(!SSP1STAT.B0) {}                  // Om buffern är full igen så:
                          temp_adc_data |= SSP1BUF;               // OR:a in buffern i lägsta 8 bit
                          temp_adc_data >>= 1;                    // Skifta allt en bit nedåt pga skräp
                          temp_adc_data &= 0xfff;                 // Maska av variablen och nolla översta nibbeln
                          adc_data = 0;                           // Nolla den riktiga variablen
                          adc_data = temp_adc_data;               // Fyll på med den nya datan
                          LATA.B5 = 1;                            // Inaktivera ADC:n med Chip Select hög
                          new_value = 1;                          // Ge flagga om att vi har ett nytt ADC-värde
                          Counter = 0;                            // Nolla räknaren
                                     }
              }
     }


void interrupt(void) {                            // Denna ISR snurrar med ~500 Hz
                                                  // så varje siffra (4 st) uppdateras
                                                  // med 150 Hz

     if(INTCON.TMR0IF) {                          // När Timer0 överflödar, så:

              LATA = 0;                           // Släck anod
              LATD = 0;                           // Nolla segmenten
              i++;                                // Räkna upp vilken display som ska laddas nästa gång
              i &= 0x03;                          // Om >3 så nolla
              j = voltage[i];                     // Ge j värdet som respektive element innehåller
              LATD = NUMBER[j];                   // Aktivera rätt segment beroende på ovan
              if(i == 3) {LATD &= 0x7f;}          // Om tecken 3 så AND:a in en 0:a, dvs tänd decimaltecknet
              LATA = DIGIT[i];                    // Tänd ny anod enligt räknaren
              Counter++;                          // Öka räknaren som vid 200 triggar ny ADC-läsning
              INTCON.TMR0IF = 0;                  // Nolla overflow flaggan
              }
}
Användarvisningsbild
adent
Inlägg: 4103
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 »

Jag tycker du ska ta och läsa på lite om race conditions nu. Det känns som du är i precis rätt läge att göra det :)
Jag tror inte du har några problem i ditt program. Men det är bra att läsa nu!

När du gör det kommer det säkert stå om trådar och processer. Men tänk på ditt huvudprogram som snurrar på där i sakta mak...
och så PANG är det dags att köra ett interrupt, närsomhelst. Då kan man nästan anse huvudprogrammet som en tråd och
interruptet som en annan.

Wikipedia brukar i regel vara lite dålig på att förklara, men du kan kika på detta stycke och googla vidare.

http://en.wikipedia.org/wiki/Race_condition#Software

Edit: Det är i alla fall bra att ha det i bakhuvudet, även om du inte riktigt förstår eller orkar nu.

MVH: Mikael
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

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

Inlägg av johano »

ie skrev: ...
Rad 4:
"if(i >= 4) {i = 0;}" kan skrivas kortare: "i &= 0x03", dvs du använder bara de två lägsta bitarna och behöver inte använda något villkor.
...
Varning för den!

Det första uttrycket kommer nolla i om det är större än 3 medan det andra kommer nolla alla bitar utöver bit 1och2 (vilka lämnas orörda): det är INTE samma sak.

Testa t.ex. följande:

int i = 15;
i &= 0x3;

Nu kommer i vara 3 och inte 0

/johan
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

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

Inlägg av Wedge »

Magnus_K skrev:@Icecap: Ahaa, så datan lägger sig i olika sorters minne beroende på hur jag deklarerat variablerna. Det visste jag inte men hänger med på skillnaden mellan RAM och ROM.
Att du ska använda const på sånt du inte tänkt ändra på är korrekt.

Men const är inte ett magiskt ord som flyttar variabler från RAM till ROM.
Jag säger inte att const aldrig gör så att data hamnar i ROM, men det är ingen absolut regel att så sker, inte ens i inbyggda system där man faktiskt HAR ett ROM. Det finns gott om exempel på const-variabler i RAM. Const säger bara, inte helt överraskande, att värdet är konstant och inte får ändras.
Vad som händer med en helt vanlig variabel som du sätter const på är kompilatorberoende, men i många fall kommer variabeln (lagringsutrymmet) att försvinna helt och omvandlas till ett smartare program.

Kompilatorn kommer dessutom att hjälpa dig att hitta buggar genom att protestera när den ser kod som kladdar i const-variabler. Har man const-deklarerat variabler i RAM är man hyggligt skyddad mot att ens eget program kladdar sönder datat, men det kan fortfarande ske genom stack overflow, vilda pekare, felaktig DMA-hantering eller annat som ger sig på minne utanför den vanliga programkörningen.

En programmerare som nödvändigtvis vill styra över var data ska lagras får vanligen tillgripa kompilatorspecifika nyckelord (t ex PROGMEM för AVR GCC).
Användarvisningsbild
Icecap
Inlägg: 26151
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

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

Inlägg av Icecap »

Som Wedge skriver är man inte säker på att en const sparas i ROM i alla system.

AVR har en långsam hantering av värden från ROM varför det går snabbare att kopiera alla konstanter från ROM till RAM vid uppstart. Bara vid att ge den ett specifikt kommando för varje const blir det lagt i ROM.

Min erfarenhet med PIC18Fxxxx och XC8 är att const läggs i ROM per automatik.

Men jag hade ett skräckexempel på detta. I en Fujitsu-baserat projekt skulle jag ha en massa text (7 olika språk) och de texter hade jag såklart som const - och de sparades såklart i ROM.

Sedan hade jag en tabell för varje mening och indexerade med valda språk.
const char* Start_Text[] = {Start_Text_DK, Start_Text_UK, Start_Text_DE, Start_Text_SE};

Och eftersom jag lade till texter minskade RAM!!! Jag hade ingen tid att lösa det på rätt sätt då så jag lade in texterna som ASM och då jag återvände till dom testade jag lite olika och fick lite tips av en kollega. Slutresultatet blev:
const char* const Start_Text[] = {Start_Text_DK, Start_Text_UK, Start_Text_DE, Start_Text_SE};

Då släppte tabellerna all RAM och allt blev placerat i ROM.

Så ibland kan det bli klurigt...
Senast redigerad av Icecap 17 december 2014, 13:35:37, redigerad totalt 1 gång.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

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

Inlägg av Wedge »

Strängar kopieras till RAM för att det hör till språkets egenskaper att man kan ändra strängar. Inget konstigt med det.
Med const på strängar talar man om för kompilatorn att strängen inte kan ändras, och därmed är det fritt fram för kompilatorn att placera strängen i ROM om den vill och kan.
Const är fortfarande bara ett sätt att ange att data inte kan ändras, och inget annat.

void foo( const int bar ); // Argumentet ligger på stacken eller i ett register, och är read-only. Inte ROM.
extern volatile const int banan; // Ge mig tillgång till banan, jag lovar att jag inte ändrar på den. Inte ROM.
const nånTypHär kanske = ??; //Kanske i ROM, kanske i RAM, kanske som inlinekonstant i koden, kanske bara programkod. Vem vet.
Användarvisningsbild
adent
Inlägg: 4103
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 »

Icecap skrev: <bortklippt>
MEN - vissa kompilers kan faktisk bygga upp en tabell över delrutinerna och sedan indexera i den tabell med X och då spara tid. Detta sköts av kompilern och man ska bara programmera utan att bry sig om vilket.
För MSP430 finns just __even_in_range() för att kunna skapa en snabbare switch - case:

Läs nedersta gröna rutan:
http://e2e.ti.com/support/microcontroll ... 6/t/238317

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 »

Här ligger jag efter men vet inte hur jag ska göra för att det ska bli ett så långt inlägg... Vi provar så här:

@adent
Nu kanske det är så att jag pratar i nattmössan och förstått "race conditions" fel men det finns en risk att jag redan tänkt i dessa banor.
Det jag har försökt ha i bakhuvet, speciellt efter jag började använda ISR:er, är att inte tex skriva till samma variabel i både main-rutinen och ISR:en. Exempel:

Kod: Markera allt

main loop{
adc_data = voltage_level;
adc_data = <<8;
}

ISR{
adc_data = default_level;
}
Kanske världens sämsta exempel men jag kom inte på något bättre nu.
Det jag vill komma till att jag tolkar "race conditions" som att om ISR:en skulle ske mitt emellan de två raderna i main loopen så skulle adc_data-värdet se väldigt lustigt ut efter bitskiftningen. Har jag förstått det rätt?
Vid närmare eftertanke så har jag nog inte ens tänkt på det i den "skarpa" koden i tråden men ibland slår det mig och då kollar jag över det.

Det du nämner om __even_in_range() har jag för mig jag har läst om på någon Arduino-sidan (eller om det var i forumet) också. Hinner inte kolla nu men vet inte om något liknande finns för min kompilator men hjälpsektionen för switch säger inget om det.

@johano:
Hör vad du säger men om "i++" är det enda som påverkar variabeln i och detta sker alltid precis innan i &= 0x3;, finns det då någon risk att bitar "utifrån" kommer in i variabeln och kan ställa till det du säger?
Visst att min if-sats kanske är lite hängslen och livrem men jag har lite svårt att förstå hur ofta ej önskade bitar kan skrivas här och var.

@Wedge och Icecap:
Då förstår jag. Mycket det ni skriver är lite överkurs och i nuläget är jag inte så brydd över vart min data lägger sig, bara den stannar kvar :)
Inom tid tänkte jag testa att skriva och hämta data till ett EEPROM och då kanske jag får tänka lite mer hur det är uppbyggt. Vi får se. Men ni ska ha tack för alla förklaringar. I vilket fall som helst så är det alltid jättebra att ha när jag går tillbaka och läser om hela trådarna.
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

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

Inlägg av johano »

Nej, just i det här fallet, där du vill att i ska räknas upp till 3 och sedan börja om på 0, så funkar det alldeles utmärkt med i &= 3
Min varning var bara en kommentar till kommentaren att detta skulle vara ekvivalent med "if (i >= 4 ) i = 0;

/johan
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

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

Inlägg av sodjan »

> Har jag förstått det rätt?

Ja, jag tror det. Det man normalt gör är att tillfälligt
stänga av interrupt under tiden som man gör de känsliga
operationerna i main (eller någon annanstans utanför ISR'en).
Interruptet kommer att ligga på kö och utföras när man
slår på interrupt igen, inget missas bara fördröjs lite.

Det brukas kallas "atomic operations", sådant som inte
får eller kan avbrytas.

http://en.wikipedia.org/wiki/Linearizab ... structions
Användarvisningsbild
Icecap
Inlägg: 26151
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

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

Inlägg av Icecap »

Magnus_K: det jag gör är att en ISR aldrig "konkurrerar" med "icke-ISR" och vice-versa.

Om vi tar AD-omvandlingen kommer interruptrutinen att spara det lästa värde i en variabel. Sedan skulle jag ha satt en flagga som betyder "OK, det finns nytt värde, jobba på det!". När main-loopen kommer till "finns det en flagga för nytt AD-värde?" blir svaret ja. Flaggan kan vara att AD-omvandlaren har omvandlat en gång och sedan väntar, då är flaggan "Klar med omvandlingen".

Rutinen gör sedan vad som ska göras vid att först kopiera värdet till ett arbetsminne, sedan nolla flaggan och därefter göra de uträkningar som ska göras. Beroende på projekt och hur viktigt det är att AD samplas med jämn hastighet eller inte kunde jag istället för flaggan ha gjort så att när värdet var kopierat till arbetsminnet hade jag startat en omvandling mer. Men detta gör man efter behov.

Sedan kunde AD-omvandlaren/ISR'n skriva till värde-variabeln allt den vill.

Huvudregeln är:
Värden: ISR läsa, mainloop skriva ELLER ISR skriva, mainloop läsa.
Flaggor: Båda läsa och skriva.

Om värdet innebär att man måste läsa fler läsningar (t.ex. ett 16 bit värde i en 8 bit C) är det en mycket bra idé att stänga av alla interrupt först, läsa/kopiera värdet och sedan slå på interrupts igen, precis som sodjan beskriver. På detta vis säkrar man sig mot att man läser ena hälft av gamla värdet och andra hälft av nya värdet.
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 »

Tar nya tag i den här tråden istället för att skapa en ny. Har suttit ett par kvällar nu men får inte ordning på det här.

Det är displaystyrningen till mitt huvudur. Displayen är en VFD men kod-vis så kommer det inte skilja något från att styra denna än som en 4:a siffrig 7-segmentare. I mitt fall så är det en PIC16F690 som skickar data till ett skiftregister, som i sin tur styr segmenten. Vilken siffra som ska visas väljs direkt av MCU:n, dvs inte via någon annan krets.
Väldigt bekymrad då denna tråd börjar med just det här, och det är det jag försökt efterlikna men med då vissa modifieringar.
Den postade koden är just det som har med displayen att göra så det kan hända att det saknas en } eller annat. Dock så kompilerar koden fint med resultatet blir inte som väntat.

Det jag helt enkelt vill göra är att till en början visa 12:34 på displayen.
Nedan kod generar 41XX3, där X innebär inget tecken. Ser någon av er vad som skulle kunna orsaka det här?
Jag har testat att plocka bort MCU:n och skiftregistret och kört varje segment/siffra manuellt och det fungerar kanon. På så vis har jag uteslutit hårdvarufel.

Kod: Markera allt

unsigned short debounceCtr = 0;
unsigned short secCtr = 0;
unsigned short ADC_value = 0;
unsigned short D1, D2, D3, D4, DP;
unsigned short brown_outCOUNTER = 0;
unsigned short segmentData = 0;
bit pushButton_Status;
bit newPulse;
bit newTRANSFER;
bit setSLAVE;
bit pulseACTIVE;
bit slaveRUNNING;
unsigned int timeCounter = 0;
unsigned int analogTime;
unsigned int digitalTime;
unsigned int digitCounter = 0;
unsigned int analogCounter = 0;

#define pushButton PORTB.B4
#define rotarySwitch PORTC.B3
#define secPulse PORTC.B7
#define HOURS timeCounter / 60
#define MINUTES timeCounter
#define DATA_LATCH PORTB.B6
#define DATA PORTB.B5
#define DATA_CLK PORTB.B7
#define SLAVE_NORTH PORTA.B4
#define SLAVE_SOUTH PORTA.B5
#define NORTH 0
#define SOUTH 1

const char NUMBER[11] = {
      0b10000000,    //DP
      0b01111011,    //0
      0b00011000,    //1
      0b01101101,    //2
      0b00111101,    //3
      0b00011110,    //4
      0b00110111,    //5
      0b01110111,    //6
      0b00011101,    //7
      0b01111111,    //8
      0b00111111     //9
};

const char GRID[5] = {

      0b00100000,   // X0:00
      0b00010000,   // 0X:00
      0b00000100,   // 00X00
      0b00000010,   // 00:X0
      0b00000001    // 00:0X
};

void BASIC_init() {

      OSCCON = 0b01110000;              //8MHz HFINTOSC
      
      CM1CON0 = 0;
      CM2CON0 = 0;

      ANSEL = 0;// b10000000;               //AN7 enable (RC3)
      ANSELH = 0;

      INTCON = 0b11100000;               //Enable global, peripheral, Timer and INT-interrupt (INT borttagen)
      
      OPTION_REG = 0x3;
      TMR0 = 56;
      INTCON.T0IF = 0;


      PORTA = 0b00000000;
      PORTB = 0b00000000;
      PORTC = 0b00000000;
      TRISA = 0b00001111;
      TRISB = 0b00010000;
      TRISC = 0b10001000;
      
      newTRANSFER = 1;
}

void main() {

     BASIC_init();

     while(1) {

     if(newTRANSFER) {                                //Send data as soon as one GRID been updated
        
           unsigned short j;
           unsigned short i = digitCounter;              //Send the correct segmentData for correct GRID

           switch (i) {
           case 0:
             segmentData = NUMBER[2];
             break;
           case 1:
             segmentData = NUMBER[3];
             break;
           case 2:
             segmentData = NUMBER[0];
             break;
           case 3:
             segmentData = NUMBER[4];
             break;
           case 4:
             segmentData = NUMBER[5];
             break;
           default:
             segmentData = NUMBER[8];
             break;
           }
           
           for(j=0;j<=7;j++) {                            //Manually shift segmentbits to shift register
                if(segmentData & (1<<j)) {
                   DATA = 1;
                   DATA_CLK = 1;
                } else {
                   DATA = 0;
                   DATA_CLK = 1;
                }
                DATA = 0;
                DATA_CLK = 0;
                newTRANSFER = 0;
           }

        }
     }

}

void interrupt(void) {

if(INTCON.T0IF) {

             INTCON.T0IF = 0;                        // Reset overflow flag
             TMR0 = 56;
             PORTC = 0;                              // Turn grids off
             digitCounter++;                         // Count 1 step up to next GRID to be displayed
             if (digitCounter >= 5) {                // Re-start counter if top number is reached was last displayed
                 digitCounter = 0;
             }
             DATA_LATCH = 1;                         // Latch new segmentData
             PORTC = GRID[digitCounter];             // Turn the correct GRID on
             DATA_LATCH = 0;                         // Release latch
             newTRANSFER = 1;                        // Ready to send new data to shift register
     }
}
Skriv svar