0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Raspberry Pi Pico でタッチディスプレイを動かす

Last updated at Posted at 2025-11-14

pico_TouchPanel.jpg

Raspberry Pi Picoでも動かすことの出来そうなタッチディスプレイをスイッチサイエンスさんで買いました。
Waveshare 3.5型静電容量式タッチスクリーンディスプレイ(320 x 480、SPI/I2C接続)

製造メーカーのWikiはこちらです。
3.5inch Capacitive Touch LCD Wiki

C++サンプルコード

時代の流れなのか、RaspberryPiだからなのか、WikiのPicoのサンプルコードはMicroPythonだけでした。
そこで、Pico C/C++ SDKでビルド可能な同等機能のC++コードを書いてみました。ついでに余っているCPUコアでLチカする機能も加えました。
冒頭画像はこちらのコードで動いている様子です。

CMakeLists.txtでは次のソースファイルとライブラリーを加えて下さい。

add_executable(プロジェクト名 main.cpp LocalTouchLcd.cpp )
target_link_libraries(プロジェクト名 pico_stdlib pico_multicore hardware_spi hardware_gpio hardware_i2c)

作成したC++のソースコードとヘッダーファイルを以下に記します。

main.cpp
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "LocalTouchLcd.h"

void Core1Main(void);

int main()
{
    multicore_launch_core1(Core1Main);
	//----------------
	CLocalLcd *LLP = new CLocalLcd;
	(LLP->Init)();
	CLocalTouch *LTP = new CLocalTouch;
	(LTP->Init)();
    stdio_init_all();
	//----------------
	(LLP->LcdFill)(0xf800);
	sleep_ms(1000);
	(LLP->LcdFill)(0x07e0);
	sleep_ms(1000);
	(LLP->LcdFill)(0x001f);
	sleep_ms(1000);
	(LLP->LcdFill)(0xa33f);
	//----------------
    int nCnt = 0;
	while(1) {
		int nRet, nPosX, nPosY;
		nRet = (LTP->GetTouchXy)(&nPosX, &nPosY);
		if(nRet==0) {
			nCnt ++;
			(LLP->DrawSquare)(nPosX, nPosY, 4, 0xff00);
			printf("point x=%03d y=%03d %d\n", nPosX, nPosY, nCnt);
		}
    }
	//----------------
	delete LTP;
	delete LLP;
	return(0);
}


void Core1Main(void)
{
	gpio_init(PICO_DEFAULT_LED_PIN);
	gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);

	while(1) {
		gpio_put(PICO_DEFAULT_LED_PIN, 1);
		sleep_ms(500);
		gpio_put(PICO_DEFAULT_LED_PIN, 0);
		sleep_ms(500);
	}
}
LocalTouchLcd.cpp
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/i2c.h"
#include "LocalTouchLcd.h"

#define	LDEF_LCD_WIDTH		320
#define	LDEF_LCD_HEIGHT		480


//==============================================================================
// LCD class
//==============================================================================
#define LDEF_SPI_PORT		spi1
#define	LDEF_SPI_SCK		10
#define	LDEF_SPI_MOSI		11
#define	LDEF_SPI_MISO		12
#define	LDEF_LCD_RST		13
#define	LDEF_LCD_BL			15
#define	LDEF_LCD_DC			14
#define	LDEF_LCD_CS			9


CLocalLcd::CLocalLcd()
{
}


CLocalLcd::~CLocalLcd()
{
}


void CLocalLcd::Init(void)
{
	InitRpp();
	InitLcd();
}


void CLocalLcd::LcdFill(int nColor)
{
	int nLoop;
	unsigned char *bpArray = new unsigned char [2 * LDEF_LCD_WIDTH];
	unsigned char bUpper = (unsigned char)((nColor>>8) & 0xff);
	unsigned char bLower = (unsigned char)(nColor & 0xff);

	for(nLoop=0; nLoop<LDEF_LCD_WIDTH; nLoop++) {
		(bpArray[2*nLoop]) = bUpper;
		(bpArray[(2*nLoop)+1]) = bLower;
	}

	SetWindows(0, 0, LDEF_LCD_WIDTH, LDEF_LCD_HEIGHT);
	gpio_put(LDEF_LCD_DC, 1);
	gpio_put(LDEF_LCD_CS, 0);

	for(nLoop=0; nLoop<LDEF_LCD_HEIGHT; nLoop++) {
		SpiWriteBase(bpArray, (2 * LDEF_LCD_WIDTH));
	}
	gpio_put(LDEF_LCD_CS, 1);

	delete [] bpArray;
}


void CLocalLcd::DrawSquare(int nPosX, int nPosY, int nSize, int nColor)
{
	int nXstart = nPosX;
	int nYstart = nPosY;
	int nXend = nXstart + nSize;
	int nYend = nYstart + nSize;
	unsigned char sArray[] = {(unsigned char)(nColor>>8), (unsigned char)(nColor&0xff)};

	SetWindows(nXstart, nYstart, nXend, nYend);
	gpio_put(LDEF_LCD_DC, 1);
	gpio_put(LDEF_LCD_CS, 0);
	int nPixelAll = (nSize+1) * (nSize+1);
	for(int nLoop=0; nLoop<nPixelAll; nLoop++) {
		SpiWriteBase(sArray, sizeof(sArray));
	}
	gpio_put(LDEF_LCD_CS, 1);
}


void CLocalLcd::InitRpp(void)
{
	gpio_init(LDEF_LCD_CS);
	gpio_set_dir(LDEF_LCD_CS, GPIO_OUT);
	gpio_init(LDEF_LCD_RST);
	gpio_set_dir(LDEF_LCD_RST, GPIO_OUT);
	gpio_init(LDEF_LCD_BL);
	gpio_set_dir(LDEF_LCD_BL, GPIO_OUT);
	gpio_put(LDEF_LCD_BL, 1);
	gpio_put(LDEF_LCD_CS, 1);

	spi_init(LDEF_SPI_PORT, (10*1000*1000));
	gpio_set_function(LDEF_SPI_MISO, GPIO_FUNC_SPI);
	gpio_set_function(LDEF_SPI_SCK, GPIO_FUNC_SPI);
	gpio_set_function(LDEF_SPI_MOSI, GPIO_FUNC_SPI);

	gpio_init(LDEF_LCD_DC);
	gpio_set_dir(LDEF_LCD_DC, GPIO_OUT);
	gpio_put(LDEF_LCD_DC, 1);
}


void CLocalLcd::InitLcd(void)
{
	gpio_put(LDEF_LCD_RST, 0);
	busy_wait_us(100*1000);
	gpio_put(LDEF_LCD_RST, 1);
	busy_wait_us(10*1000);

	SpiWriteCmd(0x11);

	busy_wait_us(120*1000);

	SpiWriteCmd(0x36);
	SpiWriteData(0x08);

	SpiWriteCmd(0x3A);
	SpiWriteData(0x05);

	SpiWriteCmd(0xF0);
	SpiWriteData(0xC3);

	SpiWriteCmd(0xF0);
	SpiWriteData(0x96);

	SpiWriteCmd(0xB4);
	SpiWriteData(0x01);

	SpiWriteCmd(0xB7);
	SpiWriteData(0xC6);

	SpiWriteCmd(0xC0);
	SpiWriteData(0x80);
	SpiWriteData(0x45);

	SpiWriteCmd(0xC1);
	SpiWriteData(0x13);

	SpiWriteCmd(0xC2);
	SpiWriteData(0xA7);

	SpiWriteCmd(0xC5);
	SpiWriteData(0x0A);

	SpiWriteCmd(0xE8);
	SpiWriteData(0x40);
	SpiWriteData(0x8A);
	SpiWriteData(0x00);
	SpiWriteData(0x00);
	SpiWriteData(0x29);
	SpiWriteData(0x19);
	SpiWriteData(0xA5);
	SpiWriteData(0x33);

	SpiWriteCmd(0xE0);
	SpiWriteData(0xD0);
	SpiWriteData(0x08);
	SpiWriteData(0x0F);
	SpiWriteData(0x06);
	SpiWriteData(0x06);
	SpiWriteData(0x33);
	SpiWriteData(0x30);
	SpiWriteData(0x33);
	SpiWriteData(0x47);
	SpiWriteData(0x17);
	SpiWriteData(0x13);
	SpiWriteData(0x13);
	SpiWriteData(0x2B);
	SpiWriteData(0x31);

	SpiWriteCmd(0xE1);
	SpiWriteData(0xD0);
	SpiWriteData(0x0A);
	SpiWriteData(0x11);
	SpiWriteData(0x0B);
	SpiWriteData(0x09);
	SpiWriteData(0x07);
	SpiWriteData(0x2F);
	SpiWriteData(0x33);
	SpiWriteData(0x47);
	SpiWriteData(0x38);
	SpiWriteData(0x15);
	SpiWriteData(0x16);
	SpiWriteData(0x2C);
	SpiWriteData(0x32);

	SpiWriteCmd(0xF0);
	SpiWriteData(0x3C);

	SpiWriteCmd(0xF0);
	SpiWriteData(0x69);

	busy_wait_us(120*1000);

	SpiWriteCmd(0x21);

	SpiWriteCmd(0x29);
}


void CLocalLcd::SetWindows(int nXstart, int nYstart, int nXend, int nYend)
{
	unsigned char bData;

	SpiWriteCmd(0x2A);
	bData = (unsigned char)((nXstart >> 8) & 0xff);
	SpiWriteData(bData);
	bData = (unsigned char)(nXstart & 0xff);
	SpiWriteData(bData);
	bData = (unsigned char)((nXend >> 8) & 0xff);
	SpiWriteData(bData);
	bData = (unsigned char)(nXend & 0xff);
	SpiWriteData(bData);

	SpiWriteCmd(0x2B);
	bData = (unsigned char)((nYstart >> 8) & 0xff);
	SpiWriteData(bData);
	bData = (unsigned char)(nYstart & 0xff);
	SpiWriteData(bData);
	bData = (unsigned char)((nYend >> 8) & 0xff);
	SpiWriteData(bData);
	bData = (unsigned char)(nYend & 0xff);
	SpiWriteData(bData);

	SpiWriteCmd(0x2C);
}


void CLocalLcd::SpiWriteBase(unsigned char *bpTxBuf, int nLen)
{
	spi_write_blocking (LDEF_SPI_PORT, bpTxBuf, nLen);
}


void CLocalLcd::SpiWriteCmd(unsigned char bCmd)
{
	gpio_put(LDEF_LCD_DC, 0);
	gpio_put(LDEF_LCD_CS, 0);
	SpiWriteBase(&bCmd, 1);
}


void CLocalLcd::SpiWriteData(unsigned char bData)
{
	gpio_put(LDEF_LCD_DC, 1);
	gpio_put(LDEF_LCD_CS, 0);
	SpiWriteBase(&bData, 1);
	gpio_put(LDEF_LCD_CS, 1);
}


//==============================================================================
// Touch class
//==============================================================================
#define LDEF_I2C_PORT				i2c1
#define LDEF_I2C_ADDRESS			0x38
#define	LDEF_I2C_SDA				6
#define	LDEF_I2C_SCL				7
#define	LDEF_I2C_IRQ				8
#define	LDEF_I2C_RST				5
#define	LDEF_I2C_REG_NUM			0X02
#define	LDEF_I2C_REG_XY				0X03

static CLocalTouch *sctp;

CLocalTouch::CLocalTouch()
{
	CP = new tagClassParameter;
	memset(CP, 0, sizeof(tagClassParameter));
	sctp = this;
}


CLocalTouch::~CLocalTouch()
{
	delete CP;
}


void CLocalTouch::Init(void)
{
    i2c_init(LDEF_I2C_PORT, 400 * 1000);
    gpio_set_function(LDEF_I2C_SDA, GPIO_FUNC_I2C);
    gpio_set_function(LDEF_I2C_SCL, GPIO_FUNC_I2C);
    gpio_pull_up(LDEF_I2C_SDA);
    gpio_pull_up(LDEF_I2C_SCL);

    gpio_init(LDEF_I2C_IRQ);
    gpio_set_dir(LDEF_I2C_IRQ, GPIO_IN);
    gpio_pull_up(LDEF_I2C_IRQ);

	gpio_init(LDEF_I2C_RST);
	gpio_set_dir(LDEF_I2C_RST, GPIO_OUT);
    gpio_put(LDEF_I2C_RST, 1);
	sleep_ms(200);
    gpio_put(LDEF_I2C_RST, 0);
	sleep_ms(200);
    gpio_put(LDEF_I2C_RST, 1);
	sleep_ms(200);

	gpio_set_irq_enabled_with_callback(LDEF_I2C_IRQ, GPIO_IRQ_EDGE_FALL, true, CLocalTouch::IrqHandler);
}


int CLocalTouch::GetTouchXy(int *npOutX, int *npOutY)
{
	if((CP->nPointCount)==0) {
		return(-1);
	}
	(CP->nPointCount) = 0;
	(*npOutX) = (CP->nPosX);
	(*npOutY) = (CP->nPosY);
	return(0);
}


void CLocalTouch::IrqHandler(uint gpio, uint32_t events)
{
	unsigned char bCmd;
	unsigned char sRxBuf[64];
	int nRet, nLen, nLocalPC;
	//--------
	bCmd = LDEF_I2C_REG_NUM;
    i2c_write_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, &bCmd, 1, false);
	nRet = i2c_read_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, sRxBuf, 1, false);
	if(nRet==0) {
		return;
	}
	nLocalPC = (int)(sRxBuf[0]);
	nLen = (int)(sRxBuf[0]) * 6;
	//--------
	bCmd = LDEF_I2C_REG_XY;
    i2c_write_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, &bCmd, 1, false);
	nRet = i2c_read_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, sRxBuf, nLen, false);
	if(nRet==0) {
		return;
	}
	//--------
	(sctp->CP->nPosX) = LDEF_LCD_WIDTH - (((int)((sRxBuf[0])&0x0f) << 8) + (int)(sRxBuf[1]));
	(sctp->CP->nPosY) = ((int)((sRxBuf[2])&0x0f) << 8) + (int)(sRxBuf[3]);
	(sctp->CP->nPointCount) = nLocalPC;
	//printf("tpirq x=%03d y=%03d\n", (sctp->CP->nPosX), (sctp->CP->nPosY));
}
LocalTouchLcd.h
class CLocalLcd {
public:
	CLocalLcd();
	virtual ~CLocalLcd();
	void Init(void);
	void LcdFill(int nColor);
	void DrawSquare(int nPosX, int nPosY, int nSize, int nColor);

private:
	void InitRpp(void);
	void InitLcd(void);
	void SetWindows(int nXstart, int nYstart, int nXend, int nYend);
	void SpiWriteBase(unsigned char *bpTxBuf, int nLen);
	void SpiWriteCmd(unsigned char bCmd);
	void SpiWriteData(unsigned char bData);
};


class CLocalTouch {
public:
	CLocalTouch();
	virtual ~CLocalTouch();
	void Init(void);
	int GetTouchXy(int *npOutX, int *npOutY);
	typedef struct {
		int nPointCount;
		int nPosX;
		int nPosY;
	} tagClassParameter;
	tagClassParameter *CP;

private:
	static void IrqHandler(uint gpio, uint32_t events);
};

続きもご覧下さい。
Raspberry Pi Pico C/C++ SDK で LVGL

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?