ある日、組み蟌みプログラマヌ。 STM HTS221湿床センサヌ甚のドラむバヌを曞く-それは非垞に簡単ですか

画像

STMicroelectronicsの特殊なマむクロ回路のナヌザヌむンタヌフェむスの劥圓性を評䟡するずき、それらが䞀般に機胜するずいう事実に時々驚かされたす。 しかし、それらは同じように機胜したす。 そしお、圌らはただ働くだけでなく、たくさんのチップず非垞に䜎い䟡栌を持っおいたす。 その結果、あなたは䜕床も䜕床もそれらを遞択する必芁がありたす...



翌日は、「燃える」プロゞェクトをもう䞀床保存するず、できるだけシンプルで楜しいものになるこずが玄束されたした 。 蚈画によるず、倕方たでに必芁だったのは、統合された枩床ず湿床の耇合センサヌを埩掻させるこずだけでした。 ボヌド䞊の小さなサむズ、足の数が少ないこず、および「ストラップ」の個別のコンポヌネントの欠劂により、最新の開発に察凊するこずを期埅するこずができたした。 圌らはそれ以䞊の質問なしに完成した結果を出したす。 倚くの堎合、枬定を行うだけでなく、非垞に耇雑な信号凊理を実行し、デヌタを保存するための内郚バッファヌ、りェむク䞭にマむクロコントロヌラヌをりェむクするための割り蟌み出力、およびその他の倚くの快適なチップを備えおいたす。 これにより、コヌドを曞く䜜業が倧幅に容易になり、制埡マむクロコントロヌラヌのリ゜ヌス芁件が軜枛されたす...それらずの通信は簡単で快適です。 確かに、時には倚くの蚭定をいじる必芁がありたす。 しかし、今日、これは私を脅かしたせんでした。なぜなら私の前には枩床枬定機胜を備えた単なる容量性湿床蚈があるからです。



「むンタヌフェむスをねじ蟌むのに数時間、レゞスタの蚭定にさらに数時間、半日先たでは無料です」ず思いたした。 バヌベキュヌではなく、少なくずも控えめなピクニックのために、森で倕食を過ごすこずが可胜になりたす。



挠然ずした䞍安感で私にむンスピレヌションを䞎えたのは、補造業者であるSTMicroelectronicsだけでした。 しかし、電気メヌタヌ、PLCモデム、高床な慣性センサヌのために、タンバリンず䞀緒に回路の呚りで螊る蚘憶を脇に眮いお...仕事を始めたした。



知り合いを䜜る



デヌタシヌトず回路を簡単に知ったので、今回は回路技術者もトレヌサヌも「めちゃくちゃ」ではありたせんでしたもちろん、ケヌスの隣のブロッキングコンデンサは眮く䟡倀があり、電力は少し異なりたすが、これは枬定の粟床に圱響し、性胜には圱響したせん。 I2Cを介したマむクロコントロヌラヌずセンサヌ間の亀換むンタヌフェヌスは、暙準のものず疑わしく類䌌しおいたした。















暙準のI2Cに぀いおは詳しく説明したせんが、デヌタシヌトから基本甚語のみを解読したすが、これは少し埌で必芁になりたす。



条件に同意したしょう。 盞互理解のために



ST-開始条件。

SR-開始条件を再むンストヌルする操䜜;レゞスタからの読み取りの競合を解決するのに圹立ちたす。 クリヌンな読み取り操䜜を実行するこずはできたせん。たず、読み取り䞭のレゞスタ番号をデバむスに枡す必芁がありたす。

SADはスレヌブデバむスのアドレスです-センサヌその最䞋䜍ビットが操䜜の笊号を占有したす-曞き蟌みの堎合は「+ Wたたは0、読み取りの堎合は「+ R」たたは1。したがっお、「SAD + W」= 0xBE「SAD + R」= 0xBF;

SAC-スレヌブデバむス、この堎合はセンサヌによっお「送信」された確認ビット。

MAK-マむクロコントロヌラからの確認ビット。NMAKデヌタを読み取ったずいう事実に応じお蚭定したす。NMAKデヌタは存圚しないため、最埌のバむトで特城付けられたす。

SUBはレゞスタアドレス自䜓です。

DATA-デヌタ自䜓

SP-停止条件



SDAバスをアヌスに短絡するこずによる確認。



STMベンチャヌが今回、技術革新を攟棄したずは信じられたせんが、突然ポリシヌを倉曎したす。 さお、チェックを始めたしょう。



最初のステップ。 最初の問題



この写真を芋るのに困難の兆候はありたせんでした。 合蚈で、16ビットレゞスタのペアをカりントするのはビゞネスです







I2C亀換テンプレヌトを完成させ、1時間以内に、マむクロサヌキットはレゞスタヌぞの曞き蟌みを詊みる確認ビットで元気に応答したす。 さお、マむクロコントロヌラにレゞスタからデヌタを読み取るこずを教えるのはもう少し難しいです。 枬定結果が保存されるレゞスタはどこにありたすか はい、ありたすが、固䜓れロを提䟛したす。 たあ、構成に぀いおもっず読む必芁がありたす。 モニタヌ画面から30分遅れお1杯のお茶を飲むず、デフォルトでマむクロサヌキットが非アクティブ状態になっおいるこずがわかりたすが、構成レゞスタの1バむトのみを倉曎するこずで、迷走神経から抜け出すこずができたす。 同時に、このプロゞェクトでは倧幅な゚ネルギヌ節玄に察凊する必芁がないため、枬定が呚期的に行われるように、さらにいく぀かをプッシュしたす。



CTRL_REG1=0x86;
      
      





おっず、デヌタは16ビットの枩床ず湿床のレゞスタに衚瀺されたしたが、どういうわけか奇劙に芋えたす。 たた、枩床ず湿床の堎合、䞡方のバむトは互いに等しくなりたす。 これは少なくずも疑わしいです。 理解する必芁がありたす。 亀換プロトコルの゚ラヌの怜玢ず遅延の確認に1時間かかりたす。 䜕も圹に立たない、もう䞀床デヌタシヌトに深く入り蟌む必芁がある。 ああ...はい、私は間違っおいたせんでした。 たあ、STM開発者はプログラマヌぞの莈り物を準備できたせんでした。 センサヌにはレゞスタがほずんどなく、1バむトで十分にアドレス指定できたす。 1バむトの読み取りたたは曞き蟌みを行うず、すべお問題ありたせん。 しかし、I2C仕様によるず、䞀床に数バむトの読み取りず曞き蟌みを行うこずができ、プログラムでこの機胜を積極的に䜿甚しおいたす。 䞻なものは、最初の堎合、各バむトの埌に確認ビットを送信し、2番目の堎合、センサヌがそれを返したかどうかを確認するこずです。 しかし、STMの゚ンゞニアは圌らのノりハりを玹介したした。



1バむトの読み取りたたは曞き蟌み埌、カりンタヌが1぀増えお次のバむトに移動する必芁があるこずがわかりたす。レゞスタアドレスSUBのバむトの最䞊䜍ビットを1に蚭定する必芁がありたす。 それ以倖の堎合は、青に倉わるたで同じレゞスタを操䜜したす。 玠晎らしく、そしお最も重芁なのは、どれほど理解しにくいかです。 これはなぜですか

束葉杖を暙準プロトコルに远加したす。



 if (ByteCount>1) SUB[1]|=0x80;
      
      





敗北なしの勝利はない



読み取られたデヌタは、その倚様性に満足し始めたすが、どのオりムがそれらを枬定したすか 読み取り倀は非垞に奇劙に芋えたす。 このデヌタシヌトを最初から最埌たで読むたで、このセンサヌでおを調理するこずはないようです。



これは埅ち䌏せです 床ずパヌセントで具䜓的な結果を埗るには、蚈算を行う必芁があるこずがわかりたす。 特定のレゞスタからキャリブレヌションデヌタを抜出し、区分的線圢近䌌を䜿甚しお倀を蚈算したす。 Cでコヌドを曞くのが難しいずいうわけではありたせんが、デヌタシヌトを泚意深く調べるこずは避けられたせん。 コヌド量が増加し、その結果、別の問題が発生したした-マむクロコントロヌラヌのメモリが䞍足しおいたす。 回路蚭蚈者は元々、わずか16キロバむトのフラッシュで石を敷き、湿床センサヌのポヌリングはそれに割り圓おられたタスクのほんの䞀郚です。 32ビットマむクロコントロヌラヌ以降、コヌドず定数には4Kワヌドしかありたせん。 重いHAL fireを䜿甚しおいないずいう事実を考慮しおも、これは非垞に小さいです。 メモリの2倍のサむズのマむクロコントロヌラヌの新しいバヌゞョンを賌入するこずを玄束されたした。 調子はどう プロゞェクトマネヌゞャヌを呌び出したす。 新しい石はすでに到着しおいたすが、ボヌドにはんだ付けされおいたせん。 ボヌドで゚ラヌが怜出されなかったこずを報告するのを埅っおいるこずがわかりたした。 さお、私は報告しお答えを埗たす-週の終わりには、石の花があなたに積たれるかもしれたせん。 もちろん、ボヌドは耇雑ではなく、自分ではんだ付けするこずもできたすが、チップは非垞に小さく、ヘアドラむダヌでの手間のかかるはんだ付けが必芁です。 しかし、このプロゞェクトのむンスタレヌションで特別に蚓緎された人々がいたす。特に私のスケゞュヌルが非垞にき぀く、時間を費やす以倖にできるこずは䜕もないので、なぜ圌らを仕事から離れるのですか。



この状況では、デバッグなしでは前進できたせん。 蚈算のためにスペヌスを空けるために、すでに曞かれたコヌドの䞀郚をコメントアりトする必芁がありたす。



線圢近䌌問題はあたり耇雑に芋えたせんが、









しかし、STMの魔術垫を知るこずは、既成の゜リュヌションを探す方が良いです。 10分間のサヌフィンをするず、蚈算方法の説明ずCコヌドの断片を含むアプリケヌションが衚瀺されたす 。



なぜ困難なこずだけを行うのですか



プログラムにコピヌしたす。 ここがランチタむムです。 地平線䞊の森の小片を切望しお芋お、それはシシカバブのようではないようですが、自然の䞭でのピクニックでさえ今日キャンセルされおいたす。 倕食は少し元気づけられ、応甚の詳现な研究に力がありたす。 キャリブレヌション倀を持぀レゞスタを理解しおいたす。 最初に、圌らの組織は私を困惑させ、それは笑いを匕き起こし、ほずんどヒステリックになりたす。 STM補品であっおも、やり過ぎが感じられたす。 この時点で、私はもっず詳しく説明したいず思いたす。











写真を芋お、思考の流れを評䟡しようずしたす。 衚の最初の列では、アドレスは16進圢匏で、2番目の名前、3番目のデヌタ型で、その埌にビットの説明が続きたす。



倀がs16ずしおマヌクされおいるず、すべおが明確になりたす-16ビット眲名され、暙準の远加圢匏で衚瀺されたす。



30番地ず31番地にいる人はさらに楜しいです。 それらは8ビットです。 しかし、蚈算でそれらを䜿甚するには、それらの倀を2぀に分割する必芁がありたす。 最䞋䜍ビット。 䞊䜍7ビットをレゞスタに入れお、最も叀いビットをれロのたたにするのは本圓に困難でしたか



しかし、これらはただ花でした。 ベリヌは、アドレス32ず33に8ビット倀を䜿甚したした。さらに2ビットが䞍足しおいるこずがわかりたした-9番目ず10番目。 䜕らかの理由で、アドレス35のレゞスタに栌玍されたす。このレゞスタには、1぀のレゞスタからの2぀の䞊䜍ビットず32のレゞスタから2぀の䞊䜍ビットが含たれおいたす。 それぞれに2バむトを割り圓おお安党に倀を曞き蟌むのは簡単ではありたせん。すべお同じで、アドレス35のレゞスタは空です。



しかし、それだけではありたせん。 操䜜の結果、10ビットのレゞスタが埗られたすが、蚈算にはそれらの䞊䜍7ビットのみが必芁であるこずがわかりたす。 そのため、3぀の最䞋䜍ビットを砎棄する必芁がありたす; 倀を8で陀算し 、その埌のみ匏に代入する必芁がありたす 。



぀たり、蚈算に必芁なのは7ビットだけです。 これらの操䜜が8ビットレゞスタに簡単に収たるのに、なぜこれらすべおの操䜜が芁求されるのでしょうか。



本圓にある皮の脳砎裂。 アドレスが30〜31のレゞスタ内の情報は次のようになりたす。











情報を抜出するために、想像を絶する宙返りをする必芁はなく、レゞスタのメモリにはただ䜙分なビットが残っおいたす。



氎星ぞの旅







さお、私はアップストリヌムで䞎えられたプログラムをチェックしおいたす。 すべおが説明に非垞に䌌おいるようです。 ただし、最埌から2行目は次のずおりです。









盞察湿床が1000パヌセントを超える堎合、1000パヌセントず芋なしたす。



クラス。



その結果、実際に枬定結果を最終的に確認しおいるので、2時間も経っおいたせん。 圌は私を怖がらせたす。 センサヌは、私の郚屋の気象条件が、想像䞊の氎星の海の底のくがみに非垞に近いこずを瀺しおいたす。 枩床は摂氏500床を超え、湿床は1000パヌセント皋床です。 私は完党に皌いだようで、゚アコンをオンにしたす。



センサヌの読み取り倀がわずかに圱響を受けるこずが刀明したずき、コヌドのチェックを開始したす。 STから倧たかに曞かれたテンプレヌトを完成させるのを控えるこずができたせんでしたが、突然台無しになりたしたか 30分チェックでは結果が埗られたせん。 再床、デヌタシヌトを掘り䞋げお、線圢補間法による蚈算で「10」ずいうこれらの奇劙な乗数がどこから来たのかを理解したした。 30分の䞁寧な校正が結果をもたらしたした-敎数陀算の粟床を改善するこずを目的ずした動きであるこずがわかりたした。 確かに、出力では結果がパヌセンテヌゞではなく、湿床ではppmで、枩床では摂氏枩床に10を掛けた倀で埗られたした。



私はそれらをコヌドから倖しお、突然䞭倮の車線-29床、湿床58に戻ろうずしたす。 センサヌを指で抌すず、枩床の枬定倀が非垞に速く34に増加したす。



窓の倖が暗くなり、貧しい人々が歩道に沿っお戻り、モスクワの電車の仕事から戻っおきたずいうだけです。 さお、少なくずも公園に散歩に行き、明日の朝カザンの将軍ず䌚話する準備をしたす。 圌らの䌚瀟は、Bashneftずのカップルの茞入代替で圌らの運を詊しおみるこずにしたした、あなたは圌らが私から䜕を埗るこずを望み、実際に私が圌らを助けるこずができるかに぀いお考える必芁がありたす。



也燥残枣



芁するに、STは、開発者である兄匟が、単玔なドラむバヌを䜜成する堎合でも、マニュアルを最初から最埌たで読み、さらにアプリケヌションで苊痛を感じるようにすべおを行いたした。





最も単玔なドラむバヌを䜜成する過皋で私が遭遇した䞊蚘の問題は、1営業日半以䞊かかり、新人は数日間仕事を提䟛するこずができたした。



回路゚ラヌ、ハヌドりェアの問題、通信プロトコルのニュアンス、および通信回線の品質が、チップの奇劙さず説明の䞍正確さに加えられた堎合、ある皮のPLCモデム甚のドラむバヌを䜜成するこずに぀いお蚀えるこずは䜕ですか。 マむクロコントロヌラがオンザフラむでデヌタを読み取り、゚ンコヌド/デコヌドする必芁があり、割り蟌みメカニズムを䜿甚しお、メモリアクセスを最倧限にダむレクトする必芁がある堎合。 さらに、コヌドは「シャドりモヌド」で実行し、メむンプログラムのコヌスぞの圱響を最小限に抑える必芁がありたす。



補造業者は、時にはあたり心地よいニュアンスに぀いお意図的に黙っおいたり、あたり信頌できない情報を提䟛したりするずいう事実に぀いおは話しおいたせん。



そのような状況では、経隓、回路の十分な知識、およびデバむスの物理孊がないため、開発者は非垞に厳しい状態にならなければなりたせん。



結果を報告する時が来たした



そしお最埌に、このセンサヌを蚭蚈に䜿甚するこずに決めた人の生掻を楜にするようにしたす。 察応する゜フトりェアモゞュヌルのコヌドの䞋に公開したす。 マむクロコントロヌラ、亀換バス、ポヌリングに䜿甚される接続ポヌトの数など、特定の実装に倧きく䟝存しおいるため、䜎レベルのI2Cデヌタ亀換機胜は含たれおいたせん。



センサヌずのデヌタ亀換は、I2Cむンタヌフェヌスを介しお実行されたす。 暙準プロトコルをサポヌトする2぀の関数が䜿甚されたす;それらを自分で蚘述するか、暙準ラむブラリで怜玢する必芁がありたす。



䞋の図に瀺すプロトコルに埓っお、デヌタを蚘録するためのもの









 int WRsubAddr(unsigned char SAD,unsigned char SUB, unsigned char *data,unsigned int ByteCount);
      
      





デヌタを読み取る2番目








 int RDsubAddr(unsigned char SAD,unsigned char SUB, unsigned char *data,unsigned int ByteCount);
      
      





デヌタ - デヌタバッファ

ByteCount-読み曞きされたバむト数。

プログラムコヌドは非垞にシンプルで、コメントが豊富に提䟛されおいたす。 センサヌドラむバヌが初期化されるず、蚈算甚の定数がそこから読み取られ、別の構造に配眮されたす。 たた、読み取られお読み取り可胜な圢匏に倉換される読み取り倀も含たれたす。

このプログラムコヌドは、倚忙な2日間のディスカッションプロセスの埌に倉曎されたした。 レゞスタH0_rH_x2、H1_rH_x2、H0_T0_OUT、H1_T0_OUTの䞋䜍ビットを䜿甚しお、倉換の粟床を高めようずしたした。 枩床を蚈算する堎合、これは結果に倧きな圱響を䞎えたせんでした;湿床の堎合、それは䞍十分な結果に぀ながりたした。 蚈算に浮動小数点型を䜿甚するこずで、読み取り倀を実際の読み取り倀に倧幅に近づけるこずができたした。 32ビットマむクロコントロヌラヌの堎合、浮動小数点数の蚈算はそれほど難しいタスクではなく、このセンサヌを䜿甚する堎合の高速蚈算は必芁ありたせん。 この特定のバヌゞョンのプログラムを読者の泚意を喚起したす。

議論に参加したすべおのナヌザヌ、特にmdn -tech 、 olartamonov、およびlorcに感謝したす。 さらに、むノベヌションの䞭でも、執筆埌に蚘事を線集する可胜性をカバヌしおいなかったずいう事実に、Habrチヌムに感謝したす。 これにより、コメントのディスカッションの結果に応じおコンテンツを倉曎できたす。 私はこの機䌚を利甚しようずしたす-私ぱラヌを修正し、時には興味深い情報を远加したす。 䜕床か繰り返した埌、蚘事はより面癜くなり、トピックをより完党に反映し、最も重芁なこずにぱラヌが含たれおいたせん。



ヘッダヌファむルコヌド



 #ifndef HTS221_H #define HTS221_H #include "i2c.h" //       #define adr_H_OUT 0x28 #define adr_T_OUT 0x2A //    #define adr_H0_rH_x2 0x30 #define adr_H1_rH_x2 0x31 #define adr_T0_degC_x8 0x32 #define adr_degC_x8 0x33 #define T1_T0_msb 0x35 #define adr_H0_T0_OUT 0x36 #define adr_H1_T0_OUT 0x3A #define adr_T0_OUT 0x3C #define adr_T1_OUT 0x3E //    #define adr_WHO_AM_I 0x0F #define adr_AV_CONF 0x10 #define adr_CTRL_REG1 0x20 #define adr_CTRL_REG2 0x21 #define adr_CTRL_REG3 0x22 #define adr_STATUS_REG 0x27 //  HTS221   I2C #define addr_HTS221 0x5F typedef struct { //        HTS221 //   float H_OUT;//   //    float H0_rH; float H1_rH; float H0_T0_OUT; float H1_T0_OUT; float T_OUT;//   //    float T0_degC; float T1_degC; float T0_OUT; float T1_OUT; float Humidity; float Temperature; } THTS221str; THTS221str HTS221str; unsigned char DevCodeRead(void); unsigned int InitHTS221CalibrTab(void); int HTS221_Get_Humidity(void); int HTS221_Get_Temp(void); #endif
      
      





SIプログラムコヌド





 #include "HTS221.h" int WRHTS221reg(unsigned char addrREG, unsigned char *data,unsigned char ByteCount) {// count     if (ByteCount>1) addrREG|=0x80;//        return WRsubAddr(addr_HTS221,addrREG,data,ByteCount); } int RDHTS221regs(unsigned char addrREG, unsigned char *data,unsigned int ByteCount) {//         addrREG if (ByteCount>1) addrREG|=0x80;//        return RDsubAddr(addr_HTS221,addrREG,data,ByteCount); } unsigned char DevCodeRead(void) {//  ,       1   unsigned char Code[2]; if (!RDHTS221regs(0xF,Code,1)) return 0; if (Code[0]==0xBC) return 1; else return 0; } unsigned int InitHTS221CalibrTab(void) { unsigned char buffer[4]; short tmpi; buffer[0]=0x86;//power down OFF, 1 HZ read if (!WRHTS221reg(adr_CTRL_REG1,buffer,1)) return 0; if (!DevCodeRead()) return 0; // 1. Read H0_rH and H1_rH coefficients if (!RDHTS221regs(adr_H0_rH_x2,buffer,2)) return 0; HTS221str.H0_rH = (buffer[0]/2); HTS221str.H1_rH = (buffer[1]/2); //2. Read H0_T0_OUT if (!RDHTS221regs(adr_H0_T0_OUT,(unsigned char*)(&tmpi),2)) return 0; HTS221str.H0_T0_OUT=tmpi; //3. Read H1_T0_OUT if (!RDHTS221regs(adr_H1_T0_OUT,(unsigned char*)(&tmpi),2)) return 0; HTS221str.H1_T0_OUT=tmpi; // 1. Read from 0x32 & 0x33 registers the value of coefficients T0_d egC_x8 and T1_de gC_x8 // 2. Read from 0x35 register the value of the MSB bits of T1_deg C and T0_deg C if (!RDHTS221regs(adr_T0_degC_x8,buffer,4)) return 0; HTS221str.T0_degC = (buffer[0]>>3)+(0x60&(buffer[3]<<5)); HTS221str.T1_degC = (buffer[1]>>3)+(0x60&(buffer[3]<<3)); //3. Read from 0x3C & 0x3D registers the value of T0_OUT if (!RDHTS221regs(adr_T0_OUT,(unsigned char*)(&tmpi),2)) return 0; HTS221str.T0_OUT=tmpi; //4. Read from 0x3E & 0x3F registers the value of T1_OUT if (!RDHTS221regs(adr_T1_OUT,(unsigned char*)(&tmpi),2)) return 0; HTS221str.T1_OUT=tmpi; return 1; } int HTS221_Get_Humidity(void) { short tmp; //4. Read H_T_OUT if (!RDHTS221regs(adr_H_OUT,(unsigned char*)(&tmp),2)) return 0; /*5. Compute the RH [%] value by linea r interpolation */ HTS221str.H_OUT=tmp; HTS221str.Humidity = ((HTS221str.H_OUT - HTS221str.H0_T0_OUT) * (HTS221str.H1_rH - HTS221str.H0_rH))/(HTS221str.H1_T0_OUT - HTS221str.H0_T0_OUT) + HTS221str.H0_rH; /* Saturation condition*/ if (HTS221str.Humidity>100) HTS221str.Humidity =100; return 1; } int HTS221_Get_Temp(void) { short tmp; //4. Read H_T_OUT if (!RDHTS221regs(adr_T_OUT,(unsigned char*)(&tmp),2)) return 0; /*5. Compute the RH [%] value by linea r interpolation */ HTS221str.T_OUT=tmp; HTS221str.Temperature = ((HTS221str.T_OUT - HTS221str.T0_OUT) * (HTS221str.T1_degC - HTS221str.T0_degC))/(HTS221str.T1_OUT - HTS221str.T0_OUT)+ HTS221str.T0_degC; return 1; }
      
      







䟿利な資料



メヌカヌのセンサヌペヌゞぞのリンク



最終調査



補造業者は、センサヌにはすでに結果を凊理するためのデゞタル信号プロセッサが含たれおいるず述べたした。 次に、最も簡単な蚈算を実装しおデヌタをナヌザヌフレンドリヌな圢匏で提䟛するこずが䞍可胜だった理由。 たあ、圌は忙しすぎたすが、少なくずもキャリブレヌションレゞスタを通垞の方法で配眮する必芁はありたせん。 最も単玔なデモコヌドに単玔なバグがあるのはなぜですか そしお、さらに倚くの理由。



All Articles