2014年6月18日水曜日

TIMソースのタイミングでDMA割り込み

タイマで生成したタイミングでDMA転送

今回はTIM3の更新でDMAトリガです

まずTIM3の初期化

    TIM_InitStructure.TIM_Period = 1500 - 1;
    TIM_InitStructure.TIM_Prescaler = 0;
    TIM_InitStructure.TIM_ClockDivision = 0;
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_InitStructure);
    TIM_Cmd(TIM3, ENABLE);

今回は72MHzで48kHzを作りたいのでカウンタは1500 分周は無し
これで72000000/1500/1=48000Hzが作れる

なお、タイマ割り込みは使わず、ただの分周器として使いたいだけなのでNVICの初期化は不要

次にDMAの初期化

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(DAC_BASE + 0x00000008 + 0x00000004);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(&DAC_Buff[0]);
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = 480;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel3, &DMA_InitStructure);
        
    DMA_Cmd(DMA1_Channel3, ENABLE);
    TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE);

DMAの転送元はuint16_t配列のDAC_Buffを 転送先はDMA1の12bit左詰めレジスタを指定
(DACはDAC1->ODRみたいに指定できないのが面倒)

基本的に普通の初期化方法と同じ
今回はぐるぐるとバッファの中身を出力させたいのでCircularモード
そしてM2MはDisableに

DMAの転送トリガはDMA_M2M or ペリフェラルトリガなので、M2MがEnaの場合はどんどん出力されていく

そしてDMA_Cmdの後にTIM_DMACmdでタイマとタイミングを指定する

タイマとトリガとDMAチャネルの組み合わせは決まっているので注意
組み合わせはRM0008のDMAの説明に書いてある


例えばSPI1はDMA1_ch2がRX DMA1_ch3がTXになっているが、TIM2更新もDMA1_ch2に割り当てられている
予めうまく組み合わせを考えておかないと、修正で面倒なことになる


TIMでタイミングを作ってDMA転送は結構簡単に使える感じ
ただ今回はDACとかいろいろの組み合わせで正常動作していないように見えてしまったためにややこしいことになった。。

注意点として、DMAとTIMを組み合わせてもあまり高速な転送はできない せいぜい6MHzくらい

DACはTIMでいいけど、ADCは注意が必要
ADCを使う場合はADCのトリガをTIMにして、DMAのトリガをADCにする
ちょっとフクザツだけどパズルみたいで面白い
ちゃんと作れれば

0 件のコメント:

コメントを投稿