Forum: Mikrocontroller und Digitale Elektronik PWM-Signal erzeugen


von B. L. (blan)


Lesenswert?

hallo,
ich habe einen AT91SAM7S256 und möchte ein PWM-Signal erzeugen. Mein 
Quarz hat einen Takt von 18.432 MHz. Um eine höhere Frequenz zu benutzen 
nehm ich PLL. Als Divisor nehm ich 5 und als Multiplikator 25. Daraus 
errechnet sich doch ein Takt von 96 MHz oder?
1
( 18.432Mhz / 5 ) * ( 25 + 1 ) = 95,8464Mhz - also fast 96Mhz

mein Code sieht so aus:
1
#include "board.h"
2
#include "debug.h"
3
#include "uart.h"
4
5
#define nop() __asm__ __volatile__("nop")
6
7
#define PWM_0 ( 1U << 0 )
8
#define PWM_1 ( 1U << 1 )
9
#define PWM_2 ( 1U << 2 )
10
11
#define PCK_0 ( 1U << 6 )
12
13
#define LED_A ( 1U << 18 )
14
#define LED_B ( 1U << 17 )
15
16
int main(void)
17
{
18
  AT91PS_PMC  pPMC  = AT91C_BASE_PMC;
19
  AT91PS_PIO  pPIOA = AT91C_BASE_PIOA;
20
  AT91PS_RSTC pRSTC = AT91C_BASE_RSTC;
21
    
22
    AT91PS_PWMC pPWM = AT91C_BASE_PWMC;
23
    AT91PS_PWMC_CH pPWM0 = AT91C_BASE_PWMC_CH0;
24
    AT91PS_PWMC_CH pPWM1 = AT91C_BASE_PWMC_CH1;
25
    AT91PS_PWMC_CH pPWM2 = AT91C_BASE_PWMC_CH2;
26
    
27
    /* LED_A und LED_B einschalten */
28
    pPIOA->PIO_PER = ( LED_A | LED_B );
29
    
30
    /* LED_A und LED_B als Ausgang benutzen */
31
    pPIOA->PIO_OER = ( LED_A | LED_B );
32
    
33
    /* LED_A und LED_B auf HIGH schalten */
34
    pPIOA->PIO_SODR = ( LED_A | LED_B );
35
    
36
    /* PWM Controller aktivieren */
37
    pPMC->PMC_PCER = ( 1 << AT91C_ID_PWMC );
38
    
39
    /* PWM_0 bis PWM_2 einschalten */
40
    pPIOA->PIO_PDR = ( PWM_0 | PWM_1 | PWM_2 );
41
    
42
    /* PCK_0 aktivieren */
43
    pPMC->PMC_SCER = AT91C_PMC_PCK0;
44
    
45
    /* PCK_0 einschalten */
46
    pPIOA->PIO_PDR = PCK_0;
47
    
48
    /* PCK_0 B-Modus */
49
    pPIOA->PIO_BSR = PCK_0;
50
    
51
    /* PCK_0 konfigurieren */
52
    pPMC->PMC_PCKR[ 0 ] = AT91C_PMC_CSS_PLL_CLK;
53
    
54
    /* PWM_0 konfigurieren */
55
    pPWM0->PWMC_CPRDR = 2;
56
    pPWM0->PWMC_CMR = 0;    /* Clock = MCK */
57
    pPWM0->PWMC_CUPDR = 1;
58
    
59
    /* PWM_1 konfigurieren */
60
    pPWM1->PWMC_CPRDR = 2;
61
    pPWM1->PWMC_CMR = 1;    /* Clock = MCK / 2 */
62
    pPWM1->PWMC_CUPDR = 1;
63
    
64
    /* PWM_2 konfigurieren */
65
    pPWM2->PWMC_CPRDR = 2;
66
    pPWM2->PWMC_CMR = 2;    /* Clock = MCK / 4 */
67
    pPWM2->PWMC_CUPDR = 1;
68
    
69
    /* PWM_0 bis PWM_2 aktivieren */
70
    pPWM->PWMC_ENA = AT91C_PWMC_CHID0;
71
    pPWM->PWMC_ENA = AT91C_PWMC_CHID1;
72
    pPWM->PWMC_ENA = AT91C_PWMC_CHID2;
73
    
74
    /* Debug einschalten */
75
    pPMC->PMC_PCER = ( 1 << AT91C_ID_US1 );
76
    
77
    /* Debug initialisieren */
78
    debug_init();
79
    
80
  while(1)
81
  {
82
      unsigned int i;
83
      
84
      for( i = 0; i < 1000000; i++ )
85
          nop();
86
          
87
      pPIOA->PIO_CODR = LED_A;
88
      pPIOA->PIO_SODR = LED_B;
89
      debug_puts( "LED_A\n" );
90
      
91
      for( i = 0; i < 1000000; i++ )
92
          nop();
93
          
94
      pPIOA->PIO_SODR = LED_A;
95
      pPIOA->PIO_CODR = LED_B;
96
      debug_puts( "LED_B\n" );
97
  }
98
99
  return 0;
100
}

ich bin davon ausgegangen, dass meine PLL-Frequenz stimmt, da mein USART 
mit den vorrausgesetzten 48Mhz funktioniert.
1
#define EXT_CK  ( 18432000ul ) /* MAINCK */
2
#define PLLCK   ( EXT_CK / PLL_DIV * ( PLL_MUL + 1 ) )
3
#define MCK     ( PLLCK / 2 ) /* Master clock */
4
5
#define DEBUG_BAUDRATE ( 115200 )
6
#define DEBUG_BRD      (  MCK / 16 / DEBUG_BAUDRATE );

das problem ist jetzt, dass ich keine richtigen Signale bekomme.

Bei PWM_0 würde ich ein 48Mhz Rechteck-Singal erwarten, bekomm aber ein 
24MHz Sinus.

Bei PWM_1 würde ich ein 24Mhz Rechteck-Signal erwarten, bekomm aber ein 
Berg mit 12Mhz.

Bei PWM_2 würde ich ein 12Mhz Rechteck-Signal erwarten, bekomm aber 
erneut ein Berg mit 12MHz.

Das PCK_0 Signal sollte ja eigentlich den Takt von PLL ausgeben. 
Allerdings bekomm ich eine normale Spannung.

kann mir jemand sagen was ich am Code falsch gemacht habe? eventuell hab 
was mit dem PWM Channel Period Register falsch gemacht? stimmt mein 
MCK überhaupt? ich hab das Oszilloskop leider nicht jeden Tag zur 
Verfügung und wäre für ein Tipp sehr dankbar.

P.S: Die Bilder von dem Oszilloskop werde ich heute noch nachtragen.

Danke!

von unbekannter (Gast)


Lesenswert?

Hi,

ich habe mir deinen Code nicht angeschaut. Trotzdem moechte ich dir den 
Hinweis geben, dass VIELLEICHT dein Oszi nicht schnell genug ist?!

Denn wer misst, misst Mist.

von B. L. (blan)


Lesenswert?

hi,

also bei Bandbreite steht an dem Oszi: 60MHz und das sollte für alle 
Frequenzen bis auf das PCK_0 reichen oder nicht?

blan

von Tim (Gast)


Lesenswert?

moin,

> also bei Bandbreite steht an dem Oszi: 60MHz und das sollte für alle
> Frequenzen bis auf das PCK_0 reichen oder nicht?


nein. Wenn du ein Rechteck willst, dann nicht. Das Stecktrum eines 
Rechtecks hat Harmonsiche bei ungerade vielfachen der Grundfrequenz,
also bei 1*f, 3*f, 5*f und so weiter. Wenn du nun ein Rechteck mit 48MHz 
willst dann besteht das aus einer Grundwelle bei 48MHz, einer Oberwelle 
bei 3*48MHz=144MHz, einer bei 5*48MHz und so weiter. Du siehst also 
schon, dass 60MHz Bandbreite nicht reichen um die Oberwellen zu sehen, 
wohl aber für die Grundwelle. Deswegen ist dein 24MHz Rechteck nur ein 
Sinus (die erste Oberwälle wäre bei 72MHz) und deine 12MHz Dinger sind 
zusammengekleistert
aus Grundwelle, erster und zweiter Oberwälle.
Dein Oszi ist also zu lahm.

Wikipedia hat ein schönes Bild, da siehst du wie sich die einzelnen 
Frequenzen zu einem Rechteck überlagern. Such mal im englischen 
Wikipedia nach square wave.

Grüße

von Tim (Gast)


Lesenswert?

entschuldigung für die ganzen Wellen mit ä

von Random .. (thorstendb) Benutzerseite


Lesenswert?

* grins * wohl an Gartenbau gedacht? ;-)

von B. L. (blan)


Angehängte Dateien:

Lesenswert?

hi,

okay das wusst ich natürlich nicht. hab in anhang nochmal so ein bild 
vom oszi reingetan. kann ich dann davon ausgehen, dass es recktecke mit 
der richtigen frequenz sind?
was mich allerdings noch wundert: warum sind die frequenzen halb so groß 
wie ich angenommen habe - hängt das mit dem oszi zusammen oder liegt das 
am code?
und ist meine berechnung für das PLL richtig?

mfg blan

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.