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.
Markus L. schrieb: > _XTAL_FREQ Probiert man nicht aus, sondern setzt es entsprechend des verwendeten CPU-Taktes (Quarz oder Oszillator).
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.
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.
/* * 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
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 | }
|
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
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
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
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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.