PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeitschleife funktioniert nicht (mit C programmiert)



pointhi
27.03.2010, 10:42
Ich hab mir den C-Compiler SourceBoost heruntergeladen, und auch schon erste Programme geschrieben, die einwandfrei liefen. Da ich schon Assembler programmierte, und ich dort oft Zeitschleifen benötige, wollte ich eine solche Zeitschleife auch für meine C-Programme entwickeln. In meinem Testprogramm sollte ein Taster alle 250ms abgefragt werden, und danach ein LED nach dem Tasterzustand ein oder aus-geschalten werden.

Hier der Code:


/************************************************** ***************************
Dateiname: PortTest.c
Autor: pointhi
Datum: März 2010
Version: 1.00

Letzte Änderung: keine

************************************************** ****************************
Funktionsbeschreibung des Programms:

Abfragen des Taster in einem Intervall von 250ms

*///******************************* include **********************************

#include <.\PIC16F630.h>
#include <.\stdio.h>
#include <.\stdlib.h>

//************************ Programmweite Variablen ***************************

//***************************** kofiguration *********************************

#pragma __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _MCLRE_OFF & _CPD_OFF & _INTRC_OSC_NOCLKOUT

/*
CP: Code Protection bit
ON
-> OFF
WDT: Watchdog Timer Enable bit
ON
-> OFF
BODEN: Brown-out Detect Enable bit
-> ON
OFF
PWRTE: Power-up Timer Enable bit
-> ON
OFF
MCLRE: GP3/MCLR pin function select
ON
-> OFF
CPD: Data Code Protection bit
ON
-> OFF
Oscillator Variations:
LP_OSC = Low power crystal on GPIO4 and GPIO5
XT_OSC = Crystal/resonator on GPIO4 and GPIO5
HS_OSC = High speed crystal/resonator on GPIO4 and GPIO5
EC_OSC = I/O function on GPIO4 pin, CLKIN on GPIO5
-> INTRC_OSC_NOCLKOUT = I/O function on GPIO4 pin, I/O function on GPIO5
INTRC_OSC_CLKOUT = CLKOUT function on GPIO4 pin, I/O function on GPIO5
EXTRC_OSC_NOCLKOUT = I/O function on GPIO4 pin, RC on GPIO5
EXTRC_OSC_CLKOUT = CLKOUT function on GPIO4 pin, RC on GPIO5

*///############################ Interupt ####################################

void interupt (void)
{

int status_int;
status_int = status; // Rettet den Inhalt von STATUS



status = status_int; // Schreibt den Wert von STATUS zurück

asm
{
retfie
}
}
//########################## Unterprogramme ##################################

//--------------------- Zeitschleife 1ms ---------------------

void pause1ms(void)
{
int loop;
int i;
int oszilator;
oszilator = 40; // Verwendeter Oszilator (40 = 4MHz, 80 = 8MHz)
for(i = 0; i >= oszilator; i ++)
{
for(loop = 0; loop >= 30; loop ++);
}
}
//----------------- Zeitschleife einstellbar -----------------

void pause(int loop)
{
int i;
for (i = 0; i >= loop; i ++)
{
pause1ms();
}
}
//############################ Hauptprogramm #################################

void main(void)
{
porta = 0; // Setzt alle Ports auf Low
portc = 0;
trisa = 0; // 1 = Eingang, 0 = Ausgang
trisc = 255;
intcon = 0; // Deaktiviert alle Interupts

while(1)
{
if(portc.0 == 1)
porta = 255;
else
porta = 0;
pause(250);
}
}


//################################## Ende ####################################


Das Problem ist, dass keinerlei Zeitverzögerung auftritt. Ich kann darum den LED z.b. 8 mal pro Sekunde schalten, obwohl es max. 4 mal sein dürfte.

Findet ihr ein problem?

vklaffehn
27.03.2010, 12:29
Moin!
Ich kenne mich zwar mit Deinem Compiler nicht aus, könnte mir aber vorstellen, dass dieser die Warteschleife wegoptimiert, weil da drin ja nichts passiert? Manchmal sieht man bei solchen Schleifen, dass da per Inline Assembler ein 'NOP' eingebaut wird, damit der Compiler denkt, da passiert was, alternativ kann man für Dein Vorhaben aber evtl. besser einen Timer bzw. Interrupt nutzen?

MfG Volker

Matzenerich
27.03.2010, 15:39
Hallo pointhi,
aus meiner Sicht sind Deine for-Schleifen falsch aufgebaut, denn die Fortführbedingungen sind nie erfüllt. Im ersten Lauf ist i bzw. loop = 0. Am Ende erfolgt i / loop++ => jeweils eins und eins ist nicht größer oder gleich oszillator oder 30. Deshalb erfolgt keine Verzögerung.

Gruß
Matzenerich

pointhi
29.03.2010, 12:13
Hier ist der erstellte Assemblercode:
Man sieht darin, dass ganz und gar nicht optimiert wird.




;/////////////////////////////////////////////////////////////////////////////////
;// Code Generator: BoostC Compiler - http://www.sourceboost.com
;// Version : 6.96
;// License Type : Lite License (Unregistered)
;// Limitations : PIC12,PIC16 max code size:2048 words, max RAM banks:2, Non commercial use only
;/////////////////////////////////////////////////////////////////////////////////

include "P16F630.inc"
; Heap block 0, size:53 (0x0000002B - 0x0000005F)
__HEAP_BLOCK0_BANK EQU 0x00000000
__HEAP_BLOCK0_START_OFFSET EQU 0x0000002B
__HEAP_BLOCK0_END_OFFSET EQU 0x0000005F
; Heap block 1, size:0 (0x00000000 - 0x00000000)
__HEAP_BLOCK1_BANK EQU 0x00000000
__HEAP_BLOCK1_START_OFFSET EQU 0x00000000
__HEAP_BLOCK1_END_OFFSET EQU 0x00000000
; Heap block 2, size:0 (0x00000000 - 0x00000000)
__HEAP_BLOCK2_BANK EQU 0x00000000
__HEAP_BLOCK2_START_OFFSET EQU 0x00000000
__HEAP_BLOCK2_END_OFFSET EQU 0x00000000
; Heap block 3, size:0 (0x00000000 - 0x00000000)
__HEAP_BLOCK3_BANK EQU 0x00000000
__HEAP_BLOCK3_START_OFFSET EQU 0x00000000
__HEAP_BLOCK3_END_OFFSET EQU 0x00000000
gbl_status EQU 0x00000003 ; bytes:1
gbl_indf EQU 0x00000000 ; bytes:1
gbl_tmr0 EQU 0x00000001 ; bytes:1
gbl_pcl EQU 0x00000002 ; bytes:1
gbl_fsr EQU 0x00000004 ; bytes:1
gbl_porta EQU 0x00000005 ; bytes:1
gbl_portc EQU 0x00000007 ; bytes:1
gbl_pclath EQU 0x0000000A ; bytes:1
gbl_intcon EQU 0x0000000B ; bytes:1
gbl_pir1 EQU 0x0000000C ; bytes:1
gbl_tmr1l EQU 0x0000000E ; bytes:1
gbl_tmr1h EQU 0x0000000F ; bytes:1
gbl_t1con EQU 0x00000010 ; bytes:1
gbl_cmcon EQU 0x00000019 ; bytes:1
gbl_option_reg EQU 0x00000081 ; bytes:1
gbl_trisa EQU 0x00000085 ; bytes:1
gbl_trisc EQU 0x00000087 ; bytes:1
gbl_pie1 EQU 0x0000008C ; bytes:1
gbl_pcon EQU 0x0000008E ; bytes:1
gbl_osccal EQU 0x00000090 ; bytes:1
gbl_wpua EQU 0x00000095 ; bytes:1
gbl_wpu EQU 0x00000095 ; bytes:1
gbl_ioca EQU 0x00000096 ; bytes:1
gbl_ioc EQU 0x00000096 ; bytes:1
gbl_vrcon EQU 0x00000099 ; bytes:1
gbl_eedata EQU 0x0000009A ; bytes:1
gbl_eeadr EQU 0x0000009B ; bytes:1
gbl_eecon1 EQU 0x0000009C ; bytes:1
gbl_eecon2 EQU 0x0000009D ; bytes:1
pause1ms_00000_1_loop EQU 0x00000024 ; bytes:2
pause1ms_00000_1_i EQU 0x00000026 ; bytes:2
pause1ms_00000_1_oszilator EQU 0x00000028 ; bytes:2
CompTempVar574 EQU 0x0000002A ; bytes:1
CompTempVar575 EQU 0x0000002A ; bytes:1
pause_00000_arg_loop EQU 0x00000020 ; bytes:2
pause_00000_1_i EQU 0x00000022 ; bytes:2
CompTempVar576 EQU 0x00000024 ; bytes:1
ORG 0x00000000
GOTO _startup
ORG 0x00000004
pause1ms_00000
; { pause1ms ; function begin
MOVLW 0x28
BCF STATUS, RP0
MOVWF pause1ms_00000_1_oszilator
CLRF pause1ms_00000_1_oszilator+D'1'
CLRF pause1ms_00000_1_i
CLRF pause1ms_00000_1_i+D'1'
label1
MOVF pause1ms_00000_1_i+D'1', W
XORLW 0x80
MOVWF CompTempVar574
MOVF pause1ms_00000_1_oszilator+D'1', W
XORLW 0x80
SUBWF CompTempVar574, W
BTFSS STATUS,Z
GOTO label2
MOVF pause1ms_00000_1_oszilator, W
SUBWF pause1ms_00000_1_i, W
label2
BTFSS STATUS,C
RETURN
CLRF pause1ms_00000_1_loop
CLRF pause1ms_00000_1_loop+D'1'
label3
MOVF pause1ms_00000_1_loop+D'1', W
XORLW 0x80
MOVWF CompTempVar575
MOVLW 0x80
SUBWF CompTempVar575, W
BTFSS STATUS,Z
GOTO label4
MOVLW 0x1E
SUBWF pause1ms_00000_1_loop, W
label4
BTFSS STATUS,C
GOTO label5
INCF pause1ms_00000_1_loop, F
BTFSS STATUS,Z
GOTO label3
INCF pause1ms_00000_1_loop+D'1', F
GOTO label3
label5
INCF pause1ms_00000_1_i, F
BTFSC STATUS,Z
INCF pause1ms_00000_1_i+D'1', F
GOTO label1
; } pause1ms function end

ORG 0x0000002C
pause_00000
; { pause ; function begin
CLRF pause_00000_1_i
CLRF pause_00000_1_i+D'1'
label6
MOVF pause_00000_1_i+D'1', W
XORLW 0x80
MOVWF CompTempVar576
MOVF pause_00000_arg_loop+D'1', W
XORLW 0x80
SUBWF CompTempVar576, W
BTFSS STATUS,Z
GOTO label7
MOVF pause_00000_arg_loop, W
SUBWF pause_00000_1_i, W
label7
BTFSS STATUS,C
RETURN
CALL pause1ms_00000
INCF pause_00000_1_i, F
BTFSC STATUS,Z
INCF pause_00000_1_i+D'1', F
GOTO label6
; } pause function end

ORG 0x0000003F
main
; { main ; function begin
BCF STATUS, RP0
CLRF gbl_porta
CLRF gbl_portc
BSF STATUS, RP0
CLRF gbl_trisa
MOVLW 0xFF
MOVWF gbl_trisc
BCF STATUS, RP0
CLRF gbl_intcon
label8
BTFSS gbl_portc,0
GOTO label9
MOVLW 0xFF
MOVWF gbl_porta
GOTO label10
label9
CLRF gbl_porta
label10
MOVLW 0xFF
MOVWF pause_00000_arg_loop
CLRF pause_00000_arg_loop+D'1'
CALL pause_00000
GOTO label8
; } main function end

ORG 0x00000053
_startup
BCF PCLATH,3
BCF PCLATH,4
GOTO main
END


Wegen der for-schleife: Ich konnte keinen Fehler finden. Villeicht habe ich dich falsch verstanden. könntest du dass ein wenig genauer erläutern?

Ich habe auch ein Problem vom Assemblercode entdeckt, dass der Auslösßer sein könnte. Ich werde ihn heute noch untersuchen:



MOVLW 0xFA
MOVWF pause_00000_arg_loop
CLRF pause_00000_arg_loop+D'1'
CALL pause_00000


Dabei wird zuerst der Wert 250 in die Variable pause_00000_arg_loop geschrieben, und danach durch CLRF pause_00000_arg_loop+D'1' wieder gelöscht. Was das +D'1' bedeutet, weiß ich nicht, da ich dass noch nie angewendet habe.

Ist dass villeicht das problem?

Matzenerich
29.03.2010, 23:11
Hallo pointhi,
ich meine damit

void pause1ms(void)
{
int loop;
int i;
int oszilator;
oszilator = 40; // Verwendeter Oszilator (40 = 4MHz, 80 = 8MHz)
for(i = 0; i >= oszilator; i ++)
{
//erster Durchgang i=0
for(loop = 0; loop >= 30; loop ++);
}
// hier i++ i ist dann 1 ABER eins ist nicht >= Oszillator (ist ja 40),
somit wird die Schleife nicht weiter durchlaufen, da die
Fortführbedingung ( i>=40 ) nicht erfüllt ist. Das meine ich damit, bei
den anderen ist es ebenso müsste eigentlich < sein.
}
//----------------- Zeitschleife einstellbar -----------------

void pause(int loop)
{
int i;
for (i = 0; i >= loop; i ++)
{
pause1ms();
}
}

pointhi
30.03.2010, 14:07
Ich dachte immer, dass die Schelife so lage durchlaufen wird, bis i >= oszillator true ist.

Mit der Zeitschleife habe ich auch fortschritte gemacht.
Hab es mit der while schleife geschaft. Die schleife hat zurzeit noch eine Toleranz +- 10%. Dass muss ich verbessern, wenn ich Servos steuern möchte. Werde es heute ncoh mit der for-schleife versuchen. ist ja nur ein Zeichen, dass ich ändern muss.

Danke für die gute Antwort. Wenn ich die Zeitschleife richtig optimiert habe, werde ich sie in diesem Tread veröffentlichen.

Siro
02.04.2010, 12:42
Kleiner Fehler, mit großer Wirkung:
Überall wo >= steht must Du lediglich <= schreiben.

Siro

pointhi
03.04.2010, 09:16
Die häufigsten Fehler beim Programmieren sind oft nur ein paar Zeichen :cheesy: (;, =, ==, <=, >=,...)