質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Q&A

1回答

2815閲覧

PIC16F1におけるSPIの2byte送信は可能でしょうか

Per271

総合スコア8

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

0グッド

0クリップ

投稿2021/07/20 15:32

編集2021/07/20 16:24

PIC16F1シリーズでSPIスレーブモードを使用している場合、16bitの連続データ送信は可能でしょうか。

この環境での16bit連続送信は不可能なのか、
もし可能であれば改善すべき点を、
不可能であれば別の手段(dsPICでは16bit送信ができる?など)のアドバイスを頂けないでしょうか。

前提・実現したいこと

使用しているマイコンはPIC16F1503です。XC8コンパイラを使用しています。

SPI通信をしている既存の機材があり、そのスレーブ側の動きをPICで再現し代替したいと考えております。
そのためマスター側の処理は変更ができず、スレーブ側でのみの対応となります。

マスター側は「8bitの要求コマンド」「8bitの受信用ダミーデータ」を連続で16bit送信します。
1byte目は「0x07」、「0x0F」のいずれか
2byte目は「0xFF」

スレーブ側はマスター側からの受信と同時に、「8bitの受信用ダミーデータ」「8bitの返送データ」を交換します。
1byte目は「0xFE」
2byte目は現在のステータスを返す予定です(試作ではダミーや00を送信しています)

本来はマスター側の要求により返答内容を決定しますが、その手前でコケたためより簡易なプログラムで検証しております。

試したこと

いくつかの簡単なテストプログラムを作成しました。

  • A:常にダミーデータだけを送信するプログラム

SSP1IF割り込みが発生
→受信データの空読みと、次回の送信用ダミーデータを代入

  • B:割り込み後に手動で2バイト送信するプログラム

SSP1IF割り込み発生
→受信データの空読みと、2byte目の送信データ(0x00)を代入
→2byte目の受信空読みと、次回1byte目のダミーデータを代入

  • C, D

割り込みを停止し、A, Bのそれぞれをメインのwhile内で実行
一時的に試したためソースコードには記載しておりません

発生している問題

どのパターンでも、実際に返送しているデータには前半1byteにダミーデータがあるのみで、
後半1byteにはマスターから受信したデータをそのまま返信しているようです。

パターンBに記載している0x00の送信データはどこにも見当たりません。

イメージ説明

該当のソースコード

c

1// PIC16F1503 Configuration Bit Settings 2// 'C' source line config statements 3 4// CONFIG1 5#pragma config FOSC = INTOSC // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin) 6#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) 7#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) 8#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR) 9#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) 10#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled) 11#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) 12 13// CONFIG2 14#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) 15#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) 16#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) 17#pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled) 18#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) 19 20// #pragma config statements should precede project file includes. 21// Use project enums instead of #define for ON and OFF. 22 23#include <xc.h> 24 25const char DUMMY = 0xFE; 26unsigned char buf = 0; 27 28void __interrupt() isr(){ 29 if (PIE1bits.SSP1IE == 1 && PIR1bits.SSP1IF == 1){ 30 31 // Pattern A 32 33 // Read Receive Data 34 buf = SSP1BUF; 35 // Set Send Data 36 SSP1BUF = DUMMY; 37 38 //Clear Flag 39 PIR1bits.SSP1IF = 0; 40 41 42 // Pattern B 43 /* 44 // Read Receive Data1 45 buf = SSP1BUF; 46 // Set Send Data2 47 SSP1BUF = 0x00; 48 49 // Wait Send 50 while(!SSP1STATbits.BF); 51 52 // Read Receive Data2 53 buf = SSP1BUF; 54 // Set Next Send Data1 55 SSP1BUF = DUMMY; 56 57 //Clear Flag 58 PIR1bits.SSP1IF = 0; 59 */ 60 } 61} 62 63void main(void) { 64 // General Setup 65 OSCCON = 0b01111011; // 16MHz 66 67 // Pin Setup 68 ANSELA = 0x00; // All Digital Pin 69 ANSELC = 0x00; // All Digital Pin 70 APFCON = 0b00100000; // SDO1:RA4 71 WPUA = 0b00010000; 72 TRISA = 0b11101111; // RA4:SDO output 73 TRISC = 0b00111011; // RC2:SDO output 74 75 // SPI setup 76 SSP1STAT = 0b00000000; // SMP:must be cleared in Slave, CKE:0 Idle to Active 77 SSP1CON1 = 0b00110100; // WCOL, SSPOV:status, SSPEN:SPI Enable, CKP:1 Idle High, SSPM:0100 Slave with SS 78 SSP1BUF = DUMMY; 79 80 // Interrupt Setup 81 PIR1bits.SSP1IF = 0; 82 PIE1bits.SSP1IE = 1; 83 INTCONbits.PEIE = 1; 84 INTCONbits.GIE = 1; 85 86 while(1); 87 return; 88} 89

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

なんか、SPIという通信方式を理解されていないように思われます

受信割り込みというのは基本的に1バイトごとに発生します
その割り込みを受けて、ハンドラ関数は、受信データを1バイト読み込む、というのを繰り返します。
が、提示のコードは1バイト読み込んでもそれを捨ててもう1バイト読もうとしてます
これではダメですね

また、送信データにしても、
最初の1バイトは通信が始まる前に設定しておく必要があり、割り込み発生時点で、その次のバイトを設定する、というシーケンスとなります

投稿2021/07/20 16:11

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Per271

2021/07/20 16:22

私の理解では、1バイトごとに発生した割り込みに対して空読み(マスターからの受信データは不要でバッファをクリアするため)を実施しています。 これがもう一度読もうとしていることになるのでしょうか? またハンドラ関数とはソースコード上のどこにありますか? 送信データは最初のmain文でバッファにセットしています。 SSP1BUF = DUMMY; これでは不足していますでしょうか。 割り込み処理の最後にも次回送信用のデータをセットしているつもりです。 レジスタの扱いに誤りがありますでしょうか。 内容が複雑になりそうなので目標はパターンA(1バイトごとにダミーデータをセット)の実現で結構です。
y_waiwai

2021/07/20 16:27 編集

なんでハンドラ関数(割り込み関数)内で buf = SSP1BUF; が2回でてくるんでしょうか 割り込み関数の実装を見直しましょう 1バイト送信を2回繰り返したら2バイト送信となります
Per271

2021/07/20 16:36

パターンAでは1回のみとなっているかと思います。 こちらが想定した動きをしなかったため、1回の割り込みで2回目の送信までを手動で行うパターンBを作成しました。これについては私の試行錯誤の結果ですので無視いただいて構いません。 パターンAに絞り、1バイト受信→次回送信データセットを行っても、2バイト目がマスター受信データの返送になってしまっている要因についてお分かりになりましたらご教示願います。
y_waiwai

2021/07/20 16:51

送信レジスタがダブルバッファの場合、前もって設定する送信データは複数の必要があるかも。 そこらへんはCPUのデータシートを確認しよう オシロがあるなら、SPIのクロックとデータのラインをモニタしていけばどんなデータを送受信してるかわかるでしょ。それで追いかけていけばいいかと
Per271

2021/07/20 17:05

> 前もって設定する送信データは複数の必要がある とは具体的にどのような処理でどこに設定するような動きを想定されてますでしょうか。 データシートを読む限りでは送受信にあたりSSP1BUF以外に操作可能なレジスタがないと私は理解しております。 当方オシロはありませんが添付の通りロジアナで波形を確認しております。 現状では思いつく限りのどのようなプログラムを書いても2バイト目の出力に変化がなく1バイト目の受信データの再送状態です。 この出力に何らかの変化を与えられる処理さえ分かれば追いかけられるのですが、現状では波形に変化がなく波形からのアプローチはできておりません。
y_waiwai

2021/07/20 17:10

ならmain関数にある送信データの設定をデータ変えて2回繰り返して、波形を見てみよう。
y_waiwai

2021/07/20 23:15

データシート見てみたらダブルバッファないのね。 それじゃ割り込みは最終ビットの半サイクル間で応答せんとせんといかんのでー、 SPIを500Kで駆動するなら500nsって、送信データのセットが間に合ってない可能性ありますねー SPIのクロックを10Kとか100Kぐらいに落としてやってみればうまくいくんじゃないかと
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問