Forum: Mikrocontroller und Digitale Elektronik ATXmega32e5 SPI und Timer eliminieren sich gegenseitig?


von MOBA 2. (Gast)


Lesenswert?

Hallo Leute,

ich habe eine kleine Schaltung mit einem ATXMega32e5 aufgebaut. Dieser 
XMega hat ein SPI Flash (AT45DB161D), 3 PWM kanäle für RGB-LEDs und 
einen für Sound sowie ein UART-Wlan Modul (ESP8266). Dabei nutze ich:
PWM Leds:  PC0-PC2
PWM-Sound: PD5
SPI auf PORTC
UART auf PORTD


Soweit so gut.

Jetzt das Problem: Ich bekomme nichts zum Laufen auf dem XMega32e5 
(meine Erfahrungen mit der A-Serie ging gut).

Ich habe folgende Phänomene:

Ich kann die PWM-Kanäle initialisieren und beschreiben (funktioniert, 
siehe Quellcodeauszug).
1
  //Timer PWM Configs
2
  //Timer Counter 0 Type
3
   TCC4.CTRLE = TC45_BYTEM_NORMAL_gc;                        //8-Bit Timer
4
   TCC4.CTRLE = TC45_CCAMODE_COMP_gc|TC45_CCBMODE_COMP_gc|TC45_CCCMODE_COMP_gc;  //Ausgabe bei A&B&C
5
   TCC4.CTRLA = TC45_CLKSEL_DIV4_gc;                        //4 Div, 31,25khz
6
  TCC4.CTRLB = TC45_WGMODE_SINGLESLOPE_gc;                    //SingleSlope mit PER als TOP
7
  TCC4.PER = PWM_Aufloesung;                            //TOP Zählwert
8
9
  //For Interrupt @ CCD for Sound and ovf for time
10
  TCC4.INTCTRLA = TC45_CCDINTLVL_HI_gc |TC45_OVFINTLVL_HI_gc;            //Activate COMP-LVL Interrupt
11
  TCC4.CCD = 250;                                  //Lichtmuster/Sound, Tastrate: 32khz ==> 250er @ div4
12
  
13
  
14
  
15
  //PWM Audio Output @ 1953,125Hz   AND OVF INT for TimeCalc                 
16
  TCD5.CTRLE = TC45_BYTEM_NORMAL_gc | TC45_CCBMODE_COMP_gc;    //8-Bit Timer & Ausgabe bei B
17
  TCD5.CTRLA = TC45_CLKSEL_DIV1_gc;                //1 Div ==> 125kHz
18
  TCD5.CTRLB = TC45_WGMODE_SINGLESLOPE_gc;            //SingleSlope mit PER als TOP
19
  TCD5.PER = PWM_Aufloesung;                    //TOP Zählwert
20
21
22
  //activate interrupt levels
23
  PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm;  //Interrupt Level freigeben (alle)
24
  sei();


Jetzt wird es Interessant und es kommt das Problem:

Wenn ich SPI initialisiere, dann geht dieser außer MISO-Pin. Dieser 
treibt weak gegen Masse (wenn ich bspw. Kurzschluss vom MISO und 
SCK-Signal mache, habe ich auf MISO max. 1,5V als HIGH).

Wenn ich vom HW-PWM Initialisierung folgende Zeilen auskommentiere:
1
   TCC4.CTRLE = TC45_BYTEM_NORMAL_gc;                        //8-Bit Timer
2
   TCC4.CTRLE = TC45_CCAMODE_COMP_gc|TC45_CCBMODE_COMP_gc|TC45_CCCMODE_COMP_gc;  //Ausgabe bei A&B&C
3
   TCC4.CTRLA = TC45_CLKSEL_DIV4_gc;                        //4 Div, 31,25khz

dann geht das SPI nicht mehr. Es geht genauso wenig wenn ich
1
spi->port->DIRCLR = SPI_MISO_bm;
2
spi->port->PIN6CTRL = PORT_OPC_PULLUP_gc;
3
4
zu 
5
6
spi->port->DIRCLR |= SPI_MISO_bm;
7
spi->port->PIN6CTRL = PORT_OPC_PULLUP_gc;

ändere. Dies bewirkt zwar dann, dass MISO wirklich INPUT gepullt ist, 
dafür geht kein SPI mehr.


Ich habe das Gefühl, dass irgendwas da gesetzt ist, was irgendwelche 
Portzugriffe überschreibt. Ich verstehe das absolut nicht. Es läuft auf 
internem OSC mit 32MHz.


Hier die Initialisierung vom SPI.
1
SPI_MasterInit(&spiMasterC, &SPIC, &PORTC, FALSE, SPI_MODE_3_gc, SPI_INTLVL_OFF_gc, FALSE, SPI_PRESCALER_DIV128_gc);
2
3
Die Funktion dazu:
4
5
void SPI_MasterInit(SPI_Master_t *spi, SPI_t *module, PORT_t *port, uint8_t lsbFirst, SPI_MODE_t mode, SPI_INTLVL_t intLevel, uint8_t clk2x, SPI_PRESCALER_t clockDivision)
6
{
7
  spi->module         = module;
8
   spi->port           = port;
9
   spi->interrupted    = 0;
10
11
12
  /* Interrupt level. */
13
  spi->module->INTCTRL = intLevel;
14
15
16
  /* No assigned data packet. */
17
  spi->dataPacket = NULL;
18
19
  
20
   /* MOSI, SCK and SS as output. */
21
  spi->port->DIRSET = (SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm);
22
  
23
   /* MISO as input. and pulled */
24
  spi->port->DIRCLR = SPI_MISO_bm;
25
  spi->port->PIN6CTRL = PORT_OPC_PULLUP_gc;
26
27
28
  spi->module->CTRL   = clockDivision |                  /* SPI prescaler. */
29
                        (clk2x ? SPI_CLK2X_bm : 0) |     /* SPI Clock double. */
30
                        SPI_ENABLE_bm |                  /* Enable SPI module. */
31
                        (lsbFirst ? SPI_DORD_bm  : 0) |  /* Data order. */
32
                        SPI_MASTER_bm |                  /* SPI master. */
33
                        mode;                            /* SPI mode. */
34
}



Wenn ich das SPI Initialisiere wie folgt vor der while
1
  PORTC.DIR = (SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm | (1<<3) | (1<<4));
2
  PORTC.PIN6CTRL = PORT_OPC_PULLUP_gc;
3
4
  SPIC.INTCTRL = SPI_INTLVL_OFF_gc;
5
  SPIC.DATA = 0;
6
  SPIC.CTRL = (SPI_PRESCALER_DIV128_gc | SPI_INTLVL_OFF_gc | SPI_MODE_0_gc | SPI_MASTER_bm | SPI_ENABLE_bm);
7
8
  FLASH_ON;
9
  AT45DB_SELECT;
10
  
11
  do
12
  {
13
    SPIC.DATA = 0xD7;
14
    while(!(SPIC.STATUS & SPI_IF_bm));
15
  }while (!SPIC.DATA);
16
  
17
  while(1)
18
  {
19
    PORTC.OUTTGL = 0xFF;
20
  }

Get das SPI an sich NUR (!) wenn ich die 3 ersten Zeilen vom TCC4 
einkommentiere. Jedoch ist dabei das Signal auf MISO immer 0V. Wenn ich 
ein High Signal (bspw Brücke zu SCK) herstelle, habe ich das Signal 
jedoch mit einem max. Pegel von 1,5V, anstelle der 3,3V.

von Felix Adam (Gast)


Lesenswert?

Du könntest das REMAP-Register vom Port C neu beschreiben mit 0, siehe 
Datenblatt Seite 152 in diesem Datenblatt:

http://www.atmel.com/Images/Atmel-42005-8-and-16-bit-AVR-Microcontrollers-XMEGA-E_Manual.pdf

Das Phänomen klingt so, als würde ein Timerausgang auf den SPI 
gemappt...

von MOBA 2. (Gast)


Lesenswert?

Hallo,

PORTC.REMAP = 0
PORTD.REMAP = 0

Habe ich beides.

von Felix Adam (Gast)


Lesenswert?

Dann poste bitte den kompletten Code oder ein Minimalbeispiel, das sich 
genauso verhält wie von dir beschrieben. Anders lässt sich das nicht 
sinnvoll gegenprüfen.

Es könnte sich höchstens jemand dazu äußern, der den ATxmega32e5 selbst 
einsetzt und den SPI benutzt.

von MOBA 2. (Gast)


Lesenswert?

Hallo,

hier der bereits reduzierte Quellcode, den ich nutze zum Testen:
1
#define F_CPU      32000000UL
2
#define NULL      0
3
4
#include <avr/io.h>
5
#include <avr/delay.h>
6
#include <avr/wdt.h>
7
#include <avr/eeprom.h>
8
#include <avr/interrupt.h>
9
#include <stdlib.h>
10
#include "at45db.c"    //includes spi library, needs uartlib
11
12
13
14
15
void init(void)
16
{
17
  wdt_reset();
18
    
19
  //ClockSource
20
  OSC.CTRL |= OSC_RC32MEN_bm;
21
  while(!(OSC.STATUS & OSC_RC32MRDY_bm));
22
  CCP = CCP_IOREG_gc;
23
  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
24
    
25
    
26
  //Set My Ports
27
  PORTA.DIR=0xFF;
28
  PORTC.DIR=0xBF;
29
  PORTD.DIR=0xFF;
30
  PORTR.DIR=0xFF;
31
    
32
  PORTA.OUT=NULL;
33
  PORTC.OUT=NULL;
34
  PORTD.OUT=NULL;
35
  PORTR.OUT=NULL;
36
    
37
    
38
  //Note: Remap off!
39
  PORTC.REMAP = NULL;
40
  PORTD.REMAP = NULL;
41
    
42
    
43
  //Timer HW-PWM Configs
44
  //Timer Counter 0 Type
45
  TCC4.CTRLE = TC45_BYTEM_NORMAL_gc | TC45_CCAMODE_COMP_gc|TC45_CCBMODE_COMP_gc|TC45_CCCMODE_COMP_gc;    //8-Bit Timer & Ausgabe bei A&B&C
46
  TCC4.CTRLA = TC45_CLKSEL_DIV4_gc;                        //4 Div, 31,25khz
47
  TCC4.CTRLB = TC45_WGMODE_SINGLESLOPE_gc;                    //SingleSlope mit PER als TOP
48
  TCC4.PER = PWM_Aufloesung;                            //TOP Zählwert
49
50
  //For Software Interrupt @ CCD for Sound and ovf for time
51
  TCC4.INTCTRLA = TC45_CCDINTLVL_HI_gc ;            //Activate COMP-LVL Interrupt
52
  TCC4.CCD = 250;                        //Lichtmuster/Sound, Tastrate: 32khz ==> 250er @ div4
53
    
54
    
55
  //Software Timer for Interrupt for Time
56
  TCC5.CTRLE = TC45_BYTEM_BYTEMODE_gc;
57
  TCC5.CTRLA = TC45_CLKSEL_DIV256_gc;
58
  TCC5.INTCTRLA = TC45_OVFINTLVL_MED_gc;
59
  TCC5.PER = Compare_1kHz;                  //125 -> @ duv 256 ==> 1Khz
60
    
61
    
62
  //HW-PWM Audio Output @ 1953,125Hz   AND OVF INT for TimeCalc
63
  TCD5.CTRLE = TC45_BYTEM_NORMAL_gc | TC45_CCBMODE_COMP_gc;    //8-Bit Timer & Ausgabe bei B
64
  TCD5.CTRLA = TC45_CLKSEL_DIV1_gc;                //1 Div ==> 125kHz
65
  TCD5.CTRLB = TC45_WGMODE_SINGLESLOPE_gc;            //SingleSlope mit PER als TOP
66
  TCD5.PER = PWM_Aufloesung;                    //TOP Zählwert
67
68
69
  //activate interrupt levels
70
  PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm;  //Interrupt Level freigeben (alle)
71
  sei();
72
    
73
    
74
  cli();
75
  PORTC.DIR = (SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm | (1<<3) | (1<<4));
76
  PORTC.PIN6CTRL = PORT_OPC_PULLUP_gc;
77
78
  SPIC.INTCTRL = SPI_INTLVL_OFF_gc;
79
  SPIC.DATA = 0;
80
  SPIC.CTRL = (SPI_PRESCALER_DIV128_gc | SPI_INTLVL_OFF_gc | SPI_MODE_0_gc | SPI_MASTER_bm | SPI_ENABLE_bm);
81
82
  FLASH_ON;
83
  AT45DB_SELECT;
84
    
85
  //AT45DB161 busy?  
86
  do
87
  {
88
    SPIC.DATA = 0xD7;
89
    while(!(SPIC.STATUS & SPI_IF_bm));
90
  }while (!SPIC.DATA);
91
}
92
93
94
95
96
int main(void)
97
{
98
  init();
99
  
100
  //if reached only if SPI working!
101
  while(1)
102
  {
103
    _delay_ms(1000);
104
    PORTD.OUTTGL = 0xFF;
105
  }
106
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Aus den Errata:
1
Issue:        Automatic port override on PORT C
2
     When Waveform generation is enabled on PORT C Timers, Automatic port override of peripherals other than Tc
3
     may not work even though the pin is not used as waveform output pin.
4
Workaround:
5
     No workaround.

Ist das vielleicht dein Problem?

Ansonsten bliebe natürlich immer noch, den Atmel-Support zu belästigen.

von MOBA 2. (Gast)


Lesenswert?

Hallo,

verste ich das richtig, dass man dann quasi keine Peripherie nutzen 
kann, sobald Timer auf PORTC aktiviert ist?

Was haben die denn da gebaut?!


Aber! Jetzt trotzdem mal eine Sache: Lässt sich denn NUR das SPI 
aktivieren auf PORTC? Also wenn man Timer komplett deaktiviert lässt, 
das geht nämlich auch nicht bei mir.

Hatte schonmal sowas ähnliches mit den ATXMega256D3, da bin ich dann auf 
A1 umgestiegen - schrecklich!

von Felix A. (madifaxle)


Lesenswert?

Wenn das in den Errata stimmt, wäre das ärgerlich. Aber dann müsste es 
ohne die Timer ja gehen.

Eine letzte Frage hätte ich daher trotzdem:
wie sind die Macros

FLASH_ON;
AT45DB_SELECT;

definiert? Vielleicht hat sich genau hier der Fehler eingeschlichen. Der 
Rest vom Code sieht durchaus richtig aus. Das Fehlerbild würde passen, 
wenn der Chip keine Spannung bekommen würde. Dass auch die gemessen 
wurde, konnte ich den Posts nicht entnehmen.

von MOBA 2. (Gast)


Lesenswert?

Hallo,

Spannungen passen alle,  auch als Kontakte.
FLASH_ON schaltet nur den Reset Pin des Flash auf High
Select schaltet den Cs/Ss pin des flash auf low.

von MOBA 2. (Gast)


Lesenswert?

Hallo nochmal,

ich würde versuchen zu pfuschen. Ist es wohl möglich, dass Signal per 
HW-SPI zu senden und per Software-SPI an anderem PIN auszulesen? Dann 
kann die HW und der Chip bleiben, sonst ist es arg viel Mehraufwand für 
mich...

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Auch wenn der Thread schon etwas älter ist: Master SPI über USART geht, 
auch wenn der Timer4 aktiv ist. Das USART muss auf die oberen Pins 5/6/7 
des Ports gemappt sein.

von MOBA 2. (Gast)


Lesenswert?

Ahh okay das ist gut zu wissen. Jetzt wäre nur noch die Frage, ob der 
nen Bootloader unterstützt, denn mein Bootloader der bei den A-Series 
XMEGA geht, findet keine SPM Enable bits.

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.