yoshiyuki's blog

Arduino/Teensy/Raspberry pi pico を利用した I2C, SPI 通信アプリを紹介します

Raspberry Pi Pico Sample code / USB-Serial 通信で GPIO を制御する

Raspberry pi pico の C++ のサンプルコードです。

  • Raspberry pi pico の GP3-0 は Digital Output, GP7-4 は Digital Input になります
  • Raspberry pi pico は USB-serial 通信で1 byte 以上のデータを受信すると受信データと同じ数のデータを返信します
  • Raspberry pi pico は受信データの各 byte の Bit 3-0 の値に応じて GP3-0 の High/Low を制御します。例えば Bit 0 の値が 1 だった場合、GP0 の出力を High にします。Bit 7-4 の値は参照しません
  • Raspberry pi pico の返信データは、受信データに応じて GP3-0 を制御してから 1 msec 経過後の GP7-0 の High/Low 状態を示します。Bit 7-0 の値が GP 7-0 の High/Low 状態を示します。例えば 0xA5 が返信された場合、GP7, 5, 2, 0 が High、GP6, 4, 3, 1 が Low だったことを示します
  • Raspberry pi pico は受信データが複数 byte の場合、受信したデータを 1 byte ずつ、 1 msec 間隔で処理します。例えば 0x05, 0x0A の 2 byte を受信した場合:
    1. GP3/2/1/0 = Low/High/Low/High を出力する
    2. 1 msec 経過
    3. GP7-0 の High/Low 状態をデータにして返信する
    4. GP3/2/1/0 = High/Low/High/Low を出力する
    5. 1 msec 経過
    6. GP7-0 の High/Low 状態をデータにして返信する

USB-Serial 通信アプリの動作確認用に作成しました。

プロジェクトフォルダ: pico_test

pico_test
 |-- pico_sdk.import.cmake
 |-- CMakeLists.txt
 |-- module_serial
 |    |-- module_serial.h
 |    |-- module_serial.c
 |     -- CMakeLists.txt
  -- test_02
      |-- test_02.c
       -- CMakeLists.txt

pico_test\CMakeLists.txt

cmake_minimum_required(VERSION 3.12)

# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)

project(pico_ctrl C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})

# Initialize the SDK
pico_sdk_init()

include(example_auto_set_url.cmake)

# Add subdirectory
add_subdirectory(test_01)
add_subdirectory(module_serial)

pico_test\module_serial\module_serial.h

#ifndef MODULE_SERIAL_H
#define MODULE_SERIAL_H

uint32_t serial_available();

uint32_t serial_read(uint8_t *read_data, int read_data_length);

uint32_t serial_write(uint8_t *write_data, int write_data_length);

uint32_t serial_write_1byte(uint8_t write_data);

#endif

pico_test_module_serial\module_serial.c

#include <stdio.h>
#include "pico/stdlib.h"
#include "class/cdc/cdc_device.h"
#include "./module_serial.h"

uint32_t serial_available(){
    return tud_cdc_available();
}

uint32_t serial_read(uint8_t *read_data, int read_data_length){
    return tud_cdc_read(read_data, read_data_length);
}

uint32_t serial_write(uint8_t *write_data, int write_data_length){
    uint32_t uintTMP;
    uintTMP = tud_cdc_write(write_data, write_data_length);
    tud_cdc_write_flush();
    return uintTMP;
}

uint32_t serial_write_1byte(uint8_t write_data){
    int i = 0;
    uint8_t write_data_buffer[1];
    write_data_buffer[0] = write_data;
    while(tud_cdc_write_available() < 1){
        sleep_ms(1);
        i++;

        if(i > 1000){
            tud_cdc_write_clear();
        }
    }
    uint32_t uintTMP = tud_cdc_write(write_data_buffer, 1);
    tud_cdc_write_flush();
    return uintTMP;
}

pico_test\module_serial\CMakeLists.txt

add_library(module_serial
        module_serial.c
        )

# Pull in our pico_stdlib which pulls in commonly used features
target_link_libraries(module_serial pico_stdlib)

# enable usb output, disable uart output
pico_enable_stdio_usb(module_serial 1)
pico_enable_stdio_uart(module_serial 0)

pico_test\test_02\test_02.c

#include <stdio.h>
#include "pico/stdlib.h"

#include "../module_serial/module_serial.h"

int main() {
    int i;
    int cntDAT;
    uint8_t getDAT[1];
    uint8_t inDAT[256];
    uint8_t outDAT[256];

    stdio_init_all();   // Setup for Serial port

    for(i=0;i<8;i++){
        gpio_init(i);   // set GP0-7 to GPIO
        gpio_pull_down(i);  // enable pull-down for GP0-7

        if(i < 4){
            gpio_set_dir(i,true);   // set GP0-3 to Output
        }
        else{
            gpio_set_dir(i,false);  // set GP4-7 to Input
        }
    }

    while (true) {
        cntDAT = 0;

        while(serial_available() > 0){
            serial_read(getDAT, 1);
            inDAT[cntDAT] = getDAT[0];
            cntDAT++;
            sleep_ms(10);
        }

        if(cntDAT > 0){
            for(i=0;i<cntDAT;i++){
                gpio_put_all(0x00000000 | (0x0F & inDAT[i]));   // set GP0-3 output level
                sleep_ms(1);
                outDAT[i] = 0xFF & gpio_get_all();              // get GP0-7 state
            }

            for(i=0;i<cntDAT;i++){
                serial_write(outDAT + i, 1);
            }
        }
        
        sleep_ms(100);
    }
}

pico_test\test_02\CMakeLists.txt

add_executable(test_02
        test_02.c
        )

# Pull in our pico_stdlib which pulls in commonly used features
target_link_libraries(test_02 pico_stdlib module_serial)

# enable usb output, disable uart output
pico_enable_stdio_usb(test_02 1)
pico_enable_stdio_uart(test_02 0)

# create map/bin/hex file etc.
pico_add_extra_outputs(test_02)

# add url via pico_set_program_url
example_auto_set_url(test_02)