ラズパイ5は、AIハット、AIカメラも発売され、大変話題です。さらにPCIe搭載のCompute Module 5も発売されて、アカデミックで設立されたラズベリーですが、ついに株式上場もしました。ただし今回は、今では少しレトロになってしまったRPI4Bを使います。このRPI4BとMicrochip社のPIC18との、2.304MbpsでのUART高速通信を試行しました。
配線図です。今回使うPIC18F2620は5Vです。一方、RPI4Bのロジックレベルは3.3Vです。レベル変換には秋月電子通商のFXMA108を使いました。(OEピンを10KΩで5Vのhighにプルアップしてdisable状態です。PIC起動時にプログラム上からlowにしてenableにしています。)そしてブレッドボードでは失敗したので、ユニバーサル基板にハンダ付しました。さらに0.2sqの単線(撚り線ではなく)を使用しました。実行結果は、2.304Mbpsでは延長50cmでした。1mまで延長すると、460Kbpsまで落ちました。明らかに、通信速度は、導線の長さでした。
次は、今回使用したラズパイ側のPythonプログラムです。BookwormのPython 3.11.2をThonny上で動作させています。またRPI4BのUARTは、Serial Consoleをオフ、Serialをオンにしただけの簡易設定です。mini PORTのUARTです。
先にPICを起動し、受信待機状態にします。
RPI4BのThonnyから、"Hello PIC Im Pi.Hello PIC Im Pi." をPICへ送信します。
Thonnyで、"HELLO Pi Im PIC@" をPICから受信すれば、2.304MbpsでのUART送受信が成功です。
同じRPI4BでBuster(x32)とBookworm(x64)を試してみましたが、どちらも以下のプログラムで動きます。Buster(x32)の方が、V2カメラ・画像解析のソフトが充実・完成しているので、現実的には使い易いですが。
#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側、つまりPIC18F2620のXC8プログラムです。Microchip社のMPLAB XIDEとXC8を使います。開発環境は、x64ビットWindowsパソコン用のMPLAB X IDE v6.00とXC8 Compiler v2.4.0です。PICkit3が使える最終版です。また26K22でも、プログラム中でコメントアウトしているconfigとアナログ設定を入れ替えるだけで、動きます。PIC18F2620と26K22の相違点は多いですが、今回のUARTに関しては同じです。
//main.c MPLAB X IDE v6.00, XC8 Compiler v2.4.0
#include <xc.h>
#define _XTAL_FREQ 36864000
#define LED_A0 LATA1
#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 = PORTC
#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;
near unsigned char Temp1;
near uint16_t Wi, Wi_last;
near uint32_t Di;
void main()
{
//Analog setting 2620
ADCON0 = 0x00;
ADCON1 = 0x0F;
////Analog setting 26k22
//ANSELA = 0b00100000 ; // AN4(RA5)
//ANSELB = 0b00000000 ;
//ANSELC = 0b00000000 ;
TRISA = 0b00100000 ; // RA5
TRISB = 0b00000000 ;
TRISC = 0b00000000 ;
PORTA = 0b00000000 ;
PORTB = 0b00000000 ;
PORTC = 0b00000000 ;
// C port //1 0 0 1 0 0 0 0
// //RX TX SDO SDI SCK C2 C1 C0
TRISC = 0x90;
// TXSTA //0 0 1 0 0 1 0 0
// //CSRC TX9 TXEN SYNC - BRGH TRMT TX9D
TXSTA = 0x24;
// RCSTA //1 0 0 1 0 0 0 0
// //SPEN RX9 SREN CREN ADDEN FERR OERR RX9D
RCSTA = 0x90;
// BAUDCON //0 0 0 0 0 0 0 0
// //ABDOVF RCIDL RXDTP TXCKP BRG16 - WUE ABDEN
BAUDCON = 0x00;
// SPBRG (36.864 MHz)
// SPBRG = 0x13, 013H=19, 36.864/(16(1+19)) = 115.2 Kbps
// SPBRG = 0x04, 004H=4, 36.864/(16(1+4)) = 460.8 Kbps
// SPBRG = 0x01, 001H=1, 36.864/(16(1+1)) = 1.152 Mbps
// SPBRG = 0x00, 000H=0, 36.864/(16(1+0)) = 2.304 Mbps
SPBRG = 0x00;
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(; ; )
{
if(TRMT==1)
{
TXREG = vBuffer[Wi];
Wi++;
}
if(Wi>Wi_last) { break; }
}
FXMA_CS0_IO=1;
while(1) {
LED_A0 = 0;
__delay_ms(250) ;
LED_A0 = 1;
__delay_ms(250) ;
}
}
さらに今回は、x32ビットのWindowsパソコン用のMPLAB IDEとC18でも作成しました。なんとネットに接続していない自閉症のWin7の登場です。また2620は、いにしえの秋月プログラマーキットの時代に使っていましたから、懐かしい顔ぶれが揃っています。お久しぶり。話がそれましたが、ここでの開発環境は、x32ビットのWindowsパソコン用の最終版のMPLAB_IDE_8_92とMPLAB_C18_3.46です。PICkit3を使います。インラインアセンブリングが散在しています。一方、XC8はC18と全く異なるので、XC8ではインラインアセンブリングを全く使いません。PICは5年ほど全く使っていなかったので、レトロなUART通信を再試行するのに、少し苦労しました。includeに必要なHardwareProfile.hとConfiguration Bitsの画面コピーも添付します。
// MainDemo.c MPLAB_IDE_8_92, MPLAB_C18_3.46
#include <p18f2620.h>
//#include <p18f26k22.h>
#include <GenericTypeDefs.h>
#include <delays.h>
#include <HardwareProfile.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 Temp1;
near BYTE i;
near WORD Wi;
near DWORD Di;
#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 ;
// C port //1 0 0 1 0 0 0 0
// //RX TX SDO SDI SCK C2 C1 C0
TRISC = 0x90;
// TXSTA //0 0 1 0 0 1 0 0
// //CSRC TX9 TXEN SYNC - BRGH TRMT TX9D
TXSTA = 0x24;
// RCSTA //1 0 0 1 0 0 0 0
// //SPEN RX9 SREN CREN ADDEN FERR OERR RX9D
RCSTA = 0x90;
// BAUDCON //0 0 0 0 0 0 0 0
// //ABDOVF RCIDL RXDTP TXCKP BRG16 - WUE ABDEN
BAUDCON = 0x00;
// SPBRG (36.864 MHz)
// SPBRG = 0x13, 013H=19, 36.864/(16(1+19)) = 115.2 Kbps
// SPBRG = 0x04, 004H=4, 36.864/(16(1+4)) = 460.8 Kbps
// SPBRG = 0x01, 001H=1, 36.864/(16(1+1)) = 1.152 Mbps
// SPBRG = 0x00, 000H=0, 36.864/(16(1+0)) = 2.304 Mbps
SPBRG = 0x00;
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;
while(1){
LED0_IO = 0;
Delay10KTCYx(250);
LED0_IO = 1;
Delay10KTCYx(250);
}
}
#pragma tmpdata
C18用のHardwareProfile.hです。
// HardwareProfile.h MPLAB_IDE_8_92, MPLAB_C18_3.46
#ifndef __HARDWARE_PROFILE_H
#define __HARDWARE_PROFILE_H
// Clock frequency value. This value is used to calculate Tick Counter value
#define GetSystemClock() (36864000ul) // 9.216MHz Crystal, PLL x4
#define GetInstructionClock() (GetSystemClock()/4)
#define GetPeripheralClock() GetInstructionClock()
// IO pins
#define LED0_TRIS (TRISAbits.TRISA1) // LED
#define LED0_IO (LATAbits.LATA1)
#define FXMA_CS0_TRIS (TRISCbits.TRISC0) // fxma OE
#define FXMA_CS0_IO (LATCbits.LATC0)
#endif
C18用2620のConfiguration Bitsの画面コピーです。
C18用26K22のConfiguration Bitsの画面コピーです。
次回は、今回は確認できなかったPICが受信した文字を、キャラクターlcdに表示します。