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
Nu ska vi vara lugna och fina. Mycket nära en lösning tror jag! Så här gjorde jag nu:
Ändrade voltage[3] till voltage[4]. (Har även testat detta tidigare utan framgång men nu bortser vi från det)
Resultat: 4 st väldigt stabila nollor. Inget fladder som det var innan.
Sedan gav jag fasta elementvärden enligt vad du skrev.
Resultat: Displayen började fladdra okontrollerat.
Sist provade jag att ha kvar fasta "voltage"-värde och ändrade tillbaka till voltage[3].
Resultat: Displayen visar stabilt "2234".
För mig helt oförklarligt men kanske säger er något?
EDIT: Har bekräftat att första siffran följer med vad man skriver ut på andra siffran..
Ändrade voltage[3] till voltage[4]. (Har även testat detta tidigare utan framgång men nu bortser vi från det)
Resultat: 4 st väldigt stabila nollor. Inget fladder som det var innan.
Sedan gav jag fasta elementvärden enligt vad du skrev.
Resultat: Displayen började fladdra okontrollerat.
Sist provade jag att ha kvar fasta "voltage"-värde och ändrade tillbaka till voltage[3].
Resultat: Displayen visar stabilt "2234".
För mig helt oförklarligt men kanske säger er något?
EDIT: Har bekräftat att första siffran följer med vad man skriver ut på andra siffran..
Re: Behöver nybörjarhjälp att programmera i C
unsigned short voltage[3]; <- 3:an ska vara 4 om du accessar [0], [1], [2] och [3]. (fyra stycken!).
I övrigt vette tusan just nu
Jag är inte så bra på Pic även om det inte borde spela någon roll i det här fallet.
MVH: Mikael
I övrigt vette tusan just nu

MVH: Mikael
Re: Behöver nybörjarhjälp att programmera i C
hmmm, är ditt interrupt ett riktigt interrupt? Ser ut som en vanlig funktion där du kollar interruptflaggan? Men det kan vara jag som inte begriper
mig på just den c-kompilatorn för Pic
Klistra in hela koden, så kanske det blir lättare. Skulle kunna vara nått med avsaknad volatile kanske... (Brukar jag förslå, men det brukar i regel inte vara det
)
MVH: Mikael
mig på just den c-kompilatorn för Pic

Klistra in hela koden, så kanske det blir lättare. Skulle kunna vara nått med avsaknad volatile kanske... (Brukar jag förslå, men det brukar i regel inte vara det

MVH: Mikael
- 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ä nu blir det läggdags.
Provade att ändra den arrayen från en short till en int samt från 3 till 4. Ingen framgång så jag ändrade tillbaka till en short men behöll 4. Vad tror du hände? Displayen visar "1234", precis som den ska.
Nä, det är nog för sent nu. Lite synd bara att man inte förstår vad som var fel...
Också fundersam kring det du precis skrev. Fick lära mig i en annan tråd att om man har en array, tex test[10], så består denna av 11 element då man börjar räkna från 0.
Lärde mig detta då jag skulle ha 100 element och skulle då skriva [99]. Det ä därför jag är lite envis med att skriva 3 nu då jag har 4 element.
EDIT: Såg din post nu. Får man säga pass?
Trodde interrupt vad just en rutin som körs när en flagga/overflow händer. Har nog förstått fel.
Volatile vet jag inte vad det är men ska läsa lite! Tack för hjälpen adent!
Provade att ändra den arrayen från en short till en int samt från 3 till 4. Ingen framgång så jag ändrade tillbaka till en short men behöll 4. Vad tror du hände? Displayen visar "1234", precis som den ska.
Nä, det är nog för sent nu. Lite synd bara att man inte förstår vad som var fel...
Också fundersam kring det du precis skrev. Fick lära mig i en annan tråd att om man har en array, tex test[10], så består denna av 11 element då man börjar räkna från 0.
Lärde mig detta då jag skulle ha 100 element och skulle då skriva [99]. Det ä därför jag är lite envis med att skriva 3 nu då jag har 4 element.
EDIT: Såg din post nu. Får man säga pass?

Volatile vet jag inte vad det är men ska läsa lite! Tack för hjälpen adent!
Re: Behöver nybörjarhjälp att programmera i C
Kom ihåg att det är kompilatorspecifikt (och kanske processorspecifikt) hur du talar om för kompilatorn vad som är interrupt (det är inte riktigt en del av C så att säga) och jag kan inte din kompilator. Det var därför jag var nyfiken på att se allt, då kanske jag fattat eller kunnat säga bu eller bä eller va? 
Det du lärt dig är fel. skriver du: unsigned char buffer[4]; så får du en 4 tecken stor array. första tecknet nås via buffer[0], andra via buffer[1], tredje via buffer[2] och fjärde och sista via buffer[3].
Om du deklarerar: unsigned char buffer[3]; och skriver till buffer[3] så kommer du med all sannolikhet att skriva över en annan variabel som kompilatorn valt att lägga efter din 3 bytes stora array. Det kan skapa väldigt mystiska fel...
Kanske är det detta som spökar någonannanstans i din kod?
MVH: Mikael

Det du lärt dig är fel. skriver du: unsigned char buffer[4]; så får du en 4 tecken stor array. första tecknet nås via buffer[0], andra via buffer[1], tredje via buffer[2] och fjärde och sista via buffer[3].
Om du deklarerar: unsigned char buffer[3]; och skriver till buffer[3] så kommer du med all sannolikhet att skriva över en annan variabel som kompilatorn valt att lägga efter din 3 bytes stora array. Det kan skapa väldigt mystiska fel...

MVH: Mikael
- 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
Jag får nog ta och läsa igenom både detta och den andra tråden igen med friska ögon. Smått förvirrad just nu
Du har säkert helt rätt i att det kan vara detta som spökar. Det kanske blev någon skillnad på detta när jag temporärt ändrade från short till int och tillbaka, dvs ändrade storlek på variabeln.
Ska posta hela koden imorrn när jag fått städa den lite.

Du har säkert helt rätt i att det kan vara detta som spökar. Det kanske blev någon skillnad på detta när jag temporärt ändrade från short till int och tillbaka, dvs ändrade storlek på variabeln.
Ska posta hela koden imorrn när jag fått städa den lite.
Re: Behöver nybörjarhjälp att programmera i C
Varför använder du short som sifferminne? Behöver du verkligen 16 bit till ett 7-segment display?
Vad med att använda 4 st unsigned char?
För att säkerställa hur den specifika kompiler använder vissa variabler har jag testat att skriva ut deras storlekar:
printf("Byte: %u\r\n", sizeof(char));
printf("int: %\r\nu", sizeof(int));
printf("Short: %\r\nu", sizeof(short));
printf("Long: %u\r\n", sizeof(long));
Då vet jag exakt hur kompilern uppfattar de olika variablers storlek och kan anpassa programmet.
Men för att göra det enkelt för dig: du behöver 4 st bytes (unsigned char) som scannerminne.
Vad med att använda 4 st unsigned char?
För att säkerställa hur den specifika kompiler använder vissa variabler har jag testat att skriva ut deras storlekar:
printf("Byte: %u\r\n", sizeof(char));
printf("int: %\r\nu", sizeof(int));
printf("Short: %\r\nu", sizeof(short));
printf("Long: %u\r\n", sizeof(long));
Då vet jag exakt hur kompilern uppfattar de olika variablers storlek och kan anpassa programmet.
Men för att göra det enkelt för dig: du behöver 4 st bytes (unsigned char) som scannerminne.
Senast redigerad av Icecap 13 december 2014, 13:10:12, redigerad totalt 1 gång.
Re: Behöver nybörjarhjälp att programmera i C
> För att säkerställa hur den specifika kompiler använder vissa variabler har jag testat att skriva ut deras storlekar:
Jag har inte sett en C-kompilator som inte har det tydligt angivet i dokumentationen.
> Trodde interrupt vad just en rutin som körs när en flagga/overflow händer.
Interrupt är ett avbrott som sker i hårdvaran. Varje C-kompilator har sitt
sätt att ange vilken C-funktion som ska kopplas till detta avbrott.
Från XC8 (Microchips egen kompilator. tc_int() är alltså ISR'en.
Motsvararde i MikroC. Själva ISR'en är hårt namnsatt till "interrupt()" i MikroC.:
Jag har inte sett en C-kompilator som inte har det tydligt angivet i dokumentationen.
> Trodde interrupt vad just en rutin som körs när en flagga/overflow händer.
Interrupt är ett avbrott som sker i hårdvaran. Varje C-kompilator har sitt
sätt att ange vilken C-funktion som ska kopplas till detta avbrott.
Från XC8 (Microchips egen kompilator. tc_int() är alltså ISR'en.
Kod: Markera allt
void interrupt tc_int(void)
{
if (TMR0IE && TMR0IF) {
TMR0IF=0;
++tick_count;
return;
}
// process other interrupt sources here, if required
}
Kod: Markera allt
void interrupt()
{
if (TMR0IE && TMR0IF) {
TMR0IF=0;
++tick_count;
return;
}
// process other interrupt sources here, if required
}
- 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
Då tror jag nog att jag gjort rätt ändå va?
Jag valde variabeltyp utifrån denna lista i manualen: Som jag tolkar detta så är det lämpligast om jag använder unsigned short eller char. Sen kan man också använda "bit" och "sbit" men dom är för små.
ISR:en blev nog rätt för att jag kollat hur andra har gjort. Vet inte anledningen till när man skriver "void" eller lämnar tomt mellan () men det kan jag nog läsa mig till.
Hade inte en aning om att sättet att skriva interrupten var styrt av kompilatorn men nu vet jag det!
Jag valde variabeltyp utifrån denna lista i manualen: Som jag tolkar detta så är det lämpligast om jag använder unsigned short eller char. Sen kan man också använda "bit" och "sbit" men dom är för små.
ISR:en blev nog rätt för att jag kollat hur andra har gjort. Vet inte anledningen till när man skriver "void" eller lämnar tomt mellan () men det kan jag nog läsa mig till.
Hade inte en aning om att sättet att skriva interrupten var styrt av kompilatorn men nu vet jag det!
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: Behöver nybörjarhjälp att programmera i C
OK, jag är van vid att short är 16 bit men är det 8 är det helt fint.
Det som skiljer med interrupt kontra icke-interrupt rutiner är vilka instruktioner som de börjar och slutar med.
En interruptrutin avslutas med "return from interrupt" medan en icke-interrupt avslutas med "return."
Om det behövs kommer interrupt-rutiner att inledas med att spara undan viktiga register, t.ex. statusregister och det/de återställs såklart innan avslut.
Detta betyder att man måste berätta för kompilern måste veta att "detta är en interrupt-rutin" så att inledningen och avslutet kan vara korrekt.
Annars är det ingen skillnad.
Det som skiljer med interrupt kontra icke-interrupt rutiner är vilka instruktioner som de börjar och slutar med.
En interruptrutin avslutas med "return from interrupt" medan en icke-interrupt avslutas med "return."
Om det behövs kommer interrupt-rutiner att inledas med att spara undan viktiga register, t.ex. statusregister och det/de återställs såklart innan avslut.
Detta betyder att man måste berätta för kompilern måste veta att "detta är en interrupt-rutin" så att inledningen och avslutet kan vara korrekt.
Annars är det ingen skillnad.
Re: Behöver nybörjarhjälp att programmera i C
Om du lägger upp hela projektet här ska jag ta en titt på problemet.
- 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å här ser denna del av projektet ut. Detta kompilerar ok. Har lagt till en miljard kommentarer bara för att du tydligt ska få se hur jag tänker. Blir det rörigt så kan jag radera alla kommentarer och posta igen.
Det som fungerar kanon nu är interruptscannern (längst ner).
Jag misstänker det är tok i både "new_value"-rutinen och "counter"-rutinen.
Det gick bra att ge de olika voltage[]-elementen fasta värden och detta visade på de 4 LED:arna men mitt lilla hittepå som ska splitta tex "1234" till "1", "2", "3" och "4" fungerar inte. Jobbar på detta just nu.
Sist men inte minst så måste jag få ordning på kommunikationen mellan PIC:en och ADC:n. Jag har kollat med skopet och jag får data tillbaka från ADC:n men jag tror jag inte lyckas med att ta hand om MSBs+LSBs utan jag får hela tiden MSBs+MSBs+MSBs osv.
Kommer sitta med detta ikväll så hittar jag själv vad som är tok så säger jag till.
Tack för hjälpen!
Det som fungerar kanon nu är interruptscannern (längst ner).
Jag misstänker det är tok i både "new_value"-rutinen och "counter"-rutinen.
Det gick bra att ge de olika voltage[]-elementen fasta värden och detta visade på de 4 LED:arna men mitt lilla hittepå som ska splitta tex "1234" till "1", "2", "3" och "4" fungerar inte. Jobbar på detta just nu.
Sist men inte minst så måste jag få ordning på kommunikationen mellan PIC:en och ADC:n. Jag har kollat med skopet och jag får data tillbaka från ADC:n men jag tror jag inte lyckas med att ta hand om MSBs+LSBs utan jag får hela tiden MSBs+MSBs+MSBs osv.
Kommer sitta med detta ikväll så hittar jag själv vad som är tok så säger jag till.
Tack för hjälpen!
Kod: Markera allt
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 = 0b00111010; //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
}
#define SEGMENTPORT PORTD
#define DIGITPORT PORTA
unsigned int adc_data;
unsigned int temp_adc_data = 0x0000;
unsigned int 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 *= 48823; // Omvandla ADC-värdet till spänningsnivå
total_voltage /= 10000; // Skala ner detta så tex 1V blir 1000
voltage[3] = total_voltage % 1000; // I resterande kod så skalas spänningsnivån
total_voltage /= 10; // ner i dekader och placerade i respektive
voltage[2] = total_voltage % 100; // element. Avslutas med att sätta rutinen i
total_voltage /= 10; // väntestadie med att nolla new_value.
voltage[1] = total_voltage % 10;
total_voltage /= 10;
voltage[0] = total_voltage % 1;
new_value = 0;
}
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 && (adc_flag == 0)) { // Om buffern fyllts på med data och
// ingen tidigare data behandlats så:
temp_adc_data = SSP1BUF; // Flytta buffern till variablen
temp_adc_data <<= 8; // Skifta dessa 8 bitar uppåt
adc_flag = 1; // Sätt "data behandlad"-variablen
SSP1BUF &= 0x00; // Nolla buffern
PIR1.B3 = 0; // Nolla buffer-flaggan
}
if(SSP1IF && (adc_flag == 1)) { // Om buffern fyllts på med data och
// ingen tidigare data behandlats 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
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
}
}
}
}
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
voltage[3] = total_voltage % 1000; ger värdet mellan 0 och 999.
Testa:
voltage[3] = total_voltage / 1000;
voltage[2] = (total_voltage / 100) % 10;
voltage[1] = (total_voltage / 10) % 10;
voltage[0] = (total_voltage) % 10;
Testa:
voltage[3] = total_voltage / 1000;
voltage[2] = (total_voltage / 100) % 10;
voltage[1] = (total_voltage / 10) % 10;
voltage[0] = (total_voltage) % 10;
- 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
Vad ska man säga Icecap? Klockrent säger jag!
Gjorde din ändring och gav sedan total_voltage ett fast värde men struntade i biten att konvertera till "spänningsnivå".
Funktionen presenterade värdet så fint på displayen.
Nästa steg så gav jag total_voltage ett fast "ADC-värde" med spänningskonvertering och visningen fungerade exemplariskt!
Kanon. Tack!
Testade slutligen att köra skarpt men då blir det bara nollor. Med andra ord är kommunikationen med ADC:n inte bra.
Ska jobba vidare med detta nu samt försöka förstå lite närmre vad din ändring verkligen gjorde jämfört med min.

Gjorde din ändring och gav sedan total_voltage ett fast värde men struntade i biten att konvertera till "spänningsnivå".
Funktionen presenterade värdet så fint på displayen.
Nästa steg så gav jag total_voltage ett fast "ADC-värde" med spänningskonvertering och visningen fungerade exemplariskt!
Kanon. Tack!
Testade slutligen att köra skarpt men då blir det bara nollor. Med andra ord är kommunikationen med ADC:n inte bra.
Ska jobba vidare med detta nu samt försöka förstå lite närmre vad din ändring verkligen gjorde jämfört med min.
Re: Behöver nybörjarhjälp att programmera i C
Jag tycker att du sköter det bra. Det kanske är en brant inlärningskurva men du tar en sak i sände och får den att fungera - och det är så jag gör också. Om det sedan är "rätt" vete gudarna 
Det fungerar för mig - så något bra är det ju i det.

Det fungerar för mig - så något bra är det ju i det.