MPLAB XC8 compiler foutmeldingen

Voor een project betreffende de bouw van een laadkabel voor elektrische auto's ( https://github.com/kortas87/simple-evse) wil ik het programma compileren.
Het moet in een PIC16F1825 geflasht worden.
Nou werk ik altijd met Assembly dus eerst ben ik al een middag bezig geweest om de compiler XC8 erbij te plaatsen en werkend te krijgen binnen MPLABX 6.05. :(

Bij het compileren komen er wat foutmeldingen en ik heb totaal geen verstand van dat rare taaltje C ;) .
De vraag is dus hoe ik de boel gecompileerd krijg zonder foutmeldingen.

Dit is het programma:

c code:

/*
 * File:   main.c
 * Author: Petr Kortanek, i4wifi a.s.
 *
 * Created on 23rd November 2013
 *
 * 2014-01-11 - RA3 (MCLR, prog 1) input for button
 * 2014-04-09 - RA0 (ICSPDAT, prog 4) potentiometer input
 * 2014-08-11 - fixed PWM duty (+10bit), RA1 (ICSPCLK, prog 5) input switch 6A / 10A
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#define _XTAL_FREQ 4000000
#define Button_pressed PORTAbits.RA3

#pragma config LVP = OFF, MCLRE = OFF, BOREN = OFF, PLLEN = OFF, FOSC = INTOSC, WDTE = OFF, CP = OFF, PWRTE = OFF

char latcha = 0;
char latchc = 0;
char pilot_value = 255;
char pot_value = 255;
char pot_value2 = 255;
char adchannel = 2;
char measure_nth = 0;
char button_pressed_counter = 0;
char amps = 16;
char amps_to_set = 16;
char setbypot = 0;
short duty = 500; //50%

//attached to RC1
void relayon() {
  latchc = latchc | 0b00000011;//RC1+backup RC0
  PORTC = latchc;
}
void relayoff() {
  latchc = latchc & 0b11111100;//RC1+backup RC0
  PORTC = latchc;
}

//attached to RC2
void ledon() {
  latchc = latchc | 0b00000100;
  PORTC = latchc;
}
void ledoff() {
  latchc = latchc & 0b11111011;
  PORTC = latchc;
}

void button_flashing() {
  for (int i=0; i<20; i++) {
    ledon();
    __delay_ms(30);
    ledoff();
    __delay_ms(30);
  }
}

void setAmps() {
  setbypot = 0;

  //we get current limit from the pot
  if (pot_value <= 222) { //<4.4V, amps 6-80
    amps = 6 + (222-pot_value)/3;
    setbypot = 1;
  }
  //we get current limit from the "pot2" (set 6A / 10A)
  if (pot_value2 <= 222) { //<4.4V,
    amps = 10;
    if (pot_value2 <= 25) { //short => amps 6 ~ >3kOhm
      amps = 6;
    }
    setbypot = 1;
  }
  if (setbypot == 0) {
    amps = amps_to_set;
  }
  //minimum
  if (amps < 5)
    amps = 5;
  //maximum
  if (amps > 80)
    amps = 80;
  
  //compute PWM duty
  if (amps < 51)
    duty = 1000 - (100 * amps) / 6;
  else
    duty = 1000 - (4*amps+640);

  //set PWM output 10bit
  CCPR1L = duty >> 2;
  duty &= 0b00000011;
  duty <<= 4;
  CCP1CON = duty + 12; //1100

}

void main() {

    OSCCON = 0b01101010; // 4MHz

    TRISA = 0b11111111; //pilot detect RA2, button detect RA3, pot RA0, pot2 RA1
    TRISC = 0b11110000; //relay RC1 (+backup RC0), LED RC2, pilot RC3
    latcha = 0;
    latchc = 0;
    PORTA = latcha;
    PORTC = latchc;

    ADCON1 = 0b01100000; // f/64 4MHz, 16 us
    ADON = 1; //channel: RA2=PWM detect, RA0=pot value, RA1=pot2 value
    ADCON0bits.CHS = 2;

    //pilot PWM RC3
    PSTR1CONbits.STR1C = 1;
    APFCON1bits.P1CSEL = 0; //P1C function is on RC3
    
    PR2 = 249 ;//period value
    CCP1CON = 0b00001100; //PWM mode

    OPTION_REG = 0b00000001; //pullups and TMR0
    WPUAbits.WPUA3 = 1; //button pressed detect - MCLR
    WPUAbits.WPUA1 = 1;  //6A / 10A input RA1

    //T2CON timer ON + prescaler 4
    T2CON = 0b00000101 ;

    //INTCON = 0b11100000;
    GIE = 1;
    PEIE = 1;
    
    ADIE = 1;
    TMR2IE = 1;
    
    setAmps();

    while(1) {

        //MODE set current
        if(Button_pressed == 0) {
          button_pressed_counter++;
          //setting mode entered - rapid led flashing
          if (button_pressed_counter == 5) {
            button_flashing();
            amps_to_set = 0;
          }
          if (button_pressed_counter >= 5) {
            amps_to_set++;
            setAmps();
            ledoff();
            __delay_ms(300);
            ledon();
            __delay_ms(300);
          } else {
            __delay_ms(800);
          }

        //MODE normal operation
        } else {
          if(button_pressed_counter>=5) {
            //current setting mode exit confirmation
            button_flashing();
          }
          button_pressed_counter = 0;

          //car connected (pilot pulled down <8V)
          if(pilot_value < 111) {
            relayon();
            ledon();
            __delay_ms(800);

          } else {
            ledon();
            __delay_ms(30);
            relayoff();
          }
          ledoff();
          __delay_ms(300);
        }
    }
}

void interrupt isr() {

  //channel: RA2=PWM detect or RA0=pot value
  if (ADIF) {
    if (adchannel == 0) {
      pot_value = ADRESH;
      setAmps();
      adchannel = 1;
    } else if (adchannel == 1) {
      pot_value2 = ADRESH;
      setAmps();
      adchannel = 2;
    } else   {
      pilot_value = ADRESH;
      adchannel = 0;
    }
    ADCON0bits.CHS = adchannel;
    ADIF = 0;
  }

  if (TMR2IF) {
    TMR2IF = 0;
    //voltage must be measured when voltage is "up"
    measure_nth++;
    if (measure_nth>98) {
      __delay_us(950);
      GO_nDONE = 1;
      measure_nth = 0;
    }
  }
}

En dit zijn de meldingen:
CLEAN SUCCESSFUL (total time: 6ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'C:/Users/Wes/MPLABXProjects/simple_EVSE.X'
make -f nbproject/Makefile-default.mk dist/default/production/simple_EVSE.X.production.hex
make[2]: Entering directory 'C:/Users/Wes/MPLABXProjects/simple_EVSE.X'
"C:\Program Files\Microchip\xc8\v2.41\bin\xc8-cc.exe" -mcpu=16F1825 -c -mdfp="C:/Program Files/Microchip/MPLABX/v6.05/packs/Microchip/PIC12-16F1xxx_DFP/1.3.90/xc8" -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -mwarn=-3 -Wa,-a -DXPRJ_default=default -msummary=-psect,-class,+mem,-hex,-file -ginhx32 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall -mdefault-config-bits -std=c99 -gdwarf-3 -mstack=compiled:auto:auto -o build/default/production/nbproject/main.p1 nbproject/main.c
nbproject/main.c:96:17: warning: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Wconversion]
CCPR1L = duty >> 2;
~ ~~~~~^~~~
nbproject/main.c:99:18: warning: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Wconversion]
CCP1CON = duty + 12; //1100
~ ~~~~~^~~~
nbproject/main.c:187:8: error: variable has incomplete type 'void'
void interrupt isr() {
^
nbproject/main.c:187:17: error: expected ';' after top level declarator
void interrupt isr() {
^
;
2 warnings and 2 errors generated.
(908) exit status = 1
nbproject/Makefile-default.mk:101: recipe for target 'build/default/production/nbproject/main.p1' failed
make[2]: Leaving directory 'C:/Users/Wes/MPLABXProjects/simple_EVSE.X'
nbproject/Makefile-default.mk:85: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/Wes/MPLABXProjects/simple_EVSE.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
make[2]: *** [build/default/production/nbproject/main.p1] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 1s)

Je mist de definitie van het woord "interrupt"

C weet van zichzelf niet wat een interrupt is, maar normaal levert de chipbakker of compilerbakker een header (.h) file mee waarin dat voor de compiler uitgelegd staat.

Die header file hang je dan met "#include <blahblah.h>" in je C file, en dan zijn je twee interrupts weg.

Je kunt lomp zijn en gewoon

c code:


#define interrupt

bovenaan zetten, dan zal de compiler wellicht tevreden zijn maar het zal hoogstwaarschijnlijk niet werken.

c code:

char latcha = 0;

nbproject/main.c:96:17: warning: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Wconversion]
CCPR1L = duty >> 2;

De waarschuwing zegt dat je 2 verschillende soorten varaibelen wilt gebruiken in 1 vergelijking.
De vergelijking heeft links een integer en rechts een char als type vande variabele Een integer en char worden door de compiler heel andere behandelt en zijun wat hem betreft niet hetzelfde.

Een char gebruik je eigenlijk alleen als je er ook echt een ASCII karakter mee bedoelt. En anders een integer

zoals

c code:

char A = 'A';
char B = 66; // ASCII code voor B

De opbouw van je programma kan ook anders

nu gebruik je

c code:

   while(1) {

Om zo een eindeloze loop te creëren maar de functie

c code:

void main()

Is zelf al een eindeloze loop. Alles wat ervoor staat kan je dan verplaatsen naar de functie

c code:

void setup()

De compiler start de de functie setup() altijd voor main() ook al zet je ze andersom in je programma. De setup is ook precies wat het zegt, daar zet je alle dingen die maar 1x en voor het hoofdprogramma moeten worden uitgevoerd.

En dan de while(1) dan weglaten. Het maakt verder niet uit voor je programma maar het maakt het programma een stuk overzichtelijker

Mensen zijn soms net als een gelijkrichter, ze willen graag hun gelijk hebben.

De #define interrupt heb ik erbij gezet. Dan compileert hij wel maar de andere meldingen blijven en er komt een melding bij dat de interrupt nooit uitgevoerd wordt.

@ BenLeentje: De void setup() { heb ik erbij gemaakt maar dan zegt hij dat deze nooit uitgevoerd wordt....

PS: main() is zeker GEEN eindeloze loop! Dus die vlieger gaat niet op om de while(1) weg te laten.
En setup() is typisch iets arduino achtigs en bestaat normaal in C niet.

Code begint altijd in main bij C (even wat details daargelaten). In een arduino omgeving (wat dit NIET is) staat in main iets a la:

c code:


main() {
    setup();
    while(1)
       loop();
    }
}

Maar niet van belang hier. De loop etc is gewoon goed in bovenstaande code.

Verder:

c code:


  CCPR1L = duty >> 2;

'duty' is gedeclareerd als een short, dus in meeste gevallen dus een 16-bits getal. Zelf geef je aan dat het promillen zijn dus 0-1000 (of 999 whatever).

Het register CCPR1L is een 8 bits getal (uint8_t waarschijnlijk).

Met de '>> 2' shift deel je dus door 4 en is de maximale waarde dus 250, dit past in een int8_t so far so good.

De compiler klaagt erover met een warning want die denkt dat die een short in een int8 moet proppen, wat dus normaal niet past.

Om het op te lossen kun je de uitkomst van de shift (for formeel een 'int' oplevert) 'casten' naar een uint8_t (unsigned char = byte).

c code:


  CCPR1L = (uint8_t)(duty >> 2);

De uint8_t definitie zit in elke moderne compiler in de header file <stdint.h> die je boven in de file moet includen.

Bij CCP1CON heb je een soortgelijk probleem, dat lijkt niet te kloppen? Moet daar hiet het CCP1H register gezet worden?
Ik ken het capture/compare spul van die CPU niet dus daar moet even wat uitgezocht worden.

=====
edit:

Nu die interrupt.

Om een interrupt te gebruiken moet je die speciaal declareren: dat het ook een echte ISR functie is. DWZ de functie gebruikt niet de normale manier van aanroepen waarbij argumenten op de stack gezet worden en variablen geretourneerd worden etc.

De speciale interrupt declaratie zorgt ervoor dat dat functie ALLE registers saved die gebruikt worden in die functie en dat het einde niet een normale return is maar een IRET (interrupt return).

Dus domweg het keyword 'interrupt' verwijderen werkt niet (die define constructie) en je code loopt gewoon vast.

Helaas is er geen standaard voor om in C een interrupt als zodanig te definieren.
Meestal is het iets als volgt:

c code:


void __interrupt isr() {

}

Zover ik even snel kan vinden zou dit toch correct moeten zijn voor de XC8 compiler:

code:


void interrupt isr(void)
{
....
}

En zou de xc.h headerfile included moeten worden. (Ik denk die laatste void die er ontbreekt als argument, is een deprecated construstie maar je weet het nooit)

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Verder zitten er nog een paar andere problemen in de code:

pilot_value , pot_value, pot_value2 moeten 'volatile' gedeclareerd worden:

c code:


volatile char pilot_value = 255;
volatile char pot_value = 255;
volatile char pot_value2 = 255;

Moraal/reden: Alles wat in een ISR aangepast is/wordt en ook in andere delen van de software nodig is moet je volatile declareren anders kan/zal de compiler dat weg optimalizeren.

Verder is het beter om de variable 'adchannel/measure_nth' statisch in de ISR te declareren (en boven in weg te mikken) want wordt nergens anders gebruikt:

c code:


void interrupt isr() {

  static char adchannel = 2;
  static char measure_nth = 0;

  //channel: RA2=PWM detect or RA0=pot value
  if (ADIF) {
...

Dat het bij de auteur werkt is waarschijnlijk omdat er -O0 bij de compiler staat en die schoefelt die bugs nu onder de mat.

Als code met -O3 niet werkt en met -O0 wel heb je echt het zelf (de originele auteur hier dus) verprutst ergens. Ga daar maar vanuit.

Er is nog veel meer te verbeteren, maar ik laat het hier even bij. De rest is "koper poetsen".

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Bedankt voor de opmerkingen.
Volgens een template moet de interrupt routine inderdaad zo geschreven worden:
void interrupt isr(void)
Toch geeft dit een foutmelding bij mij.

Voor wat betreft CCP1CON zou het nog wel kunnen kloppen wat de auteur heeft gedaan. In CCP1CON staan namelijk de 2 LSB bitjes van de 10 bits duty cycle.

Raar van die interrupt.

Als je even dat hele isr blok weghaalt, krijg je dan nog steeds een foutmelding?

Ik denk dat er ergens anders een ; ontbreekt namelijk en de isr krijgt "de schuld".

Kan ook een van de register definities zijn in de ISR functie die nog included moet worden en je daardoor een fout krijgt die je op het verkeerde been zet.

[Bericht gewijzigd door henri62 op 21 maart 2023 18:57:48 (29%)

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Ik zag in een voorbeeld dat ze de hele interrupt-routine als apart source-bestand plaatsen. Dat lukt me nog niet om werkend te krijgen.

Ik zit er al over te denken om het hele programma handmatig om te zetten naar Assembly want dit programma rammelt wel aan meer kanten volgens mij.
Dat dit ooit gewerkt heeft bij de schrijver snap ik niet.

Arco

Special Member

Duidelijk dat ze niet echt weten waar ze mee bezig zijn...Voor output gebruiken ze de PORTx registers, dat moeten de LATx registers zijn.
(PORTx is input-only. Output werkt wel, maar dan krijg je het R-M-W effect)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 21 maart 2023 21:46:30 schreef Zonnepaneeltje:
Ik zag in een voorbeeld dat ze de hele interrupt-routine als apart source-bestand plaatsen. Dat lukt me nog niet om werkend te krijgen.

Heb je nu die ISR eruit gehaald en bouwt het dan?
Zo nee: zit het niet in de isr code maar erboven ergens.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Op 21 maart 2023 21:57:24 schreef Arco:
Duidelijk dat ze niet echt weten waar ze mee bezig zijn...Voor output gebruiken ze de PORTx registers, dat moeten de LATx registers zijn.
(PORTx is input-only. Output werkt wel, maar dan krijg je het R-M-W effect)

Hetgeen hierboven ondervangen wordt door gebruik te maken van een hulpvariable latchc, die in zijn geheel naar PORTC wordt geschreven.

Volgend project: funcgen met ad9833 afmaken...

Op 21 maart 2023 21:57:24 schreef Arco:
Duidelijk dat ze niet echt weten waar ze mee bezig zijn...Voor output gebruiken ze de PORTx registers, dat moeten de LATx registers zijn.
(PORTx is input-only. Output werkt wel, maar dan krijg je het R-M-W effect)

Dat zijn ze bij microchip ook niet. Die doen wel meer rare dingen met registers die niet te volgen zijn. Dan krijg je inderdaad crappy code die door toeval werkt.

Zie bijvoorbeeld hierboven CCPR1L je zou dan verwachten dat de 2 andere bitjes in CCPR1H moeten, maar blijkbaar niet?? Ik heb het datasheet er niet bijgepakt maar lijkt me stug dat het zo is.

Op 21 maart 2023 23:02:30 schreef picsels:
[...]Hetgeen hierboven ondervangen wordt door gebruik te maken van een hulpvariable latchc, die in zijn geheel naar PORTC wordt geschreven.

Hoort niet en geeft soms andere ongewenste bijverschijnselen.
Dat is die andere opmerking van mij dat ik nog veel meer commentaar heb op die code (maar dat veroorzaakt nog niet dat het niet wil compileren), dit is er ook een van. Eigenlijk is heel veel code die je op het internet vindt gewoon broddelwerk.

Op 21 maart 2023 21:46:30 schreef Zonnepaneeltje:
Ik zit er al over te denken om het hele programma handmatig om te zetten naar Assembly want dit programma rammelt wel aan meer kanten volgens mij.
Dat dit ooit gewerkt heeft bij de schrijver snap ik niet.

Heeft geen nut en wordt er zeker niet beter van want is dan HELEMAAL niet meer leesbaar. De assembly mnemonics van de PIC serie zijn het meest rampzalig die ik ooit gezien heb. Het is en blijft broddelwerk.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
Arco

Special Member

Extra latch register aanmaken is onoverzichtelijk en is zinloos bij een enhanced 16F processor.

Registers doen wat ze doen moeten als je de moeite neemt om de datasheet te lezen. (als je dat niet doet, moet je niet de registers de schuld geven, maar jezelf)
CCPR1L/H houden de 10 bits, daar is niks vreemds aan...

Sommige registers veranderen inderdaad in de loop der tijd. Dat komt o.a. door de steeds groeiende functionaliteit en geheugengroei, daar valt niet aan te ontkomen.
(soms moet je ook deels breken met het verleden, als je door blijft gaan zonder wijzigingen krijg je onnodig complexe processoren)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 21 maart 2023 23:28:19 schreef Arco:
CCPR1L/H houden de 10 bits, daar is niks vreemds aan...

Zou ik ook zeggen. Maar hier boven niet dus daar worden 2 MSB's in een ander register geschreven. Kortom dat is dus fout?

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Toch even een stuk datasheet gepakt:

http://ww1.microchip.com/downloads/en/devicedoc/31014a.pdf

Register 14-1: CCPxCON Register

bit 7:6 Unimplemented: Read as '0'

bit 5:4 DCxB1:DCxB0: PWM Duty Cycle bit1 and bit0
Capture Mode:
Unused
Compare Mode:
Unused
PWM Mode:
These bits are the two LSbs (bit1 and bit0) of the 10-bit PWM duty cycle. The upper eight bits (DCx9:DCx2) of the duty cycle are found in CCPRxL

bit 3:0 CCPxM3:CCPxM0: CCPx Mode Select bits
0000 = Capture/Compare/PWM off (resets CCPx module)
0100 = Capture mode, every falling edge
0101 = Capture mode, every rising edge
0110 = Capture mode, every 4th rising edge
0111 = Capture mode, every 16th rising edge
1000 = Compare mode,
Initialize CCP pin Low, on compare match force CCP pin High (CCPIF bit is set)
1001 = Compare mode,
Initialize CCP pin High, on compare match force CCP pin Low (CCPIF bit is set)
1010 = Compare mode,
Generate software interrupt on compare match
(CCPIF bit is set, CCP pin is unaffected)
1011 = Compare mode,
Trigger special event (CCPIF bit is set)
11xx = PWM mode

...

Dus toch goed zoals het in de code staat. Zie je nu dat het onlogisch is?

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.
Arco

Special Member

Met PWM krijg je dit soort toestanden doordat alle PWM in beginsel 8 bit waren natuurlijk.
Toen dat meer werd, was het 't simpelst om die bits ervoor te 'plakken' (om de bestaande situaties niet zoveel te wijzigen)

Misschien heb je hier meer aan, code vertaald in Mikrobasic (compiler is gratis te downloaden)
(deze C code was als uitzondering eens een keer redelijk leesbaar... :) )

Assembly kan natuurlijk ook, maar da's wat Spartaans en onnodig...

pic basic code:


'==============================================================================
' File: laadkabel.mbas
' Created on 21-03-2023
'==============================================================================
Program Laadkabel
'#define _XTAL_FREQ 4000000
'#pragma config LVP = OFF, MCLRE = OFF, BOREN = OFF, PLLEN = OFF, FOSC = INTOSC, WDTE = OFF, CP = OFF, PWRTE = OFF

Dim Button_Pressed As sBit At PORTA.3
Dim PilotValue     As Byte
    PotValue       As Byte
    Potvalue2      As Byte
    AdChannel      As Byte
    MeasureNth     As Byte
    ButtonPressCnt As Byte
    Amps           As Byte
    AmpsToSet      As Byte
    Setbypot       As Byte
    Duty           As Integer

'==============================================================================
Sub Procedure RelayOn()
'==============================================================================
  latc = latc Or %00000011
End Sub

'==============================================================================
Sub Procedure RelayOff()
'==============================================================================
  latc = latc And %11111100
End Sub

'==============================================================================
Sub Procedure LedOn()
'==============================================================================
  latc = latc Or %00000100
End Sub

'==============================================================================
Sub Procedure LedOff()
'==============================================================================
  latc = latc And %11111011
End Sub

'==============================================================================
Sub Procedure Button_Flashing()
'==============================================================================
  Dim lCnt As Byte
  For lCnt = 0 To 20
    LedOn()
    Delay_ms(30)
    LedOff()
    Delay_ms(30)
  Next lCnt
End Sub

'==============================================================================
Sub Procedure SetAmps()
'==============================================================================
  SetByPot     = 0

  'we get current limit from the pot
  If PotValue <= 222 Then                 '<4.4V, amps 6-80
    Amps = 6 + (222-PotValue) /3
    SetByPot = 1
  End If

  'we get current limit from the "pot2" (set 6A / 10A)
  If PotValue2 <= 222 Then                '<4.4V
    Amps        = 10
    If PotValue2 <= 25 Then Amps = 6 End If
    SetByPot    = 1
  End If
  If SetByPot = 0 Then Amps = AmpsToSet End If
  If Amps < 5 Then Amps = 5 End If
  If Amps > 80 Then Amps = 80 End If
  ' compute PWM duty
  If Amps < 51 Then
    Duty = 1000 - (100 * Amps) / 6
  Else
    Duty = 1000 - (4*Amps+640)
  End If
  'set PWM output 10bit
  CCPR1L = Duty >> 2
  Duty = Duty And %00000011
  Duty = Duty << 4
  CCP1CON = Duty + 12      ' 1100
End Sub

'==============================================================================
sub procedure IntProc() iv 0x0004 ics ICS_AUTO
'==============================================================================
  If ADIF_bit Then
    Select Case AdChannel
      Case 0
        PotValue   = ADRESH
        SetAmps()
        AdChannel  = 1
        CHS0_bit   = 1
        CHS1_bit   = 0
      Case 1
        PotValue2  = ADRESH
        SetAmps()
        adchannel  = 2
        CHS0_bit   = 0
        CHS1_bit   = 1
      Case Else
        PilotValue = ADRESH
        AdChannel  = 0
        CHS0_bit   = 0
        CHS1_bit   = 0
    End Select
    ADIF_bit       = 0
  End If
  If TMR2IF_bit Then
    Inc(MeasureNth)
    If MeasureNth > 98 Then
      Delay_us(950)
      ADGO_bit     = 1
      MeasureNth   = 0
    End If
    TMR2IF_bit     = 0
  End If
end sub

'==============================================================================
Sub Procedure Init()
'==============================================================================
  TRISA           = %11111111
  TRISC           = %11110000
  LATA            = 0
  LATC            = 0
  '----------------------------------------------------------------------------
  OSCCON          = %01101010    '4MHz
  
  ADCON1          = %01100000    'f/64 4MHz, 16 us
  ADON_bit        = 1            'chan: RA2=PWMdet, RA0=potval, RA1=pot2val
  CHS1_bit        = 1
  
  STR1A_bit       = 1
  P1CSEL_bit      = 0            'P1C function is on RC3

  PR2             = 249          'period value
  CCP1CON         = %00001100    'PWM mode
  OPTION_REG      = %00000001    'pullups and TMR0
  WPUA0_bit       = 1            'button pressed detect - MCLR
  WPUA1_bit       = 1            '6A / 10A input RA1

  T2CON           = %00000101    'T2CON timer ON + prescaler 4
' INTCON          = %11100000
  GIE_bit         = 1
  PEIE_bit        = 1
  ADIE_bit        = 1
  TMR2IE_bit      = 1

  PilotValue      = 255
  PotValue        = 255
  PotValue2       = 255
  AdChannel       = 2
  MeasureNth      = 0
  ButtonPressCnt  = 0
  Amps            = 16
  AmpsToSet       = 16
  Duty            = 500
  SetByPot        = 0

  SetAmps()
End Sub

'==============================================================================
Main:

'==============================================================================
  Init()
  while True
    'MODE set current
    If Button_pressed = 0 Then
      Inc(ButtonPressCnt)
      'setting mode entered - rapid led flashing
      If ButtonPressCnt = 5 Then
        Button_Flashing()
        AmpsToSet = 0
      End If
      If ButtonPressCnt >= 5 Then
        Inc(AmpsToSet)
        SetAmps()
        LedOff()
        Delay_ms(300)
        LedOn()
        Delay_ms(300)
      Else
        Delay_ms(800)
      End If
    Else
      If ButtonPressCnt >=5 Then
        'current setting mode exit confirmation
        Button_Flashing()
      End If
      ButtonPressCnt = 0
       'car connected (pilot pulled down <8V)
      If PilotValue < 111 Then
        RelayOn()
        LedOn()
        Delay_ms(800)
      Else
        LedOn()
        Delay_ms(30)
        RelayOff()
      End If
      LedOff()
      Delay_ms(300)
    End If
  Wend
End.

Hexfile:

Laadkabel.hex

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Wauw Arco, bedankt hiervoor.
Pickte :) die Microbasic compiler dit programma zonder morren?

Zodra de pcb af is zal ik de hex erin flashen.

Arco

Special Member

Compileren ging goed. Of het werkt (of zou moeten werken) heb ik niet bekeken.
Het is als het goed is een kopie van de C code, dus als die niet goed is werkt deze ook niet... :)

Een schoonheidsprijs verdient die code niet met al die delays, maar als het werkt, werkt het...

[Bericht gewijzigd door Arco op 22 maart 2023 11:49:37 (30%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com