第 31 章_Renesas MCU Zero Basic 導入チュートリアル シリーズ - WIFI および Bluetooth モジュール ドライバの実験

このチュートリアルは、Wei Dongshan Baiwen.com によって作成されたDShanMCU-RA6M5 開発ボードに基づいて書かれています。必要な学生はここから入手できます: https://item.taabao.com/item.htm?id=728461040949

サポート情報の入手: https://renesas-docs.100ask.net

ルネサス MCU ゼロベース エントリ シリーズ チュートリアルの概要: https://blog.csdn.net/qq_35181236/article/details/132779862


第31章 WIFI & Bluetoothモジュールドライバー実験

この章の目的

  • WiFi Bluetooth チップ W800 の通信プロトコルを理解する;
  • シリアル ポートを使用して AT コマンドを送受信し、開発ボード ネットワーキングを実装する方法を学びます。

31.1 W800 工場出荷時のファームウェアのプログラミング

W800 ファームウェアをプログラミングするときは、X/Y モデム シリアル ポート プロトコルを使用する必要があります。したがって、X/Y モデム プロトコルをサポートするシリアル ポート ツールが必要です (本書では Xshell を使用します)。

31.1.1 Xshell ソフトウェアのインストール

Xshell の無料試用版のダウンロード入口アドレスは次のとおりです。

https://www.xshell.com/zh/free-for-home-school/

Web サイトにアクセスして情報を入力すると、Xshell 担当者が、入力した電子メール アドレスに無料のダウンロード リンクを送信します。

電子メール内のリンクをコピーしてブラウザに貼り付け、ダウンロード、ダウンロード、インストールを行います。

31.1.2 Xshellの使用

Xshell がインストールされたら、ダブルクリックしてソフトウェアを実行し、ポップアップ セッション ウィンドウで [新規] をクリックしてシリアル ポート接続を追加します。

次に、次の図に示すように、「接続」項目でプロトコルを「シリアル」に設定します。

次に、「接続」の「シリアル ポート」に移動してシリアル ポートを選択します (下の図の COM20 は一例です。次のセクションの手順に従って USB シリアル ポートを使用して W800 を接続した後、ポートが異なる場合があります) ) を選択し、図に示すように通信パラメータを設定します。

設定後、右下の「接続」をクリックして、指定したシリアルデバイスに接続します。

31.1.3 ハードウェア接続

W800 のハードウェア インターフェイス図は次のとおりです。

上の図に示すようにハードウェアを接続した後、Xshell を使用してシリアル ポートを開き、次に上の図の WIFI_RESET ピンを GND に短絡して W800 をリセットします。その後、W800 は文字「C」を Xshell に送信し続けます。以下の図に示すように:

この状態に入ると、次のセクションの内容に従ってファームウェアをプログラムできます。

31.1.4 ファームウェアのプログラミング手順

W800 がプログラミング状態になったら、次の図に示すように、Xshell 表示ウィンドウでマウスを右クリックし、[転送] -> [YMODEM (Y)] -> [YMODEM で送信 (S)] を選択します。

次に、データ パッケージ内のファームウェアの場所に移動し、w800.fls を選択してプログラミングを開始します。

最後に、転送とプログラミングが完了するまで待ちます。

プログラミングが完了すると、W800 はまだプログラミング状態にあることを示す「C」を出力し続けます。この時点で、BOOT ピンを GND から切り離し、W800 を手動で再度リセットして、W800 が復帰できるようにします。以下の図に示すように、通常の動作状態です。

Xshell が「ユーザータスク」を出力すると、W800 が動作状態に入ったことを意味します。このとき、Xshell ウィンドウにコマンド「AT+」と車両キーを直接入力することができます (Xshell は入力コマンドを表示しません)。「+OK」が返されれば、次のようにファームウェアのプログラミングは成功です。形:

31.2 AT+ コマンドの概要

W800 のファームウェア AT+ コマンドについては、本書の付属資料に含まれる公式マニュアル「WM_W800_SDK_AT コマンド ユーザーマニュアル.pdf」に詳しく説明されています。

W800 は多くの AT+ コマンドをサポートしていますが、本書では一般的に使用されるいくつかのコマンドのみを示します。

命令 コマンド形式 応答 説明する
AT+ 「AT+\r\n」 「+OK\r\n\r\n」 テスト コマンド、応答 +OK はテストの成功を示します
AT+Z 「AT+Z\r\n」 「+OK\r\n\r\n」 ソフトウェア リセット後、+OK という応答は、リセット コマンドが正常に送信されたことを示します。リセット後、「ユーザー タスク」という応答が返されます。
AT+E 「AT+E\r\n」 「+OK\r\n\r\n」 切り替えコマンドをエコーする場合は、コマンドを 1 回入力すると状態が切り替わり、エコー状態では W800 がコマンドと結果を合わせて応答します。
AT+RSTF 「AT+RSTF\r\n」 「+OK\r\n\r\n」 FLASH で工場出荷時の設定を復元します。復元された設定は、システムが再起動されるまで有効になりません。
AT+WPRT "AT+WPRT=[!?][タイプ]\r\n" 例: AT+WPRT=0\r\n "+OK[=type]\r\n\r\n" 例: +OK=0\r\n\r\n ワイヤレスネットワークタイプの設定/照会:l 0:STA;l 2:SoftAP;l 3:APSTA
AT+WSCAN 「AT+WSCAN\r\n」 「+OK=……」 このコマンドは、無線ネットワークの種類が STA の場合にのみ有効で、無線ネットワークのスキャンに使用され、完了後に戻ります。
AT+SSID 「AT+SSID=[!?][SSID]」例:AT+SSID=100ask\r\n 「+OK[=ssid]\r\n」 ワイヤレスネットワーク名、つまりSSIDを設定/照会します。
AT+キー 「AT+KEY=[!?][フォーマット],[インデックス],[キー]\r\n」 「+OK[=フォーマット,インデックス,キー]\r\n」 ネットワークキーの設定/問い合わせ
AT+WJOIN 「AT+WJOIN\r\n」 「+OK=<bsid>,<type>…\r\n」 現在のネットワーク タイプが STA の場合、このコマンドの機能は AP に接続することです。現在のネットワーク タイプが SoftAP または APSTA の場合、このコマンドの機能は
AT+WLEAV 「AT+WLEAV\r\n」 「+OK\r\n\r\n」 無線ネットワークの種類が STA の場合、現在の無線ネットワークを切断するために使用されます。
AT+NIP 「AT+NIP=[!?][タイプ]…\r\n」 「+OK[=タイプ]…\r\n」 ワイヤレス ネットワーク カードが STA として機能する場合、このコマンドはローカル IP アドレスの設定/照会に使用されます。
AT+LKSTT 「AT+LKSTT\r\n」 +OK[=ステータス、IP、ネットマスク、ゲートウェイ、dns1、dns2]\r\n\r\n ローカルネットワーク接続ステータスのクエリ
AT+SKCT 「AT+SKCT=[プロトコル]…\r\n」 「+OK=<socket>\r\n」 ソケットを作成します。クライアント モードでは、接続が完了する (成功または失敗) まで待ってから戻ります。サーバー モードでは、作成が完了したらすぐに戻ります。
AT+SKCLS 「AT+SKCLS=<socket>\r\n」 「+OK\r\n\r\n」 指定されたソケットを閉じます。
AT+SKSND 「AT+SKSND=[ソケット],[サイズ]\r\n」 「+OK\r\n\r\n」 OK 応答後にデータ ストリームを送信する
AT+SKRCV 「AT+SKRCV=[ソケット],[サイズ]\r\n」 「+OK\r\n\r\n」 OK と応答すると、rxdata のデータがシリアル ポートに送信されます。

31.3 モジュール構成

この実験では UART のみを使用します。FSP で UART とそのピンを構成するには、前の操作を参照してください。この実験は構成結果のみを示しています。

31.3.1 ハードウェア接続

オンボード W800 の概略図を以下に示します。

使用される RA6M5 プロセッサ ピンは P505 と P506 で、SCI の UART6 の TX/RX ピンに対応します。

31.3.2 UARTモジュール構成

  1. UART6

  1. UART7

31.4 ドライバー

31.4.1 デバイスオブジェクトのカプセル化

「30.3 デバイスオブジェクトのカプセル化」をベースに、タイマーのデバイスオブジェクトを改良し、遅延機能を実現するタイムアウト機能を追加しました。コードは以下のように表示されます。

static struct TimerDev gSystickDevice = {
    
    
    .name = "Systick",
    .channel = 0xFF,
    .status = 0,
    .Init = SystickInit,
    .Start = NULL,
    .Stop = NULL,
    .Read = NULL,
    .Timeout = HAL_Delay,
    .next = NULL
};
void SystickTimerDevicesCreate(void)
{
    
    
    TimerDeviceInsert(&gSystickDevice);
    gSystickDevice.Init(&gSystickDevice);
}
static int HAL_Delay(struct TimerDev *ptdev, uint32_t timeout)
{
    
    
    if(NULL == ptdev)       return -EINVAL;
    if(0 == ptdev->status)  return -EIO;
    uint32_t dwStart = dwTick;
    uint32_t dwWait = timeout;

    /* Add a freq to guarantee minimum wait */
    if (dwWait < HAL_MAX_DELAY)
    {
    
    
        dwWait += (uint32_t)(1);
    }

    while((dwTick - dwStart) < dwWait)
    {
    
    
    }
    return ESUCCESS;
}

31.4.2 UARTの初期化

この実験では 2 つの UART を使用します。

  • UART6: WiFi Bluetooth チップ W800 と通信します。
  • UART7: デバッグ印刷。

UART6 の場合、W800 が毎回送受信するデータの長さが不定であるため、DTC や DMA を使用してデータ送信を補助するのは適切ではないため、リング バッファが使用されます。UART6 の初期化時にリング バッファが適用されましたが、UART7 はデバッグ シリアル ポートとしてリング バッファを使用しませんでした。コードは以下のように表示されます。

static struct RingBuffer *gWiFiBuffer = NULL;
static struct UartDev gWiFiDevice = {
    
    
    .name = "WiFi Uart",
    .channel = 6,
    .Init = UARTDrvInit,
    .Read = UARTDrvRead,
    .Write = UARTDrvWrite,
    .next = NULL
};
void UartDevicesCreate(void)
{
    
    
    UartDeviceInsert(&gLogDevice);
    UartDeviceInsert(&gWiFiDevice);
    gLogDevice.Init(&gLogDevice);
}
static int UARTDrvInit(struct UartDev *ptdev)
{
    
    
    if(NULL == ptdev)   return -EINVAL;
    
    switch(ptdev->channel)
    {
    
    
        case 0:case 1:case 2:
        case 3:case 4:case 5:
        case 6:
        {
    
    
            fsp_err_t err = g_uart6.p_api->open(g_uart6.p_ctrl, g_uart6.p_cfg);
            assert(FSP_SUCCESS == err);
            gWiFiBuffer = RingBufferNew(1024);
            assert(NULL != gWiFiBuffer);
            break;
        }
        case 7:
        {
    
    
            fsp_err_t err = g_uart7.p_api->open(g_uart7.p_ctrl, g_uart7.p_cfg);
            assert(FSP_SUCCESS == err);
            break;
        }
        case 8:case 9:
            break;
        default:break;
    }
    
    return ESUCCESS;
}

31.4.3 割り込みコールバック関数

UART6 および UART7 の場合、割り込みコールバック関数を提供する必要があります。動作は似ており、UART6 は「送信完了」と「受信完了」の両方の状況を処理する必要がありますが、UART7 は「送信完了」のみを処理する必要があります。UART6 割り込みコールバック関数のコードは次のとおりです。

void uart6_callback(uart_callback_args_t * p_args)
{
    
    
    switch(p_args->event)
    {
    
    
        case UART_EVENT_RX_COMPLETE:
        {
    
    
            break;
        }
        case UART_EVENT_TX_COMPLETE:
        {
    
    
            gUart6TxCplt = true;
            break;
        }
        case UART_EVENT_RX_CHAR:
        {
    
    
            gWiFiBuffer->Write(gWiFiBuffer, (unsigned char*)&p_args->data, 1);
            break;
        }
        case UART_EVENT_ERR_PARITY:case UART_EVENT_ERR_FRAMING:
        case UART_EVENT_ERR_OVERFLOW:case UART_EVENT_BREAK_DETECT:
        case UART_EVENT_TX_DATA_EMPTY:
            break;
        default:break;   
    }
}
  • 11行目:UART6の送信完了フラグをtrueとして書き込みます。
  • 16 行目: データを受信した場合は、UART6 のバッファに書き込みます。

31.4.4 UART送信機能

UART デバイスの送信関数は比較的単純で、UART6 および UART7 デバイス構造の書き込み関数を呼び出すだけです。

static int UARTDrvWrite(struct UartDev *ptdev, unsigned char * const buf, unsigned int length)
{
    if(NULL == ptdev)   return -EINVAL;
    if(NULL == buf)     return -EINVAL;
    if(0 == length)     return -EINVAL;
    
    switch(ptdev->channel)
    {
        case 0:case 1:case 2:
        case 3:case 4:case 5:
        case 6:
        {
            fsp_err_t err = g_uart6.p_api->write(g_uart6.p_ctrl, buf, length);
            assert(FSP_SUCCESS == err);
            UART6WaitTxCplt();
            break;
        }
        case 7:
        {
            fsp_err_t err = g_uart7.p_api->write(g_uart7.p_ctrl, buf, length);
            assert(FSP_SUCCESS == err);
            UART7WaitTxCplt();
            break;
        }
        case 8:case 9:
            break;
        default:break;
    }
    return ESUCCESS;
}

31.4.5 UARTデータ読み出し機能

UART6 の場合、UART データを読み取るとき、データはリング バッファから読み取られます。UART7 の場合、FSP カプセル化関数を呼び出してデータを読み取ります。コードは以下のように表示されます。

static int UARTDrvRead(struct UartDev *ptdev, unsigned char *buf, unsigned int length)
{
    
    
    if(NULL == ptdev)   return -EINVAL;
    if(NULL == buf)     return -EINVAL;
    if(0 == length)     return -EINVAL;

    switch(ptdev->channel)
    {
    
    
        case 0:case 1:case 2:
        case 3:case 4:case 5:
        case 6:
        {
    
    
            if(gWiFiBuffer->Read(gWiFiBuffer, buf, length) != length)
                return -EIO;
            break;
        }
        case 7:
        {
    
    
            fsp_err_t err = g_uart7.p_api->read(g_uart7.p_ctrl, buf, length);
            assert(FSP_SUCCESS == err);
            UART7WaitRxCplt();
            break;
        }
        case 8:case 9:
            break;
        default:break;
    }
    return (int)length;
}

31.5 W800 WiFi Bluetooth モジュール

WiFi Bluetooth モジュールのデバイス ドライバー コードは、Devices/wifi_bluetooth フォルダーのファイル dev_wifi_bt.c/.h にあります。

31.5.1 W800の初期化

W800 を初期化するには、実際には W800 で使用されるシリアル デバイスを初期化する必要があります。つまり、UART6 を初期化します。

static UartDevice *pWiFiBtDev = NULL;
int WiFiBtDevInit(void)
{
    
    
    pWiFiBtDev = UartDeviceFind("WiFi");
    if(NULL==pWiFiBtDev) return -ENXIO;
    if(pWiFiBtDev->Init(pWiFiBtDev) != ESUCCESS)    return -EIO;
    
    return ESUCCESS;
}

31.5.2 AT+コマンド復帰判定

AT+ コマンドの概要で説明したように、各 AT+ コマンドには対応する応答があります。ほとんどのコマンドでは、受信した応答が「+OK」であるかどうかを判断するだけで済みます。この関数を次の関数にカプセル化します。

static int WiFiBtDevCmdRet(const char *ret)
{
    
    
    unsigned short timeout = 3000;
    unsigned char i = 0;
    unsigned char buf[128] = {
    
    0};
    while(timeout)
    {
    
    
        if(strstr((char*)buf, ret))
        {
    
    
            return ESUCCESS;
        }
        else if(strstr((char*)buf, "+ERR"))
        {
    
    
            return -EIO;
        }
        else if(pWiFiBtDev->Read(pWiFiBtDev, &buf[i], 1)==1)
        {
    
    
            printf("%c", buf[i]);
            i++;
        }
        mdelay(1);
        timeout--;
    }
    return -EIO;
}
  • 08行目:受信データから指定された応答文字列を読み出せた場合はESUCCESSを返します。
  • 行 12: 応答に「+ERR」がある場合は、コマンドが失敗し、-EIO が返されたことを意味します。
  • 行 16: 必要な応答またはエラー応答がない場合は、引き続きバッファからデータを読み取り、出力します。
  • 行 21 ~ 22: タイムアウト待機カウントダウン。タイムアウトして終了した場合は、-EIO を返します。

31.5.3 W800 の動作モードを設定する

W800 の WiFi 機能には、STA、SoftAP、APSTA の 3 つの動作モードがあり、列挙型を定義します。

typedef enum{
    
    
    STA     = 0,
    SoftAP  = 2,
    APSTA   = 3
}WorkType;

コマンド "AT+WPRT=<type>\r\n" ('\r' が必要であることに注意してください) を発行して、W800 の動作モードを設定します。具体的な実装は非常に簡単で、UART デバイスの write 関数を呼び出してこの文字列を送信し、応答を待つだけです。コードは以下のように表示されます。

int WiFiBtDevSetWorkType(WorkType type)
{
    
    
    char str[64];
    sprintf(str, "AT+WPRT=%d\r\n", type);
    if(pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)str, strlen(str)) != ESUCCESS)
        return -EIO;
    mdelay(100);
    return WiFiBtDevCmdRet("+OK");
}

31.5.4 W800のDHCPステータスを設定する

W800 がホットスポット接続後に自動的に IP アドレスを取得するようにしたい場合は、W800 の DHCP 機能を有効にする必要があります。W800 の IP アドレスを固定したい場合は、DHCP 自動割り当て機能をオフにする必要があります。そしてIPを指定します。

DHCP 機能を有効にするコマンドは「AT+NIP=0\r\n」です。コードは次のとおりです。

int WiFiBtDevEnableDHCP(void)
{
    
    
    int ret = -EIO;
    char *str = "AT+NIP=0\r\n";
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)str, strlen(str));
    if(ESUCCESS!= ret) return ret;
    mdelay(100);
    ret = WiFiBtDevCmdRet("+OK");
    return ret;
}

IP を手動で設定するには、コマンド「AT+NIP=1,[IP],[net_mask],[gate_way]\r\n」を使用します。これにより、DHCP 機能がオフになり、IP、サブネット マスク、デフォルト ゲートウェイを指定します。 。コードは以下のように表示されます。

int WiFiBtDevDisableDHCP(const char *ip, const char *netmask, const char *gateway)
{
    
    
    int ret = -EIO;
    char str[64];
    sprintf(str, "AT+NIP=1,%s,%s,%s\r\n", ip, netmask, gateway);
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)str, strlen(str));
    if(ESUCCESS!= ret) return ret;
    mdelay(100);
    ret = WiFiBtDevCmdRet("+OK");
    return ret;
}

31.5.5 指定されたホットスポットに接続する

ホットスポットに接続するには、次の 3 つのコマンドが必要です。

  • ホットスポットの名前を設定します: AT+SSID=[SSID]\r\n;
  • ホットスポットに接続するためのパスワードを設定します: AT+KEY=[キー形式],[キーインデックス番号],[キー文字列]\r\n;
  • ホットスポットに接続します: AT+WJOIN\r\n;

キーを設定するためのパラメータについて、マニュアルには次のように説明されています。

  • キー形式: 0-16 進形式、1-ASCII 形式。
  • キーインデックス番号: 1 ~ 4 は WEP 暗号化キーに使用され、他の暗号化方式は 0 に固定されます。
  • キー文字列: 二重引用符で囲まれています。さまざまなセキュリティ モードに従って、キーの長さと形式の要件は次のように定義されます。

この実験では、ホットスポットに接続するための 3 つの命令を関数にカプセル化しています。呼び出し元は、ホットスポットの名前とパスワードを渡すだけで済みます。

int WiFiBtDevConnectWiFi(const char *name, const char *password)
{
    
    
    int ret = -EIO;

    char ssid[32];
    sprintf(ssid, "AT+SSID=%s\r\n", name);
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)ssid, strlen(ssid));
    if(ESUCCESS != ret) return ret;
    mdelay(100);
    ret = WiFiBtDevCmdRet("+OK");
    if(ESUCCESS != ret) return ret;
    
    char key[32] ;
    sprintf(key, "AT+KEY=1,0,%s\r\n", password);
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)key, strlen(key));
    if(ESUCCESS != ret) return ret;
    mdelay(100);
    ret = WiFiBtDevCmdRet("+OK");
    if(ESUCCESS != ret) return ret;
    
    char join[32] = "AT+WJOIN\r\n";
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)join, strlen(join));
    if(ESUCCESS != ret) return ret;
    mdelay(100);
    ret = WiFiBtDevCmdRet("+OK");
    int ret1 = WiFiBtDevCmdRet("\r\n\r\n");
    if(ret==ESUCCESS && ret1)
        mdelay(1000);
    return ret;
}

31.5.6 ホットスポットからの切断

ホットスポットを切断するには、コマンド「AT+WLEAV\r\n」を送信するだけです。コードは次のとおりです。

int WiFiBtDevDisconnectWiFi(void)
{
    
    
    int ret = -EIO;
    char *leavw = "AT+WLEAV\r\n";
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)leavw, strlen(leavw));
if(ESUCCESS != ret) return ret;
mdelay(100);
ret = WiFiBtDevCmdRet(+OK”);
return ret;
}

31.5.7 ローカルIPの取得

ホットスポットが接続されており、DHCP 自動 IP 取得機能が有効になっている場合、ユーザーはマシンに割り当てられた IP アドレスを知りたい場合があります。このとき、コマンド「AT+LKSTT\r\n」を使用してクエリする必要があります。マシンの IP コードは以下のように表示されます。

int WiFiBtDevGetLocalIP(void)
{
    
    
    int ret = -EIO;
    char lkstt[32] = "AT+LKSTT\r\n";
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)lkstt, strlen(lkstt));
    if(ESUCCESS != ret) return ret;
    mdelay(100);
    unsigned short timeout = 100;
    while(timeout)
    {
    
    
        unsigned char c = 0;
        if(pWiFiBtDev->Read(pWiFiBtDev, &c, 1)==1)
        {
    
    
            printf("%c", c);
        }
        mdelay(1);
        timeout--;
    }
    return ESUCCESS;
}

このコマンドは「+OK」以降の内容を印刷する必要があるため、終了の判断が難しいため、すべてのデータを受信して​​から印刷するために、意図的に長いタイムアウトを設定しています。読者はコードを改良し、コードから IP を解析できます。

31.5.8 ソケット接続の確立

W800 がホットスポットに接続された後、コマンド「AT+SKCT」を使用してサーバーと通信する必要があります。このコマンドは、プロトコル、ローカル ロール、IP アドレス、リモート ポート、ローカル ポートなどの多くのパラメータを渡す必要があります。本書では、このコマンドのパラメータがカプセル化されており、次の構造を使用して接続情報を記述しています。

typedef enum{
    
    
    TCP = 0,
    UDP = 1
}NetworkProtocol;

typedef enum{
    
    
    Client = 0,
    Server = 1
}LocalRole;

typedef struct{
    
    
    NetworkProtocol Protocl;
    LocalRole       Role;
    char            *IP;
    unsigned int    RemotePort;
    unsigned int    LocalPort;
    unsigned int    SocketPort;
}ConnectInfo;

アプリケーション プログラムは ConnectInfo 構造体を構築し、AT コマンドを構築して W800 に送信する必要があります。ネットワーク接続機能で、接続に成功するとポート番号も記録されます。コードは以下のように表示されます。

int WiFiBtDevConnect(ConnectInfo *info)
{
    
    
    int ret = -EIO;
    char skct[128];
    sprintf(skct, "AT+SKCT=%d,%d,%s,%d,%d\r\n", \
                   info->Protocl, \
                   info->Role, \
                   info->IP, \
                   info->RemotePort, \
                   info->LocalPort
                   );
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)skct, strlen(skct));
    if(ESUCCESS != ret) return ret;
    mdelay(100);
    ret = WiFiBtDevCmdRet("+OK=");
    if(ESUCCESS != ret) return ret;
    /* 获取连接成功后的socket号 */
    unsigned short timeout = 1000;
    unsigned char i = 0;
    unsigned char buf[32] = {
    
    0};
    while(timeout)
    {
    
    
        if(strstr((char*)buf, "\r\n"))
        {
    
    
            printf("\r\n");
            break;
        }
        else if(pWiFiBtDev->Read(pWiFiBtDev, &buf[i], 1)==1)
        {
    
    
            printf("%c", buf[i]);
            i++;
        }
        mdelay(1);
        timeout--;
    }
    
    for(i=0;buf[i]!='\r'; i++)
    {
    
    
        if(buf[i]>='0' && buf[i]<='9')
        {
    
    
            buf[i] = buf[i] - '0';
            info->SocketPort = info->SocketPort*10 + buf[i];
        }
    }
    printf("IP:%s - SocketPort:%d\r\n", info->IP, info->SocketPort);
    
    return ret;
}
  • 37 行目: 返されたソケット番号の最後の番号の後には '\r' が続きます。この値はソケット番号を解析するときには必要ありません。したがって、for ループの判断では '\r' まで ASCII は実行されません。を読み取って数値に変換計算します。

31.5.9 指定されたソケットの切断

ネットワークから切断するために使用されるコマンドは、「AT+SKCLS=<socket>\r\n」です。本書では、次の機能がカプセル化されています。

int WiFiBtDevDisconnect(ConnectInfo info)
{
    
    
    int ret = -EIO;
    char skcls[32];
    sprintf(skcls, "AT+SKCLS=%d\r\n", info.SocketPort);
    ret = pWiFiBtDev->Write(pWiFiBtDev, (unsigned char*)skcls, strlen(skcls));
    if(ESUCCESS != ret) return ret;
    mdelay(100);
    ret = WiFiBtDevCmdRet("+OK");
    return ret;
}

31.6 テスト手順

この実験では、まずネットワーク デバッグ アシスタントを使用して Windows コンピューターの TCP サービスを開き、次にボードを起動します。ボード上のプログラムは、まず W800 を使用してホットスポットに接続し、次に Windows コンピュータへの TCP 接続を確立します。

テスト関数のコードは次のとおりです。

void WiFiBtAppTest(void)
{
    
    
    UartDevicesRegister();
    TimerDevicesRegister();
    
    WiFiBtDevInit();
    WiFiBtDevSetWorkType(STA);
    WiFiBtDevEnableDHCP();
    WiFiBtDevConnectWiFi("X-IOT", "x-iot.cq");
    WiFiBtDevGetLocalIP();
    
    ConnectInfo connect = {
    
    
        .Protocl = TCP,
        .Role = Client,
        .IP = "192.168.50.193",
        .RemotePort = 8080,
        .LocalPort = 1024
    };
    int ret = WiFiBtDevConnect(&connect);
    while(1)
    {
    
    
        if(ret != ESUCCESS)
        {
    
    
            ret = WiFiBtDevConnect(&connect);
            delay(1);
        }
    }
}

31.7 テスト結果

シリアル ポート アシスタントを開いて情報を確認し、ネットワーク アシスタントを開いて TCP サービスを開始します。次に、コンパイルされたバイナリ ファイルをボードに書き込んで実行すると、次の図に示すように、シリアル ポート アシスタント上の W800 の応答情報と、ネットワーク アシスタント上のネットワーク接続情報を確認できます。


この章の終わり

おすすめ

転載: blog.csdn.net/qq_35181236/article/details/132866703