30 DACで三角波とノイズを発生させる (割り込みなし)
DACで三角波を発生させてみます.それと、ノイズも発生できるのでやってみます.
STM32-DISCOVERYには12bitのDACが2チャンネル内蔵されています.
DACの出力pinはどこでしょうか?
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00251732.pdf
↑この資料のTable.4に書かれています.
PA4 20pin DAC1_OUT
PA5 21pin DAC2_OUT
以下のprogramはつぎの三角波出力を得られます.
DAC1_OUT 11.5Hz 750mVpp (0mV~750mV)
DAC2_OUT 45Hz 1500mVpp (0mV~1500mV)
programをみるとわかりますが、このDACコントロールはタイマ割り込みでDAC値をupdateするような作業はしてません.
DACのhardwareで自動的にDAC値をupdateさせています.
block diagramは下図のように考えればあたらずとも遠からずです.
ミソはDACのサンプリング周波数をTIM2で作り、それを内部信号のTRGOというラインに乗せてDACへ流入させます.
DACデータはclock毎に±1されて12bitの三角波データになります.ノイズのときはACCのところがランダムになるんでしょう.
いじれるパラメータは①振幅です.振幅が決まると自動的に②周波数が決まってしまいます.
③ボトム電圧を任意に設定できます.
サンプルプログラム
project folderをページ末尾からDLできます.eclipseへの組み込み方はこちらを参照してください.
main.c
#include "stm32f10x.h" CPUのハードウエアに関連する各種設定をしています
GPIO_InitTypeDef GPIO_InitStructure; GPIOの設定に必要な構造体
DAC_InitTypeDef DAC_InitStructure; DACの設定に必要な構造体
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; タイマの設定に必要な構造体
int main(void)
{
↓clock設定は一番先にやることをオススメします.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); APB2にぶら下がったGPIOAにclock供給します
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); APB1にぶらさがったDACにclock供給します
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); APB1にぶらさがったTIM2にclock供給します
↓GPIOの設定
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; bit4,bit5を指定
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; ここは要注意です.DACはアナログ出力ですがここではアナログ入力に設定します.
GPIO_MODEの選択肢はこれだけあります.この中のAINにするということです.
GPIO_Mode_AIN アナログ入力
GPIO_Mode_IN_FLOATING floating入力(pull-upもpull-downもしない)
GPIO_Mode_IPD pull-down入力
GPIO_Mode_IPU pull-up入力
GPIO_Mode_Out_OD open-drain出力
GPIO_Mode_Out_PP push-pull出力 (フツーの出力)
GPIO_Mode_AF_OD Altanate Function open-drain出力 (peripheralのIOピンとしてアサイン)
GPIO_Mode_AF_PP Altanate Function push-pull (peripheralのIOピンとしてアサイン)
GPIO_Init(GPIOA, &GPIO_InitStructure); 構造体をGPIOAに書きます
↓タイマの設定
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); タイマ設定構造体を初期化
初期化の具体的な値はこうです.
TIM_TimeBaseInitStruct->TIM_Period = 0xFFFF; カウンタmax
TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000; プリスケ÷1
TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1; 外部信号サンプルclock=タイマclock
TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up; カウントアップ
TIM_TimeBaseInitStruct->TIM_RepetitionCounter = 0x0000; 間引きなし
TIM_TimeBaseStructure.TIM_Period = 0xF; 16カウント
TIM_TimeBaseStructure.TIM_Prescaler = 0xF; プリスケ÷16
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 構造体をタイマへ書く
この設定だと、タイマクロック24MHzを256分周することになると計算されます.つまり93.75kHz
↓これがDACを使う上でのTIM2設定のミソです.TIM2のTRGOという内部出力端子へ出力する信号を選択しています.
TIM2 TRGOが、DACのトリガ信号として利用されます.つまり、サンプル周波数93.75kHzでDACが動くことになります.
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
第二引数の選択肢はこうなっています.ここではTIM_TRGOSource_Updateを採用したのでカウンタがmaxに達する毎、すなわち93.75kHzがTRGOに出力されます.
For all TIMx
TIM_TRGOSource_Reset: The UG bit in the TIM_EGR register is used as the trigger output (TRGO).
TIM_TRGOSource_Enable: The Counter Enable CEN is used as the trigger output (TRGO).
TIM_TRGOSource_Update: The update event is selected as the trigger output (TRGO).
For all TIMx except TIM6 and TIM7
TIM_TRGOSource_OC1: The trigger output sends a positive pulse when the CC1IF flag is to be set, as soon as a capture or compare match occurs (TRGO).
TIM_TRGOSource_OC1Ref: OC1REF signal is used as the trigger output (TRGO).
TIM_TRGOSource_OC2Ref: OC2REF signal is used as the trigger output (TRGO).
TIM_TRGOSource_OC3Ref: OC3REF signal is used as the trigger output (TRGO).
TIM_TRGOSource_OC4Ref: OC4REF signal is used as the trigger output (TRGO).
↓DACチャネル1の初期設定
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
TIM2 TRGOをDACのトリガとして採用します.DACのトリガとはつまりサンプリング周波数のことです.
このパラメータには次の選択肢があります.
DAC_Trigger_T2_TRGO
DAC_Trigger_T3_TRGO
DAC_Trigger_T4_TRGO
DAC_Trigger_T5_TRGO
DAC_Trigger_T6_TRGO
DAC_Trigger_T7_TRGO
DAC_Trigger_T8_TRGO
DAC_Trigger_T15_TRGO
DAC_Trigger_Ext_IT9 勉強不足で詳細不明
DAC_Trigger_Software 勉強不足で詳細不明
DAC_Trigger_None 勉強不足で詳細不明
↓発生させる信号の設定です.
①//DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
②//DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Noise;
③//DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bits10_0;
④DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
⑤DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
①コメントアウトしてありますが、これを復活させると、何も信号を発生しなくなります.
②③コメントあうとしてありますが、これを復活させるとノイズを発生します.
③はノイズの振幅を決めます. Bits11_0がフルスケールつまり3Vのノイズを発生させます.
DAC_LFSRUnmask_Bit0
DAC_LFSRUnmask_Bits1_0
DAC_LFSRUnmask_Bits2_0
DAC_LFSRUnmask_Bits3_0
DAC_LFSRUnmask_Bits4_0
DAC_LFSRUnmask_Bits5_0
DAC_LFSRUnmask_Bits6_0
DAC_LFSRUnmask_Bits7_0
DAC_LFSRUnmask_Bits8_0
DAC_LFSRUnmask_Bits9_0
DAC_LFSRUnmask_Bits10_0
DAC_LFSRUnmask_Bits11_0 約3Vpp
④⑤DACに三角波を自動発生させます.このパラメータには次の選択肢があります.
⑤は三角波の振幅を決めます.このDACは12bitですからフルスケール4095で3Vです.
DAC_TriangleAmplitude_1 約1.5mVpp
DAC_TriangleAmplitude_3 約3mVpp
DAC_TriangleAmplitude_7 約6mVpp
DAC_TriangleAmplitude_15 約12mVpp
DAC_TriangleAmplitude_31 約23mVpp
DAC_TriangleAmplitude_63 約45mVpp
DAC_TriangleAmplitude_127 約90mVpp
DAC_TriangleAmplitude_255 約180mVpp
DAC_TriangleAmplitude_511 約375mVpp
DAC_TriangleAmplitude_1023 約750mVpp
DAC_TriangleAmplitude_2047 約1.5Vpp
DAC_TriangleAmplitude_4095 約3Vpp
ここで振幅を決めたと同時に周波数も自動的に決まってしまいます.
1)DACトリガ周波数は93.75kHzとTIM2で決めました
2)三角波発生回路はDACトリガ毎に12bit出力を±1します
3)したがって、DAC_TriangleAmplitude_4095に設定したならば、登りに4095回要し、下りに4095回要するのですから、三角波の周波数は、93.75kHz÷8192=11.5Hz と計算されます.
↓DAC出力バッファを強くしたいならEnable、弱くても良いのならDisable
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
選択肢はこちら
DAC_OutputBuffer_Disable
DAC_OutputBuffer_Enable
DAC_Init(DAC_Channel_1, &DAC_InitStructure); 構造体をDACへ書く
↓DACチャネル2の初期設定
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1023;
ここでは振幅を1023に設定しています.
電圧は 3V x 1023 ÷ 4095 = 750mVpp
周波数は、93.75kHz ÷ 2048 = 45.8Hz
DAC_Init(DAC_Channel_2, &DAC_InitStructure); 構造体をDACへ書く
↓DAC1をenable.自動的にPA4がDAC出力にアサインされる.
DAC_Cmd(DAC_Channel_1, ENABLE);
↓DAC2をenable.自動的にPA5がDAC出力にアサインされる.
DAC_Cmd(DAC_Channel_2, ENABLE);
↓三角波の振幅は上で決めましたが、DC電圧のボトムをこれで決めます.
計算式は、 ボトム電圧 = 3000mV x N ÷ 4096
下記の設定だと、200mVぐらいになります.
DAC_SetDualChannelData(DAC_Align_12b_R, 0x000, 0x000);
第2引数=DAC2、第3引数=DAC1です.2と1の順番が逆なので注意してください!!.
有効な数値範囲は0~FFF.ただし、4095を超えた波形は下から折り返してきますのでご注意ください.
TIM_Cmd(TIM2, ENABLE); TIM2を動かします
while (1) { }
}
#ifdef USE_FULL_ASSERT debug用なのでとりあえず無視
void assert_failed(uint8_t* file, uint32_t line){ while(1) {} }
#endif