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?

PICとRPI4Bのuartシリアル通信 5. adc-TEMP

Last updated at Posted at 2025-01-20

初回、PICとRPI4Bの2.3Mbpsでの高速uart通信を実施しました。そしてPIC側では、キャラクターlcdとspi-sramを追加し、さらに前回は、DC-motorドライバーのTI社製DRV8835を使い、モーターを動かしました。今回は、ADコンバーターを追加してみます。

5.png

配線図です。MCP9700温度センサーを追加しただけです。MCP9700は、両端のピンをそれぞれ5Vと0Vに接続するだけで、温度に比例する電圧が真中のピンからアナログ出力されます。抵抗、コンデンサーも、必要ありません。プログラム上でADコンバーターを試行する時に便利です。室温~100℃前後まで、比較的高い直線性があります。室温付近では、0.5℃程度の誤差範囲です。プログラム中で温度較正表または較正式を適用すれば、相当な実用的精度がありますが、今回は較正していません。

RPI4B側のPythonプログラムは、初回と同じものを使います。

# RPI-0-uart-tx.py
# Serial Console OFF, Serial ON
# RPI4B Buster(x32) Python 3.7.3 (x32) Thonny, and RUN  or 
# RPI4B bookworm(x64) Python 3.11.2 Thonny, and RUN
    
import serial
    
#Open SERIALttyS0
SERIALttyS0 = serial.Serial('/dev/ttyS0', 2304000, timeout=1)
    
#Set SendMessage
SendMessage = "Hello PIC Im Pi.Hello PIC Im Pi."
    
#Send Command
SERIALttyS0.write(SendMessage.encode())
    
#Receive ReturnMessage and print
binary_ReturnMessage = SERIALttyS0.readline()
ReturnMessage = binary_ReturnMessage.decode()
print(ReturnMessage)
    
#Close SERIALttyS0
SERIALttyS0.close()

PIC側のプログラムは、A/Dコンバーターを追加しています。アナログ入力に設定しているRA5ピンの0~5Vの電圧を、PIC内蔵の10bitのA/Dコンバーターモジュールで、0~1023の数値に変換します。今回も、xc8とC18のプログラムです。
PIC18FのXC8プログラムです。

//main.c    MPLAB  X IDE v6.00,  XC8 Compiler v2.4.0,  (C90),   PICkit3
//pic18f2620 or 26k22
#include <xc.h>
#define _XTAL_FREQ 36864000
#define LED_A0		LATA0
#define lcd_B7		LATB7
#define lcd_B6		LATB6
#define lcd_B5		LATB5
#define lcd_B4		LATB4
#define lcd_stb_E	LATA1
#define lcd_rs		LATA2
#define SPIRAM1024_CS_TRIS		TRISC1
#define SPIRAM1024_CS_IO		LATC1
#define SPIRAM1024_SCK_TRIS		TRISC3
#define SPIRAM1024_SDI_TRIS		TRISC4
#define SPIRAM1024_SDO_TRIS		TRISC5
#define SPIRAM1024_SPI_IF 		SSPIF
#define SPIRAM1024_SSPBUF		SSPBUF
#define SPIRAM1024_SPICON1		SSPCON1
#define SPIRAM1024_SPICON1bits	SSPCON1bits
#define SPIRAM1024_SPICON2		SSPCON2
#define SPIRAM1024_SPISTAT		SSPSTAT
#define SPIRAM1024_SPISTATbits	SSPSTATbits 
#define FXMA_CS0_TRIS	TRISC0
#define FXMA_CS0_IO		LATC0

//2620
#pragma config OSC = HSPLL
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = ON
#pragma config BOREN = OFF
#pragma config BORV = 3
#pragma config WDT = OFF
#pragma config WDTPS = 32768
#pragma config CCP2MX = PORTBE
#pragma config PBADEN = OFF
#pragma config LPT1OSC = OFF
#pragma config MCLRE = ON
#pragma config STVREN = OFF
#pragma config LVP = OFF
#pragma config XINST = OFF
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CP2 = OFF
#pragma config CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRT2 = OFF
#pragma config WRT3 = OFF
#pragma config WRTC = OFF
#pragma config WRTB = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTR2 = OFF
#pragma config EBTR3 = OFF
#pragma config EBTRB = OFF

////26k22
//#pragma config FOSC = HSHP
//#pragma config PLLCFG = ON
//#pragma config PRICLKEN = ON
//#pragma config FCMEN = OFF
//#pragma config IESO = OFF
//#pragma config PWRTEN = ON
//#pragma config BOREN = OFF
//#pragma config BORV = 190
//#pragma config WDTEN = OFF
//#pragma config WDTPS = 32768
//#pragma config CCP2MX = PORTC1
//#pragma config PBADEN = OFF
//#pragma config CCP3MX = PORTB5
//#pragma config HFOFST = OFF
//#pragma config T3CMX = PORTC0
//#pragma config P2BMX = PORTB5
//#pragma config MCLRE = EXTMCLR
//#pragma config STVREN = OFF
//#pragma config LVP = OFF
//#pragma config XINST = OFF
//#pragma config CP0 = OFF
//#pragma config CP1 = OFF
//#pragma config CP2 = OFF
//#pragma config CP3 = OFF
//#pragma config CPB = OFF
//#pragma config CPD = OFF
//#pragma config WRT0 = OFF
//#pragma config WRT1 = OFF
//#pragma config WRT2 = OFF
//#pragma config WRT3 = OFF
//#pragma config WRTC = OFF
//#pragma config WRTB = OFF
//#pragma config WRTD = OFF
//#pragma config EBTR0 = OFF
//#pragma config EBTR1 = OFF
//#pragma config EBTR2 = OFF
//#pragma config EBTR3 = OFF
//#pragma config EBTRB = OFF

static unsigned char vBANK01[256];
static unsigned char vBuffer[32];

near uint8_t i,j,k,p,q,r,s;
near unsigned char asci, cmd, data, data0, Temp1, Temp2;
near uint16_t Wi, Wi_last, num, Wj, Wk, Wp, Wq, Wr, Ws;
near uint32_t Di, Dj, Dk;

near uint32_t dAddress, dAddreNewHead, dLength, dTotalLengh;
near uint8_t Dummy, SPICON1Save;

////   lcd functions
void LCD__vBuffer32(void);
void LCD__Data(unsigned char data);
void LCD__Command(unsigned char cmd);
void LCD__Command_Upper(unsigned char cmd);
void LCD__Init(void);
void LCD__Clear(void);
void PUT_DATA(void);
void PUT_CMD(void);

////   SPIRAM1024 functions
void SPIRAM1024Init(void);
void SPIRAM1024GetArray(near uint32_t dAddress, near uint32_t dLength);
void SPIRAM1024PutArray(near uint32_t dAddress, near uint32_t dLength);

//// ADC function
uint16_t adconv(void);


void main()
{
    //2620
    ADCON0 = 0x00;
    ADCON1 = 0x0F;

    ////26k22
    //ANSELA = 0b00100000 ;    // AN4(RA5)
    //ANSELB = 0b00000000 ;
    //ANSELC = 0b00000000 ;

    TRISA  = 0b00100000 ;    // RA5
    TRISB  = 0b00000000 ;
    TRISC  = 0b00000000 ;
    PORTA  = 0b00000000 ;
    PORTB  = 0b00000000 ;
    PORTC  = 0b00000000 ;

    TRISC = 0x90;
    TXSTA = 0x24;
    RCSTA = 0x90;
    BAUDCON = 0x00;	
    SPBRG = 0x00;

    // sram init
    #if defined(SPIRAM1024_CS_TRIS)                
        SPIRAM1024Init();                            
    #endif    

    // lcd init
    LCD__Init();
    LCD__Command(0x01);
    LCD__Command(0x0c);

    Temp1=0x30;    
    for(i = 0; i < 32; i++)        
    {
        vBANK01[i]=Temp1;
        Temp1++;
    }

    for(i = 0; i < 32; i++)
    {
        vBuffer[i]=vBANK01[i];    
    }
    LCD__vBuffer32();
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);

    SPIRAM1024PutArray(0,  32);

    for(i = 0; i < 32; i++)        
    {
        vBuffer[i]=0x30;
        vBANK01[i]=0x30;
    }
    LCD__vBuffer32();
    __delay_ms(1000);

    SPIRAM1024GetArray(0, 32);
    for(i = 0; i < 32; i++)        
    {
        vBuffer[i]=vBANK01[i];    
    }
    LCD__vBuffer32();
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);

    FXMA_CS0_TRIS =0;
    FXMA_CS0_IO=0;

    Wi=0;
    Wi_last=31;
    for(; ; )
    {
        if (RCSTAbits.OERR)
        {
            RCSTAbits.CREN = 0;
            Temp1 = RCREG;
            RCSTAbits.CREN = 1;
        }
        if(RCIF==1) 
        {
            vBANK01[Wi]  = RCREG;
            Wi++;
        }
        if(Wi>Wi_last) {  break;  }
    }

    vBuffer[0] =0x48;  // H
    vBuffer[1] =0x45;  // E
    vBuffer[2] =0x4C;  // L
    vBuffer[3] =0x4C;  // L
    vBuffer[4] =0x4F;  // O
    vBuffer[5] =0x20;  // 
    vBuffer[6] =0x50;  // P
    vBuffer[7] =0x69;  // i
    vBuffer[8] =0x20;  // 
    vBuffer[9] =0x49;  // I
    vBuffer[10]=0x6D;  // m
    vBuffer[11]=0x20;  // 
    vBuffer[12]=0x50;  // P
    vBuffer[13]=0x49;  // I
    vBuffer[14]=0x43;  // C
    vBuffer[15]=0x40;  // @
    vBuffer[16]=0x0A;  // LF

    Wi=0;
    Wi_last=17;
    for(; ; )
    {
        //2620
        if(TRMT==1)
        ////26k22
        //if(TXSTAbits.TRMT==1)
        {
            TXREG  =  vBuffer[Wi];
            Wi++;
        }
        if(Wi>Wi_last) {  break;  }
    }

    FXMA_CS0_IO=1;

    SPIRAM1024PutArray(0, 256);

    for(i = 0; i < 32; i++)        
    {
    	vBuffer[i]=0x30;
    	vBANK01[i]=0x30;
    }
    
    dAddreNewHead = 0;
    SPIRAM1024GetArray(dAddreNewHead, 32);
 
    for(i = 0; i < 32; i++)        
    {
    	vBuffer[i]=vBANK01[i];    
    }
    LCD__vBuffer32();
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    __delay_ms(250);
    
    //// 2620 pwm,  Standard CCP1 and CCP2 init
    CCP1CON  = 0b00001100 ;
    CCP2CON  = 0b00001100 ;
    T2CON	= 0b00000010 ;
    CCPR1L   = 0 ;
    CCPR1H   = 0 ;
    CCPR2L   = 0 ;
    CCPR2H   = 0 ;
    TMR2     = 0 ;
    PR2      = 249 ;
    T2CONbits.TMR2ON   = 1 ;

    ////// 26K22 pwm,  Standard CCP4 and CCP5 init
    //CCPTMRS1 = 0b00000100 ;
    //CCP4CON  = 0b00001100 ;
    //CCP5CON  = 0b00001100 ;
    //T2CON	= 0b00000010 ;
    //T4CON	= 0b00000010 ;
    //CCPR4L   = 0 ;
    //CCPR4H   = 0 ;
    //CCPR5L   = 0 ;
    //CCPR5H   = 0 ;
    //TMR2     = 0 ;
    //TMR4     = 0 ;
    //PR2      = 249 ;         // G-p182
    //PR4      = 249 ;         // G-p182
    //T2CONbits.TMR2ON   = 1 ;
    //T4CONbits.TMR4ON   = 1 ;

    // ADC init
    ADCON0 = 0b00010001 ;
    ADCON1 = 0b00000000 ;
    ADCON2 = 0b10010101 ;
    __delay_us(8) ;

    //// details
    //// 2620 ADC init details,  (2620  E-pp223-225)
    //ADCON0 = 0b00010001 ;  // select AN4(RA5).  A/D Converter module is enabled
    // ADCON0 	— 		— 		CHS3 	CHS2 	CHS1 	CHS0 	GO/DONE 	ADON
    // 			0		0		0		1		0		0		0			1	
    //ADCON1 = 0b00000000 ;  // Vss and Vdd.  PCFG<2:0> = 111 by PBADEN = 0 in Confuguration Bits.   only AN4(RA5) A/D input by TRISA  = 0b00100000, not affected by analog input of ADCON1 (2620-E-p92).
    // ADCON1 	— 		— 		VCFG1 	VCFG0 	PCFG3 	PCFG2 	PCFG1 		PCFG0
    // 			0		0		0		0		0		0		0			0	
    //ADCON2 = 0b10010101 ;  // Right justified,  Acquisition Time 4Tad,  Conversion Clock FOSC/16
    // ADCON2 	ADFM 	— 		ACQT2 	ACQT1 	ACQT0 	ADCS2 	ADCS1 		ADCS0
    // 			1		0		0		1		0		1		0			1

    //// 26k22 ADC init details,  (26k22  G-pp149-152, pp295-298)
    //ADCON0 = 0b00010001 ;  // select AN4(RA5).  A/D Converter module is enabled
    // ADCON0 	— 		CHS4	CHS3 	CHS2 	CHS1 	CHS0 	GO/DONE 	ADON
    // 			0		0		0		1		0		0		0			1	
    //ADCON1 = 0b00000000 ;
    // ADCON1 	TRIGSEL	— 		— 		— 		PVCFG1 	PVCFG0 	NVCFG1		NVCFG0
    // 			0		0		0		0		0		0		0			0	
    //ADCON2 = 0b10010101 ; 
    // ADCON2 	ADFM 	— 		ACQT2 	ACQT1 	ACQT0 	ADCS2 	ADCS1 		ADCS0
    // 			1		0		0		1		0		1		0			1


    while(1) {

        num = adconv() ;
        for(i = 0; i < 32; i++)
        {
            vBuffer[i]=num/2;    
        }
        LCD__vBuffer32();


        LED_A0 = 1;
        //////////  ClockWise / Acceleration   //////////
        for(Wi=0; Wi<=1023; Wi++)
        {
            ////2620
            CCPR1L = Wi/4 ;
            CCPR2L = 0 ;
            //////26k22
            //CCPR4L = Wi/4 ;
            //CCPR5L = 0 ;
            __delay_ms(2) ;
        }
        //////////  ClockWise / Deceleration   //////////
        for(Wi=0; Wi<=1023; Wi++)
        {
            ////2620
            CCPR1L = (1023-Wi)/4 ;
            CCPR2L = 0 ;
            //////26k22
            //CCPR4L = (1023-Wi)/4 ;
            //CCPR5L = 0 ;
            __delay_ms(2) ;
        }
        ///////////////   Breake    ////////////////////////
        //// 2620
        CCPR1L = 255 ;
        CCPR2L = 255 ;
        ////// 26k22
        //CCPR4L = 255 ;
        //CCPR5L = 255 ;
        __delay_ms(250) ;
        __delay_ms(250) ;
        __delay_ms(250) ;
        __delay_ms(250) ;


        LED_A0 = 0;
        //////////  Counter-ClockWise / Acceleration   //////////
        for(Wi=0; Wi<=1023; Wi++)
        {
            ////2620
            CCPR1L = 0 ;
            CCPR2L = Wi/4 ;
            //////26k22
            //CCPR4L = 0 ;
            //CCPR5L = Wi/4 ;
            __delay_ms(2) ;
        }
        //////////  Counter-ClockWise / Deceleration   //////////
        for(Wi=0; Wi<=1023; Wi++)
        {
            ////2620
            CCPR1L = 0 ;
            CCPR2L = (1023-Wi)/4 ;
            //////26k22
            //CCPR4L = 0 ;
            //CCPR5L = (1023-Wi)/4 ;
            __delay_ms(2) ;
        }
        ///////////////   Breake    ////////////////////////
        //// 2620
        CCPR1L = 255 ;
        CCPR2L = 255 ;
        ////// 26k22
        //CCPR4L = 255 ;
        //CCPR5L = 255 ;
        __delay_ms(250) ;
        __delay_ms(250) ;
        __delay_ms(250) ;
        __delay_ms(250) ;
     }
}


//  SC1602BS lcd functios  //
void LCD__vBuffer32(void)
{
	uint8_t ii;
	LCD__Clear();
	for(ii = 0; ii < 16; ii++){
		data= vBuffer[ii];
		LCD__Data(data);
	}
	LCD__Command(0xC0);
	for(ii = 16; ii < 32; ii++){
		data= vBuffer[ii];
		LCD__Data(data);
	}
}

void LCD__Data(unsigned char data)
{
	uint8_t jj;
	for(jj=0; jj<=1; jj++)
	{
		if (jj==0)
			data0=data;
		else
			data0=data<<4;
		lcd_B7 = 0;
		lcd_B6 = 0;
		lcd_B5 = 0;
		lcd_B4 = 0;
		if((data0 & 0x80) != 0)
			lcd_B7 = 1;
		if((data0 & 0x40) != 0)
			lcd_B6 = 1;
		if((data0 & 0x20) != 0)
			lcd_B5 = 1;
		if((data0 & 0x10) != 0)
			lcd_B4 = 1;
		PUT_DATA();
	}
	__delay_us(50);
}

void LCD__Command(unsigned char cmd)
{
	uint8_t jj;
	for(jj=0; jj<=1; jj++)
	{
		if (jj==0)
			data0=cmd;
		else
			data0=cmd<<4;
		lcd_B7 = 0;
		lcd_B6 = 0;
		lcd_B5 = 0;
		lcd_B4 = 0;
		if((data0 & 0x80) != 0)
			lcd_B7 = 1;
		if((data0 & 0x40) != 0)
			lcd_B6 = 1;
		if((data0 & 0x20) != 0)
			lcd_B5 = 1;
		if((data0 & 0x10) != 0)
			lcd_B4 = 1;
		PUT_CMD();
	}
	__delay_us(50);
}

void LCD__Command_Upper(unsigned char cmd)
{
	lcd_B7 = 0;
	lcd_B6 = 0;
	lcd_B5 = 0;
	lcd_B4 = 0;
	if((data0 & 0x80) != 0)
		lcd_B7 = 1;
	if((data0 & 0x40) != 0)
		lcd_B6 = 1;
	if((data0 & 0x20) != 0)
		lcd_B5 = 1;
	if((data0 & 0x10) != 0)
		lcd_B4 = 1;
	PUT_CMD();
	__delay_ms(5);
}

void LCD__Clear(void)
{
	LCD__Command(0x01);
	__delay_ms(250);
}

void LCD__Init(void)
{
	__delay_ms(50);
	LCD__Command_Upper(0x30);
	LCD__Command_Upper(0x30);
	LCD__Command_Upper(0x30);
	LCD__Command_Upper(0x20);
	LCD__Command(0x2E);
	LCD__Command(0x08);
	LCD__Command(0x0D);
	LCD__Command(0x06);
	LCD__Clear();
}

void PUT_CMD(void)
{
	lcd_rs  = 0;
	_delay(1);
	lcd_stb_E = 1;
	_delay(4);
	lcd_stb_E = 0;
}

void PUT_DATA(void)
{
	lcd_rs  = 1;
	_delay(1);
	lcd_stb_E = 1;
	_delay(4);
	lcd_stb_E = 0;
}


//// no-pointer spi-sram 23LC1024 functions,  referred from Microchip
// opcodes
#define READ	0x03			// Read data from memory array beginning at selected address
#define WRITE	0x02			// Write data to memory array beginning at selected address
#define RDSR	0x05			// Read Status register
#define WRSR	0x01			// Write Status register
// define
#define PROPER_SPICON1	(0x20)		// SSPEN bit is set, SPI in master mode, FOSC/4, IDLE state is low level

void SPIRAM1024Init(void)
{
	SPIRAM1024_CS_IO = 1;
	SPIRAM1024_CS_TRIS = 0;
	SPIRAM1024_SCK_TRIS = 0;
	SPIRAM1024_SDI_TRIS = 1;	
	SPIRAM1024_SDO_TRIS = 0;
	// Save SPI state (clock speed)
	SPICON1Save = SPIRAM1024_SPICON1;
	SPIRAM1024_SPICON1 = PROPER_SPICON1;
	SPIRAM1024_SPI_IF = 0;
	SPIRAM1024_SPISTATbits.CKE = 1; 
	SPIRAM1024_SPISTATbits.SMP = 0;
	// Set Burst mode
	// Activate chip select
	SPIRAM1024_CS_IO = 0;
	SPIRAM1024_SPI_IF = 0;
	// Send Write Status Register opcode
	SPIRAM1024_SSPBUF = WRSR;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Set status register to 0b01000000 to enable burst mode
	SPIRAM1024_SSPBUF = 0x40;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Deactivate chip select
	SPIRAM1024_CS_IO = 1;
	// Restore SPI state
	SPIRAM1024_SPICON1 = SPICON1Save;
}

void SPIRAM1024GetArray(near uint32_t dAddress, near uint32_t dLength)
{
	if(dLength == 0)
		return;
	// Save SPI state (clock speed)
	SPICON1Save = SPIRAM1024_SPICON1;
	SPIRAM1024_SPICON1 = PROPER_SPICON1;
	// Activate chip select
	SPIRAM1024_CS_IO = 0;
	SPIRAM1024_SPI_IF = 0;
	// Send READ opcode
	SPIRAM1024_SSPBUF = READ;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Send address
	SPIRAM1024_SSPBUF = ((uint8_t*)&dAddress)[2];
	while(!SPIRAM1024_SPI_IF);	
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	//
	SPIRAM1024_SSPBUF = ((uint8_t*)&dAddress)[1];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	//
	SPIRAM1024_SSPBUF = ((uint8_t*)&dAddress)[0];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Read data
	for(Dk = 0; Dk < dLength; Dk++)
	{
		SPIRAM1024_SSPBUF = 0;
		while(!SPIRAM1024_SPI_IF);
		vBANK01[Dk] = SPIRAM1024_SSPBUF;
		SPIRAM1024_SPI_IF = 0;
	}
	// Deactivate chip select
	SPIRAM1024_CS_IO = 1;
	// Restore SPI state
	SPIRAM1024_SPICON1 = SPICON1Save;
}

void SPIRAM1024PutArray(near uint32_t dAddress, near uint32_t dLength)
{
	if(dLength == 0)
		return;
	// Save SPI state (clock speed)
	SPICON1Save = SPIRAM1024_SPICON1;
	SPIRAM1024_SPICON1 = PROPER_SPICON1;
	// Activate chip select
	SPIRAM1024_CS_IO = 0;
	SPIRAM1024_SPI_IF = 0;
	// Send WRITE opcode
	SPIRAM1024_SSPBUF = WRITE;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Send address
	SPIRAM1024_SSPBUF = ((uint8_t*)&dAddress)[2];
	while(!SPIRAM1024_SPI_IF);	
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	//
	SPIRAM1024_SSPBUF = ((uint8_t*)&dAddress)[1];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	//
	SPIRAM1024_SSPBUF = ((uint8_t*)&dAddress)[0];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Write data
	for(Dk = 0; Dk < dLength; Dk++)
	{
		SPIRAM1024_SSPBUF = vBANK01[Dk];
		while(!SPIRAM1024_SPI_IF);
		Dummy = SPIRAM1024_SSPBUF;
		SPIRAM1024_SPI_IF = 0;
	}
	// Deactivate chip select
	SPIRAM1024_CS_IO = 1;
	// Restore SPI state
	SPIRAM1024_SPICON1 = SPICON1Save;
}

// ADC function
uint16_t adconv()
{
     uint16_t temp;
     GO_nDONE = 1 ;
     while(GO_nDONE) ;
     temp = ADRESH ;
     temp = ( temp << 8 ) | ADRESL ;

     return temp ;
}

PIC18FのC18プログラムです。

// MainDemo.c     MPLAB_IDE_8_92,  MPLAB_C18_3.46,  PICkit3
#include <p18f2620.h>
//#include <p18f26k22.h>
#include <HardwareProfile.h>
#include <GenericTypeDefs.h>
#include <delays.h>

#pragma udata bank1  = 0x100
static unsigned char vBANK01[256];
#pragma udata bank2 = 0x200
static unsigned char vBuffer[32];

#pragma udata access my_access
near unsigned char asci, cmd, data, data0, Temp1, Temp2;
near BYTE i, j, k, ii, jj, kk;
near WORD Wi, Wi_last, num, Wj, Wk, Wp, Wq, Wr, Ws;
near DWORD Di, Dj, Dk;
near DWORD dAddress, dAddreNewHead, dLength, dTotalLengh;
near BYTE Dummy, SPICON1Save;

// LCD functions
void LCD__Data(void);
void LCD__vBuffer32(void);
void LCD__Command(void);
void LCD__Clear(void);
void LCD__Init(void);
void PUT_CMD(void);
void PUT_DATA(void);

// Time functions
void TIME50(void);
void TIME5M(void);

// SPI-SRAM1024 functions 
void SPIRAM1024Init(void);
void SPIRAM1024GetArray(near DWORD dAddress, near DWORD dLength);
void SPIRAM1024PutArray(near DWORD dAddress, near DWORD dLength);

// ADC function
WORD adconv(void);


#pragma code
void main(void){

	//2620
	ADCON0 = 0x00;		// (2620-E-p223)  all A/D Converter   disabled
	ADCON1 = 0x0F;		// (2620-E-p224)  A/D Port    all Digital
	PORTA  = 0b00000000 ;
	PORTB  = 0b00000000 ;
	PORTC  = 0b00000000 ;
	TRISA  = 0b00100000 ;	// (2620-E-p92)  only AN4(RA5) A/D input.  not affected by analog input of ADCON1
	TRISB  = 0b00000000 ;
	TRISC  = 0b00000000 ;

	////26k22
	//ANSELA = 0b00100000 ;	// (26k22-G-p149)  AN4(RA5) Digital input buffer disabled.   AN3-AN0 Digital input buffer enabled. 
	//ANSELB = 0b00000000 ;
	//ANSELC = 0b00000000 ;
	//PORTA  = 0b00000000 ;
	//PORTB  = 0b00000000 ;
	//PORTC  = 0b00000000 ;
	//TRISA  = 0b00100000 ;	//  (26k22-G-p150)  only RA5(AN4) configured as an input (tri-stated).  
	//TRISB  = 0b00000000 ;
	//TRISC  = 0b00000000 ;

	TRISC = 0x90;
	TXSTA = 0x24;
	RCSTA = 0x90;
	BAUDCON = 0x00;	
	SPBRG = 0x00;

	LCD__Init();

	#if defined(SPIRAM1024_CS_TRIS)				
		SPIRAM1024Init();							
	#endif																		

	Temp1=0x41;	
	for(i = 0; i < 32; i++)		
	{
		vBANK01[i]=Temp1;	
		_asm  INCF  Temp1, 1, 0  _endasm
	}
	for(i = 0; i < 32; i++)
	{
		vBuffer[i]=vBANK01[i];	
	}
	LCD__vBuffer32();
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);

	SPIRAM1024PutArray(0,  32);	    // SRAM Write

	for(i = 0; i < 32; i++)	    	   // clear buffer
	{
		vBuffer[i]=0x30;
		vBANK01[i]=0x30;
	}
	LCD__vBuffer32();
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);

	SPIRAM1024GetArray(0, 32);	    // SRAM Read	
	for(i = 0; i < 32; i++)		
	{
		vBuffer[i]=vBANK01[i];	
	}
	LCD__vBuffer32();
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);

	LED0_IO = 0;

	FXMA_CS0_TRIS = 0;
	FXMA_CS0_IO = 0;

	for(Wi = 0; Wi < 32; Wi++)
	{
		if (RCSTAbits.OERR) 
		{
			RCSTAbits.CREN = 0;
			Temp1 = RCREG;
			RCSTAbits.CREN = 1;
		}
		_asm BTFSS  PIR1, 5, 0  _endasm      // RCIF in P1R1 = 5
		_asm BRA -2	            _endasm
		vBANK01[Wi]  = RCREG;
	}

	vBuffer[0] =0x48;  // H
	vBuffer[1] =0x45;  // E
	vBuffer[2] =0x4C;  // L
	vBuffer[3] =0x4C;  // L
	vBuffer[4] =0x4F;  // O
	vBuffer[5] =0x20;  // 
	vBuffer[6] =0x50;  // P
	vBuffer[7] =0x69;  // i
	vBuffer[8] =0x20;  // 
	vBuffer[9] =0x49;  // I
	vBuffer[10]=0x6D;  // m
	vBuffer[11]=0x20;  // 
	vBuffer[12]=0x50;  // P
	vBuffer[13]=0x49;  // I
	vBuffer[14]=0x43;  // C
	vBuffer[15]=0x40;  // @
	vBuffer[16]=0x0A;  // LF

	////for(i = 0; i < 18; i++)		
	////{
	////	_asm BTFSS TXSTA, 1, 0  _endasm      // TRMT in TXSTA = 1
	////	_asm BRA   -2	        _endasm
	////	TXREG  =  vBuffer[i];
	////}

	FXMA_CS0_IO = 1;

	SPIRAM1024PutArray(0, 256);       // SRAM Write

	for(i = 0; i < 32; i++)		
	{
		vBuffer[i]=0x30;
		vBANK01[i]=0x30;
	}
	
	dAddreNewHead = 0;
	SPIRAM1024GetArray(dAddreNewHead, 32);    // SRAM Read

	for(i = 0; i < 32; i++)		
	{
		vBuffer[i]=vBANK01[i];	
	}
	LCD__vBuffer32();
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);
	Delay10KTCYx(250);

	//// 2620 pwm,  Standard CCP1 and CCP2(RB3) init
	CCP1CON  = 0b00001100 ;
	CCP2CON  = 0b00001100 ;
	T2CON	= 0b00000010 ;
	CCPR1L   = 0 ;
	CCPR1H   = 0 ;
	CCPR2L   = 0 ;
	CCPR2H   = 0 ;
	TMR2	 = 0 ;
	PR2	  = 249 ;
	T2CONbits.TMR2ON   = 1 ;

	////// 26K22 pwm,  Standard CCP4 and CCP5 init
	//CCPTMRS1 = 0b00000100 ;
	//CCP4CON  = 0b00001100 ;
	//CCP5CON  = 0b00001100 ;
	//T2CON	= 0b00000010 ;
	//T4CON	= 0b00000010 ;
	//CCPR4L   = 0 ;
	//CCPR4H   = 0 ;
	//CCPR5L   = 0 ;
	//CCPR5H   = 0 ;
	//TMR2	 = 0 ;
	//TMR4	 = 0 ;
	//PR2	  = 249 ;		 // G-p182
	//PR4	  = 249 ;		 // G-p182
	//T2CONbits.TMR2ON   = 1 ;
	//T4CONbits.TMR4ON   = 1 ;

	//// ADC init
	ADCON0 = 0b00010001 ; 
	ADCON1 = 0b00000000 ; 
	ADCON2 = 0b10010101 ;
	Delay10TCYx(5);

	//// details
	//// 2620 ADC init details,  (2620  E-pp223-225)
	//ADCON0 = 0b00010001 ;  // select AN4(RA5).  A/D Converter module is enabled
	// ADCON0 	— 	 	— 	 	CHS3 	CHS2 	CHS1 	CHS0 	GO/DONE 	ADON
	// 		 	0	 	0	 	0	 	1	 	0	 	0	 	0		 	1	
	//ADCON1 = 0b00000000 ;  // Vss and Vdd.  PCFG<2:0> = 111 by PBADEN = 0 in Confuguration Bits.   only AN4(RA5) A/D input by TRISA  = 0b00100000, not affected by analog input of ADCON1 (2620-E-p92).
	// ADCON1 	— 	 	— 	 	VCFG1 	VCFG0 	PCFG3 	PCFG2 	PCFG1 		PCFG0
	// 		 	0	 	0	 	0	 	0	 	0	 	0	 	0		 	0	
	//ADCON2 = 0b10010101 ;  // Right justified,  Acquisition Time 4Tad,  Conversion Clock FOSC/16
	// ADCON2 	ADFM 	— 	 	ACQT2 	ACQT1 	ACQT0 	ADCS2 	ADCS1 		ADCS0
	// 		 	1	 	0	 	0	 	1	 	0	 	1	 	0		 	1

	//// 26k22 ADC init details,  (26k22  G-pp149-152, pp295-298)
	//ADCON0 = 0b00010001 ;  // select AN4(RA5).  A/D Converter module is enabled
	// ADCON0 	— 	 	CHS4 	CHS3 	CHS2 	CHS1 	CHS0 	GO/DONE 	ADON
	// 		 	0	 	0	 	0	 	1	 	0	 	0	 	0		 	1	
	//ADCON1 = 0b00000000 ;
	// ADCON1 	TRIGSEL	— 	— 	 	— 	 	 	PVCFG1 	PVCFG0 	NVCFG1 		NVCFG0
	// 		 	0	 	0	 	0	 	0	 	0	 	0	 	0		 	0	
	//ADCON2 = 0b10010101 ; 
	// ADCON2 	ADFM 	— 	 	ACQT2 	ACQT1 	ACQT0 	ADCS2 	ADCS1 		ADCS0
	// 		 	1	 	0	 	0	 	1	 	0	 	1	 	0		 	1


	while(1)
	{
		num = adconv() ;
		for(i = 0; i < 32; i++)
		{
			vBuffer[i]=num/2;	
		}
		LCD__vBuffer32();


		LED0_IO = 1;
		////////// ClockWise / Acceleration  //////////
		for(Wi=0; Wi<=1023; Wi++)
		{
			////2620
			CCPR1L = Wi/4 ;
			CCPR2L = 0 ;
			//////26k22
			//CCPR4L = Wi/4 ;
			//CCPR5L = 0 ;
			Delay10KTCYx(2) ;
		}
		////////// ClockWise / Deceleration  //////////
		for(Wi=0; Wi<=1023; Wi++)
		{
			////2620
			CCPR1L = (1023-Wi)/4 ;
			CCPR2L = 0 ;
			//////26k22
			//CCPR4L = (1023-Wi)/4 ;
			//CCPR5L = 0 ;
			Delay10KTCYx(2) ;
		}
		///////////////   Breake	////////////////////////
		//// 2620
		CCPR1L = 255 ;
		CCPR2L = 255 ;
		////// 26k22
		//CCPR4L = 255 ;
		//CCPR5L = 255 ;
		Delay10KTCYx(250) ;
		Delay10KTCYx(250) ;
		Delay10KTCYx(250) ;
		Delay10KTCYx(250) ;

		LED0_IO = 0;
		//////////  Counter-ClockWise / Acceleration  //////////
		for(Wi=0; Wi<=1023; Wi++)
		{
			////2620
			CCPR1L = 0 ;
			CCPR2L = Wi/4 ;
			//////26k22
			//CCPR4L = 0 ;
			//CCPR5L = Wi/4 ;
			Delay10KTCYx(2) ;
		}
		//////////   Counter-ClockWise / Deceleration  //////////
		for(Wi=0; Wi<=1023; Wi++)
		{
			////2620
			CCPR1L = 0 ;
			CCPR2L = (1023-Wi)/4 ;
			//////26k22
			//CCPR4L = 0 ;
			//CCPR5L = (1023-Wi)/4 ;
			Delay10KTCYx(2) ;
		}
		///////////////   Breake	////////////////////////
		//// 2620
		CCPR1L = 255 ;
		CCPR2L = 255 ;
		////// 26k22
		//CCPR4L = 255 ;
		//CCPR5L = 255 ;
		Delay10KTCYx(250) ;
		Delay10KTCYx(250) ;
		Delay10KTCYx(250) ;
		Delay10KTCYx(250) ;
	}	
}

#pragma tmpdata

//// lcd functions
void LCD__Data(void)
{
	_asm MOVWF Temp1, 0 	_endasm
	_asm MOVLW 0x0F 	 	_endasm
	_asm ANDWF PORTB, 1, 0 	_endasm
	_asm MOVF  Temp1, 0, 0 	_endasm
	_asm ANDLW 0xF0 	 	_endasm
	_asm IORWF PORTB, 1, 0 	_endasm
	PUT_DATA();
	_asm MOVLW 0x0F 	 	_endasm
	_asm ANDWF PORTB, 1, 0 	_endasm
	_asm SWAPF Temp1, 0, 0  _endasm
	_asm ANDLW 0xF0 	 	_endasm
	_asm IORWF PORTB, 1, 0 	_endasm
	PUT_DATA();
	TIME50();
}

void LCD__vBuffer32(void)
{
	LCD__Clear();
	for(kk = 0; kk < 16; kk++)		
	{
		Temp1= vBuffer[kk];
		LCD__Data();
	}
	_asm MOVLW 0xC0  	_endasm	
	LCD__Command();			
	TIME50();
	for(kk = 16; kk < 32; kk++)		
	{
		Temp1= vBuffer[kk];
		LCD__Data();
	}
}

void PUT_CMD(void)
{	
	lcd_rs  = 0;
	Nop();
	lcd_stb = 1;
	Nop();				
	Nop();
	Nop();				
	Nop();	
	lcd_stb = 0;
}

void PUT_DATA(void)
{
	lcd_rs  = 1;
	Nop();
	lcd_stb = 1;
	Nop();				
	Nop();
	Nop();				
	Nop();	
	lcd_stb = 0;
}

void LCD__Command(void)
{						
	_asm MOVWF Temp1, 0 	_endasm		
	_asm MOVLW 0x0F 	 	_endasm		
	_asm ANDWF PORTB, 1, 0 	_endasm		
	_asm MOVF  Temp1, 0, 0 	_endasm		
	_asm ANDLW 0xF0 	 	_endasm		
	_asm IORWF PORTB, 1, 0 	_endasm		
	PUT_CMD();
	_asm MOVLW 0x0F 	 	_endasm
	_asm ANDWF PORTB, 1, 0 	_endasm		
	_asm SWAPF Temp1, 0, 0  _endasm		
	_asm ANDLW 0xF0 	 	_endasm
	_asm IORWF PORTB, 1, 0 	_endasm		
	PUT_CMD();
	TIME50();				
}

void LCD__Clear(void)
{
	_asm MOVLW 0x01  	_endasm
	LCD__Command();	
	Delay10KTCYx(125);
	Delay10KTCYx(125);
}

void LCD__Init(void)
{	
	TIME5M();
	TIME5M();
	TIME5M();
	TIME5M();
	TIME5M();
	TIME5M();
	TIME5M();
	_asm MOVLW	0x0F	 	 	_endasm
	_asm ANDWF	PORTB,    1, 0 	_endasm
	_asm MOVLW	0x30		 	_endasm
	_asm IORWF	PORTB,    1, 0 	_endasm
	PUT_CMD();
	TIME5M();
	PUT_CMD();
	TIME5M();
	PUT_CMD();
	TIME5M();
	_asm MOVLW	0x0F	 	 	_endasm
	_asm ANDWF	PORTB,    1, 0 	_endasm	
	_asm MOVLW	0x20	 	 	_endasm
	_asm IORWF	PORTB,    1, 0 	_endasm
	PUT_CMD();
	TIME5M();
	_asm MOVLW 0x2E  		_endasm	
	LCD__Command();	
	_asm MOVLW 0x08 		_endasm
	LCD__Command();	
	_asm MOVLW 0x0D  		_endasm
	LCD__Command();	
	_asm MOVLW 0x06  		_endasm
	LCD__Command();	
	LCD__Clear();
}

//  about 50usec at 40MHz
void TIME50(void)
{
	_asm MOVLW	0x63	 	_endasm
	_asm MOVWF	ii, 0	 	_endasm 
	_asm NOP		 	 	_endasm
	_asm NOP		 	 	_endasm
	_asm DECFSZ	ii, 1, 0	_endasm	
	_asm BRA	-4	 	 	_endasm
}

//  about 5msec at 40MHz
void TIME5M(void)
{
	_asm MOVLW	0x64	 	_endasm
	_asm MOVWF	jj, 0	 	_endasm
	TIME50();
	_asm DECFSZ	jj, 1, 0	_endasm
	_asm BRA	-3	 	 	_endasm
}

//// no-pointer spi-sram (23LC1024) functions : referred from Microchip
// opcodes
#define READ	0x03			// Read data from memory array beginning at selected address
#define WRITE	0x02			// Write data to memory array beginning at selected address
#define RDSR	0x05			// Read Status register
#define WRSR	0x01			// Write Status register

// define
#define PROPER_SPICON1	(0x20)		// SSPEN bit is set, SPI in master mode, FOSC/4, IDLE state is low level

void SPIRAM1024Init(void)
{
	SPIRAM1024_CS_IO = 1;
	SPIRAM1024_CS_TRIS = 0;
	SPIRAM1024_SCK_TRIS = 0;		// SCK pin    output
	SPIRAM1024_SDI_TRIS = 1;		// SDI pin     input
	SPIRAM1024_SDO_TRIS = 0;		// SDO pin    output
	// Save SPI state (clock speed)
	SPICON1Save = SPIRAM1024_SPICON1;
	SPIRAM1024_SPICON1 = PROPER_SPICON1;
	SPIRAM1024_SPI_IF = 0;
	SPIRAM1024_SPISTATbits.CKE = 1; 	// Transmit data on rising edge of clock
	SPIRAM1024_SPISTATbits.SMP = 0;		// Input sampled at middle of data output time
	// Set Burst mode
	// Activate chip select
	SPIRAM1024_CS_IO = 0;
	SPIRAM1024_SPI_IF = 0;
	// Send Write Status Register opcode
	SPIRAM1024_SSPBUF = WRSR;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Set status register to 0b01000000 to enable burst mode
	SPIRAM1024_SSPBUF = 0x40;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Deactivate chip select
	SPIRAM1024_CS_IO = 1;
	// Restore SPI state
	SPIRAM1024_SPICON1 = SPICON1Save;
}

void SPIRAM1024GetArray(near DWORD dAddress, near DWORD dLength)
{
	// Ignore operations when the destination is NULL or nothing to read
	if(vBANK01 == NULL)
		return;
	if(dLength == 0)
		return;
	// Save SPI state (clock speed)
	SPICON1Save = SPIRAM1024_SPICON1;
	SPIRAM1024_SPICON1 = PROPER_SPICON1;
	// Activate chip select
	SPIRAM1024_CS_IO = 0;
	SPIRAM1024_SPI_IF = 0;
	// Send READ opcode
	SPIRAM1024_SSPBUF = READ;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Send address
	SPIRAM1024_SSPBUF = ((BYTE*)&dAddress)[2];
	while(!SPIRAM1024_SPI_IF);	
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	//
	SPIRAM1024_SSPBUF = ((BYTE*)&dAddress)[1];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	//
	SPIRAM1024_SSPBUF = ((BYTE*)&dAddress)[0];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Read data
	for(Dk = 0; Dk < dLength; Dk++)
	{
		SPIRAM1024_SSPBUF = 0;
		while(!SPIRAM1024_SPI_IF);
		vBANK01[Dk] = SPIRAM1024_SSPBUF;
		SPIRAM1024_SPI_IF = 0;
	}
	// Deactivate chip select
	SPIRAM1024_CS_IO = 1;
	// Restore SPI state
	SPIRAM1024_SPICON1 = SPICON1Save;
}

void SPIRAM1024PutArray(near DWORD dAddress, near DWORD dLength)
{
	// Ignore operations when the source data is NULL
	if(vBANK01 == NULL)
		return;
	if(dLength == 0)
		return;
	// Save SPI state (clock speed)
	SPICON1Save = SPIRAM1024_SPICON1;
	SPIRAM1024_SPICON1 = PROPER_SPICON1;
	// Activate chip select
	SPIRAM1024_CS_IO = 0;
	SPIRAM1024_SPI_IF = 0;
	// Send WRITE opcode
	SPIRAM1024_SSPBUF = WRITE;
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Send address
	////
	SPIRAM1024_SSPBUF = ((BYTE*)&dAddress)[2];
	while(!SPIRAM1024_SPI_IF);	
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	////
	SPIRAM1024_SSPBUF = ((BYTE*)&dAddress)[1];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	////
	SPIRAM1024_SSPBUF = ((BYTE*)&dAddress)[0];
	while(!SPIRAM1024_SPI_IF);
	Dummy = SPIRAM1024_SSPBUF;
	SPIRAM1024_SPI_IF = 0;
	// Write data
	for(Dk = 0; Dk < dLength; Dk++)
	{
		SPIRAM1024_SSPBUF = vBANK01[Dk];
		while(!SPIRAM1024_SPI_IF);
		Dummy = SPIRAM1024_SSPBUF;
		SPIRAM1024_SPI_IF = 0;
	}
	// Deactivate chip select
	SPIRAM1024_CS_IO = 1;
	// Restore SPI state
	SPIRAM1024_SPICON1 = SPICON1Save;
}

// ADC function
WORD adconv(void)
{
    WORD temp;
    PIR1bits.ADIF = 0; 	 	 	// clear ADIF,   26k22 datasheet, G-p316
    ADCON0bits.GO=1; 	 	 	// begin A/D conv.
    while(!PIR1bits.ADIF); 		// wait for A/D convert complete        
    temp = ADRESH ;
    temp = ( temp << 8 ) | ADRESL ;
    return temp ;
}

C18用のHardwareProfile.hとConfiguration Bitsは、2 spi-sramと同じです。

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?