Behöver nybörjarhjälp att programmera i C
- 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
Hehe, så sant!
Felsöker lite på kommunikationen och tror att felet är att jag inte får till i koden att skicka klocktåg #2 till ADC:n för att begära de sista 8 bitarna.
Kollar jag med skopet så upprepas denna cykel om och om igen vilket jag tycker är en indikation på att "startar om" kommunikationen hela tiden.
Jobbar vidare.
Felsöker lite på kommunikationen och tror att felet är att jag inte får till i koden att skicka klocktåg #2 till ADC:n för att begära de sista 8 bitarna.
Kollar jag med skopet så upprepas denna cykel om och om igen vilket jag tycker är en indikation på att "startar om" kommunikationen hela tiden.
Jobbar vidare.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
- 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
Nu är jag nära!
Jag har nog tänkt lite fel med kommunikationen. Varje gång jag får buffer-flaggan och uppfyller någon av de två if-satserna (flag 0 el 1) så körs ju rutinen om.
Testade att baka ihop de två if-satserna, så den kör all kod i ett kör, men med en liten delay i mellan. Då börjar det likna något!
Får upp ett värde på min display som ändrar sig när jag vrider på potten.
Nu blir det nog att scanna nätet på idéer hur man egentligen gör för att få detta riktigt tajt och skottsäkert.
Här är mitt halvhjärtade försök som i alla fall gjorde lite skillnad.
EDIT: Tips mottages tacksamt om hur jag får till en funktion där: Om räknaren är 200 så starta en rutin men istället för delayen nedan så pausar koden tills man får en flagga och sen kör vidare från den punkten. Hur går detta till?
Hmm, är nog livsfarligt att göra så förresten. Vad skulle hända om flaggan inte skulle komma...
Jag har nog tänkt lite fel med kommunikationen. Varje gång jag får buffer-flaggan och uppfyller någon av de två if-satserna (flag 0 el 1) så körs ju rutinen om.
Testade att baka ihop de två if-satserna, så den kör all kod i ett kör, men med en liten delay i mellan. Då börjar det likna något!
Får upp ett värde på min display som ändrar sig när jag vrider på potten.
Nu blir det nog att scanna nätet på idéer hur man egentligen gör för att få detta riktigt tajt och skottsäkert.
Här är mitt halvhjärtade försök som i alla fall gjorde lite skillnad.
EDIT: Tips mottages tacksamt om hur jag får till en funktion där: Om räknaren är 200 så starta en rutin men istället för delayen nedan så pausar koden tills man får en flagga och sen kör vidare från den punkten. Hur går detta till?
Hmm, är nog livsfarligt att göra så förresten. Vad skulle hända om flaggan inte skulle komma...
Kod: Markera allt
if(Counter >= 200) { // När ISR:en scannat 200 ggr så är det dags att
// hämta nytt ADC-värde
temp_adc_data &= 0x0000; // Nolla temp-variablen
SSP1BUF &= 0x00; // Nolla buffern
LATA.B5 = 0; // Chip Select, aktivera ADC:n
if(SSP1IF) { // Om buffern fyllts på med data så:
temp_adc_data = SSP1BUF; // Flytta buffern till variablen
temp_adc_data <<= 8; // Skifta dessa 8 bitar uppåt
SSP1BUF &= 0x00; // Nolla buffern
Delay_ms(1);
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 &= 0x00; // Nolla den riktiga variablen
adc_data |= temp_adc_data; // Fyll på med den nya datan
adc_flag = 0; // Markera att man kan börja om från början
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
PIR1.B3 = 0; // Nolla buffer-flaggan
}
}
}
- 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
Nästan där. Displayen visar rätt och uppdaterar när jag vrider potten men det är något skit kvar.
Jag tror fortfarande att jag missar en drös LSB:s då spänningen gör väldigt grova "hopp" när man vrider på potten. Rimligtvis ska jag kunna justera i alla fall 10 mV (om inte 1 mV) men nu hoppar den typ 130 mV i taget.
Så här ser programmet ut nu (plockat bort konfigureringen av µC:n då jag tror det är mindre relevant):
Jag tror fortfarande att jag missar en drös LSB:s då spänningen gör väldigt grova "hopp" när man vrider på potten. Rimligtvis ska jag kunna justera i alla fall 10 mV (om inte 1 mV) men nu hoppar den typ 130 mV i taget.
Så här ser programmet ut nu (plockat bort konfigureringen av µC:n då jag tror det är mindre relevant):
Kod: Markera allt
unsigned int adc_data;
unsigned int temp_adc_data = 0x0000;
unsigned short Counter = 0;
unsigned short new_value = 0;
unsigned short a = 0;
unsigned short b = 0;
unsigned short voltage[4];
unsigned long total_voltage;
int adc_flag = 0;
int i;
int j;
const short DIGIT[4] = {
0b00000010,
0b00000100,
0b00001000,
0b00010000
};
const short 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 &= 0x00000000; // Nolla variablen
total_voltage |= adc_data; // OR:a in 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
if(LATA.B5) {
SSP1BUF &= 0x00; // Nolla buffern
temp_adc_data &= 0x0000; // Nolla temp-variablen
}
LATA.B5 = 0; // Chip Select, aktivera ADC:n
if(SSP1IF && (adc_flag == 0)) { // Om buffern fyllts på med data så:
temp_adc_data = SSP1BUF; // Flytta buffern till variablen
SSP1BUF &= 0x00;
temp_adc_data <<= 8; // Skifta dessa 8 bitar uppåt
adc_flag = 1;
}
if(SSP1IF && (adc_flag == 1)) {
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 &= 0x00; // 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
adc_flag = 0;
}
}
}
}
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 &= (PORTA & 0x00); // Släck anod
LATD &= (PORTD & 0x00); // Nolla 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]; // Ge j värdet som respektive element innehåller
LATD |= NUMBER[j]; // Aktivera rätt segment beroende på ovan
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
}
}
Re: Behöver nybörjarhjälp att programmera i C
Lägg ut ADC värdet direkt på displerna istället för det omräknade värdet i Volt.
Gärna i HEX så ser man ganska snabbt om det finns bit-fel eller om
några LCB saknas o.s.v.
Gärna i HEX så ser man ganska snabbt om det finns bit-fel eller om
några LCB saknas o.s.v.
- 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
Bra idé!
Vet inte än hur jag omvandlar binärt tal till hex samt att det tar en del tid att att lägga in A,B,C,D,E och F för visningen.
Kopplade dock om så jag hade samma spänning på Vref som V+ med gemensam 0:a, vilket borde innebära ett visat binärt värde på 4096.
Displayen visade "3968" vilket blir F80 i hex.
Det var nog en riktigt bra idé för det här innebär ju att jag saknar "128" äpplen vilket också innebär första biten i andra byten.
Mycket bra. Nu har jag en bra punkt att felsöka från!
EDIT: Eller kanske snarare, HELA andra byten! Som jag var inne på..
Vet inte än hur jag omvandlar binärt tal till hex samt att det tar en del tid att att lägga in A,B,C,D,E och F för visningen.
Kopplade dock om så jag hade samma spänning på Vref som V+ med gemensam 0:a, vilket borde innebära ett visat binärt värde på 4096.
Displayen visade "3968" vilket blir F80 i hex.
Det var nog en riktigt bra idé för det här innebär ju att jag saknar "128" äpplen vilket också innebär första biten i andra byten.
Mycket bra. Nu har jag en bra punkt att felsöka från!
EDIT: Eller kanske snarare, HELA andra byten! Som jag var inne på..
- Jan Almqvist
- Inlägg: 1651
- Blev medlem: 1 oktober 2013, 20:48:26
- Ort: Orust
Re: Behöver nybörjarhjälp att programmera i C
Jag gissar att felet är att du läser tre gånger istället för två.
Första läsningen är OK.
Vid andra läsningen
(som sker här)
försvinner nog lågbyten...
Första läsningen är OK.
Vid andra läsningen
(som sker här)
Kod: Markera allt
SSP1BUF &= 0x00;
- 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
Såg precis ditt inlägg Jan Almqvist men måste läsa det och kolla på koden för att förstå vad du menar. Återkommer!
Oavsett så hittade jag en lösning. Kanske något som anses som otroligt farligt att göra i kod och då skulle jag hemskt gärna vilja ha tips på hur man kan ta sig runt det.
Genom att lägga in while-loopar som gör att programmet avstannar till buffern är fylld så fungerar det nu precis som det ska.
Den del som jag mekat med syns nedan och ni ser nog direkt vilka loopar jag pratar om.
Oavsett så hittade jag en lösning. Kanske något som anses som otroligt farligt att göra i kod och då skulle jag hemskt gärna vilja ha tips på hur man kan ta sig runt det.
Genom att lägga in while-loopar som gör att programmet avstannar till buffern är fylld så fungerar det nu precis som det ska.
Den del som jag mekat med syns nedan och ni ser nog direkt vilka loopar jag pratar om.
Kod: Markera allt
if(Counter >= 60) { // När ISR:en scannat 60 ggr så är det dags att
// hämta nytt ADC-värde
SSP1BUF &= 0x00; // Nolla buffern
temp_adc_data &= 0x0000; // 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 &= 0x00; // 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 &= 0x00; // 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
}
- 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
Hmm, nog jag som inte förstår. Kallas inte det för skrivning, dvs detta -> SSP1BUF &= 0x00 ska då ge klartecken för "klart att sända igen" ?Jan Almqvist skrev:Jag gissar att felet är att du läser tre gånger istället för två.
Första läsningen är OK.
Vid andra läsningen
(som sker här)
försvinner nog lågbyten...Kod: Markera allt
SSP1BUF &= 0x00;
Eller blir det någon slags läs/skrivning? Det är ju klart, ska man AND:a något så måste det ju läsas först för att veta vad man ska AND:a med.... eller?
- 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
Hur gör jag för att tillfälligt ändra ett element i en array?
Problem:
Istället för att ha ytterligare ett element som visar decimaltecknet så tänkte jag prova att tillfälligt modifera den siffra jag ska visa. B7, eller högst biten, i varje element är decimaltecknet. 1 = av, 0 = på.
Jag har denna array deklarerad:
Tillfälligt vill jag AND:a en av dessa bytes med 7F (0b01111111).
Har testat att skriva:i == 3 är alltså om scanner ska uppdatera vänstra siffran så gör {}.
Raden ovanför denna if-sats så har också "j" fått ett värde mellan 0 och 9.
"&=" fungerade inte. Kompilatorn klagade på något med "lvalue".
Problem:
Istället för att ha ytterligare ett element som visar decimaltecknet så tänkte jag prova att tillfälligt modifera den siffra jag ska visa. B7, eller högst biten, i varje element är decimaltecknet. 1 = av, 0 = på.
Jag har denna array deklarerad:
Kod: Markera allt
const short NUMBER[10] = {
0b11000000, //0
0b11111001, //1
0b10100100, //2
0b10110000, //3
0b10011001, //4
0b10010010, //5
0b10000010, //6
0b11111000, //7
0b10000000, //8
0b10010000 //9
};
Har testat att skriva:
Kod: Markera allt
if(i == 3) {NUMBER[j] & 0x7f;}
Raden ovanför denna if-sats så har också "j" fått ett värde mellan 0 och 9.
"&=" fungerade inte. Kompilatorn klagade på något med "lvalue".
Re: Behöver nybörjarhjälp att programmera i C
> {NUMBER[j] & 0x7f;}
Den AND'ar två värden, men vart ska resultatet ta vägen?
Den AND'ar två värden, men vart ska resultatet ta vägen?
- 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
Hmm, misstänkte det...
Hoppas jag svarar på din fråga nu men i nästa rad sker detta:Alltså det "AND:ande nummerelementet" skrivs till porten.
EDIT: Nej nu förstår jag nog vad du menar. Alltså vart ska det AND:ande värdet ta vägen? Nja, det är lite det som är problemet.
Testat med if(i == 3) {NUMBER[j] = (NUMBER[j] & 0x7f);} men då klagar den på "Assigning to non lvalue" igen.
EDIT2: Hmm, det kompilerar ok när jag använder "&=" och jag får dit lite punkter om jag ändra "const short" till "unsigned short" i deklarationen av arrayen, men å andra sidan börjar alla siffror fladdra och det blir bara skit till slut. Ska fortsätta jobba på det.
Hoppas jag svarar på din fråga nu men i nästa rad sker detta:
Kod: Markera allt
LATD |= NUMBER[j];
EDIT: Nej nu förstår jag nog vad du menar. Alltså vart ska det AND:ande värdet ta vägen? Nja, det är lite det som är problemet.
Testat med if(i == 3) {NUMBER[j] = (NUMBER[j] & 0x7f);} men då klagar den på "Assigning to non lvalue" igen.
EDIT2: Hmm, det kompilerar ok när jag använder "&=" och jag får dit lite punkter om jag ändra "const short" till "unsigned short" i deklarationen av arrayen, men å andra sidan börjar alla siffror fladdra och det blir bara skit till slut. Ska fortsätta jobba på det.
Senast redigerad av Magnus_K 15 december 2014, 00:12:58, redigerad totalt 1 gång.
Re: Behöver nybörjarhjälp att programmera i C
Det är för att du sagt att innehållet i NUMBER ska vara const, alltså inte gå att ändra.
- 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
Tack Zeela. Nu när dom är "unsigned" istället så går dom ändra. Dock bläddrar/blinkar hela displayen helt okontrollerat.
Så här ser funktionen ut nu:
Så här ser funktionen ut nu:
Kod: Markera allt
LATA &= (PORTA & 0x00); // Släck anod
LATD &= (PORTD & 0x00); // Nolla segmenten
if(i == 3) {NUMBER[j] |= 0x80;} // Om den vänstra LED-displayen uppdaterades senast
// så OR:a in en 1:a, dvs släck decimaltecknet
// Detta för att numret ska återställas
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]; // Ge j värdet som respektive element innehåller
if(i == 3) {NUMBER[j] &= 0x7f;} // Om det är vänstra LED-displayen som ska uppdateras
// så AND:a in en 0:a, dvs tänd decimaltecknet
LATD |= NUMBER[j]; // Aktivera rätt segment beroende på ovan
LATA |= DIGIT[i]; // Tänd ny anod enligt räknaren
Re: Behöver nybörjarhjälp att programmera i C
Här är det ju absolut enklast med något slags simulator/debugger där du kan
köra en C-rad i taget och kontrollera värden på allt. Då borde det gå ganska
enkelt att se var det inte fungerar så som du tänkte. Fanns det i MikroC?
köra en C-rad i taget och kontrollera värden på allt. Då borde det gå ganska
enkelt att se var det inte fungerar så som du tänkte. Fanns det i MikroC?
- 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
Mjoo det finns, men att kunna hantera den är en annan femma.
Har kört den några gånger för enkla övningar men jag får den inte att uppdatera variablerna automatiskt, utan jag måste uppdatera själv hela tiden genom att klicka på variablen.
Ska göra ett försök till.
Har kört den några gånger för enkla övningar men jag får den inte att uppdatera variablerna automatiskt, utan jag måste uppdatera själv hela tiden genom att klicka på variablen.
Ska göra ett försök till.