I2C не работает в PIC18F46K22 с использованием DS3231 - PullRequest
0 голосов
/ 26 октября 2019

Я использую PIC18F46K22 для отображения времени от устройства DS3231 RTC через I2C. Я сталкиваюсь с проблемой при установке подтверждения (ACKEN). Я чувствую что-то не так в своей конфигурации, особенно в Pin Configuration и настройке скорости передачи данных с помощью SSP1ADD.

Я использую 20 МГц, и мой DS3231 поддерживает 400 кГц.

При установке подтверждения(ACKEN), программа зависает, я имею в виду, что она не может установить, что она не выходит из шага.

Пожалуйста, помогите мне решить проблему, найдите прилагаемый код.

//PCI18F46K22 Pin Configurations:

#define _XTAL_FREQ 20000000

// CONFIG1H
#pragma config FOSC = HSHP    // Oscillator Selection bits->HS oscillator (high power > 16 MHz)
// PLLCFG changed
#pragma config PLLCFG = OFF    // 4X PLL Enable->Oscillator used directly
// PRICLKEN changed
#pragma config PRICLKEN = OFF    // Primary clock enable bit->Primary clock is always enabled
#pragma config FCMEN = OFF    // Fail-Safe Clock Monitor Enable bit->Fail-Safe Clock Monitor disabled
#pragma config IESO = OFF    // Internal/External Oscillator Switchover bit->Oscillator Switchover mode disabled

// CONFIG2L
// - PWRTEN
#pragma config PWRTEN = ON    // Power-up Timer Enable bit->Power up timer disabled
// - BOREN = SBORDIS
#pragma config BOREN = ON    // Brown-out Reset Enable bits->Brown-out Reset enabled in hardware only (SBOREN is disabled)
#pragma config BORV = 190    // Brown Out Reset Voltage bits->VBOR set to 1.90 V nominal

// CONFIG2H
#pragma config WDTEN = OFF    // Watchdog Timer Enable bits->Watch dog timer is always disabled. SWDTEN has no effect.
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits->1:32768

// CONFIG3H
#pragma config CCP2MX = PORTC1    // CCP2 MUX bit->CCP2 input/output is multiplexed with RC1
#pragma config PBADEN = OFF    // PORTB A/D Enable bit->PORTB<5:0> pins are configured as digital I/O on Reset
#pragma config CCP3MX = PORTB5    // P3A/CCP3 Mux bit->P3A/CCP3 input/output is multiplexed with RB5
#pragma config HFOFST = ON    // HFINTOSC Fast Start-up->HFINTOSC output and ready status are not delayed by the oscillator stable status
#pragma config T3CMX = PORTC0    // Timer3 Clock input mux bit->T3CKI is on RC0
#pragma config P2BMX = PORTC0    // ECCP2 B output mux bit->P2B is on RC0
#pragma config MCLRE = EXTMCLR    // MCLR Pin Enable bit->MCLR pin enabled, RE3 input pin disabled

// CONFIG4L
#pragma config STVREN = ON    // Stack Full/Underflow Reset Enable bit->Stack full/underflow will cause Reset
#pragma config LVP = ON    // Single-Supply ICSP Enable bit->Single-Supply ICSP enabled if MCLRE is also 1
#pragma config XINST = OFF    // Extended Instruction Set Enable bit->Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
#pragma config DEBUG = OFF    // Background Debug->Disabled

// CONFIG5L
#pragma config CP0 = OFF    // Code Protection Block 0->Block 0 (000800-003FFFh) not code-protected
#pragma config CP1 = OFF    // Code Protection Block 1->Block 1 (004000-007FFFh) not code-protected
#pragma config CP2 = OFF    // Code Protection Block 2->Block 2 (008000-00BFFFh) not code-protected
#pragma config CP3 = OFF    // Code Protection Block 3->Block 3 (00C000-00FFFFh) not code-protected

// CONFIG5H
#pragma config CPB = OFF    // Boot Block Code Protection bit->Boot block (000000-0007FFh) not code-protected
#pragma config CPD = OFF    // Data EEPROM Code Protection bit->Data EEPROM not code-protected

// CONFIG6L
#pragma config WRT0 = OFF    // Write Protection Block 0->Block 0 (000800-003FFFh) not write-protected
#pragma config WRT1 = OFF    // Write Protection Block 1->Block 1 (004000-007FFFh) not write-protected
#pragma config WRT2 = OFF    // Write Protection Block 2->Block 2 (008000-00BFFFh) not write-protected
#pragma config WRT3 = OFF    // Write Protection Block 3->Block 3 (00C000-00FFFFh) not write-protected

// CONFIG6H
#pragma config WRTC = OFF    // Configuration Register Write Protection bit->Configuration registers (300000-3000FFh) not write-protected
#pragma config WRTB = OFF    // Boot Block Write Protection bit->Boot Block (000000-0007FFh) not write-protected
#pragma config WRTD = OFF    // Data EEPROM Write Protection bit->Data EEPROM not write-protected

// CONFIG7L
#pragma config EBTR0 = OFF    // Table Read Protection Block 0->Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
#pragma config EBTR1 = OFF    // Table Read Protection Block 1->Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
#pragma config EBTR2 = OFF    // Table Read Protection Block 2->Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
#pragma config EBTR3 = OFF    // Table Read Protection Block 3->Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks

// CONFIG7H
#pragma config EBTRB = OFF    // Boot Block Table Read Protection bit->Boot Block (000000-0007FFh) not protected from table reads executed in other blocks

//-----------------------------

//--I2C Configurations
void I2C_Initialize(const unsigned long feq_K) //Begin IIC as master
{
  TRISC3 = 1;  //Set SCL pint as input pin
  TRISC4 = 1;  //Set SDA pin as input pin

  ANSELCbits.ANSC3=0;       //Disable Analog pin
  ANSELCbits.ANSC4=0;       //Disable Analog pin


  SSP1CON1=0b00101000;; /* 0x00101000 - Enable SSP port for I2C Master mode, clock = FOSC / (4 * (SSPADD+1))*/ 
  SSP1CON2=0b00000000;
  SSP1CON3=0b00000000;

  SSP1STAT=0b00000000;
  SSP1ADD=(_XTAL_FREQ/(4*feq_K*100))-1;   
}

void I2C_Hold()
{
    while (   (SSP1CON2 & 0b00011111)    ||    (SSP1STAT & 0b00000100)   ) ; //check the bis on registers to make sure the IIC is not in progress
}

void I2C_Begin()
{
  I2C_Hold();  //Hold the program is I2C is busy  
  SSP1CON2bits.SEN = 1;
}

void I2C_End()
{
  I2C_Hold(); //Hold the program is I2C is busy  
  SSP1CON2bits.PEN = 1;    
}

void I2C_Write(unsigned data)
{
  I2C_Hold(); //Hold the program is I2C is busy 
  SSP1BUF = data;        
}

unsigned short I2C_Read(unsigned short ack)
{
  unsigned short incoming;
  I2C_Hold();
  SSP1CON2bits.RCEN = 1;

  I2C_Hold();
  incoming = SSP1BUF;      //get the data saved in SSP1BUF

  I2C_Hold();
  SSP1CON2bits.ACKDT = (ack)?0:1;    //check if ack bit received  
  SSP1CON2bits.ACKEN = 1;          

  return incoming;
}
//-------------------------------

//--DS3231 Functions to set/get timings
#include "i2c.h"

typedef struct
{
  uint8_t sec;
  uint8_t min;
  uint8_t hour;
  uint8_t weekDay;
  uint8_t date;
  uint8_t month;
  uint8_t year;  
}rtc_t;


void rtc_set_clock(rtc_t *rtc);
void get_date_time(rtc_t *rtc);
char* rtc_get_month(rtc_t *rtc);


/****** Functions for RTC module *******/
int  BCD_2_DEC(int to_convert)
{
   return (to_convert >> 4) * 10 + (to_convert & 0x0F); 

}



int DEC_2_BCD (int to_convert)
{
   return ((to_convert / 10) << 4) + (to_convert % 10);

}

void rtc_set_clock(rtc_t *rtc)
{
   I2C_Begin();       
   I2C_Write(0xD0);  //0x1101 0000
   I2C_Write(0);  
   I2C_Write(DEC_2_BCD(rtc->sec)); //update sec
   I2C_Write(DEC_2_BCD(rtc->min)); //update min
   I2C_Write(DEC_2_BCD(rtc->hour)); //update hour
   I2C_Write(1); //ignore updating day
   I2C_Write(DEC_2_BCD(rtc->date)); //update date
   I2C_Write(DEC_2_BCD(rtc->month)); //update month
   I2C_Write(DEC_2_BCD(rtc->year)); //update year
   I2C_End();
}

void get_date_time(rtc_t *rtc)
{
   //START to Read
   I2C_Begin();       
   I2C_Write(0xD0); 
   I2C_Write(0);    
   I2C_End(); 

  //READ
   I2C_Begin();
   I2C_Write(0xD1);                              // Initialize data read

   rtc->sec = BCD_2_DEC(I2C_Read(1));    
   rtc->min = BCD_2_DEC(I2C_Read(1));   // Read sec from register 
   rtc->hour = BCD_2_DEC(I2C_Read(1));  
   I2C_Read(1);
   rtc->date = BCD_2_DEC(I2C_Read(1));  
   rtc->month = BCD_2_DEC(I2C_Read(1));  
   rtc->year = BCD_2_DEC(I2C_Read(1)); 

   I2C_End(); 

  //END Reading  
    I2C_Begin();
    I2C_Write(0xD1);                              // Initialize data read
    I2C_Read(1);    
    I2C_End(); 
    return;
}


char* rtc_get_month(rtc_t *rtc) {
    switch(rtc->month){
        case 1: return "JAN";
        case 2: return "FEB";
        case 3: return "MAR";
        case 4: return "APR";
        case 5: return "MAY";
        case 6: return "JUN";
        case 7: return "JUL";
        case 8: return "AUG";
        case 9: return "SEP";
        case 10: return "OCT";
        case 11: return "NOV";
        case 12: return "DEC";
    }
    return 0;
}
//------------------------


//My main function for PIC18F46K22 for DS3231 using I2C (SSP1)

rtc_t rtc;

void main()
{
    char msg_welcome[15] = "LCD Read.";
    char retValue[17];
    char a,b;
    short int i;

    TRISC2 = 0;
    LATC2 = 0;
    PORTCbits.RC2 = 0;

    I2C_Initialize(100);
    Lcd_Init();
    __delay_ms(5);

    rtc.hour = 23; //  23:59:10 am
    rtc.min =  59;
    rtc.sec =  10;

    rtc.date = 21; //21th Jan 2019
    rtc.month = 1;
    rtc.year = 19;
    rtc_set_clock(&rtc);

    Lcd_Clear();
    Lcd_Write_String(1,1,"Start communic:");
    Lcd_Write_String(2,1,"Timers:");   
    __delay_ms(1000);

    LATC2 = 1;

    Lcd_Clear();
    while(1){
            get_date_time(&rtc);
            for(i=0; i< 17; i++)
                retValue[i] = '\0';

            sprintf(retValue, "Bytes: %02d-%s-%02d", rtc.date, rtc_get_month(&rtc), rtc.year);
            Lcd_Write_String(1,1,retValue);

            for(i=0; i< 17; i++)
                retValue[i] = '\0';

            sprintf(retValue,"        %02d:%02d:%02d", rtc.hour, rtc.min, rtc.sec);
            Lcd_Write_String(2,1,retValue);
            __delay_ms(1000);
    }

    return;
}
...