Я использую 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;
}