2017-10-07 16 views
1

マイクロチップのデータシートに従って、独自のI²Cマスタ書き込み関数を作成しています。私はコードコンフィギュレータで設定を生成MPLAB Xを使用していますが、ここで興味深いのビットされていますI²CマスタPIC18F45K50で書き込み:SCLを低くします

// R_nW write_noTX; P stopbit_notdetected; S startbit_notdetected; BF RCinprocess_TXcomplete; SMP Standard Speed; UA dontupdate; CKE disabled; D_nA lastbyte_address; 
SSP1STAT = 0x80; 
// SSPEN enabled; WCOL no_collision; CKP Idle:Low, Active:High; SSPM FOSC/4_SSPxADD_I2C; SSPOV no_overflow; 
SSP1CON1 = 0x28; 
// SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 100ns; AHEN disabled; 
SSP1CON3 = 0x00; 
// Baud Rate Generator Value: SSP1ADD 80; 
SSP1ADD = 0x50; 


// clear the master interrupt flag 
PIR1bits.SSP1IF = 0; 
// enable the master interrupt 
PIE1bits.SSP1IE = 1; 

だから:標準速度、100nsの時間、マスター・モード、約50kHz clokck周波数を保持します。私は手順に従うことをしようとした

は、データシートのP238を説明: http://ww1.microchip.com/downloads/en/DeviceDoc/30000684B.pdf

ここに私のコードです:

#include "mcc_generated_files/mcc.h" 
#include <stdio.h> 

#define _XTAL_FREQ 16000000 
#define RTS_PIN  PORTDbits.RD3 
#define CTS_PIN  PORTDbits.RD2 
#define LED_PIN  PORTAbits.RA1 
#define RX_FLAG  PORTAbits.RA2 

uint8_t c; 

// Define putch() for printf()) 
void putch(char c) 
{ 
    EUSART1_Write(c); 
} 

void main(void) 
{ 
// Initialize the device 
SYSTEM_Initialize(); 

    while (1) 
    { 
     // Generate a START condition by setting Start Enable bit 
     SSP1CON2bits.SEN = 1; 
     // Wait for START to be completed 
     while(!PIR1bits.SSPIF); 
     // Clear flag 
     PIR1bits.SSPIF = 0; 
     // Load the address + RW byte in SSP1BUF 
     // Address = 85 ; request type = WRITE (0) 
     SSP1BUF = 0b10101010; 
     // Wait for ack 
     while (SSP1CON2bits.ACKSTAT); 
     // Wait for MSSP interrupt 
     while (!PIR1bits.SSPIF); 
     // Load data (0x11) in SSP1BUF 
     SSP1BUF = 0x11; 
     // Wait for ack 
     while (SSP1CON2bits.ACKSTAT); 
     // Generate a STOP condition 
     SSP1CON2bits.PEN = 1; 
     // Wait for STOP to be completed 
     while(!PIR1bits.SSPIF); 
     // Clear flag 
     PIR1bits.SSPIF = 0; 

     // Wait for 1s before sending the next byte 
     __delay_ms(1000); 
    } 
} 

スレーブデバイスは、私は別のArduino(マスター)でテストしているのArduinoです正常に動作していることを確認してください。

私の問題は、ロジックアナライザを使ってSDA/SCL信号を解析します。私はPICを起動します。正しいアドレスを送信してバイト送信しますが、2番目のSCLの最後にLOWこれは他のすべての書き込みを悪くします(SCLがLOWに保持されている場合、適切なSTART条件を持つことはできません)。最初の送信の終わりに、BTLは3msの間LOWに保持されますが、理由がなくHIGHに戻ります。

ここで誰かが間違っていることを指摘できますか?私は何かを忘れましたか?

Thanx事前に。

よろしくお願いいたします。

エリック

PS:マスターとして他のArduinoとスレーブをテストするとき、SCLとすぐ送信が終わったとしてHIGH設定されています。

+0

「こんにちは」で私のメッセージを忘れてしまったことに気付きました。 – ricothebrol

答えて

1

スレーブアドレスを送信した後、ACK(ACKSTAT)を待ってからSSPIF割り込みフラグを待っているが、データバイトの後にSSPIFをチェックしていないことがわかります。 ACKSTATのみを確認しています。 SSPIFを待って、SSPIFをクリアしてからPENを停止条件をアサートするように設定してみてください。

この現象が発生した場合、SSPCONおよびSSPSTATレジスタの状態を確認しましたが、問題のある場所を絞り込むことができます。

0

あなたの答えはたくさんあります!

データバイトをロードした後にSSP1IFをクリアしましたが、今は正常です!

データシートには、ACKSTATが他のビットの立ち下がりエッジの代わりにSCLの立ち上がりエッジで反応する唯一のレジスタビットであることが示されています。だから私のコードでは、私はSTOP条件をあまりに早く生成し、それが動作不能になる可能性があります。したがって、STOP条件は生成されず、SCLはLOWに固定され、次の送信は開始できません。

さらに、STOP条件が完了するのを待つとき、SSP1IFフラグはまだ設定されているので、実際には待機せずに直接delay()関数にジャンプします。とにかく待っているかどうかは分かりませんが、パケットを次々と送信しようとすると問題になるかもしれません。

だから私はここに私が書いた機能だし、作業している: (ところで、それは255のデータバイトまで取ることができます)

void MasterWrite(char _size, char* _data) 
{ 
    // Generate a START condition by setting Start Enable bit 
    SSP1CON2bits.SEN = 1; 
    // Wait for START to be completed 
    while(!PIR1bits.SSPIF); 
    // Clear flag 
    PIR1bits.SSPIF = 0; 
    // Load the address + RW byte in SSP1BUF 
    // Address = 85 ; request type = WRITE (0) 
    SSP1BUF = 0b10101010; 
    // Wait for ack 
    while (SSP1CON2bits.ACKSTAT); 
    // Wait for MSSP interrupt 
    while (!PIR1bits.SSPIF); 
    // Clear flag 
    PIR1bits.SSPIF = 0; 

    for (int i=0; i<_size; i++) 
    { 
     // Load data in SSP1BUF 
     SSP1BUF = *(_data+i); 
     // Wait for ack 
     while (SSP1CON2bits.ACKSTAT); 
     // Wait for MSSP interrupt 
     while (!PIR1bits.SSPIF); 
     // Clear flag 
     PIR1bits.SSPIF = 0; 
    } 

    // Generate a STOP condition 
    SSP1CON2bits.PEN = 1; 
    // Wait for STOP to be completed 
    while(!PIR1bits.SSPIF); 
    // Clear flag 
    PIR1bits.SSPIF = 0; 
} 

たくさんありがとう、再びあなたの助けのために!

よろしくお願いいたします。

エリック

関連する問題