STM32 TIM17とDMA Channel1でDACを駆動する [電子工作]
STM32でDACをDMAで駆動する場合、通常はTIM6/7の出力をトリガイベントとしてDACに繋げるかと思います(リファレンスにもそう書いてあるし)。
が、
STM32F051ではDAC, USARTx_RX, SPI1_TX, I2Cx_RXでChannel3を取り合っているので
あまりChannel3を使いたくない気がします。
USARTのRXはDMA使わなくてもいーんじゃね?というとそのような気もしますが、
Channel1がなんとなくヒマそうなので、Channel1にリクエストできるTIM17を使ってやってみます。
CubeMXでの設定
TIM17
Prescaler (PSC - 16 bits value) : 0
Counter Mode : Up
Counter Period (AutoReload Register - 16 bits value ) : 3000-1 * (48MHz / 16KHz = 3000)
Internal Clock Division (CKD) : No Division
Repetition Counter (RCR - 8 bits value) : 0
auto-reload preload : Disable
DMA request : TIM17_CH1/UP
Stream : DMA1_Channel1
Direction : Memory To Peripheral
Priority : Low
TIM17_CH1/UP: DMA1_Channel1 DMA request Settings:
Mode: Circular *
Peripheral Increment: Disable
Memory Increment: Enable *
Peripheral Data Width: Half Word
Memory Data Width: Half Word
DAC Out1 Settings:
Output Buffer : Enable
Trigger : None
DACのTriggerをNoneにしておくのがミソです。
Code Generateして、main.cに以下を追記
Private Variables (16KHzサンプリングでの440Hzのサイン波)
デバイス初期化の後で
(DMAをCircularモードにしているので、止めない限り出力しっぱなし)
HAL_TIM_Base_Start_DMA()は、なぜかDMAの転送先をタイマのARRレジスタにしてしまうので、
参考にして開始処理を書いてみました。
が、
STM32F051ではDAC, USARTx_RX, SPI1_TX, I2Cx_RXでChannel3を取り合っているので
あまりChannel3を使いたくない気がします。
USARTのRXはDMA使わなくてもいーんじゃね?というとそのような気もしますが、
Channel1がなんとなくヒマそうなので、Channel1にリクエストできるTIM17を使ってやってみます。
CubeMXでの設定
TIM17
Prescaler (PSC - 16 bits value) : 0
Counter Mode : Up
Counter Period (AutoReload Register - 16 bits value ) : 3000-1 * (48MHz / 16KHz = 3000)
Internal Clock Division (CKD) : No Division
Repetition Counter (RCR - 8 bits value) : 0
auto-reload preload : Disable
DMA request : TIM17_CH1/UP
Stream : DMA1_Channel1
Direction : Memory To Peripheral
Priority : Low
TIM17_CH1/UP: DMA1_Channel1 DMA request Settings:
Mode: Circular *
Peripheral Increment: Disable
Memory Increment: Enable *
Peripheral Data Width: Half Word
Memory Data Width: Half Word
DAC Out1 Settings:
Output Buffer : Enable
Trigger : None
DACのTriggerをNoneにしておくのがミソです。
Code Generateして、main.cに以下を追記
Private Variables (16KHzサンプリングでの440Hzのサイン波)
const uint16_t sine_440[] = { 0x003, 0x022, 0x07E, 0x115, 0x1E1, 0x2DD, 0x401, 0x545, 0x69D, 0x800, 0x964, 0xABC, 0xC00, 0xD24, 0xE20, 0xEEC, 0xF83, 0xFDF, 0xFFF, 0xFDF, 0xF83, 0xEEC, 0xE20, 0xD24, 0xBFF, 0xABC, 0x964, 0x801, 0x69D, 0x545, 0x402, 0x2DD, 0x1E1, 0x115, 0x07E, 0x022 };
デバイス初期化の後で
(DMAをCircularモードにしているので、止めない限り出力しっぱなし)
/* Enable DAC */ HAL_DAC_Start(&hdac1, DAC_CHANNEL_1); /* Enable the DMA channel */ HAL_DMA_Start_IT(htim17.hdma[TIM_DMA_ID_UPDATE], (uint32_t)sine_440, (uint32_t)&(hdac1.Instance->DHR12R1), 36); /* Enable the TIM Update DMA request */ __HAL_TIM_ENABLE_DMA(&htim17, TIM_DMA_UPDATE); /* Enable the Peripheral (Start Timer) */ __HAL_TIM_ENABLE(&htim17);
HAL_TIM_Base_Start_DMA()は、なぜかDMAの転送先をタイマのARRレジスタにしてしまうので、
参考にして開始処理を書いてみました。
コメント 0