Forum: Mikrocontroller und Digitale Elektronik PIC takten delay


von Markus T. (1lc)


Lesenswert?

Hallo Leute, ich bin ganz neu bei den Pics dabei, hab mal mein erstes 
Helloworld programm zu laufen gekriegt, eine LED blinken yay, aber nicht 
so wirklich verstanden wie ich den PIC takte um eine korrekte Zeit fürs 
__delay_ms(x) zu erreichen.
Ich will dass die LED blinkt, und zwar im Sekundentakt. 1 Sekunde an, 1 
Sekunde aus.

Hier mal mein Code
==========================================================
/*
 * File:   main.c
 * Author: Markus
 *
 * Created on 13. März 2016, 17:57
 */


#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 160000

#pragma config FOSC = IRC  // Oscillator Selection bits (Internal RC 
oscillator, CLKOUT function on OSC2)
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (PWRT 
disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits 
(Brown-out Reset disabled in hardware and software)
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is 
controlled by SWDTEN bit of the WDTCON register)

void main(void) {

    TRISB = 0x00; // Ausgang Port D
    while(1)
    {
        __delay_ms(1000);
            LATBbits.LATB7 = 0; // LED aus
            __delay_ms(1000);
            LATBbits.LATB7 = 1; // LED an

    }

    return;
}
====================================================

wobei die Zahl bei #define _XTAL_FREQ 160000, durch ausprobieren gewählt 
wurde, bei viel höheren kam eine Fehlermeldung im Compiler.

Ich benutze einen PIC18F14K22 und würde gerne den internen Takt 
benutzen.
Ich hab auch das Datasheet mit wo auf Seite 13/404 was mit System Clock 
steht, da ich allerdings sehr neu bin weiß ich nicht wie das geht.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Markus L. schrieb:
> _XTAL_FREQ

Probiert man nicht aus, sondern setzt es entsprechend des verwendeten 
CPU-Taktes (Quarz oder Oszillator).

von Markus T. (1lc)


Lesenswert?

und wie wäre der beim PIC18F14k22?
Hier ist das Datasheet

https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0ahUKEwjwpNm5ub7LAhUpQpoKHYsiAs0QFgglMAE&url=http%3A%2F%2Fwww.microchip.com%2Fmymicrochip%2Ffilehandler.aspx%3Fddocname%3Den540154&usg=AFQjCNHJWbdjaO9Cyk5raHDt-YNYAz9Crg&cad=rja

31.25kHZ hab ich schon ausprobiert, und bei 16Mhz meckert der Compiler 
rum.
Auf Seite 13/404 findet man Infos zum Oscillator.

von Ralph (Gast)


Lesenswert?

Gewöhn dir das mit dem Delay() gar nicht erst an.

Damit handelst du dir immer wieder nur Probleme ein.

Nimm direkt einen Timer.
Dafür haben die µC diese Module.

Und sooooo schwer ist das nicht einen Timer aufzusetzen.

von Markus T. (1lc)


Lesenswert?

/*
 * File:   main.c
 * Author: Markus
 *
 * Created on 13. März 2016, 17:57
 */


#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000

#pragma config FOSC = IRC    // Oscillator Selection bits (Internal RC 
oscillator, CLKOUT function on OSC2)
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (PWRT 
disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits 
(Brown-out Reset disabled in hardware and software)
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is 
controlled by SWDTEN bit of the WDTCON register)

   void delay_100ms(unsigned char n)
     {
         while (n-- != 0) {
             __delay_ms(100);
         }
     }


void main(void) {
    OSCCONbits.IRCF=0b101;
    TRISB = 0x00; // Ausgang Port D
    int time=10;
    while(1)
    {
            delay_100ms(time);
            LATBbits.LATB7 = 0; // LED Leuchtet
            delay_100ms(time);
            LATBbits.LATB7 = 1; // LED Leuchtet

    }

    return;
}

Hab das jetzt mal mit dem delay hingekriegt, die maximale Verzögerung 
bei 4Mhz ist wohl 197ms da der Pic wohl 4 Taktzyklen für ein Cycle 
braucht oder so.

Wie würde man das mit einem Timer machen da das ja besser wäre wie du 
gesagt hast?

: Bearbeitet durch User
von neuer PIC Freund (Gast)


Lesenswert?

Für einfache Sachen z.B. eine mainloop schreiben, die immer Vollgas 
läuft. Dazu eine Zeitbasis definieren, mit der weitere Aktionen 
ausgelöst werden.
Hier das ganze ohne Interrupt. Die Flags dazu werden zwar gesetzt, aber 
nur in der Hauptschleife abgefragt.

1
uint8_t         g_tick1ms;
2
uint8_t         trigger;
3
bool            toggle;
4
5
static bool Timer_Init(void)
6
{  
7
    // Timer2 generates 1ms tick
8
    T2CONbits.T2OUTPS = 0;              // = 1:1 Postscaler
9
    T2CONbits.T2CKPS = 0b10;            // = Prescaler is 16
10
    PR2 = 249;                          // fosc/4 / 16 / 250 = 1000Hz
11
    
12
    PIE1bits.TMR2IE = 0;                // polling TMR2IF in main-loop
13
    PIR1bits.TMR2IF = 0;
14
 
15
    T2CONbits.TMR2ON = 0b1;
16
    
17
    return true;
18
}
19
20
void main(void)
21
{
22
    
23
    Timer_Init();
24
        
25
    // main loop
26
    do
27
    {
28
        // generate 1ms tick
29
        if (PIR1bits.TMR2IF == 1)
30
        {
31
            PIR1bits.TMR2IF = 0;
32
            g_tick1ms++;
33
        }
34
35
        // do every 100ms
36
        if (trigger == g_tick1ms)
37
        {
38
            trigger = g_tick1ms + 100;   // rearm
39
            if (toggle)
40
                LATBbits.LATB7 = 0; // LED aus
41
            else
42
                LATBbits.LATB7 = 1; // LED an
43
            toggle = !toggle;
44
        }
45
46
47
    } while (true);
48
}

von Klaus (Gast)


Lesenswert?

Markus L. schrieb:
> Pic wohl 4 Taktzyklen für ein Cycle braucht oder so.

Der Code ist C, wenn ich das richtig sehe. Das Konzept von Taktzyklen 
gibt es in C nicht. Daher ja auch eine Funktion aus der mitgelieferten 
Libray, die in Millisekunden zählt.

> __delay_ms(100);

und falls es mal schneller sein soll

> __delay_us()

Bei den PICs gibt es diese Funktion für alle Prozessoren, auch die mit 
anderen Taktzyklen. Der Author dieser Libraryfunktionen hat die 
Eigenheiten des jeweiligen Prozessors schon richtig berücksichtigt, das 
muß man als Anwender nicht wirklich wissen. Und natürlich geht auch ein 
Wert von 1000 ms, also 1 Sekunde.

Dafür sind in C die Größen von Integervariablen begrenzt.

> #define _XTAL_FREQ 4000000

Bei den 8 und 16 Bit PIC hat ein Integer die Mindestgröße von 16 Bit, 
der Wert für _XTAL_FREQ passt also nicht da rein. Es sollte also

#define _XTAL_FREQ 4000000UL

heißen. Daß man bei einem komplexeren Programm Timer verwenden sollte, 
ist klar. Aber für einen Blinky geht das schon mit delays.

MfG Klaus

von Markus T. (1lc)


Lesenswert?

okay das mit den timern schau ich mir nocheinmal genauer  an, was ist 
denn nun die begründung dafür dass timer in größeren  projekten besser 
sind als die delay funktion? und was bedeutet das UL?
mir ist klar dass 4.000.000 nicht in 16 bit reinpasst, würde nur gerne 
erfahren was das UL hinter der 4000000 bedeutet :)

Vielen Dank

von Justus S. (jussa)


Lesenswert?

Markus L. schrieb:
> und was bedeutet das UL?

- leg den PIC weg
- kauf dir ein Grundlagenbuch für C
- lern C am PC
- kehr zurück zum PIC

von Zef R. (gokilz)


Lesenswert?

warum benutzt du keinen Timer (z.B. Timer 2), um delay zu machen?
http://ww1.microchip.com/downloads/en/DeviceDoc/31013a.pdf

Wenn das schon funktioniert, du kannst einfach den Pin toggeln.

Timer2(void)
{
   ....
}
main()
{
   if(delay)
   {
      delay = 0;
      LATBbits.LATB7 ^= 1;
   }
}

interrupt()
{
  if(TMR2IF)
    {
      TMR2IF = 0;
      delay = 1;
    }
}

ungefähr kann deine SW so aussehen

von Blinker (Gast)


Lesenswert?

Markus L. schrieb:
> was ist
> denn nun die begründung dafür dass timer in größeren  projekten besser
> sind als die delay funktion

Versuch doch einfach mal bei deiner Delay Version eine zweite LED, sagen 
wir mal mit 2,5 facher Frequenz blinken.

Wenn das dann ja klappt eine dritte mit doppelter Frequenz SOS blinken.

von Volker S. (vloki)


Lesenswert?

Markus L. schrieb:
> okay das mit den timern schau ich mir nocheinmal genauer  an, was ist
> denn nun die begründung dafür dass timer in größeren  projekten besser
> sind als die delay funktion?
Bei einer "schlechten" Delay Funktion zählt das Haupt-Programm und kann 
in der Zeit, die mit Zählen verbracht wird, nichts anderes tun.
Wird ein Timer benutzt, dann passiert das sozusagen nebenher in einem 
extra Modul.
Auf das normale Leben übertragen wäre der Timer deine (Armband)-Uhr. Du 
zählst doch auch nicht die ganze Zeit um zu wissen wie viel Uhr es 
ist...

> und was bedeutet das UL?
Steht sogar im User-Guide des Compilers. Schau mal
5.4.6 Constant Types and Formats
-> TABLE 5-10: SUFFIXES AND ASSIGNED TYPES

: Bearbeitet durch User
von Markus T. (1lc)


Lesenswert?

ah ok, durch timer kann parallelität realisiert werden und das UL steht 
anscheinend für unsigned long, sodass der wert 4mhz kein overflow 
verursacht.

Vielen Dank für die Antworten!

: Bearbeitet durch User
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.