Nucleo-F303REを買ってみました。とりあえず動作確認用にDACで正弦波を出してみます。
今回はLチカのちょっと高度版、くらいの位置づけなので、割り込みでデータを更新して、というような事は扱いません。固定波形をひたすら出し続けるだけです。
C++のコードなので、C++が動く環境で動かしてください(あるいは、使用したい言語に書き直してください)。
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_DAC1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_TIM3_CLK_ENABLE();
GPIO_InitTypeDef gpio_dac1_1 = {
.Pin = GPIO_PIN_4,
.Mode = GPIO_MODE_ANALOG,
};
HAL_GPIO_Init(GPIOA, &gpio_dac1_1);
DAC_HandleTypeDef hdac = {
.Instance = DAC1,
};
HAL_DAC_Init(&hdac);
DAC_ChannelConfTypeDef dac_conf = {
.DAC_Trigger = DAC_TRIGGER_T3_TRGO,
.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE,
};
HAL_DAC_ConfigChannel(&hdac, &dac_conf, DAC_CHANNEL_1);
TIM_HandleTypeDef htim = {
.Instance = TIM3,
.Init = TIM_Base_InitTypeDef{
.Prescaler = 0,
.CounterMode = TIM_COUNTERMODE_UP,
.Period = 72 - 1,
},
};
HAL_TIM_Base_Init(&htim);
TIM_MasterConfigTypeDef tim_master = {
.MasterOutputTrigger = TIM_TRGO_UPDATE,
};
HAL_TIMEx_MasterConfigSynchronization(&htim, &tim_master);
DMA_HandleTypeDef hdma_dac1_1 = {
.Instance = DMA1_Channel3,
.Init = DMA_InitTypeDef{
.Direction = DMA_MEMORY_TO_PERIPH,
.PeriphInc = DMA_PINC_DISABLE,
.MemInc = DMA_MINC_ENABLE,
.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD,
.MemDataAlignment = DMA_MDATAALIGN_HALFWORD,
.Mode = DMA_CIRCULAR,
.Priority = DMA_PRIORITY_MEDIUM,
},
};
HAL_DMA_Init(&hdma_dac1_1);
hdac.DMA_Handle1 = &hdma_dac1_1;
constexpr uint16_t N = 1000;
static uint16_t buff[N] = {};
for (uint16_t i = 0; i < N; i++)
{
buff[i] = static_cast<uint16_t>(
sinf(i * 2 * 3.1416f / N) * 1024 + 2048);
}
__HAL_RCC_SYSCFG_CLK_ENABLE();
SYSCFG->CFGR1 |= SYSCFG_CFGR1_DAC1_TRIG1_RMP | SYSCFG_CFGR1_TIM6DAC1Ch1_DMA_RMP;
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, reinterpret_cast<uint32_t *>(buff), N, DAC_ALIGN_12B_R);
HAL_TIM_Base_Start(&htim);
特に面倒な点はありません。F4等と同じような手順で使えます。
1点、SYSCFGの設定に気がづかず、ハマりました。リファレンスマニュアルちゃんと読めって話ですね。。。
DAC1とDMAの組み合わせ、DAC1とTIM3の組み合わせの際は、それぞれSYSCFGの設定が必要です。
72MHzをタイマで72分の1にして、1周期1000ポイントなので、1kHzの正弦波となります。
実際には1.00324kHzとカウントされていますが、これはNucleoにはHSEが未実装のため、HSIを使っていることによると思われます。データシートによるとHSIは25℃時で1%のエラーらしいので、0.3%程度の誤差は仕様の範囲内です。