〔ArduinoとPIC16F819で通信と基礎編〕 [PIC12F1822と16F819で通信] 〔マイコンのトップに戻る〕

1対nの接続概念図
マスター側のSSピンはデジタル出力ピンであればどれでもOKです。
下図はSPI通信の処理概略フロー図です。

先ずは実験風景から
---------------------------------------------------------------------
// 18F25K22
// SDとMCP3208(ADC)をSPIの同一バス上で接続し動作させるテスト
#include <xc.h>
#include <stdlib.h>
#include <string.h>
#include "skSPIlib.h"
#include "skSDlib.h"
#include "skI2Clib.h"
#include "skI2CLCDlib.h"
#define _XTAL_FREQ 32000000 // delay用に必要(クロック32MHzを指定)
#define ADC_CS LATC1 // MCP3208のCSピン
//#define CS LATC2 // SDカード選択信号(skSDlib.hで宣言されている)
// プロトタイプの宣言
void Wait(unsigned int num) ;
int ADC_analogRead(int channel) ;
// コンフィギュレーションの設定(ここの記述に無い設定はデフォルト値での動作)
// 外部クロックは使用しない(PRICLKEN_OFF)
// 動作クロックを4倍では動作させない(PLLCFG_OFF):内部クロックを使用する(INTIO7)
#pragma config PRICLKEN=OFF,PLLCFG=OFF,FOSC=INTIO7 // CONFIG1H
// 電源電圧降下常時監視機能ON(BOREN_NOSLP):監視電圧は(2.85V)に設定
// 電源ONから後65.6msにプログラムを開始する(PWRTEN_ON)
#pragma config BOREN=NOSLP,BORV=285,PWRTEN=ON // CONFIG2L
// ウオッチドッグタイマー無し(WDTEN_OFF)
#pragma config WDTEN=OFF // CONFIG2H
// 外部リセット信号は使用せずにデジタル入力(RE3)ピンとする(MCLRE_INTMCLR)
// オシレータが安定するのを待ってシステムクロックを供給する(HFOFST_OFF)
#pragma config MCLRE=INTMCLR,HFOFST=OFF // CONFIG3H
// 低電圧プログラミング機能使用しない(LVP_OFF)
#pragma config LVP=OFF // CONFIG4L
// 割り込みの処理
void interrupt InterFunction( void )
{
// I2C関連の割り込み(LCDで利用)
InterI2C() ;
}
// メインの処理
void main()
{
struct SDFILE_OBJECT fp ;// *3)
int ans ;
char dt[32] ;
PLLEN = 1; // 内部クロックを4x倍で利用する
OSCCON = 0b01100000; // 内部クロックとする(8MHzx4=32MHz)
INTCON2bits.RBPU = 0 ; // 内部プルアップを行う
WPUB = 0b00000110 ; // RB1/RB2をプルアップする
ANSELA = 0b00000000 ; // AN0-4アナログは使用しない、デジタルI/Oに割当
ANSELB = 0b00000000 ; // AN8-13アナログは使用しない、デジタルI/Oに割当
ANSELC = 0b00000000 ; // AN14-19アナログは使用しない、デジタルI/Oに割当
TRISA = 0b00000000 ; // RA0-RA7全て出力に設定
TRISB = 0b00000110 ; // RB1(SCL)RB2(SDA)は入力、他は全て出力、1で入力 0で出力
TRISC = 0b00010000 ; // RC4(SDI)は入力、他は全て出力、1で入力 0で出力
PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする)
PORTB = 0b00000000 ; // 出力ピンの初期化(全てLOWにする)
// 使用するSSピンをHIGHに設定する
PORTC = 0b00000110 ; // 出力ピンの初期化(SPIのCS以外はLOW)
// LCDモジュールの初期化処理
// アイコン未使用,コントラストは中位,VDD3.3V,16文字
InitI2C_Master() ;
LCD_Init(LCD_NOT_ICON,32,LCD_VDD3V,16) ;
LCD_Puts("Start") ;
// SPIの初期化を行う処理
// CLK極性:1 CLK位相:0 (アイドル5Vで、5V -> 0Vに変化で転送) 通信速度(32MHz/16)
SPI_Init(SPI_MODE3,SPI_CLOCK_DIV16,16) ; // SD用にて初期化 *2)
// MMC/SDCの初期化を行う
ans = SD_Init() ;
if (ans != 0) {
// SDカード初期化エラー(カード未挿入かも?)
LCD_SetCursor(0,1) ;
LCD_Puts("Error SD_Init") ;
while(1) ; // 終了
}
Wait(300) ; // 3秒後に開始
while(1) {
// MCP3208のCH0から読み込んで表示を行う
SPI_setDataMode(SPI_MODE1) ; // *2)
SPI_setClockDivider(SPI_CLOCK_DIV16,0) ; // 2MHz
ans = ADC_analogRead(0) ;
itoa(dt,ans,10) ;
LCD_SetCursor(0,0) ;
LCD_Puts(" ") ;
LCD_SetCursor(0,0) ;
LCD_Puts(dt) ;
Wait(100) ;
// SDから読み込んで表示を行う
SPI_setDataMode(SPI_MODE3) ; // *2)
SPI_setClockDivider(SPI_CLOCK_DIVADD,1) ; // 4MHz
ans = SD_Open(&fp,"TEST.TXT",O_READ) ; // ファイルのオープン *3)
if (ans == 0) {
memset(dt,0x00,sizeof(dt)) ;
ans = SD_fGets(&fp,dt,18) ; // ファイルから1行読込む *3)
LCD_SetCursor(0,1) ;
LCD_Puts(" ") ;
LCD_SetCursor(0,1) ;
LCD_Puts(dt) ;
Wait(100) ;
memset(dt,0x00,sizeof(dt)) ;
ans = SD_fGets(&fp,dt,18) ; // ファイルから1行読込む *3)
LCD_SetCursor(0,1) ;
LCD_Puts(" ") ;
LCD_SetCursor(0,1) ;
LCD_Puts(dt) ;
SD_Close(&fp) ; // ファイルのクローズ *3)
} else {
LCD_SetCursor(0,1) ;
LCD_Puts("Error SD_Open") ;
}
Wait(100) ;
}
}
// ADC_analogRead(channel) MCP3208からアナログ値を読み取る処理
// channel : 読み取るチャンネルを指定する(0-7ch)
int ADC_analogRead(int channel)
{
int d1 , d2 ;
// ADCから指定チャンネルのデータを読み出す
ADC_CS = 0 ; // SS(CS)ラインをLOWにする
d1 = SPI_transfer( 0x06 | (channel >> 2) ) ;
d1 = SPI_transfer( channel << 6 ) ;
d2 = SPI_transfer(0x00) ;
ADC_CS = 1 ; // SS(CS)ラインをHIGHにする
return (d1 & 0x0F)*256 + d2 ;
}
// Wait(num) 時間待ちの処理を行う
// num : 10ms単位で指定する
void Wait(unsigned int num)
{
int i ;
// numで指定した回数だけ繰り返す
for (i=0 ; i<num ; i++) {
__delay_ms(10) ; // 10msプログラムの一時停止
}
}
---------------------------------------------------------------------
次はArduinoでの実験風景です。
---------------------------------------------------------------------
// 大気圧センサLPS25H(SPI)とMCP3208(ADC-SPI)の同時読み込みテスト
#include <SPI.h>
#include "skLPSxxSPI.h"
#define LPS25H_CS 9
#define MCP3208_CS 10
skLPSxxx LPS(LPS25H,LPS25H_CS) ; // デバイスはLPS25Hを指定
void setup()
{
int ans ;
// シリアルモニターの設定
Serial5.begin(9600) ;
// 使用するCS(SS)ピンをHIGHに設定する
pinMode(MCP3208_CS,OUTPUT) ; // MCP3208のCS信号のピン設定
digitalWrite(MCP3208_CS,HIGH) ;
pinMode(LPS25H_CS,OUTPUT) ; // LPS25HのCS信号のピン設定
digitalWrite(LPS25H_CS,HIGH) ;
// SPIの初期化
SPI.begin() ; // SPIを行う為の初期化
SPI.setBitOrder(MSBFIRST) ; // ビットオーダー
SPI.setClockDivider(48) ; // SPI通信クロック(CLK)は1MHz
delay(5000) ; // 5Sしたら開始
// 気圧センサの初期化を行う(更新速度は1Hz)
SPI.setDataMode(SPI_MODE3) ; // CLK極性 1(idle=HIGH) CLK位相 1(HIGH->LOW)
ans = LPS.PressureInit() ;
if (ans == 0) Serial5.println("Initialization normal") ;
else {
Serial5.print("Initialization abnormal ans=") ;
Serial5.println(ans) ;
}
delay(1000) ;
}
void loop()
{
int dt ;
// MCP3208のCH0からアナログ値を読み込む
SPI.setDataMode(SPI_MODE1) ; // CLK極性 0(idle=LOW) CLK位相 1(LOW->HIGH)
dt = ADC_analogRead(MCP3208_CS,0) ;
Serial5.print("analog:") ;
Serial5.println(dt) ;
delay(1000) ;
// LPS25Hから気圧値と温度値を読み込む
SPI.setDataMode(SPI_MODE3) ; // CLK極性 1(idle=HIGH) CLK位相 1(HIGH->LOW)
LPS.PressureRead() ; // 圧力と温度を読み出す
Serial5.print("[LPS25H]") ;
Serial5.print(Press) ; // 気圧値の表示を行う
Serial5.print(" hPa ") ;
Serial5.print(Temp) ; // 温度の表示を行う
Serial5.print(" 'C ") ;
// 気圧値から高度を計算し、表示を行う
Serial5.print(LPS.AltitudeCalc(Press,-10)) ;
Serial5.println(" m") ;
delay(1000) ; // 1秒後に繰り返す
}
// ADC_analogRead(channel) MCP3208からアナログ値を読み取る処理
// ss : SPIのSS(CS)ピン番号を指定する
// channel : 読み取るチャンネルを指定する(0-7ch)
int ADC_analogRead(int ss,int channel)
{
static char f ;
int d1 , d2 ;
// 指定されたSSピンを出力に設定する(但し最初コールの1回のみ)
if (f != 1) {
pinMode(ss,OUTPUT) ;
digitalWrite(ss,HIGH) ;
f = 1 ;
delay(1) ;
}
// ADCから指定チャンネルのデータを読み出す
digitalWrite(ss,LOW) ; // SS(CS)ラインをLOWにする
d1 = SPI.transfer( 0x06 | (channel >> 2) ) ;
d1 = SPI.transfer( channel << 6 ) ;
d2 = SPI.transfer(0x00) ;
digitalWrite(ss,HIGH) ; // SS(CS)ラインをHIGHにする
return (d1 & 0x0F)*256 + d2 ;
}
---------------------------------------------------------------------
記事一部変更(*3) 2017/02/26
記事一部変更(*2) 2016/06/13
変更(*1) 2015/04/24
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.