Forum: Mikrocontroller und Digitale Elektronik PWM von Intel in C übersetzen für C8051F340


von Ilja F. (Gast)


Lesenswert?

Hallo Leute ich versuche das PWM-Measuaring Assembler Code von Intel in 
C zu übersetzen, so dass es im Mikrocontroller C8051F340 laufend kann. 
Aber bis jetzt habe ich nicht geschaft, da ich kenne mich nicht zu viel 
in C und die Code sollen in C geschrieben werden. Kann jemand mir 
helfen? oder Typs geben?
ich bedanke mich schon

hier die Assembler-Code:
1
; RAM locations to store capture values
2
CAPTURE DATA 30H
3
PULSE WIDTH DATA 32H
4
FLAG BIT 20H.0
5
;
6
ORG 0000H
7
JMP PCA INIT
8
ORG 0033H
9
JMP PCA INTERRUPT
10
;
11
PCA INIT: ; Initialize PCA timer
12
MOV CMOD, #00H ; Input to timer 4 1/12 X Fosc
13
MOV CH, #00H
14
MOV CL, #00H
15
;
16
; Initialize Module 0 in capture mode
17
MOV CCAPM0, #21H ; Capture positive edge first
18
; for measuring pulse width
19
;
20
SETB EC ; Enable PCA interrupt
21
SETB EA
22
SETB CR ; Turn PCA timer on
23
CLR FLAG ; clear test flag
24
;
25
; ********************************************************************************
26
; Main program goes here
27
; ********************************************************************************
28
;
29
; This example assumes Module 0 is the only PCA module
30
; being used. If other modules are used, software must
31
; check which module's event caused the interrupt.
32
;
33
PCA INTERRUPT:
34
CLR CCF0 ; Clear Module 0's event flag
35
JB FLAG, SECOND CAPTURE ; Check if this is the first
36
; capture or second
37
FIRST CAPTURE:
38
MOV CAPTURE, CCAP0L ; Save 16-bit capture value
39
MOV CAPTURE01, CCAP0H ; in RAM
40
MOV CCAPM0, #11H ; Change module to now capture
41
; falling edges
42
SETB FLAG ; Signify 1st capture complete
43
RETI
44
;
45
SECOND CAPTURE:
46
PUSH ACC
47
PUSH PSW
48
CLR C
49
MOV A, CCAP0L ; 16-bit subtract
50
SUBB A, CAPTURE
51
MOV PULSE WIDTH, A ; 16-bit result stored in
52
MOV A, CCAP0H ; two 8-bit RAM locations
53
SUBB A, CAPTURE01
54
MOV PULSE WIDTH01, A
55
;
56
MOV CCAPM0, #21H ; OptionalÐneeded if user wants to
57
CLR FLAG ; measure next pulse width
58
POP PSW
59
POP ACC
60
RETI

Ilja

von Bernhard S. (b_spitzer)


Lesenswert?

Da ist doch kaum was drin... An Adresse 0x33 die ISR für die 
PCA-Einheit, das war's auch schon. Insgesamt ist der gegebene Code aber 
noch recht unvollständig.

In C in etwa so:
1
#include <controller-spezifisches.h>
2
bit Flag;
3
unsigned char Capture;     // oder braucht es hier einen INT??
4
unsigned char Pulse_Width; // alles als Globale Variablen deklariert....
5
6
void main (void)
7
{
8
// PCA INIT: ; Initialize PCA timer
9
 CMOD = 0x00; // Input to timer 4 1/12 X Fosc
10
 CH = 0x00;
11
 CL = 0x00;
12
13
// Initialize Module 0 in capture mode
14
 CCAPM0 = 0x21; // Capture positive edge first
15
                // for measuring pulse width
16
17
 EC = 1;        // Enable PCA interrupt
18
 EA = 1;
19
 CR = 1;        // Turn PCA timer on
20
 FLAG = 0;      // clear test flag
21
22
 while (1){}    // warte auf Interrupts
23
 // die Hauptschleife fehlt aber in dem obigen Ausschnitt!!
24
25
}
26
27
void ISR_PCA(void) interrupt 6 // nachschauen, wie das Dein Compiler haben will!!
28
{
29
  CCF0 =0;  // Clear Module 0's event flag
30
  if (FLAG==0) // Check if this is the first
31
  {            // capture or second
32
   // FIRST CAPTURE:
33
   CAPTURE = CCAP0L;   // Save 16-bit capture value
34
   CAPTURE01 = CCAP0H; // in RAM  ------ die wurde gar nicht deklariert!!
35
   CCAPM0 = 0x11;      // Change module to now capture
36
                       // falling edges
37
   FLAG = 1;           // Signify 1st capture complete 
38
   }
39
   else // SECOND CAPTURE:
40
   {
41
     Pulse_Width = CAPTURE - CCAP0L; // oder so ähnlich...
42
     Pulse_Width01 = CCAP0H - CAPTURE; // Pulse_Width01 ist nicht definiert!!
43
     CCAPM0 = 0x21;     // OptionalÐneeded if user wants to
44
     FLAG = 0;          // measure next pulse width
45
   }
46
}

Insgesamt ist die 16-Bit Subtraktion in C natürlich einfacher machbar. 
Schau, was in der Anwendung eigentlich wirklich gemacht werden soll! Der 
Rest ist dann Hausaufgabe.

von Ilja F. (Gast)


Lesenswert?

Hallo Bernhard;
Zuerst Vielen Dank. Mein Mikrocontroller ist der C8051F340 von Silab.
Es sollte eigentlich nur die Pulse-Breite des Signal gemessen werden, 
also zwischen eine steigende und fallende Flanke. Ich werde sehr 
denkbar, wenn du Ideen hast um die Code zu vervollständigen. Ich arbeite 
auch daran.

Vielen Dank

von Guest (Gast)


Lesenswert?

Offensichtlich sind Pulse Width und Capture 16bit unsigned int. Deswegen 
wir zunächst das C(arry) Flag ge-cleart und dann 2 subtraktionen 
gemacht.
Also vereinfacht sich der Interrupt zu

1
void ISR_PCA(void) interrupt 6 // nachschauen, wie das Dein Compiler haben will!!
2
{
3
  CCF0 =0;  // Clear Module 0's event flag
4
  if (FLAG==0) // Check if this is the first
5
  {            // capture or second
6
   // FIRST CAPTURE:
7
   CAPTURE = ((uint16_t)CCAP0H<<8) | CCAP0L;   // Save 16-bit capture value
8
   CCAPM0 = 0x11;      // Change module to now capture
9
                       // falling edges
10
   FLAG = 1;           // Signify 1st capture complete 
11
   }
12
   else // SECOND CAPTURE:
13
   {
14
     Pulse_Width = CAPTURE - ((uint16_t)CCAP0H<<8) | CCAP0L;
15
     CCAPM0 = 0x21;     // OptionalÐneeded if user wants to
16
     FLAG = 0;          // measure next pulse width
17
   }
18
}

von Ilja F. (Gast)


Lesenswert?

Hallo Leute!!!
 Vielen Dank für eure Hilfe. Ich habe die Code wie folgt angepasst:
1
#include <c8051f340.h>
2
bit FLAG;
3
unsigned char CAPTURE;  
4
unsigned char CAPTURE01;   // oder braucht es hier einen INT??
5
unsigned char Pulse_Width;
6
unsigned char Pulse_Width01;
7
             // alles als Globale Variablen deklariert....
8
9
10
void port_init (void);
11
void pca_init (void);
12
13
 void main (void)
14
{
15
16
   port_init ();             //
17
   pca_init ();     
18
   PCA0MD &= ~0x40;                // Disable Watchdog Timer
19
   OSCICN |= 0x03;                 //             //
20
   EA=1;
21
22
// PCA INIT: ; Initialize PCA timer
23
 PCA0MD = 0x00; // Input to timer 4 1/12 X Fosc
24
 TH0 = 0x00;
25
 TL0 = 0x00;
26
27
 IE = 1;          // Enable PCA interrupt
28
 EA = 1;
29
 CR = 1;          // Turn PCA timer on
30
 
31
32
 while (1){ }            // warte auf Interrupts
33
           
34
35
}
36
37
void pca_init (void)
38
{
39
    PCA0CN    = 0x40;        //
40
    PCA0CPM0  = 0x21;        //Capture positive edge first   for measuring pulse width
41
  PCA0MD    = 0x00;          //
42
  EIE1= 0x10;            //
43
    FLAG=0;
44
}
45
46
void port_init (void)
47
{  P0SKIP = 0xff;              //
48
   P1SKIP = 0x03;             //
49
   XBR1   = 0x42;          //
50
   P1MDOUT |= 0x04;           //
51
}
52
53
54
void Int_0_ISR(void) interrupt 0
55
{
56
  CF =0;      // Clear Module 0's event flag
57
  if (FLAG==0) // Check if this is the first
58
  {      
59
      // capture or second
60
   // FIRST CAPTURE:
61
   CAPTURE = PCA0CPL0;       // Save 16-bit capture value
62
   CAPTURE01 = PCA0CPH0; 
63
   PCA0CPM0 = 0x11;          // Change module to now capture
64
                             // falling edges
65
   FLAG = 1;                 // Signify 1st capture complete 
66
   }
67
   else // SECOND CAPTURE:
68
   {
69
     Pulse_Width = CAPTURE - PCA0CPL0;
70
     Pulse_Width01 = PCA0CPH0 - CAPTURE; 
71
     PCA0CPM0 = 0x21;     // OptionalÐneeded if user wants to
72
     FLAG = 0;          // measure next pulse width
73
   }
74
}

Aber es funktioniert nicht!! kann Jemand mal schauen und mir helfen zu 
korrigieren oder anzupassen?
Vielen Dank.
Grüße

von Bernhard S. (b_spitzer)


Lesenswert?

Ilja flecher schrieb:

1
  IE = 1;          // Enable PCA Interrupt
2
 void Int_0_ISR(void) interrupt 0
> Aber es funktioniert nicht!! kann Jemand mal schauen und mir helfen zu
Bei meinem AT89C5131 heisst das Freigabebit für den PCA-Interrupt EC. 
Die Zeile müsste also EC = 1; heissen.
Die ISR ist für den externen Interrupt 0, der müsste mit EX0=1; 
freigegeben sein. Eine ISR für den PCA (Interrupt 6) fehlt ganz.

von Bernhard S. (b_spitzer)


Lesenswert?

Nachtrag:
IE = 1; kann je nach Inhalt der Include-Datei auch den externen 
Interrupt 0 freischalten. Bei neueren Derivaten heißen die 
Freigaberegister aber meist IEN0 und IEN1.
Mit IE = 1 setzt Du das gesamte Freigaberegister auf 0b00000001, danach 
EA auf 1 und es steht 0b10000001 drin. Also Ext0 ist frei und globale 
Freigabe.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ilja flecher schrieb:
> Aber es funktioniert nicht!!
Bitte hilfreiche, deutliche und klare Angaben:
WAS funktioniert nicht?
WIE hast du das festgestellt?
> while (1){ }
WAS erwartest du von diesem Code?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.