DACでsine波を発生させるオーソドックスな方法は、メモリに1波分のデータを格納しておき、それをDACに注ぎ込むやりかたでしょう.
ここでは、メモリに32点からなるsine波データを格納します.
そのデータをDACへ一定間隔で転送してゆくことで任意周波数のsine波を発生させるわけですが、ここでのキモの機能は、DMAを使うことです.
DMAが、RAM上の32ワードデータをDACへ転送してくれますので、CPUが忙しくお世話をする手間を省けます.
わたしはDMAを使ったことはなかったので今回初めて使いましたが、便利なもんですね.
サンプルプログラムの総合ブロック
●内部clockは24MHzです.
●DACのsampling周波数(fs)はTIM2が生成します.DACのspecからfs=1MHzが上限です.sine1波が32点で成るので31.25kHzがsine波の上限周波数となります.
●ブルーの回路がDMA関連回路です.DMAは、RAMへ格納した32個のデータをcyclicにDACへ転送し続けます.
●TIM3はLEDを5Hzでチカチカさせます.
●UARTはPCと通信します.TIM2の設定を変更してfsを変更することで、sine波周波数を50kHz~0.1Hzぐらいまで設定変更できます.
DACの出力pinはどこでしょうか?
STM32-DISCOVERYのCPUには12bitのDACが2チャンネル内蔵されています.
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00251732.pdf
↑この資料のTable.4にピンアサインが書かれています.
PA4 20pin DAC1_OUT
PA5 21pin DAC2_OUT
DACに出力するデータをどのレジスタに書けばいいの?
そのためのレジスタがあります.しかもたくさんある.実際にはレジスタを直接叩くのではなく、ライブラリ関数をcallしますので不要な知識ですけど、、、、、
●DAC_DHR12R1[11:0] DAC1 12bitがデータ
●DAC_DHR12L1[15:0] DAC1 左詰の[15:4]が12bitデータ
●DAC_DHR8R1[7:0] DAC1 8bitがデータ →フルスケール電圧は同じで分解能が256になる
●DAC_DHR12R211:0] DAC2 12bitがデータ
●DAC_DHR12L2[15:0] DAC2 左詰の[15:4]が12bitデータ
●DAC_DHR8R2[7:0] DAC2 8bitがデータ →フルスケール電圧は同じで分解能が256になる
●DAC_DHR12RD[32:0] [27:16]がDAC2の12bitデータ [11:0]がDAC1の12bitデータ
●DAC_DHR12LD[32:0] [31:20]がDAC2の12bitデータ [15:4]がDAC1の12bitデータ
●DAC_DHR8RD[15:0] [15:8]がDAC2の8bitデータ [7:0]がDAC1の8bitデータ
●DAC_DOR1[11:0] DAC1 12bitデータ ※
●DAC_DOR2[11:0] DAC2 12bitデータ ※
なんでこんなに分かれているのかというと、それはたぶんDMAとの親和性のためだと思います.メモリに積んだデータのアサインにこのような柔軟性を与えておくとDMAが幸福になるんでしょう.
今回、DMAが転送する先のレジスタはDAC_DHR12RDです.
DMAの基礎知識
●DMA1にはchannel1~channel7の7つのDMAチャンネルがある
● メモリ → メモリ
peripheral → メモリ
メモリ → peripheral
peropheral → peripheral
●DMAがぶつかったときのために4段階の優先度設定ができる
●データ幅は8bit,16bit,32bitのいずれか.データ幅はsourceとdestinationが別々に設定できる
●メモリアドレスのA~Bまでを転送しておしまいのモードと、A~Bをグルグル回るモードがある
●転送量は最大65536個
●割り込みは3種類、転送完了/転送失敗/半分のところ
●channel1~channel7が受信できるDMA requestには下表の制限がある.
このサンプルプログラムでは、DACがfsでデータを受け取りたいので、DACがDMAにデータをよこせとrequestします.
DACの都合でDMAが動くというわけです.
ゆえに、下表のDAC_Channel1またはDAC_Channel2がDACの発するrequestであり、それらを受信できるDMA1はchannel3およびchannel4だというのが下表が言いたいことです.
他のchannelを見ると、
ADCをDMAするにはchannel1をつかえと言ってます.
USARTの送受信をDMAで行うこともできるようです.
サンプルプログラムでどんなことをさせるか?
sine波発生器をつくります.周波数をPCのterminal softで指定します.振幅は3Vpp固定です.
PC上のterminal softを起動し、115200bps+parityなし+8bit+stop1bit+フロー制御なしで接続します.
オシロで観測すると30kHzぐらいのsine/cos波が出てるはずです.
PA4 sine波
PA5 cos波
terminal softからenterを打ちますと、つぎのメッセージが帰ってきます.
command:
command error
f 10000 : frequency 10kHz (max 50kHz)
このメッセージが言うところは、f ほにゃらら というコマンドを打つと、sine波の周波数を設定できるということです.
やってみましょう.
f 5333 5333Hzにしろ
command: (0)f/ (1)5333/ 受信したコマンドが、"f" と "5333" の2単語からなるというメッセージ
requred freq. 5333.000000 Hz ---> set freq. 5357.000000 Hz 計算の結果5333Hzではなく5357Hzになったというメッセージ
f 10000 : frequency 10kHz (max 50kHz)
周波数の上限は50kHzです.これはDACのspecを超えてますけど、使えてしまいます.
50kHz以上にするのはTIM2の分解能的につらいかもしれませんのでgive-upということで.
周波数の下限は試してませんけど、0.1Hzは正常に発生できました.
アンチエリアシングフィルタを挿入せずに、sine波1周期を32分割と荒いので波形はそれなりにカクカクとして高調波成分を含んでしまっています.
32分周ではなく、256分周とかにすれば信号品質を改善することは可能ですが、やってません.orz
UARTをUSBにつなぐ回路は?
UARTをUSBに変換する回路を使ってUSB経由でPCに接続します.
つかうのは秋月電子で売られているこの回路です. http://akizukidenshi.com/catalog/g/gK-01977/
STM32-DISCOVERYとの実体配線図はこのようになります.
ここではUSART3 defaultを使うので、下辺のPB10(TX),PB11(RX)から配線を取り出します.
他のUSARTを使いたい場合は下図の各所から配線を取り出します.
terminal softは別途用意してPCにインストールしてください.
XPとかの古いwindowsではhyper-terminalというのが最初からインストールされていましたが、vista以降は無くなってしまったと思います.
サンプルプログラムの解説
サンプルプログラムはこのページの末尾からDLできます.projectの組み込み方法はこちらを参照してください.
重要な注意: 当初compile errorが出ました.エラー回避のために、syscalls.cというファイルを追加してあります.これはyagartからDLしたファイルですが、これがないとcompileできません.トラブルシュートの詳細はこちらのページを参照してください.
main.c
#include "stdio.h" このC標準関数3兄弟を使おうとするとsyscalls.cが必要になります.詳しくはこちらを参照.
#include "string.h"
#include "stdlib.h"
#include "stm32f10x.h" STM32のhardwareに根ざした設定を多数やってます
#include "usrlib-uart3d.h" UART3を使う自作ライブラリ
#include "usrlib-gpio.h" GPIOを使う自作ライブラリ
↓このdefineは排他的にどちらかを殺してどちらかを生かしてください.なぜか?
上のDMA requestの説明で触れたとおり、DACのrequestを受信できるDMAチャネルはDMA_Channel3もしくはDMA_Channel4だと説明しました.
以下のcodeでは、両方とも動かして試してみるようにしてあります.
#define DMA_CHANNEL3
//#define DMA_CHANNEL4
NVIC_InitTypeDef NVIC_InitStructure; 割込優先度コントローラNVIC設定用構造体
GPIO_InitTypeDef GPIO_InitStructure; GPIO設定用構造体
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; タイマ設定用構造体
DAC_InitTypeDef DAC_InitStructure; DAC設定用構造体
DMA_InitTypeDef DMA_InitStructure; DMA設定用構造体
char UARTbuf[100]; UART転送バッファ
↓sine波の32分割テーブル DACが12bitのストレートバイナリなので、0~4095のデータです
const uint16_t Sine12bit[32] = {
2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
↓cosine波の32分割テーブル
const uint16_t Cos12bit[32] = {
4095, 4056,
3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647,
2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056 };
uint32_t DualSine12bit[32]; のちほど登場します.DACへDMA転送するのはこのデータです
void Menu(void); UARTのメニュー処理ルーチン
int main(void) メインルーチン始まり
{
int x;
↓つかうperipheralのclockをenableしています.
clock周波数を変更するようなことは特にしてないので24MHzが供給されます.
RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1, ENABLE); DMAはAHBにぶら下がっています
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // DAC sampling frequency
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // LED flash timer
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // DAC output port (PA4/PA5)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // USART1 TX/RX (default)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // LED(PC8,PC9), TAMPER(PC13)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
第一引数の選択肢は下記です.
RCC_AHBPeriphClockCmd()
RCC_AHBPeriph_DMA1, RCC_AHBPeriph_SRAM, RCC_AHBPeriph_FLITF, RCC_AHBPeriph_CRC, RCC_AHBPeriph_SDIO
RCC_APB1PeriphClockCmd()
RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7, RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2, RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC
RCC_APB2PeriphClockCmd()
RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE, RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1, RCC_APB2Periph_USART1, RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17
↓割込優先度コントローラの設定
NVIC割り込みコントローラは4bitの優先度を持っていて、つまり最大で16個の割り込み優先度設定が出来るようです、
割り込み優先度には、PreemptionPriority とSubPriority にカテゴライズされています.
前者が大分類、後者が小分類というような階層になっています.
大分類に3bitを割り当て、小分類に1bitを割り当てるような階層作りができます.
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
それをやるのがこの↑関数です.引数によって、大分類と小分類のbitアサインを決めます.
| PreemptionPriority | SubPriority |
---------------------------------------------------------
NVIC_PriorityGroup_0 | 0 (0bit) | 0-15 (4bit) |
NVIC_PriorityGroup_1 | 0-1 (1bit) | 0-7 (3bit) |
NVIC_PriorityGroup_2 | 0-3 (2bit) | 0-3 (2bit) |
NVIC_PriorityGroup_3 | 0-7 (3bit) | 0-1 (1bit) |
NVIC_PriorityGroup_4 | 0-15(4bit) | 0 (0bit) |
ここでは、TIM3とUSART3の2つの割り込みを使うので NVIC_PriorityGroup_1,2,3,4 どれでもOKです.
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; TIM3割り込み
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 最高優先度
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; UART3割り込み
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 最高優先度
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
UART_Init(); UARTの設定のため自作ライブラリの初期設定をコール
↓LEDチカチカの設定
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; PC8とPC9がLEDのポート.そこを出力に設定する.
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 出力ドライブ能力は最低でよい
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; フツーの出力ポートに設定
GPIO_Init(GPIOC, &GPIO_InitStructure);
↓タイマの設定
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 24000; 24MHz / 24000 / 200 = 5Hz
TIM_TimeBaseStructure.TIM_Prescaler = 200;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); カウンタmaxで割り込み発生
TIM_Cmd(TIM3, ENABLE); TIM3動け
↓DACの出力であるPA4,PA5のport設定.
①GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
②GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
③GPIO_Init(GPIOA, &GPIO_InitStructure);
①PA4,PA5がDAC出力である理由は過去記事を参照のこと.
②DAC出力ですが、digital出力と衝突しないようにアナログ入力portに設定します.これは注意点です.
③構造体をGPIOAに書く
↓TIM2のDACサンプル周期割り込み
①TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
②TIM_TimeBaseStructure.TIM_Period = 23;
③TIM_TimeBaseStructure.TIM_Prescaler = 0;
④TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
⑤TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
⑥TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
⑦TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // fs = 1MHz (max 1MHz)
⑧TIM_Cmd(TIM2, ENABLE);
①構造体を初期化
②③カウンタmax=23、プリスケ=1に設定.結果として1MHzで割り込み発生
④ここではどうでもいいので割愛
⑤カウンタupでつかう
⑥構造体をTIM2に書く
⑦TIM2のカウンタmaxイベントをTRG出力する ---> DACへ与える
⑧TIM2動け
↓DACの設定
①DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO; // sampling frequency
②DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
③DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
④DAC_Init(DAC_Channel_1, &DAC_InitStructure);
⑤DAC_Init(DAC_Channel_2, &DAC_InitStructure);
①DACを駆動するトリガをセレクトします.つまりこの信号がサンプル周波数になります.
ここではTIM2の出力をセレクトしますので、DAC_Trigger_T2_TRGOです.
DAC_Trigger_Ext_IT9, DAC_Trigger_None, DAC_Trigger_Software, DAC_Trigger_T15_TRGO,
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が自律的に何らかの信号をクリエイトする機能です.ここではなにもしないのでnoneにします.
DAC_Wave_Noise, DAC_Wave_Triangle, DAC_WaveGeneration_Noise, DAC_WaveGeneration_None, DAC_WaveGeneration_Triangle
③出力バッファは不要にしておきます
④DAC_Channel1に設定
⑤DAC_Channel2に設定
↓DACでDMA転送するデータをつくる.
DMAがDACに32bitでデータを転送します.
32bitのデータにDAC2[31:16],DAC1[15:0]に2chのデータが同居して格納されます.
ここでは、cosineテーブルを[31:16]に、sineテーブルを[15:0]に納めています.
かつ、[15:0]のうち右詰で[11:0]にsineデータを格納しています.
この、上位/下位に12bitが右詰で同居するセッティングが、上で述べたDAC_DHR12RDと仕様的に一致しているわけです.完璧な理解が必要なところです.
for (x=0;x<32;x++) // Fill Sine32bit table [31:16]DAC2 [15:0]DAC1
{
DualSine12bit[x] = ( Cos12bit [x]<<16) + (Sine12bit[x]);
}
↓DMAの設定 たくさんあります
#ifdef DMA_CHANNEL3
①DMA_DeInit(DMA1_Channel3);
#endif
#ifdef DMA_CHANNEL4
①DMA_DeInit(DMA1_Channel4);
#endif
②DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12RD);
③DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&DualSine12bit;
④DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
⑤DMA_InitStructure.DMA_BufferSize = 32;
⑥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_Word;
⑩DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
⑪DMA_InitStructure.DMA_Priority = DMA_Priority_High;
⑫DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
#ifdef DMA_CHANNEL3
⑬DMA_Init(DMA1_Channel3, &DMA_InitStructure);
⑭DMA_Cmd(DMA1_Channel3, ENABLE);
#endif
#ifdef DMA_CHANNEL4
⑬DMA_Init(DMA1_Channel4, &DMA_InitStructure);
⑭DMA_Cmd(DMA1_Channel4, ENABLE);
#endif
⑮DAC_Cmd(DAC_Channel_1, ENABLE); // PA4
⑮DAC_Cmd(DAC_Channel_2, ENABLE); // PA5
#ifdef DMA_CHANNEL3
⑯DAC_DMACmd(DAC_Channel_1, ENABLE);
#endif
#ifdef DMA_CHANNEL4
⑯DAC_DMACmd(DAC_Channel_2, ENABLE);
#endif
①とりあえず初期化
②DMAの転送先アドレス.DACのDHR12RDレジスタにします.DACのレジスタは下記の構造体で名前はDACで定義されています.なので&(DAC->DHR12RD)でアドレスを指定できます.
typedef struct
{
__IO uint32_t CR;
__IO uint32_t SWTRIGR;
__IO uint32_t DHR12R1;
__IO uint32_t DHR12L1;
__IO uint32_t DHR8R1;
__IO uint32_t DHR12R2;
__IO uint32_t DHR12L2;
__IO uint32_t DHR8R2;
__IO uint32_t DHR12RD;
__IO uint32_t DHR12LD;
__IO uint32_t DHR8RD;
__IO uint32_t DOR1;
__IO uint32_t DOR2;
__IO uint32_t SR;
} DAC_TypeDef;
③メモリの転送元TOPアドレス.上で作ったDualSine12bitを指定.
④DMAの転送方向を設定. DMA_DIR_PeripheralDST(メモリ→periperal) DMA_DIR_PeripheralSRC(peripheral→メモリ)
⑤何個のデータを転送するかを設定.ここでは32
⑥peripheralアドレスを自動incrementするか? DMA_PeripheralInc_Disable(しない) DMA_PeripheralInc_Enable(する)
⑦メモリアドレスを自動incrementするか? DMA_MemoryInc_Disable(しない) DMA_MemoryInc_Enable(する)
⑧peripheralデータ幅の設定. DMA_PeripheralDataSize_Byte(8bit) DMA_PeripheralDataSize_HalfWord(16bit) DMA_PeripheralDataSize_Word(32bit)
⑨メモリデータ幅の設定. DMA_MemoryDataSize_Byte(8bit) DMA_MemoryDataSize_HalfWord(16bit) DMA_MemoryDataSize_Word(32bit)
⑩一発で終了か、グルグル回るか? DMA_Mode_Circular(グルグル) DMA_Mode_Normal(一発で終了)
⑪DMAがバスを占有する優先順位 DMA_Priority_High, DMA_Priority_Low, DMA_Priority_Medium, DMA_Priority_VeryHigh
⑫メモリ→メモリのDMAである設定 DMA_M2M_Disable, DMA_M2M_Enable
⑬DMA設定構造体をDMA_Channel3とDMA_Channel4に書きます. 引数の選択肢はDMA_Channel1~7です
⑭DMAよ動け!
⑮DACよ動け!
⑯これが最も留意するべきヶ所と思います.
DACのDMA request信号は、DAC_Channel_1とDAC_Channel_2の2つ出力されます.
DMAへ向けて出力するrequestをどっちにするかを設定しています.
このサンプルプログラムではDACの2ch共同じ動作をさせているので、原理的にはどちらでもOKなんですけど、上のTable54 の制限のためどっちかに決めなくてはいけません.
どちらにするべきかは、DMA_Channelにより決まります.この関係になります.
DMA_Channel3 → DAC_Channel_1
DMA_Channel4 → DAC_Channel_2
while(1) { Menu(); } メニュールーチンを永久ループ
}
↓debug機能なのでとりあえず無視
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line){ while (1) { } }
#endif
↓TIM3割り込みルーチンです.LEDをチカチカさせています
void TIM3_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
LedBlueToggle();
}
↓メニュー処理ルーチン
void Menu(void)
{
int n,i;
char tmp[30];
if(UART_STR_EXIST==0) return; // there is not any command line
n=separate_line(command); // divide a line into words
// display command line
strcpy(UARTbuf,"\r\ncommand: ");
for(i=0;i<n;i++)
{
sprintf(tmp,"(%d)%s/ ",i,Field[i]);
strcat(UARTbuf,tmp);
}
strcat(UARTbuf,"\r\n");
UART_PutString(UARTbuf);
if(strcmp(Field[0],"f")==0) コマンド f xxxxの処理 ---> TIM2を書き換えてサンプリング周波数を変更している
{
float f;
f = atof(Field[1]); 要求周波数
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
if(f>=100) 要求周波数が100Hz以上のとき
{
TIM_TimeBaseStructure.TIM_Period = (uint16_t)(24000000/32/f)-1; カウントmax値設定(サンプリング周波数変更)
TIM_TimeBaseStructure.TIM_Prescaler = 0; プリスケ=1
sprintf(UARTbuf,"requred freq. %f Hz ---> set freq. %f Hz\r\n",f,(float)(24000000/32/(int)(24000000/32/f))); UART表示
}
else 要求周波数が100Hz未満のとき
{
TIM_TimeBaseStructure.TIM_Period = (uint16_t)(24000000/32/f/1000)-1;
TIM_TimeBaseStructure.TIM_Prescaler = 1000; プリスケ=1000
sprintf(UARTbuf,"requred freq. %f Hz ---> set freq. %f Hz\r\n",f,(float)(24000/32/(int)(24000/32/f)));
}
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 設定構造体をTIM2に書く
UART_PutString(UARTbuf); UART表示
}
else UART_PutString("command error\r\n"); コマンドfでなければコマンドエラー
UART_PutString("f 10000 : frequency 10kHz (max 50kHz)\r\n"); メニュー表示
UART_STR_EXIST=0;
return;
}