はじめに
本記事は UIAPduinoでLチカ(内臓LEDと外付けLED) でLED点灯まではできていることを前提とします。
次の拡張としてはスイッチ押下で点灯とかやってみようかなと思っています。
上記記載していた通り、拡張してみたので投稿します。
ボタンLED
ゴールとしては、ボタン(タクトスイッチ)を押している間だけLEDが光るようにします。
1. 構成
- 外付けLED … D2 / PC0
- D2 / PC0 → 抵抗 → LED → GND - ボタン … D7 / PC5
- D7 / PC5 → ボタン → GND
画像出典:UIAP「UIAPduino Pro Micro CH32V003 V1.4」ピン配置図
License: Creative Commons Attribution 4.0 International
https://www.uiap.jp/uiapduino/pro-micro/ch32v003/v1dot4#with-ch32fun-development-environment
ボタンは D7 と GND を押したときだけつながるように内部プルアップにします。
つまり、ボタンを押していない間が HIGH、 押している間は LOW とします。
2. ボタン(タクトスイッチ) について
以下を参考にしました。
左右の端子で接続が切れており、ボタンが押されることで左右の端子がつながります。
よってボタンを押した場合にのみGNDの線につながるように配置します。
3. コード
#include "ch32fun.h"
#include <stdio.h>
// LEDピン定義 D2 / PC0
#define LED_PIN PC0
// ボタンピン定義: D7 / PC5
#define BUTTON_PIN PC5
int main()
{
SystemInit();
// GPIOを有効化
funGpioInitAll();
// LED_PINを出力に設定
funPinMode( LED_PIN, GPIO_Speed_10MHz | GPIO_CNF_OUT_PP );
// BUTTON_PINを入力に設定
// プルアップにする
funPinMode( BUTTON_PIN, GPIO_CNF_IN_PUPD );
funDigitalWrite( BUTTON_PIN, FUN_HIGH );
while(1)
{
// ボタンが押されているかをチェック
if ( funDigitalRead( BUTTON_PIN ) == FUN_LOW )
{
// D2 を HIGH に設定して LED を点灯
funDigitalWrite( LED_PIN, FUN_HIGH );
}
else
{
// D2 を LOW に設定して LED を消灯
funDigitalWrite( LED_PIN, FUN_LOW );
}
Delay_Ms( 10 );
}
}
4. コード解説
プルアップにする
GPIO の入力モード設定としてプルアップ、プルダウンの設定が可能です。
ch32fun のサンプル でも使われているように funPinMode( <ピン>, GPIO_CFGLR_IN_PUPD ) 、 funDigitalWrite( <ピン>, FUN_HIGH ) でプルアップ設定が可能です。
ボタンを押した場合は、 D7 / PC5 → タクトスイッチ → GND とつながり、 D7 は LOW になります。
ただし 押していないとき は D7 はどこにもつながっていない状態となり、浮いてしまい不安定な状態となるため「何も押していないときは HIGH になる」 ようにします。
1行目
funPinMode(BUTTON_PIN, GPIO_CNF_IN_PUPD);
BUTTON_PIN を入力ピンにして、 Pull-Up / Pull-Down を使えるモードにしています。
2行目
funDigitalWrite( BUTTON_PIN, FUN_HIGH );
BUTTON_PIN は入力であるため、この状態で FUN_HIGH を書き込むと「内部プルアップを有効」にできるようです。
5. さらに詳細
プルアップ等の設定、関数仕様とかドキュメントがあれば知りたいのですが、基本豊富にあるサンプルコードなどを参考にしてねという感じなんですかね?
見当たらなかったので以下は理解した内容です。
#define funPinMode( pin, mode ) { GpioOf(pin)->CFGLR = (GpioOf(pin)->CFGLR & (~(0xf<<(4*((pin)&0xf))))) | ((mode)<<(4*((pin)&0xf))); }
#define funDigitalWrite( pin, value ) do{ GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf)); }while(0)
それぞれ、 CFGLR と BSHR レジスタを操作しているためリファレンスマニュアルを確認します。
CH32V003 のリファレンスマニュアルがこちら。7章に GPIO の説明があります。
https://www.wch-ic.com/downloads/CH32V003RM_PDF.html
GPIOx_CFGLR
GPIOx_CFGLR というポートコンフィグレーションレジスタで各ピンごとに、
CNFy[1:0] MODEy[1:0]
という4ビットで設定となります。上位2ビットで入力/出力の種類、下位2ビットで入力か出力(速度選択)かを設定しています。
先ほど1行目で設定していた GPIO_CNF_IN_PUPD は 0x08 の値のため Mode = 00b が 入力モード で、CNF = 10b のときに With pull-up and pull-down mode となっています。
GPIOx_BSHR
こちらは説明をみると、 BRy はこれらのビットに「1」を書き込むと対応する OUTDR のビットが 「0 」にクリアされます。
「0」を書き込むとなんの影響もない。
BSy はこれらのビットに「1」を書き込むと対応する OUTDR のビットが 「1」になります。
「0」を書き込むとなんの影響もない。
funDigitalWrite は 1<<((!(value))*16 + ((pin) & 0xf)) のようにして、 BSy, BRy の切り替えを行って書き込んでいるんですね。
よって、実際に何を書き込んでいるかは OUTDR をさらに次にあげる確認します。
GPIOx_OUTDR の ODRy ビット
2行目の funDigitalWrite( BUTTON_PIN, FUN_HIGH ); はプルアップ/プルダウン入力モードのときに、プルアップするかプルダウンするかを選択するものになります。説明をいかに翻訳します。
For output modes.
(y=0-7), the data output by the port. These data can
only be operated in 16-bit form. the I/O port
outputs the values of these registers externally.
For modes with drop-down inputs.
1: Pull-up input;
0: Pull-down input.
出力モードの場合。
(y=0-7)、ポートから出力されるデータ。これらのデータは 16ビット形式でのみ処理可能です。
I/Oポートは これらのレジスタの値を外部に出力します。
ドロップダウン入力を持つモードの場合。
1: プルアップ入力
0: プルダウン入力
よって、2行目で設定している FUN_HIGH は 0x01 であるため、プルアップ入力を設定していることになります。
以上より、入力モード(プルアップ/プルダウンモード)の上でプルアップ入力を設定となります。
最後に
想像以上にch32fun で動作させる場合、
example を参考に手直しすればトライアンドエラーでもいけはしますが理解するにはレジスタの知識が要るなと思いました。
実際とりあえずサンプル参考に動かしてみてから後から何やっているのかを調べる感じになってました(本当ならちゃんと理解してから動かした方がいい気はしますが)。
投稿者の人気記事



-
Ala
さんが
前の日曜日の22:08
に
編集
をしました。
(メッセージ: 初版)
ログインしてコメントを投稿する