編集履歴一覧に戻る
akira.keiのアイコン画像

akira.kei が 2025年12月19日16時29分50秒 に編集

初版

タイトルの変更

+

忘れられたUSB内蔵PIC16F1455をイマドキ使う(その2)

タグの変更

+

PIC

+

PIC16F1455

記事種類の変更

+

セットアップや使用方法

ライセンスの変更

+

(MIT) The MIT License

本文の変更

+

[<前の記事]() : [次の記事>]() ## CDC Basic Microchipの作ったデモは「文字を読んだら+1して返す」というものになっている。 ``` void MCC_USB_CDC_DemoTasks(void) { if( USBGetDeviceState() < CONFIGURED_STATE ) return; if( USBIsDeviceSuspended()== true ) return; if( USBUSARTIsTxTrfReady() == true) { uint8_t i; uint8_t numBytesRead; numBytesRead = getsUSBUSART(readBuffer, sizeof(readBuffer)); for(i=0; i<numBytesRead; i++) { switch(readBuffer[i]) { case 0x0A: case 0x0D: writeBuffer[i] = readBuffer[i]; break; default: writeBuffer[i] = readBuffer[i] + 1; break; } } if(numBytesRead > 0) putUSBUSART(writeBuffer,numBytesRead); } CDCTxService(); } ``` これを利用して「PCから送られた1文字を読んで、それが0x05(ENQ)だったら温湿度センサーに測定開始コマンドを送り、少し待って温湿度センサーのデータを6バイト読んで、PCに返す」というのを書いた(つもりだった)。 ところが1文字受信というのがどうもうまくいかない。試行錯誤して以下のようにしたらなんとかなった。 ``` void USB_CDC_Tasks(void) { uint8_t n; if( USBGetDeviceState() < CONFIGURED_STATE ) return; if( USBIsDeviceSuspended()== true ) return; n=getsUSBUSART(readBuffer, 1); if(n==1 && readBuffer[0]==ENQ) { rflg=1; lpcnt=0; I2C_WriteNBytes(ADDR,cmd,1); LED_Toggle(); } if(rflg) lpcnt++; if(lpcnt>LPMAX) { rflg=0; lpcnt=0; I2C_ReadNBytes(ADDR,writeBuffer,6); putUSBUSART(writeBuffer,6); } CDCTxService(); } ``` ## Copilotぇ 最終的にはちゃんとできたが、途中でうまくいかないので悩んでCopilotと相談してみたが、こいつが嘘ばっかりだった。曰く「USBUSARTIsTxTrfReady()というのは受信とは関係ない。USBUSARTIsRxReady()を使ったらどうか。」 なるほどなるほど。でもUSBUSARTIsRxReady()なんて定義されていないじゃん。「それは関数でなくマクロで定義されているので()をつけないで」 なるほどなるほど。でもUSBUSARTIsRxReadyって定義はプロジェクト内にないんだけど? 「そう無いんだ。こんなふうに定義せよ」と、もうこのあたりにCopilotに見切りをつけた。 結局、While(1)ループするたびに1文字読んで、読み込み数が0でなければフラグを立てて測定開始する、という感じにした。USB接続でなければ単純に20msディレイをタスク内に入れるんだが、なんかループがすごい勢いで回っているので、Task内ではインクリメントするだけにした。 このループカウントが一定数を超える(だいたい20msになるよう調整)くらいでセンサーから読んで返す、という感じにしたらちゃんとできた。Copilotの嘘を検証するためにCopilotに相談するという無駄作業。ユーザが多くて良質な記事が多いPythonプログラムと、ユーザが少なく細かいところまで記事にしないPICプログラムとではやはり賢さが違うようだ。