CY8CKIT-059 PSOC 5LPで波形生成

投稿日 2015/07/19

PSOC 5LPの廉価ボードCY8CKIT-059で遊んでいます。


今回はトランジスタ技術2013年12月号の記事「高速DMA転送とD-Aコンバータを使った任意波形の生成」を参考にして再現してみました。


この記事では三角波を生成していますが、今回はそれに加え正弦波も生成させてみました。

CY8CKIT-059_WAVE_1.jpg

波形生成のコンポーネントと配線


使用するコンポーネントは、


Clock 1MHz

DMA Direct Memory Access SRAM->VDAC8

VDAC8 電圧出力8ビットDAコンバータ 1.02V Strobe(External) High Speed

Opamp 出力バッファ

Pin 波形信号出力用 P3[6]

シールバッテリ簡易充電回路

CY8CKIT-059_WAVE_2.jpg

生成した12.5KHzの正弦波

1.02Vpp


波形生成の原理は、メモリ(配列)に生成する波形のデータを予め計算で求めセットしておき、それを所定の間隔(今回は1uS)でDAコンバータに送るだけです。


配列の内容(つまりSRAMの内容)をDMA経由でDAコンバータに送り、アナログ信号に変換します。


DMAは1MHzのクロックでトリガがかかるので、1uS毎にDAコンバータに変換を要求します。


VDAC8は電圧レンジ 0 - 1.020Vで使います。この場合精度は4mV/bitとなり、変換スピードは1Mspsです。ですからこれ以上クロックの速度は上げられません。


DMAはメモリ->ペリフェラル転送モードで使います。メモリは波形データを入れた配列です。配列には波形の1周期分のデータを入れておきます。要素数は任意ですが、正弦波の生成は80ポイントとしました。1us/ポイントなので1周期80uSの正弦波です。つまり周波数は1/80us = 12.5KHzです。


DMAの設定は面倒なのでDMA Wizardを使います。PSoC CreatorのToolメニューから呼び出せます。DMA WizardでSourceをSRAM, DestinationをVDAC8_1にします。Length(配列の長さ)はsizeof(配列名)で与えます。Sourceは配列名で与えます。設定は簡単です。DMA関連部分のCコードが表示されるので、Main.cにコピペすればOKです。DMA Wizardが出力したソースコードはDMA_Initialize()にそのまま放り込んであります。(main.cの青い部分)


正弦波のデータは計算で求めておきます。エクセルで計算するのが便利です。計算はエクセルのsin()関数に角度をラジアンで渡してやるだけです。


だたしDAコンバータが8ビットなので0から255(2**8)の範囲に収まるようにします。0が128です。

 

1周期80ポイントとしたので、1データ当たり4.5度となります。(360 / 80 = 4.5)

 

SIN(RADIANS(角度0 - 355.5度 4.5ステップ)) * 127 + 128

 


トランジスタ技術の記事で生成している三角波は、triangle_wave[] という配列です。要素数は30まので1/30us = 33.333KHzとなります。(Clockが1MHzの場合)


正弦波のデータはsin_wave[]という配列です。こちらは要素数80です。1/80us = 12.5KHzとなります。


三角波か正弦波かはDMAの設定部分で決まります。下のmain.cでは三角波のコードはコメントアウトしてあります。(赤の部分)

 

波形生成はDMAでDAコンバータにデータを転送しているので、初期設定以外にはCPUは関与していません。(設定後for(;;)ループ)


以下はmain.cです。

(トランジスタ技術の記事に追加した部分は緑色で表示)


/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include <device.h>


uint8 triangle_wave[] = {20, 30, 40, 50, 60, 70, 80, 90,
    100, 110, 120, 130, 140, 150, 160,
    170, 160, 150, 140, 130, 120, 110,
    100, 90, 80, 70, 60, 50, 40, 30,};


uint8 sin_wave[] = {
    128,138,148,158,167,177,186,194,203,210, 
    218,225,231,236,241,245,249,251,253,255, 
    255,255,253,251,249,245,241,236,231,225, 
    218,210,203,194,186,177,167,158,148,138, 
    128,118,108,98,89,79,70,62,53,46, 
    38,31,25,20,15,11,7,5,3,1, 
    1,1,3,5,7,11,15,20,25,31, 
    38,46,53,62,70,79,89,98,108,118};

 

void DMA_Initialize()
{
    /* Variable declarations for DMA_1 */
    /* Move these variable declarations to the top of the function */
    uint8 DMA_1_Chan;
    uint8 DMA_1_TD[1];

    /* DMA Configuration for DMA_1 */
    #define DMA_1_BYTES_PER_BURST 1
    #define DMA_1_REQUEST_PER_BURST 1
    #define DMA_1_SRC_BASE (CYDEV_SRAM_BASE)
    #define DMA_1_DST_BASE (CYDEV_PERIPH_BASE)
    DMA_1_Chan = DMA_1_DmaInitialize(DMA_1_BYTES_PER_BURST, DMA_1_REQUEST_PER_BURST, 
        HI16(DMA_1_SRC_BASE), HI16(DMA_1_DST_BASE));
    DMA_1_TD[0] = CyDmaTdAllocate();
    //CyDmaTdSetConfiguration(DMA_1_TD[0], sizeof(triangle_wave), DMA_INVALID_TD, TD_INC_SRC_ADR);
    //CyDmaTdSetAddress(DMA_1_TD[0], LO16((uint32)triangle_wave), LO16((uint32)VDAC8_1_Data_PTR));
    CyDmaTdSetConfiguration(DMA_1_TD[0], sizeof(sin_wave), DMA_INVALID_TD, TD_INC_SRC_ADR);
    CyDmaTdSetAddress(DMA_1_TD[0], LO16((uint32)sin_wave), LO16((uint32)VDAC8_1_Data_PTR));
    CyDmaChSetInitialTd(DMA_1_Chan, DMA_1_TD[0]);
    CyDmaChEnable(DMA_1_Chan, 1);
}


void main()
{
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    VDAC8_1_Start();
    Opamp_1_Start();
    
    DMA_Initialize();
    
    /* CyGlobalIntEnable; */ /* Uncomment this line to enable global interrupts. */
    for(;;)
    {
        /* Place your application code here. */
    }
}

/* [] END OF FILE */

 

 

 


(JF1VRR)