Hallo Freunde,
ich hab wieder einmal eine Frage an euch Spezialisten bezüglich STM32
µController.
Vorweg kurze Information was mich machen will:
Ich will Infrarot-Signale (38kHz Bursts) via PWM über einen Pin
ausgeben. Dazu gibt es ein Array, nennen wir es BitArray, welches als
Bitmuster die Burst-zu-Pause Übertragung enthält.
Z.B.: 110010 gibt aus: Burst-Burst-Pause-Pause-Burst-Pause
Ein Burst ist dabei immer 20 PWM-Perioden
Ich könnte das jetzt konventionell ohne DMA implementieren mittels
TIM_RepetitionCounter. Jedoch muss ich da nach jedem Burst (oder jeder
Pause) in der Interrupt Routine, das BitArray überprüfen, die PWM
sperren oder nicht und dann den Timer neu starten. Ist im Prinzip
möglich, aber noch lieber wäre mir, wenn der Prozessor nur Resourcen
beim Start und beim Ende verbraucht, nicht während der Übertragung.
Daher meine Überlegung: DMA
Ich hab mir das Ganze so vorgestellt: Es gibt bei dem Timern ja das CCER
Register, mit welches ich den PWM Ausgang sperren kann. Genau auf dieses
Register möchte ich via DMA schreiben. Meiner Meinung ist das ein
MemoryToPeripheral Prozess, der nach jedem Timer TIM_IT_Update den DMA
ausführen soll.
Vorweg: Ist dies so Möglich wie ich mir das Vorstelle?
Ich habe schon einen Codeauszug, doch irgendwie bleibt der DMA Data
Counter immer auf der selben Stelle und erhöht bzw. erniedrigt sich
nicht.
Initialisierung:
1 | // DMA for IR command sending LED
|
2 | DMA_DeInit(CMD_LED_DMA_STREAM);
|
3 | DMA_InitStructure.DMA_Channel = CMD_LED_DMA_CHANNEL;
|
4 | DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) TIM1->CCER;;
|
5 | DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) g_bitarray;
|
6 | DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
7 | DMA_InitStructure.DMA_BufferSize = 16;
|
8 | DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
9 | DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
10 | DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
|
11 | DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
12 |
|
13 | DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // Kein Autoreload
|
14 | DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
15 | DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
16 | DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
17 | DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
18 | DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
19 | DMA_Init(CMD_LED_DMA_STREAM, &DMA_InitStructure);
|
20 |
|
21 | // Interrupt. Calles if DMA sequence is finished
|
22 | DMA_ITConfig(CMD_LED_DMA_STREAM, DMA_IT_TC, ENABLE);
|
23 |
|
24 | NVIC_InitStructure.NVIC_IRQChannel = CMD_LED_DMA_IRQ;
|
25 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
26 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
|
27 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
28 | NVIC_Init(&NVIC_InitStructure);
|
DMA IR Sending Start:
1 | DMA_MemoryTargetConfig(CMD_LED_DMA_STREAM, (uint32_t) g_bitarray, DMA_Memory_0);
|
2 | DMA_SetCurrDataCounter(CMD_LED_DMA_STREAM, 16);
|
3 |
|
4 |
|
5 | DMA_Cmd(CMD_LED_DMA_STREAM, ENABLE);
|
6 |
|
7 | // TIMUpdate DMA Request enable.
|
8 | TIM_DMACmd(IR_TIMER, TIM_IT_Update, ENABLE);
|
9 |
|
10 | // Enalbe PWM Timer.
|
11 | TIM_CCxCmd(IR_TIMER, PROXIMITY_TIMER_CHANNEL, TIM_CCx_Enable);
|
12 | TIM_CtrlPWMOutputs(IR_TIMER, ENABLE);
|
13 | TIM_Cmd(IR_TIMER, ENABLE);
|
Der Code ist noch nicht fertig, mir ist kalr, dass ich so das ganze CCER
Register überschreibe und nicht das benötigte Bit. Zur Zeit ist mir erst
mal Wichtig ob mein Vorhaben überhaupt möglich ist.
Hoffe Ihr könnt mir helfen.
lg
Manuel