2017-10-07 1 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 주파수를.

#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); 
    } 
} 

슬레이브 장치가 나는 또 다른 아두 이노 (마스터)로 테스트 한 아두 이노입니다 : 여기 http://ww1.microchip.com/downloads/en/DeviceDoc/30000684B.pdf

내 코드입니다 :

나는 과정이 데이터 시트의 p238을 설명 따르도록 시도 제대로 작동하는지 확인하십시오.

내 문제는 : 로직 애널라이저를 사용하여 SDA/SCL 신호를 분석 할 때 PIC를 시작할 때 정확한 주소를 보내고 바이트를 전송하지만 2 번째 SCL이 끝나면 LOW 이는 다른 모든 글을 나쁜 것으로 만듭니다 (SCL이 LOW로 유지되면 적절한 START 조건을 가질 수 없음). BTW는 첫 번째 전송이 끝날 때 SCL을 3ms 동안 로우로 유지하지만 아무런 이유없이 다시 하이로 전환됩니다.

내가 잘못하고있는 부분을 지적해도 될까요? 내가 뭔가 잊었 니?

고지.

감사합니다.

에릭

PS : 마스터와 같은 다른 아두 이노와 슬레이브를 테스트 할 때, SCL이 즉시 전송이 끝난으로 HIGH 설정됩니다.

+0

그냥 내가 "안녕하세요"내 메시지를 시작하는 것을 잊었다 것으로 나타났습니다, 예의의 부족 죄송합니다 ... – ricothebrol

답변

1

슬레이브 주소를 보낸 후 ACK (ACKSTAT)를 기다리고 나서 SSPIF 인터럽트 플래그를 기다리고 있지만 데이터 바이트 다음에 SSPIF가 없는지 확인하고 있습니다. ACKSTAT 만 확인하고 있습니다. 어쩌면 PND가 정지 조건을 어서 트하도록 설정하기 전에 SSPIF를 기다리고 지우는 것이 좋습니다.

이 문제가 발생할 때 SSPCON 및 SSPSTAT 레지스터의 상태를 확인 했습니까? 문제가있는 곳을 좁히는 데 도움이 될 수 있습니다.

0

고맙습니다.

데이터 바이트를로드 한 후 SSP1IF를 지웠고 이제는 정상적으로 작동합니다!

데이터 시트는 ACKSTAT가 다른 비트의 하강 에지 대신 SCL의 상승 에지에서 반응하는 유일한 레지스터 비트임을 나타냅니다. 그래서 내 코드에서 STOP 조건을 너무 일찍 생성하기 때문에 작동하지 않을 수 있습니다. 따라서 어떠한 STOP 조건도 발생하지 않으며 SCL은 LOW로 고정되어 다음 전송을 시작할 수 없습니다.

또한 STOP 조건이 완료 될 때까지 기다릴 때 SSP1IF 플래그가 설정되어 있기 때문에 실제로 기다리지 않고 delay() 함수로 직접 점프합니다. 어쨌든 그가 기다리는 것이 중요할지 모르지만, 패킷을 하나씩 보내려고해도 문제가 될 수 있습니다.

그래서 내가 여기에 내가 쓴 함수, 그리고 작동되는 : 을 도와 다시 많은 고맙습니다

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; 
} 

을 (BTW는 255 데이터 바이트까지 걸릴 수 있습니다)!

감사합니다.

에릭

관련 문제