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シリアル通信 4. DC-motor (drv8835)

Last updated at Posted at 2025-01-15

前回まで、PICとRPI4Bのuart通信を実施しました。PIC側では、キャラクターlcdに受信文字を表示し、受信文字のspi-sramへの書込み・読み出しを確認し、ハードウェアーpwmを使ってLEDの明るさを変えてみました。

今回は、このハードウェアーpwmを使って、PIC側でDC-motorを動かしてみます。直接では電流容量的に無理なので、DC-motorドライバーのTI社製DRV8835を使いました。

4.png

配線図です。DRV8835はロジック電源(Vcc)とモーター動力電源(VM)が分かれています。2電源ありますから、両方にダイオードを追加しています。GNDは共通です。コイルも抵抗も入れていません。ブラシモーターなので、モーター出力ラインに、Common Modeフィルター、VDR(バリスタ―)、0.1μFの積層セラミックコンデンサーを追加しています。そしてDRV8835のIN1とIN2にPWMパルス信号を入力すれば、モーターが動きます。

4.jpg

使っている電源が異なるので、5.2Vと5.3Vと電圧も異なります。DRV8835のVM側は、11Vまで大丈夫なのですが、小さなモーターが5Vでした。VM側は、9V電池から少し容量の大きい3端子DC/DC5Vレギュレーター(NJM7805,~1.5Amax)で、5.3Vへ降圧しています。製作途中、モーターを基板に埋め込むのが、少し大変でした。今回使っているVDRバリスターは5年前に買ったリード線タイプですが、現在は販売終了しています。すべて面実装タイプになっているようです。写真で、モーターが回っているのでセイルが少しブレています。

※ DCモーターは、何回でも回る360度回転型のギヤ付ブラシモーターです。サーボ機能は付いていません。外観は似ていますが、180度回転型のサーボモーターではありません。以下のプログラムでは、ギヤモーターが何回転もします。

PWM周波数は、下表のように 2.25kHz です。この周波数は、可聴音域(20Hz~20kHz)の高音域です。モーターが回り始める0.5秒ほど前から、「キーン」という高音が、DCモーターから聞こえます。モーターのブラシ付近が、振動して音波を出しているのだと思います。普通のオーディオの大音量スピーカー配線に耳を当てても音は聞こえませんから。

My PWM Frequency.png

一般にブラシモーターの電磁ノイズは、数MHz~数百MHzと言われているので、人間の耳では聞き取れません。コモンモードはノーマルモードとは異なりますが、数kHz~数百kHzのノイズ対策を想定しています(詳細は未確認)。

今回使っているコモンモードACM12VはTDK製です。メインの用途は、車載パワーラインのオルタネーターなどのフィルターのようです。DRV8835もそうですが、モバイルバッテリー用です。購入する時に見かけたページです。ご参考になれば。(外部:TDKのページ)
コンデンサの機能「共振回路と発振回路」
https://www.tdk.com/ja/tech-mag/condenser/004

この中で、アンテナがコンデンサーの開いたものであることを、初めて知りました。過去にも、地上波テレビアンテナで、放射アンテナの形状が、直線偏波・円偏波に影響があることを初めて知って、衝撃を受けたことがありましたが。

一方、今回のpwmの分解能(Resolution)は、10bitですから1024ステップです。ただしプログラム中では、下位1/4の256ステップしか使っていません。プラスチック歯車なので、フルパワーの最高速の回転にすると壊れるかもしれません。小さなモーターなので電流も1.5Amaxには達しないと思います。

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側のプログラムは、mainの最下部のwhile内をDC-motor用に少し変えていますが、他は前回と全く同じです。今回も、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);


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(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 ;

    while(1) {

        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;
}
  

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);

#pragma code
void main(void){

	//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;

	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 ;

	while(1)
	{
		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;
}

C18用のHardwareProfile.hとConfiguration Bitsは、前々回と同じです。

次回はPIC側で、温度センサーMCP9700の電圧を、PICのA/Dコンバーターを使って、表示します。

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?