読者です 読者をやめる 読者になる 読者になる

PIC24F_btstackのマイコン側ソース解説

電子工作

以前トランジスタ技術GitHubに公開したBT_IOについて主な処理の解説

PIC24FのUSB HOSTでBluetooth通信を - hrdakinoriのいろいろ
hrdakinori/PIC24F_btstack · GitHub


mPORTxxxなど出てくる関数は、Microchip PIC24F Peripheral Libraryを使用しています
直接レジスタを操作せずにマイコンの周辺機能を使用できます
MPLAB XのXC16コンパイラに入っているライブラリでこのあたりにヘルプがあります
Microchip\xc16\v1.10\docs\periph_lib\Microchip PIC24F Peripheral Library.chm

マイコン側の処理

電源が入るとUSB HOSTでBluetoothのUSBドングルを認識してbtstackを初期化後
BluetoothのSPP(Serial Port Profile)でペアリング待ち状態になります。
USBドングルのLEDが点滅していると接続して通信できる状態のはずです。
スイッチの状態とLEDの点灯、消灯を送受信できます。

ポートの初期化

main.c

int main ( void )
{
〜省略〜
        // シリアル通信の送受信ピンの機能割り当て
        // ログを出力できます
	// Configure U2RX - put on pin 17 (RP8)
	RPINR19bits.U2RXR = 8;
	// Configure U2TX - put on pin 16 (RP7)
	RPOR3bits.RP7R = 5;

        // アナログポートとI/Oピンの共有ピンをI/Oに変更
	// Analog IN Disable
	AD1PCFG = 0xffff;

        // スイッチの入力ピンのプルアップを有効に
	EnablePullUpCN12;
        // LED接続ピンを出力に
	// Port output setup
	mPORTBOutputConfig(0x8000);
〜省略〜
}
スイッチの監視とSPPへの送信

sw_processは定周期に呼ばれます
ポートの変化があったらSPPで送信します。
swcountをカウントダウンして、チャタリング防止にポートの変化検出後しばらく見ないようにしています
main.c

static int sw_process(struct data_source *ds)
{
	static short swcount;
	static short lastsw;
	if(swcount == 0)
	{
                // ポートのデータ読み出し
		short sw = mPORTBReadBit(0x4000);
                // 変化があったら
		if(sw != lastsw)
		{
                        // スイッチの接続ピンの場合
			if(sw == 0x4000)
			{
                                // SPPでデータ"S0"を送ります
				bt_spp_send((uint8_t*)"S0",2);
			}else{
                                // SPPでデータ"S1"を送ります
				bt_spp_send((uint8_t*)"S1",2);
			}
                        // スイッチを監視しないカウント回数
			swcount = 1500;
                        // 現在の値を保存しておきます
			lastsw = sw;
		}
	}
	if(swcount != 0)
	{
                // カウントダウン
		swcount--;
	}
	return 0;
}
SPPからの受信

SPPからデータを受信するとbt_spp_recive_callbackが呼ばれます
packetに受信データ、sizeに受信サイズが入っています。
大きなデータは分割されて届く可能性があります
bt_spp.c

int bt_spp_recive_callback(uint16_t channel, uint8_t *packet, uint16_t size)
{
	packet[size] = 0;
    // 0番目のデータによって処理を分ける(今回は'l''L'のみ)
    // 送られてくるデータが"L1","L0"または"l1","l0"を想定
	switch(*(packet+0))
	{
		case 'l':
		case 'L':
            // 1番目のデータが'1'の場合
			if(*(packet+1) == '1')
			{
                                // LEDの接続されているポートを1に
				mPORTBSetBits(0x8000);
			}else{
                                // LEDの接続されているポートを0に
				mPORTBClearBits(0x8000);
			}
			break;
	}
	return 0;
}
装置名の変更

ここの文字を変更すると認識される装置名が変わります
bt_spp.c

void bt_packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
〜省略〜
// USBドングルのアドレス下2桁でフォーマット
                   if ( COMMAND_COMPLETE_EVENT(packet, hci_write_class_of_device) ) {
						sprintf(bt_localname,"PICBT%04x",bt_localid);
                        hci_send_cmd(&hci_write_local_name, bt_localname);
                   }
                   if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                        bt_flip_addr(event_addr, &packet[6]);
						bt_localid = ((event_addr[4] << 8) | event_addr[5]);
//                        printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
                        break;
                    }
〜省略〜
}
PIN番号の変更

ここの文字を変更するとPIN番号が変わります
bt_spp.c

void bt_packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
〜省略〜
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
〜省略〜
}

ペアリングの改善

このあたりを見てみるとよいかもです。
スキータイム計測機 開発日誌 トラ技9月号のBT_IOのペアリングを自動化する
leibunのテクニカルブログ: BTSTACKのペアリングを簡単にしてみる


C言語マイコンの周辺機能の解説などは他のサイトにお任せします
何かの参考になればよいのですが