〔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プログラムの一時停止 } } ---------------------------------------------------------------------
--------------------------------------------------------------------- // 大気圧センサ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.