2016.12.11
ずいぶん久しぶりにupdateするために戻ってきました.といってもSTM32の
アフィリエイトを追加するためですが.
ここの情報も陳腐化してしまったように思いますが、ちょっちメンテナンスはかったるいかな.orz orz orz
開発環境については、今ではLinuxで動くsdccを使っています.raisonanceもなくcosmicでもなく.
こちらがsdccについて書いた記事です.参考まで.
CコンパイラをRaisonance→Cosmicへ変更するかったるさ
フリーコンパイラsdccをSTライブラリと組み合わせて使う件
=== STMのアフィリエイト始めました ===
STM32のwelcome-kitです
試用レポはいずれまた...
=====================
cosmic
C compilerの16kB無償版のサポートが終了したようです.
raisonance C compiler
でworkspaceを構成する手順をUPしました.
2011.10
STM8S-DISCOVERYについて思うこと
秋
葉の秋月電子で、STM8S-discovery というマイコンが売られています.
こ
の機能で750円とは、異様に安い!
STMicro
の戦略価格なのだろうけど、いつまでもこの値段で売り続けてほしいと思います.
じ
つは私は、この手のマイコンをあまりマジメにいじったことはありませんでした.
PICはライタを用意しなくちゃいけないところがめんどくさくて使わなくなってしまったのと、ラインナップが豊富すぎてどれを
選択するか迷ってしまいます.
arduinoは、いろんな情報がたくさん溢れているんだけど、値段の高さがイマイチだと思うなぁ.
電気製作ホビーって、所詮LEDチカチカぐらいしかやらない人が多いわけでしょ.
それにしてはarduinoのあの値段はチト高くなイカ?
で
も、STM8S-discoveryはライタが付属して売られているようなもんなので、いいかもと思い手に取りました.
あ
と、STMicro提供のFWライブラリが便利ですね.これがなかったらSTM8S-discoveryを使う気になりませんでした.
こんなページを書いていますけど、わたしの専門分野はアナログ回路とデジタル信号処理なので、system系の知識はあんまりないんです.
だから、STM8Sで割り込みをさせるにはどうしたらいいんだろう???というレベルのヘタレです.
なので、そういうヘタレ視点で解説していきますので、理解しやすくなれたらいいなと思います.
製
作記事については、このようなことを考えています.
たかがLEDチカチカであっても、マ
シン語のloopで時間稼ぎしたLEDチカチカだけじゃ技術的な到達度があまりにもプアすぎます.
ぜひともタイマ割り込みでチカチカさせるぐらいのことは学んだら
いかがでしょうか?
ま
た、スタンドアロン的にLEDをチカチカさせる装置を作っても応用上のメリットはないので、わーい、僕にも動かせたよ〜でおしまいになってしまいます.
応用上のメリットを産むには、制
御装置と表
示装置と記憶装置をSTM8S-DISCOVERYに取り付けるのが有用と思います.
そこで、USBでPCと通信すること、LCD表示をつけること、SDカードにlogを書くこと、を執念深くやってます.
BlueToothもつけたら便利だろうなぁ.
-----------------------------------
当ページはリンクフリーです.
当ページのサンプルプログラムを自由に活用なり改変なり再配布なりしてい
ただいてOKです.
当ページの情報を活用した結
果生じたいかなる損害も、当方は関知しませんの で、自己責任で当webページの情報を活用してくださいませ.
当方はSTMicro社とはぜんぜん無関係に活動しておりますので、当ページの不明点についてSTMicro社に質問するなどはお控えくださいませ.
メール hirapy1219@gmail.com
ブログ
http://hirasaka001.blogspot.com/
-----------------------------------
解説 Raisonance Cコンパイラ対応
・実例01 STMicroのライブラリとRaisonance
Cコンパイラをつかった割り込み処理でLED点滅プログラムの全インストール手順
・実例02 STMicroのライブラリとRaisonance
Cコンパイラをつかった割り込み処理でUARTを動かすプログラム(その1)
・
実例03 STM8Sのclockについて詳しくなる
・実例04 STM8SのGPIOについて学ぶ
・STM8Sのタイマについて学ぶ
・実例05 TIM1は外部へ信号を出力しない.タイマ割り込みをする.割り込みルーチンでLEDをチカチカ
させる
----周期割り込みプログラムの書き方----
・実例06 TIM1は外部へ信号を出力する.任意 のデューティー比のパルスを生成する
----モータ制御回路入門----
・モータ制御回路におけるデッドタイムの意味
・実例07 TIM1は外部信号を受信する.外部信号の周波数を測定する
----時間測定のやりかた----
・実例08 TIM1はロータリエンコーダを受信する
----ロータリエンコーダ回路----
・実例09 TIM1はONE SHOTとして動作する
----単発パルスの発生----
・実例20 タイマ割り込みを、TIM1/TIM2/TIM3/TIM4
でやる方法を比較する
・実例21 パルス生成を、TIM1/TIM2/TIM3/TIM4 でやる方法を比較する
・実例22 周波数測定を、TIM1/TIM2/TIM3/TIM4 でやる方法を比較する
・実例23 ロータリエンコーダを、TIM1/TIM2/TIM3/TIM4 でやる方法を比較する
・実例24 ONE SHOTを、TIM1/TIM2/TIM3/TIM4 でやる方法を比較する
・実例29 UARTを動かす(その2)
----PWMでLEDの明度調節----COM PORTとの通信----
・実例30 複数の外部ピン割り込みを処理するには? ----GPIO
割り込み----
・実例31 ADCの使い方
----10ch電圧計---- (ADC使用時はHSIしか使えないというウソを大訂正
2012.3.9)
・実例31b ADCの使い方
----アナログウォッチドッグ---- (ADC使用時はHSIしか
使えないというウソを大訂正 2012.3.9)
・
実例32 LCD表示器を取り付ける
・実例33 SPIインターフェース ----SDカードをSTM8Sで読み書きする----
・まずはちょろっと下調べ
・SDカードドライバ1
----STM8S200向けのサンプルプログラムをSTM8S105に移植する-----
・SDカードドライバ2
----任意のblockをread/writeする----
・FAT16
をSTM8Sに移植するための調査
----windows7で2GBのSDカードをFAT16でformatした状態を解析----
・SDカードドライバ3
----SDカードにFAT16でログを保存する----
・実例34
浮動小数点演算、関数演算の実行速度 ----巨大データのコンパイル方法----
・実例35 不揮発性データの書き込み方
・実例36 STM8SをBLUETOOTHでPCにつないでみる
(ADC使用時はHSIしか
使えないというウソを大訂正 2012.2.26)
・実例40
デバッガの使い方
製作 Raisonance
Cコンパイラ対応
・製作01 USBでPCと接続する多CH温度ロガー (ADC使用時はHSIしか
使えないというウソを大訂正 2012.1.21)
・製作02 USBでPCと接続するハイパワーステッピングモータドライバ
・製作03 ハイパワー赤外線リモコンの製作
・製作04 USBでPCと接続+SDカードに記録+LCD表示
多チャンネル温度ロガー 集大成、ソースコード解説工事中
・製作05 USBでPCと接続する発振器&周波数カウンタ
・製作06 デジタルノギスをUSBでPCと接続する
・製作
07 USBでPCと接続するサーボモータドライバ
トラブルシュート集
設計資
料
・STM8S-DISCOVERY
回路図(pdf)
・STM8Sの外部ピ
ンの解説(pdf)
・メモリマッピング(pdf)
・割り込みベクタ一
覧表(pdf)
・STM8S
HW仕様 (14771) (pdf)
・STM8S
レジスタ仕様 (14587) (pdf)
・cosmic C コンパイラのソースコードを、raisonance
Cコンパイラのソースコードに書き換える方法
・option
byteの解説
細部まで活用するには知っておくべきでしょう
・COM
portからSTM8S discoveryのFLASHを焼けるか?
こういう手口で焼きたい場面もあろうかと思います
設計資料old
・STM8S に不揮発性データを保存するには?
-----自分でFLASHを焼きかえるプログラム----- cosmic Cコンパイラにて
・ST visual develop 開発環境の設定注意点
cosmic Cコンパイラの話題なのでもはや古い話題です
製作編 old (cosmic Cコンパイラにて)
・ド
ライブレコーダMBDR-1 制御回路の製作
・熱帯魚の温度ロガーの製作
(補正データ不揮発機能追加)
・Nゲージ電車模型 線路のポイント切り替え回路の製作
サ
ンプルプログラムの運用について:
たとえば実例01のサンプルプログラムをdownloadして解凍するとこのようなファイル構成が解凍されます.
STM8S_StdPeriph_Lib_VxxxがSTMicro社のライブラリです.
本来同ライブラリが含むファイルのうち、必須なもののみ残し、不要なのはサンプルプログラムからは削除してあります.
ゼロからinstallしたいときは、詳しいinstall手順を実例01に書いてありますのでお読みください.
少々リンク切れの可能性がありますが、ご容赦のほどを.
STVDを起動するときには、
test01-LEDFlashの下にある.stw という拡張子のファイルをダブルクリックすれば、STVDが起動します.
Buildボタンを押せばDebugの下に.hexファイルが生成されるはずです.では、good luck!
以下はこのページを作ったときの最初の資料です.
メンテしてないのでリンクが切れたりしていますので、こ
こから上の解説をメインに読まれることをオススメします.
STMicroのデータシートはこちらです.
STM8S discovery取説 (um0817) (pdf)
STM8S HW仕様 (14771) (pdf)
STM8S レジスタ仕様 (14587) (pdf)
STM8S FWライブラリ仕様 (zip)
←この中のhelpファイルが仕様書
FW ライブラリは便利です.いちいちレジスタ構造を理解する必要はあまりなく、このFWライブラリを使いこなせばよいというわけです.
以
下、個別moduleの解説です.このページの下方へのリンク.
STM8S
discovery 回路図
STM8S105C6T6ピン配置図
メモリとレジスタ
マッピング
クロック発生回路
割り込み
タイマ
GPIO
ADC
STM8S discovery回路図(pdf)
し かし、なんでこのHWを\750で売ってくれるんだろ? よほど大量生産しても工場出荷の原価は\500を超えてしまうと思われます.流通コストとかを考えると赤字なんじゃないかしら? 感謝、感謝、、、、
PA3 とかPD1とかいうのは、汎用IO(GPIO)のポート番号のことです.たとえばPA3はGPIOA[7:0]の3bit目という意味.(HS)と書かれ ているのは、たぶんhigh speed output bufferに対応しているという意味なんだろう.
続 く TIM3_CH2 とか SPI_MISO とかは、TIM3やSPIのようなIC内部ペリフェラルの入出力です.GPIO機能と殺して、TIM3_CH2機能をオンするという具合に、排他的にしか 使えません.切り替え方法は、いまいち理解できてません.
さ らに続いて [CLK_CCO] みたいな、[ ]付きの機能を利用するには、めんどくさいことをしなくちゃいけません.STM8S内部の「optionBYTE」と呼ばれるFLASHを書き換えないと 機能変更できないのです.option BYTE書き換えツールは、開発環境をインストールすると同時にインストールされるstvp.exeです.stvp.exeのつかいかたは、エレキジャックのこのページを参考にしましょう.
ど うしてoption BYTEを書き換えなくちゃいけないのかというと、パワーオン直後にsoftがPORTを初期化完了するまでの一瞬に、IO-PORTに設計者が望まない 信号が出てしまい、機器が誤動作するのを防ぐためなんだそうです.なるほど賢いと思った私.
端 子の機能を1pinから順に簡単に述べると、
NRST
リセットだろう
PA1
とか
GPIOポートのこと
OCSIN/OSCOUT 水晶発信子取付端子 または外部クロック入力端子
VSS
電源GND
VCAP
電源のデカップコンデンサ取付端子
VDD
+電源 3.3〜5V
VDDIO
IOポート用の電源入力端子
TIM2_CH3 とか
Timer2の、チャンネル3の入力あるいは出力の意味
VDDA/VSSA
アナログ電源入力端子
AIN6 とか &
nbsp; ADCの入力端子6の意味
I2C_SDA とか
シリアルインタフェース規格I2Cのための端子
SPI_NSS とか
シリアルインターフェース規格SPIのための端子
CLK_CCO
クロックを外部出力できる端子
SWIM
プログラマやデバッガがSTM8Sとデータをやりとりするための端子
UART
いわゆるRS232のための端子.UART機能を使うには、電圧を±12Vに変換するICを外付けする必要が
あります
TLI
なにか知らない.データシート読んでないです.
メモリとレジスタマッピング (pdf)
詳 細なレジスタマッピングは、各ペリフェラルの解説pdfのなかに書かれている.
クロック発生回路 (pdf)
ク ロック発生源
STM8S のCLK発生源は3つあります.CPU内部16MHz発振回路、CPU内部128kHz発振回路、外部クロック入力 です.ちなみに、reset直後は、内部16MHzを8分周した2MHzがCPUクロックとして選択されます.
で すが、目一杯高速なクロックで動かしたいとか、省電力のために遅いクロックで動かしたいとか言うニーズがあると思います.そのために、CLKをどうやって 切り替えるか?を知っておく必要があるわけです.次のC言語関数が、FWライブラリに用意されています.
●CLK_ClockSwitchConfig ( CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE );
引 数の選択肢はこうなっています.
・CLK 切替手順を指定する CLK_SWITCHMODE_AUTO または CLK_SWITCHMODE_MANUAL は、なにかよくわからないが、盲目的にAUTOでいいんだと思います.
・
どのクロックにするか?
CLK_SOURCE_HSI 内部16MHz
CLK_SOURCE_LSI
内部128kHz (option
BYTEを書き換えないと設定できない)
CLK_SOURCE_HSE 外部水晶 or
外部入力
注 意: 内部128kHzをCPU clkとして使うには、option BYTEを書き換える必要があります.これを怠ると、内部128kHzに切り替えろと命じても無視されて、内部16MHzに強制的に切り替わってしまうよ うです.stvp.exeを起動して、option BYTEタグを見てください.それっぽ い切替部分があります.
・CLK_CURRENTCLOCKSTATE_DISABLE& nbsp;または CLK_CURRENTCLOCKSTATE_ENABLE は、よくわかりません.DISABLEでもENABLEでも目に付くような動作への影響には気づきませんでした.
ク ロック切替関数の説明は以上です.
プ リスケーラ
プ
リスケーラというかクロックDividerは2段あります.
1)HSIDIV[1:0]で設定されるやつ
2)CPUDIV[2:0]で設定されるやつ
reset
後は、CPUDIV[2:0]=0なので、fMASTER=fCPUになります.よってreset後に、CLK_ClockSwitchConfigで、
外部クロックに変更すると、プリスケーラ1も2も入らないので、STM8S-discoveryの場合は16MHzがCPUに供給されるということになり
ます.
プ リスケーラの設定コマンドはこれです.
●CLK_HSIPrescalerConfig( CLK_PRESCALER_CPUDIV1 );
・
引数の選択肢は、
CLK_PRESCALER_HSIDIV1 High speed internal clock prescaler:
1
CLK_PRESCALER_HSIDIV2 High speed internal clock prescaler:
2
CLK_PRESCALER_HSIDIV4 High speed internal clock prescaler:
4
CLK_PRESCALER_HSIDIV8 High speed internal clock prescaler:
8
CLK_PRESCALER_CPUDIV1 CPU clock division factors 1
CLK_PRESCALER_CPUDIV2 CPU clock division factors 2
CLK_PRESCALER_CPUDIV4 CPU clock division factors 4
CLK_PRESCALER_CPUDIV8 CPU clock division factors 8
CLK_PRESCALER_CPUDIV16 CPU clock division factors
16
CLK_PRESCALER_CPUDIV32 CPU clock division factors
32
CLK_PRESCALER_CPUDIV64 CPU clock division factors
64
CLK_PRESCALER_CPUDIV128 CPU clock division factors
128
プ リスケーラは以上.
CLK 外部出力
CLK_CCO という出力ポートがあり、なんかしらのCLKを出力できるようになっています.FWライブラリにそれを選択する関数がありますが、詳しく読んでいません.
割り込みベクタ (pdf) いろいろなペリフェラルから発生する割り込みは、それぞれあらかじめ番号が決まっています.割り込みベクタは8000H番地以降と決まっています.
FW ライブラリを用いた割り込みの実装方法の具体例として、タイマ3による周期的割り込みの実装例を以下に示します.タイマの使い方は後述します.以下の6つ の手順をやります.
@
メインルーチン
main( ) {
TIM3_TimeBaseInit( TIM3_PRESCALER_32, 1000 );
クロック周波数2MHzを、タイマのプリスケーラで32分周して62.5kHzのカウントCLKとし、それを1000発カウントするというタイマのカウン
タを形成する.つまり16msの割り込みです.
TIM3_ITConfig(TIM3_IT_UPDATE,
ENABLE);
タイマカウンタ[15:0]が1000に達したら割り込みするようにします
TIM3_Cmd(ENABLE); タイマ動作開始
enableInterrupts(); 割り込み許可のマシン語マクロ
while
(1) { } 永久ループ
}
A
割り込みルーチン
@far @interrupt void
Tim3Update_isr(void) 割り込みで飛んでくるルーチン
{
TIM3_ClearFlag(TIM3_FLAG_UPDATE);
HWがタイマ割り込みFLAG=1にするので、それをSWでクリアします
な んか処理をする
return;
}
@far という修飾語は、COSMIC compiler特有の機能で、64kBを超えるアドレッシングを必要とするときにつけられます.もっとも、STM8Sのメモリマップによると、割り込み vectorは8000H番地で、program codeは8080H番地以降なので、とてもご近所なので、@farは不要かと思われますが、@farを除去するとcompileできないのでつけておか ざるを得ないようです.
@interrupt という修飾語は、COSMIC compiler特有の機能で、その関数が割り込みルーチンであることを明示しています.compilerがレジスタの退避のcodeを自動生成してくれ るのでしょう.
B割り込みベクタ記述
FWライブラリが提供する
stm8_interrupt_vector.c
に割り込みvectorを記述します.TIM3のoverflow割り込み番号は15番なので、つぎのようにします.
struct
interrupt_vector const _vectab[] = {
中略
{0x82, Tim3Update_isr}, /* irq15 */
中略
};
C
割り込みベクタをextern
FWライブラリが提供する
stm8_interrupt_vector.c にmain.cで記述した割り込みルーチンをexternしておきます.
extern @far @interrupt void Tim3Update_isr(void);
DFW
ライブラリをincludeする
FWライブラリが提供する stm8s_conf.h
にある TIM3のdefine分のコメントをはずす
#define _TIM3 (1)
EFW
ライブラリとprojectに追加
FWライブラリが提供するTIM3用のヘッダファイルとコード
ファイル stm8s_tim3.c stm8s_tim3.h をprojectに追加します
タイマ
いろいろと機能豊富で全部読んでません.TIM1〜TIM5ぐら
いまで内蔵されているようです.TIM1が最も機能豊富で、後続のTIMほど機能が簡素になっているようです.
初 歩的な構成説明をすると、たとえばTIM2は、16bitのカウンタを1つだけ持っています.そのカウンタ値と比較するコンパレータを3つ持って います.したがって、カウンタが一巡するサイクルごとに、4つの割り込みを発生できるわけです.3つのコンパレータ出力のことを、チャンネルと読んでい て、TIM2_CH1/TIM2_CH2/TIM2_CH3 のように名前をつけています.
ARR [15:0]は、グルグルまわるカウンタのmax値を指定するレジスタで、カウンタ値がARRに達するとカウンタはゼロに戻ります.CCR[15:0] は、カウンタ値と比較する値です.チャネルが3つあるので、CCR1, CCR2, CCR3の3つ設けられています.
タ
イマモードとはなにか?
一発タイマか、エンドレスなタイマか、みたいなことをタイマモー
ドと呼んでいます.
●input
capture mode (pdf)
TIM2_CH1/TIM2_CH2/TIM2_CH3 のようなチャネルを入力に設定して、そこに入力されるパルスの時間を測定するモードのこと.
●output
compare mode (pdf)
波形を生成するモードなのですが、PWMモードとの違いがいまいちよくわからないんです.
カウンタとCCR[15:0]の一致を検知して、そこで出力を変化させるというmodeらしい.
繰り返し信号を出力させることもできるし、単発パルスを出力させることもできる.
ただし、単発パルスの場合は、外部トリガ信号に同期した単発パルスを出せるわけではないらしい.
●force
output mode (pdf)
波形を生成するモードの一種.OC1M[2:0]を、下記のどちらかにして、チャンネル出力を強制的に固定するmodeのこと.
100: 出力0固定
101: 出力1固定
この機能が何の意味を持つのかよくわかりませんが、出力には何も現れないが、CPU内部的には、割り込みを生じさせるといった、ステルス性を得たい時に使
うモードらしいです.
●PWM mode (pdf)
波形を生成するモードの一種.ARR[15:0]周期のパルスを発生させるモード.Hi区間はコンパレート値CCR[15:0]で規定される.たとえば、
CLK=2MHzで、ARR=999で、CCR=300にすれば、duty30%の2kHzが出力されるわけです.
●PWM
modeのedge-aligned mode
カウンタをグルグル回して、CCRを変化させることで、出力のdutyを変えられる.そんな動作をさせるモード.モータ制御回路において、PWMでVsを
上下させることがありますが、PWMをHW的に発生させるためのカラクリの一つと思われます.
●PWM
modeのcenter-aligned mode
たぶんTIM1でしかできないと思いますが、カウンタ値を三角波的に動かすのが特徴.(edge-aligned
modeでは鋸歯状波的でした)
そこでCCRを変化させると、High区間が左右から伸縮するような波形変化をします.三角波をコンパレートしているのだからそうなります.これもモータ
制御回路のためと思われます.
●PWM
modeのone pulse mode
カウンタを一発屋動作にすることで、モノマルチ的な動作をさせます.
タイムベース (pdf)
カウンタへ与えるクロックを適宜プリスケーラし、かつ16bitカウントする回路ブロックで
す.
設
定する関数はこれを知っておけばOKです.
TIM2_TimeBaseInit( TIM3_PRESCALER_32, PERIOD-1 );
プ
リスケーラの分周比は、この中から選びます.PSC[3:0]によって2のべき乗分周されます.ここでいうプリスケーラは、クロック回路に存在した2つの
プリスケーラとはまた別の、第3のプリスケーラですので、混同しないようにしましょう.
TIM2_PRESCALER_1 =
((u8)0x00),
TIM2_PRESCALER_2 =
((u8)0x01),
TIM2_PRESCALER_4 =
((u8)0x02),
TIM2_PRESCALER_8 =
((u8)0x03),
TIM2_PRESCALER_16 = ((u8)0x04),
TIM2_PRESCALER_32 = ((u8)0x05),
TIM2_PRESCALER_64 = ((u8)0x06),
TIM2_PRESCALER_128 = ((u8)0x07),
TIM2_PRESCALER_256 = ((u8)0x08),
TIM2_PRESCALER_512 = ((u8)0x09),
TIM2_PRESCALER_1024 = ((u8)0x0A),
TIM2_PRESCALER_2048 = ((u8)0x0B),
TIM2_PRESCALER_4096 = ((u8)0x0C),
TIM2_PRESCALER_8192 = ((u8)0x0D),
TIM2_PRESCALER_16384 = ((u8)0x0E),
TIM2_PRESCALER_32768 = ((u8)0x0F)
PERIOD は、レジスタARR[15:0]に書かれます.カウンタはゼロスタートで、ARRまでカウントupしたら、自動的に0に戻ります.
た だし、TIM1は、ダウンカウントもできるようです.TIM2とかTIM3はアップカウントだけしかできません.
カ ウンタの現在値は、{TIM2_CNTRH[8:0],TIM2_CNTRL[8:0]} で読めます.
インプットステージ (pdf)
input capture
modeのように外部入力のパルス時間を測りたいときや、外部入力をカウンタトリガに使いたいときに、お世話になる回路.したがって、単純にタイマをグル
グル回すだけならこの回路にお世話になることはないです.
pdf の図82の左方のTIMx_CH1は、外部ピンのことです.ピン配置図に書かれているやつのことです.これらの外部ピンは、inputとして 使うかoutputとして使うかを排他的に選択して使います.したがって、CH1の外部パルス周期を測る場合は、CH1から信号出力はできません.そのよ うなときには、CH1で外部パルス周期を測って、CH2から信号出力することならできるようです.
pdfの図83のレジスタICF[3:0]で制御されるfilter
は、チャタリング防止用のフィルタです.ICF[3:0]の選択肢はこのように多様ですが、普通のdigital信号を受信する限りにおいては、0000
で良いのではないかと思います.ノイズまみれの信号を受信する場合にはケアするのもよいかもしれません.NはN回カウントするまで判断を留保するという意
味です.したがって、ICF[3:0]が大きな数字であるほど、ノイズに強固な設定だと言えます.
0000: No filter, fSAMPLING= fMASTER
0001: fSAMPLING=fMASTER, N = 2
0010: fSAMPLING=fMASTER, N = 4
0011: fSAMPLING=fMASTER, N = 8
0100: fSAMPLING=fMASTER/2, N = 6
0101: fSAMPLING=fMASTER/2, N = 8
0110: fSAMPLING=fMASTER/4, N = 6
0111: fSAMPLING=fMASTER/4, N = 8
1000: fSAMPLING=fMASTER/8, N = 6
1001: fSAMPLING=fMASTER/8, N = 8
1010: fSAMPLING=fMASTER/16, N = 5
1011: fSAMPLING=fMASTER/16, N = 6
1100: fSAMPLING=fMASTER/16, N = 8
1101: fSAMPLING=fMASTER/32, N = 5
1110: fSAMPLING=fMASTER/32, N = 6
1111: fSAMPLING=fMASTER/32, N = 8
レ ジスタCC1Pで、入力信号のpos/neg edgeを選択できます.
レ ジスタCC1Sで、入力をCH1かCH2かを選択できます. TRCはなんだか不明.
レ ジスタIC1PSCは一種のfilterで、edgeの1|2|4|8回ごとに割り込みをかけるという意味がある.
レ ジスタCC1Eは、タイマのenable.
こ
れらの設定をするFWライブラリ関数はこれです.
TIM2_ICInit ( TIM2_CHANNEL_1, TIM2_ICPOLARITY_RISING,
TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV1, 0)
5
つの引数はこんな選択肢があります.
どのチャネルか?
TIM2_CHANNEL_1
TIM2_CHANNEL_2
TIM2_CHANNEL_3
チャ
ネル入力信号の立ち上がりエッジか立ち下がりエッジか?
TIM2_ICPOLARITY_RISING
TIM2_ICPOLARITY_FALLING
チャ
ネル入力の選択
TIM2_ICSELECTION_DIRECTTI
TIM2_CH1を入力としてつかう
TIM2_ICSELECTION_INDIRECTTI
TIM2_CH2を入力として使うような意味(不正確)
TIM2_ICSELECTION_TRGI
TIM2_CH1
をトリガ入力として使うような意味(不正確)
割
り込み頻度 (チャタリング防止の一種)
TIM2_ICPSC_DIV1
入力信号のedgeの1回ごとに割り込みをかける
TIM2_ICPSC_DIV2
入力信号のedgeの2回ごとに割り込みをかける
TIM2_ICPSC_DIV4
入力信号のedgeの4回ごとに割り込みをかける
TIM2_ICPSC_DIV8
入力信号のedgeの8回ごとに割り込みをかける
チャタリング防止フィルタの性能
0000: No filter, fSAMPLING= fMASTER
0001: fSAMPLING=fMASTER, N = 2
0010: fSAMPLING=fMASTER, N = 4
0011: fSAMPLING=fMASTER, N = 8
0100: fSAMPLING=fMASTER/2, N = 6
0101: fSAMPLING=fMASTER/2, N = 8
0110: fSAMPLING=fMASTER/4, N = 6
0111: fSAMPLING=fMASTER/4, N = 8
1000: fSAMPLING=fMASTER/8, N = 6
1001: fSAMPLING=fMASTER/8, N = 8
1010: fSAMPLING=fMASTER/16, N = 5
1011: fSAMPLING=fMASTER/16, N = 6
1100: fSAMPLING=fMASTER/16, N = 8
1101: fSAMPLING=fMASTER/32, N = 5
1110: fSAMPLING=fMASTER/32, N = 6
1111: fSAMPLING=fMASTER/32, N = 8
--------
割り込みのこと
カ
ウンタがARRに達したら、割り込みをかけたいなら、単にこの関数を呼び出せばよい.
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
割
り込みが発生すると、TIM2_SR1レジスタのbit0に存在するUIF bitがHWによって1にされる.
これを、クリアするには、割り込みルーチンでSW的にclearする.
TIM2_ClearFlag(TIM3_FLAG_UPDATE);
こ うすることで、次回の割り込みを待てるようになる.
簡 単なcodeの例、
void
main(void) {
TIM2_TimeBaseInit( TIM2_PRESCALER_1, 1000 );
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
TIM2_Cmd(ENABLE);
enableInterrupts();
while (1) {; }
}
@far
@interrupt void Tim2Update_isr(void) {
TIM2_ClearFlag(TIM2_FLAG_UPDATE);
好みの割り込み処理
return;
}
GPIO (pdf)
STM8S
discoveryに載っている、STM8S105C6T6 は、次のGPIOピンを持っています.
PA[6:1] PB[7:0]
PC[7:1] PD[7:0]
PE[7:5]
PE[3:0]
PF[4] PG[1:0]
したがって、ここに載っていないPA[0]のようなGPIOにアクセスしても意味がありません.
STM8S discovery回路図に記載されているとおり、ピンヘッダCN1〜4に、これらのGPIOが配線されています.
GPIO は5000H番地以降にマッピングされていますが、FWライブラリを使うぶんにはそれを意識する必要はありません.
以 下にFWライブラリ関数の例を書きます.
GPIO_Init(GPIOB, 0b10101010,
GPIO_MODE_OUT_PP_LOW_FAST);
bit7531を出力ポートに設定
GPIO_Init(GPIOD, 0b00000001,
GPIO_MODE_OUT_PP_HIGH_FAST); &
nbsp; bit0を出力ポートに設定
入
出力ポートの機能はこの選択肢があります.
GPIO_MODE_IN_FL_NO_IT
Input floating, no external interrupt
GPIO_MODE_IN_PU_NO_IT
Input pull-up, no external interrupt
GPIO_MODE_IN_FL_IT
Input floating, external interrupt
GPIO_MODE_IN_PU_IT
Input pull-up, external interrupt
GPIO_MODE_OUT_OD_LOW_FAST Output open-drain, low
level, 10MHz
GPIO_MODE_OUT_PP_LOW_FAST Output push-pull, low
level, 10MHz
GPIO_MODE_OUT_OD_LOW_SLOW Output open-drain, low
level, 2MHz
GPIO_MODE_OUT_PP_LOW_SLOW Output push-pull, low
level, 2MHz
GPIO_MODE_OUT_OD_HIZ_FAST Output open-drain,
high-impedance level,10MHz
GPIO_MODE_OUT_PP_HIGH_FAST
Output push-pull, high level, 10MHz
GPIO_MODE_OUT_OD_HIZ_SLOW Output open-drain,
high-impedance level, 2MHz
GPIO_MODE_OUT_PP_HIGH_SLOW
Output push-pull, high level, 2MHz
GPIO_Write(GPIOB,
0x80);
バイト出力
GPIO_WriteHigh(GPIOA,
GPIO_PIN_2); bit操作
GPIO_WriteLow(GPIOD, GPIO_PIN_6);
GPIO_WriteReverse(GPIOE,
GPIO_PIN_5); bit反転
u8 reg =
GPIO_ReadInputData(GPIOF);
portリード
u8 reg = GPIO_ReadOutputData(GPIOA);
BitStatus bit = GPIO_ReadInputPin(GPIOC, GPIO_PIN4);
GPIO_ExternalPullUpConfig(GPIOB, GPIO_PIN_6, ENABLE); とあるbitをpull-upする
ADC (pdf)
基
本仕様
10-bit
{DRH:DRL}={[9:2],[1:0]} あるいは {[9:8],[7:0]}
かは、ALIGNレジスタで選択できる.reset時は前者になる.
一発変換 あるいは
連続変換
1変換に14clkかかる
プリスケーラ = fMASTER ÷ 2 to
18 レジスタは、SPSEL[2:0]
トリガ入力2系統
外部トリガ (ADC_ETR)
あるいは タイマトリガ (TRGO)
変換終了割り込み
ADC レンジ GND〜VDD
入力は10pinあって、マルチプレクサされて、一度に変換できるのは1ヶだけ
---------
いろいろな変換モード
●single
conversion mode
一発だけ変換するモード. CONT=0にしておいて、ADON=1にすると変換スタートする.
変換終了すると、データは ADC_DRレジスタに格納される.
EOCフラグが立つ.EOCIE=1であれば割り込みがかかる.
●continuous
conversion mode
連続してADCするモード. CONT=1 かつ ADON=1 で動き始める.
デー
タの扱いに2種類ある.
1)ODBUF=1 ならば、10サンプルデータが、レジスタにストアされる.割り込みは10サンプル毎である.
データが読まれなければ、OVR フラグが立つ.
2)ODBUF=0 ならば、そんなことはしない.割り込みは1サンプル毎である.
●single
scan mode
10ヶあるアナログ入力pinを、自動で順番にADCするモード.変換が一巡したら、それでおしまい.
変換開始は、ADON=1 である.CONT=0 にしておくこと.
デー タは、10ヶのレジスタ ADC_DBxR に格納される.読まれずに上書きされたらOVRフラグが立つ.
EOC フラグと割り込みは、10ヶの連続変換が完了したら発生する.
●Continuous
scan mode
10ヶあるアナログ入力pinを、自動で順番にADCするモード.止まらずにscanしつづける.
変換開始は、ADON=1 である.CONT=1 にしておくこと.
注
意:EOCフラグをむやみにクリアしないで.
理由は、EOCフラグとCH[3:0]レジスタが、ADC_CSRというレジスタアドレスに同居しているので、
read-modify-write操作によって、CHが不用意に書き換えられてしまうからである.
scan modeでは、CH[3:0]はHWによって自動的に変更される.
じゃぁどうしたらよいのか?
英文を読んでも理解できなかったが、ADC_CSRレジスタアドレスを読むのではなく、RAM上から
同レジスタ情報を読んでどうたらこうたら、と書かれているが、意味がわからない.
---------
アナログウォッチドッグ機能
ADC 変換データの値が、XX以下あるいはXX以上になったら、割り込みというような機能.AWDフラグが立つ.(データシートにAWDGという記述があるがそ れは誤植と思われる)
詳 細は読んでない.
---------
変換トリガ機能
外
部pin ADC_ETR の立ち上がりエッジでTRGすることができる.EXTTRG=1にする.
あるいは、Timerが発するTRGOでTRGすることができる.
外
部トリガをつかう手順
1)ADON=0、SOC=0 にしてADCを止める
2)トリガ信号を選ぶ.EXTSEL[1:0]
3)EXTTRG=1にするが、他のbitを動かさないために、マシン語のBSETを使ってくれ
4)TRG信号がactiveならば、ADCがオンすると英文が書かれているように読めるんだが、言ってる意味が理解不能
5)ADCオン以後、少し待つ
6)外部TRGが来ると、変換が始まる
--------
FW関数群
●ADC1_Cmd(FunctionalState
NewState); ADCをスタートする
●ADC1_StartConversion(void);
ADCをスタートする
コードによるとADC_Cmdでスタートするのと同じ作用と思われる
●FlagStatus
ADC1_GetFlagStatus(); EOCフラグの状態をreadする
●ITStatus EOS =
ADC1_GetITStatus();
EOC pendingフラグの状態をreadする
●ADC1_ClearFlag();
EOCフラグをクリアする
●ADC1_ClearITPendingBit(); EOC
pendingフラグをクリアする
●ADC1_ITConfig( ENABLE ); 割り込みENABLE/DISABLE
●u16 a = ADC1_GetConversionValue(); 変換データを読む.コードによると単にレジスタをreadしているだけだが、debuggerでモニタしたところ0〜65535まで振れるようになってい るようだ.
●ADC2_Init(
一気に全部ADC設定するコマンド
ADC2_CONVERSIONMODE_CONTINUOUS,
ADC2_CHANNEL_0,
ADC2_PRESSEL_FCPU_D18,
ADC2_EXTTRIG_TIM,
EXTTRGをDISABLE,
ADC2_ALIGN_LEFT,
ADC2_SCHMITTTRIG_CHANNEL0,
schmittをDISABLE);
コードを読むとわかるのだが、このコマンドは、ADC2_Cmdも内部でやってくれて、つまりADCをスタートもしてくれる.
以下、8つの引数のパラメータ
ADC2_CONVERSIONMODE_SINGLE
一発変換
ADC2_CONVERSIONMODE_CONTINUOUS 連続変換
ADC2_CHANNEL_0 〜 ADC2_CHANNEL_9 入力をどれにするか?
ADC2_PRESSEL_FCPU_D2
fADC2 = fcpu/2.
AD変換クロック選択.14クロックで1変換
ADC2_PRESSEL_FCPU_D3 fADC2 =
fcpu/3.
ADC2_PRESSEL_FCPU_D4 fADC2 =
fcpu/4.
ADC2_PRESSEL_FCPU_D6 fADC2 =
fcpu/6.
ADC2_PRESSEL_FCPU_D8 fADC2 =
fcpu/8.
ADC2_PRESSEL_FCPU_D10 fADC2 = fcpu/10.
ADC2_PRESSEL_FCPU_D12 fADC2 = fcpu/12.
ADC2_PRESSEL_FCPU_D18 fADC2 = fcpu/18.
ADC2_EXTTRIG_TIM
タイマ変換トリガ
ADC2_EXTTRIG_GPIO ADC_ETR
pin変換トリガ
EXTTRG をDISABLE または DISABLE,
ADC2_ALIGN_LEFT
データの取りだし DH=[9:2] DL=[1:0]
ADC2_ALIGN_RIGHT DH=[9:8]
DL=[7:0]
ADC2_SCHMITTTRIG_CHANNEL0 〜 9 省電力のため、どのAINの Schmitt trigger をdisableしたいか?
schmitt をDISABLE または ENABLE
●ADC2_ConversionConfig(
簡潔にInitするコマンド.
ADC2_CONVERSIONMODE_CONTINUOUS,
ADC2_CHANNEL_0,
ADC2_ALIGN_LEFT );
ADC2_CONVERSIONMODE_SINGLE
一発変換
ADC2_CONVERSIONMODE_CONTINUOUS 連続変換
ADC2_CHANNEL_0 〜 ADC2_CHANNEL_9
ADC2_ALIGN_LEFT
データの取りだし DH=[9:2] DL=[1:0]
ADC2_ALIGN_RIGHT DH=[9:8]
DL=[7:0]
変 換開始させるためにADC2_Cmdを別途callする必要がある.ADC2_Init()だとうまく動くが、このコマンドだとADCが動かないようだ. 原因は不明.
●ADC2_PrescalerConfig(ADC2_PRESSEL_FCPU_D2);
プリスケーラ設定
ADC2_PRESSEL_FCPU_D2 fADC2 =
fcpu/2.
ADC2_PRESSEL_FCPU_D3 fADC2 =
fcpu/3.
ADC2_PRESSEL_FCPU_D4 fADC2 =
fcpu/4.
ADC2_PRESSEL_FCPU_D6 fADC2 =
fcpu/6.
ADC2_PRESSEL_FCPU_D8 fADC2 =
fcpu/8.
ADC2_PRESSEL_FCPU_D10 fADC2 =
fcpu/10.
ADC2_PRESSEL_FCPU_D12 fADC2 =
fcpu/12.
ADC2_PRESSEL_FCPU_D18 fADC2 =
fcpu/18.
●ADC2_SchmittTriggerConfig(ADC2_SCHMITTTRIG_CHANNEL0, DISABLE); 省電力のためシュミットをDISABLE
ADC2_SCHMITTTRIG_CHANNEL0 〜 9 どのAINの Schmitt trigger をdisableしたいか?
schmitt をDISABLE または ENABLE
●ADC2_ExternalTriggerConfig(ADC2_EXTTRIG_TIM, ENABLE);
ADC2_EXTTRIG_TIM
タイマ変換トリガ
ADC2_EXTTRIG_GPIO ADC_ETR
pin変換トリガ
EXTTRG をDISABLE または ENABLE
-------
scan modeの用の関数群
センサを複数取り付けることがよくあると思います.そういうときは、たいていscan
modeを利用することでしょう.とても使用価値のあるモードです.
どれか1つのADC入力ポート AIN0~9 をAD変換するには、上記の関数でよいのですが、single scan
modeあるいはcontinuous scan modeの場合は、ちょっとちがう関数が登場します.また、scan
modeは、ADC1でなら使えますが、ADC2では使えません.ADC2は機能が貧弱なのです.
まず、ADC1の設定は、このおまじないがオススメです.とくに、
CONTINUOUS と 15 のところは実際に動かしてみるとこの設定でしか動きません.
理由は謎ですが....
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,
15, ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE,
ADC1_ALIGN_LEFT, ADC1_SCHMITTTRIG_CHANNEL7, DISABLE);
ADC1_DataBufferCmd(ENABLE);
ADC1_ScanModeCmd(ENABLE);
ADC1_StartConversion();
次に、AD変換データを読むには、ADC1_GetConversionValue( )は使えなくて、その代わりに、scan
modeでは、10ヶのAD変換データが{DB0RH[7:0],DB0RL[7:0]}~{DB9RH[7:0],DB9RL[7:0]}
に自動的に格納されますので、AD変換データを読み取るには、ADC1_GetBufferValue( ) を利用します.つまりこういうことです.
ADIN0のデータ{DB0RH[7:0],DB0RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(0)
ADIN1のデータ{DB1RH[7:0],DB1RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(1)
ADIN2のデータ{DB2RH[7:0],DB2RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(2)
ADIN3のデータ{DB3RH[7:0],DB3RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(3)
ADIN4のデータ{DB4RH[7:0],DB4RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(4)
ADIN5のデータ{DB5RH[7:0],DB5RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(5)
ADIN6のデータ{DB6RH[7:0],DB6RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(6)
ADIN7のデータ{DB7RH[7:0],DB7RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(7)
ADIN8のデータ{DB8RH[7:0],DB8RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(8)
ADIN9のデータ{DB9RH[7:0],DB9RL[7:0]}を読む &
nbsp; ---->
ADC1_GetBufferValue(9)
下記のコード例を参照してください.
-------
アナログウォッチドッグ機能用の関数群
これも、scan
mode同様に、ADC1でしか使えません.できることは、AD変換データの値の上限と下限を指定しておくと、それを越えたら割り込みがかかるっていうカ
ラクリです.目先使う気がないので、データシートを読んでないです.
●void ADC1_AWDChannelConfig(ADC1_Channel_TypeDef Channel,
FunctionalState NewState);
●void ADC1_SetHighThreshold(u16 Threshold);
●void ADC1_SetLowThreshold(u16 Threshold);
●FlagStatus ADC1_GetAWDChannelStatus(ADC1_Channel_TypeDef Channel);
-----------
コード例1
AIN6をエンドレスで繰り返し(continuous)AD変換する.EOC割り込みなし
ADC1_DeInit();
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_6,
ADC1_PRESSEL_FCPU_D18, ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_LEFT,
ADC1_SCHMITTTRIG_CHANNEL6, DISABLE);
ADC1_StartConversion();
while (1) {
adc_data=ADC1_GetConversionValue();
なにか処理
}
コード例2 &
nbsp; AIN6を一度AD変換したら止まる(single).EOC割り込みなし
ADC1_DeInit();
ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC1_CHANNEL_6,
ADC1_PRESSEL_FCPU_D18, ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_LEFT,
ADC1_SCHMITTTRIG_CHANNEL6, DISABLE);
while (1) {
ADC1_StartConversion();
ここで必要な都度startさせるのです
adc_data=ADC1_GetConversionValue();
なにか処理
}
コード例3 &
nbsp; 一度AD変換したら止まる(single).scanモード.EOC割り込みなし
CONTINUOUSかつ15にしておかな
いとscanが動かないみたいだ.
ADC1_DeInit();
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, 15,
ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_LEFT,
ADC1_SCHMITTTRIG_CHANNEL7, DISABLE);
ADC1_DataBufferCmd(ENABLE);
ADC1_ScanModeCmd(ENABLE);
while(1) {
ADC1_StartConversion();
adc_data7=ADC1_GetBufferValue(0);
かならずしも律儀に全部読む必要はないです
adc_data7=ADC1_GetBufferValue(1);
adc_data7=ADC1_GetBufferValue(2);
adc_data7=ADC1_GetBufferValue(3);
adc_data7=ADC1_GetBufferValue(4);
adc_data7=ADC1_GetBufferValue(5);
adc_data7=ADC1_GetBufferValue(6);
adc_data7=ADC1_GetBufferValue(7);
adc_data7=ADC1_GetBufferValue(8);
adc_data7=ADC1_GetBufferValue(9);
なにか処理
}