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

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

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

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

マイコン

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

Q&A

解決済

2回答

1434閲覧

PICのMSSPを利用してAT93C56をSPI駆動時に書き込みができない

teratail2020

総合スコア9

C

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

マイコン

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

0グッド

1クリップ

投稿2021/04/19 09:36

前提・実現したいこと

PIC18F14K50のMSSPを利用してEEPROM、AT93C56にデータの書き込み・読み出しを行いたいと考えています。SDIにはSPIを使用し、AT93C56は16ビットモードで使用するものとします。現在、下記回路とソースコードを作成しました。コードはEEPROMの0x05番地に0xF0F0を書き込み、読み出し後、再度0x05番地に0b0101110011011101を書き込み、読み出すことでEEPROMの内容の書き込み・読み出し・上書き動作を確認することを意図したものです。

回路図

図にテキストで示した通り、ORGピンはVccに接続し16ビットモードで動作するようにしております。
イメージ説明

該当のソースコード

/* * File: ADCTest.c * Author: FUJITSU * * Created on 2021/03/18, 23:00 */ // PIC18F14K50 Configuration Bit Settings // 'C' source line config statements // CONFIG1L #pragma config CPUDIV = NOCLKDIV #pragma config USBDIV = OFF // CONFIG1H #pragma config FOSC = IRC #pragma config PLLEN = OFF #pragma config PCLKEN = ON #pragma config FCMEN = OFF #pragma config IESO = OFF // CONFIG2L #pragma config PWRTEN = ON #pragma config BOREN = SBORDIS #pragma config BORV = 22 // CONFIG2H #pragma config WDTEN = ON #pragma config WDTPS = 32768 //(10ms~18ms x WDTPS) // CONFIG3H #pragma config HFOFST = OFF #pragma config MCLRE = ON // CONFIG4L #pragma config STVREN = ON #pragma config LVP = OFF #pragma config BBSIZ = OFF #pragma config XINST = OFF // CONFIG5L #pragma config CP0 = OFF #pragma config CP1 = OFF // CONFIG5H #pragma config CPB = OFF #pragma config CPD = OFF // CONFIG6L #pragma config WRT0 = OFF #pragma config WRT1 = OFF // CONFIG6H #pragma config WRTC = OFF #pragma config WRTB = OFF #pragma config WRTD = OFF // CONFIG7L #pragma config EBTR0 = OFF #pragma config EBTR1 = OFF // CONFIG7H #pragma config EBTRB = OFF // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #include <xc.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include "AT93C56_AT93C66.h" #define _XTAL_FREQ 4000000 /* * */ void __interrupt() Inter(void){ if(PIR1bits.SSPIF){ PIR1bits.SSPIF = 0; } } void WrenEEPROM(void){ volatile uint8_t Dummy = 0x00; __delay_us(1); //Wait more than 500ns Dummy = SSPBUF; //BF Flag clear EEPROM_CS = 1; //EEPROM select SSPBUF = EEPROM_EWEN; while(!SSPSTATbits.BF){NOP();}; Dummy = SSPBUF; EEPROM_CS = 0; __delay_us(1); //Wait more than 500ns } uint16_t ReadEEPROM(uint8_t address){ //Connect ORG pin of EEPROM to Vcc for 16bit mode volatile uint8_t readData = 0x00; uint16_t returnVal = 0x00; EEPROM_CS = 1; __delay_us(1); readData = SSPBUF; SSPBUF = EEPROM_READ; while(!SSPSTATbits.BF){NOP();}; readData = SSPBUF; SSPBUF = address; while(!SSPSTATbits.BF){NOP();}; readData = SSPBUF; SSPBUF = 0x00; while(!SSPSTATbits.BF){NOP();}; readData = SSPBUF; returnVal = (uint16_t)readData; returnVal = (returnVal << 8); SSPBUF = 0x00; while(!SSPSTATbits.BF){NOP();}; readData = SSPBUF; returnVal |= (uint16_t)readData; EEPROM_CS = 0; __delay_us(1); //Wait more than 500ns return returnVal; } void WriteEEPROM(uint8_t address, uint16_t data){ volatile uint8_t holdData = 0x00; EEPROM_CS = 1; __delay_us(1); holdData = SSPBUF; SSPBUF = EEPROM_WRITE; while(!SSPSTATbits.BF){NOP();}; holdData = SSPBUF; SSPBUF = address; while(!SSPSTATbits.BF){NOP();}; holdData = SSPBUF; holdData = (uint8_t)(data >> 8); SSPBUF = holdData; while(!SSPSTATbits.BF){NOP();}; holdData = SSPBUF; holdData = (uint8_t)(data); SSPBUF = holdData; while(!SSPSTATbits.BF){NOP();}; holdData = SSPBUF; EEPROM_CS = 0; __delay_us(1); } void main(void) { OSCCONbits.IRCF = 0b101; //4MHz OSCCONbits.SCS = 0b11; //Use internal oscillator while(!OSCCONbits.IOFS){NOP(); //SDI Setting //EEPROM/SPI //RB4:SDI //RB5:CS //RB6:CLK //RC7:SDO //MODE0:(CKP = 0),CKE = 1 //立ち上がりで取り込み、立下りで遷移 //MODE1:(CKP = 0),CKE = 0 //立ち上がりで遷移、立下りで取り込み(サンプルコードを見る限り、立下りで取り込みが正解?) //MODE2:(CKP = 1),CKE = 1 //立ち上がりで遷移、立下りで取り込み //MODE3:(CKP = 1),CKE = 0 //立ち上がりで取り込み、立下りで遷移 EEPROM_TRIS = 0; SSPSTATbits.SMP = 0; SSPSTATbits.CKE = 1; TRISCbits.TRISC7 = 0; TRISBbits.TRISB4 = 1; ANSELHbits.ANS10 = 0; TRISBbits.TRISB6 = 0; SSPCON1bits.CKP = 0; SSPCON1bits.SSPM = 0b0001; //Master Mode 0000:/4 0001:/16 0010/64  4us with /16 => 4Mhz SSPCON1bits.SSPEN = 1; //SDI Setting Enable IPR1bits.SSPIP = 1; PIE1bits.SSPIE = 1; uint16_t getByte = 0x0000; WrenEEPROM(); WriteEEPROM(0x05,0xF0F0); getByte = ReadEEPROM(0x05); WriteEEPROM(0x05,0b0101110011011101); getByte = ReadEEPROM(0x05); while(1){ CLRWDT(); } } /* * File: AT93C56_AT93C66.h * Author: FUJITSU * * Created on 2021/03/23, 18:24 */ #ifndef AT93C56_AT93C66_H #define AT93C56_AT93C66_H //Setting IO port #define EEPROM_CS (LATBbits.LB5) #define EEPROM_TRIS (TRISBbits.TRISB5) //utlize of 16bit mode #define EEPROM_READ (0b110) #define EEPROM_ERASE (0b111) #define EEPROM_WRITE (0b101) #define EEPROM_EWEN (0b10011 << 3) #define EEPROM_ERAL (0b100) #define EEPROM_ERAL_SEC (0b10 << 6) #define EEPROM_WRAL (0b100) #define EEPROM_WRAL_SEC (0b01 << 6) #define EEPROM_EWDS (0b100) #define EEPROM_EWDS_SEC (0b00 << 6) #endif /* AT93C56_AT93C66_H */

発生している問題・エラーメッセージ

下図はSDI(黄)とSDO(水)の関係を示したものとなります。
※SDI/SDOはコントローラサイドを基準とします。
イメージ説明

次にSDOとCLKの波形を以下の3つに分割して示します。

①EWENから1回目の読み出しアドレス指定まで
イメージ説明

②1回目の読み出し用空書き込みから2回目の読み出しアドレス指定まで
イメージ説明

③2回目の読み出し用空書き込み
イメージ説明

これらは以下のプロセスをたどっています。

EWENコマンドを送信=>
※以下1回目の読み書き
書き込みコマンドを送信=>
書き込みアドレス(0x05)を送信=>
16ビット書き込みデータ上位8ビット(0xF0)送信=>
16ビット書き込みデータ下位8ビット(0xF0)送信=>
読み出しコマンドを送信=>
読み出しアドレス(0x05)を送信=>
読み出し用ダミーデータを2バイト送信=>
※以下2回目の読み書き
書き込みコマンドを送信=>
書き込みアドレス(0x05)を送信=>
16ビット書き込みデータ上位8ビット(0b01011100)送信=>
16ビット書き込みデータ下位8ビット(0b11011101)送信=>
読み出しコマンドを送信=>
読み出しアドレス(0x05)を送信=>
読み出し用ダミーデータを2バイト送信=>

以上の波形を見ると多少の波形ひずみはあるもののおよそ意図したとおりの動作となっています。

次にSDIとCLKの波形を以下の3つに示します。

④1回目の読み出し
イメージ説明

⑤2回目の読み出し
イメージ説明

⑥下位バイト読み出し波形の詳細
イメージ説明

④~⑥の波形を見ると読み出しはできていますが出力値はどちらも0x0F75となっており、
①~③の波形で書き込んだ0xF0F0、0x5CDDとは異なった値が出力されています。
また、読み出しアドレスを手付かずのアドレスに指定した場合の読み出し値は0xFFFFとなりました。
以上より読み出し機能自体は正常に動作していると判断します。

これらから書き込み不良がどこかで発生しているものと思いますが、特定できません。
この問題の解法が分かる方は教授願います。
よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

現在の出力値0x0F75は以下の経緯で設定されました。以前SDIポートをデジタル入力にしてなかったため入力が常に0x0000となってしまう問題が生じました。そこでいろいろ試行錯誤していた時に適当に設定した値が0x0F75となります。一度、偶然にも値の設定が実施され再現性がない状態となっております。

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

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

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

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

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

y_waiwai

2021/04/19 10:01

その手のオシロがあるなら、波形記憶させて1バイトごとのアクセス波形が見れるのでは それで書き込み時のデータシーケンスを追いかけていけば、不具合があるならわかると思われますが #ちょっと気になるのがSDI/SDOはプルアップの必要はないでしょうか
teratail2020

2021/04/19 10:24

EEPROMへの入力波形を追いかけていった図が①~③となります。文中に記載したとおり、波形観測ではこの書き込み許可・書き込み・読み出し動作に問題は見つかりませんでした。コーディング通りの波形となっています。それであるのに読み出しによる出力波形を見ると書き込みが実施されていない状態であり原因不明です。 #たしかにSDI・SDOのプルアップは必要です。ご指摘ありがとうございます。しかしながら波形は不安定化していないため関係性は低いかと思います。
y_waiwai

2021/04/19 10:51

ついでに、質問文では触れられてませんがCSの波形はどうでしょうか
teratail2020

2021/04/19 11:12

CSの波形も問題ありません。CLKが駆動している個所ではHIGHになっていました。
guest

回答2

0

最初から、というか、最初だけ行きますけど、

ORGがプルアップされている→16bitモードですよね?

で、AT93C56の16bitだとデータシートでは
EWEN 1 00 11XXXXXX
となっていますよね?
つまり、0b10011000000を送る事になります。(Xを0にするとして)
なので、HIGHバイトの0b100を先に送り、次に0b11000000を送る事になるのでは?

※デバイス的には、スタートビットの最初の1から、CSをLOWにするまで読み込むようです。
けれども、SPIを使うのなら、先頭から10011000 000@@@@@と2バイト目の途中でCSを切り替える訳には行きません。
なので、最初にダミーの0を付けて、00000100 11000000と2バイト送ってからCSを下げる事になるかと。

投稿2021/04/19 15:21

nac_tnk

総合スコア463

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

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

teratail2020

2021/04/20 04:56

解法を提案くださりありがとうございます。指摘内容は正確でした。申し訳ありませんが先に回答くださったozwk様をベストアンサーとさせていただきます。
guest

0

ベストアンサー

データシートを読む限り書きこみ完了まで最長10ms(最短100us)かかるっぽいですけど待ってますか?

投稿2021/04/19 12:40

ozwk

総合スコア13521

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

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

teratail2020

2021/04/20 04:57 編集

ありがとうございました。結論から言いますと皆さんの回答の全てが正しかったです。 最初に回答くださったozwk様をベストアンサーとさせていただきます。 さて実際には以下のコーディングを追加すると解決しました。 1.EWENを0b10011000から0b00000100,0b11000000と2つに分割。 2.書き込み後にtWP待機するコードの追加。 3.(補足)tWP待機する代わりにDIを監視することでBusy=>Readyの状態を取得することができますが、DIピンはデフォルトでハイ・インピーダンスのためコントローラでピン状態を取得する場合プルアップ/プルダウン処理が必要。 以上となります。解法を提案くださりありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問