Отговори на тема  [ 255 мнения ]  Отиди на страница Предишна  1 ... 13, 14, 15, 16, 17  Следваща
I2C малко помощ 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: I2C малко помощ
Какво друго има около контролера освен сензора по и2ц? Ако останалата периферия е малко и/или ще приеме добре слизането на 3.3 значи е добро решение.


Сря Мар 07, 2018 9:01 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Юли 11, 2007 9:16 am
Мнения: 1705
Мнение Re: I2C малко помощ
Сега остана само да дефинираш какво е "останалата част от схемата" и решението ще се появи от самосебе си.


Сря Мар 07, 2018 9:02 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
Нищо кой знае какво.
Смъкването на 3,3V ще е съпътствано с преработката на 3 делителя на напрежение, които са оразмерени за референт 4,096V и с евентуалната промяна на 2 изходни съпротивления, през които се управляват оптрони.


Сря Мар 07, 2018 9:34 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
Опитвам се да подкарам I2C комуникацията между pic16F1847 и RTC модул, изпълнен на базата на DS3231:

Изображение

За конфигурирането на I2C на контролера използвам инструмента MCC , който генерира следният код:

Код:
/**
  MSSP2 Generated Driver File

  @Company
    Microchip Technology Inc.

  @File Name
    i2c2.c

  @Summary
    This is the generated header file for the MSSP2 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  @Description
    This header file provides APIs for driver for I2C2.
    Generation Information :
        Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.65.2
        Device            :  PIC16F1847
        Driver Version    :  2.02
    The generated drivers are tested against the following:
        Compiler          :  XC8 1.45
        MPLAB              :  MPLAB X 4.15   
*/

/*
    (c) 2018 Microchip Technology Inc. and its subsidiaries.
   
    Subject to your compliance with these terms, you may use Microchip software and any
    derivatives exclusively with Microchip products. It is your responsibility to comply with third party
    license terms applicable to your use of third party software (including open source software) that
    may accompany Microchip software.
   
    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
    IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
    FOR A PARTICULAR PURPOSE.
   
    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
    HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
    THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
    CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
    OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
    SOFTWARE.
*/

/**
  Section: Included Files
*/

#include "i2c2.h"

/**
  I2C Driver Queue Status Type

  @Summary
    Defines the type used for the transaction queue status.

  @Description
    This defines type used to keep track of the queue status.
*/

typedef union
{
    struct
    {
            uint8_t full:1;
            uint8_t empty:1;
            uint8_t reserved:6;
    }s;
    uint8_t status;
}I2C_TR_QUEUE_STATUS;

/**
  I2C Driver Queue Entry Type

  @Summary
    Defines the object used for an entry in the i2c queue items.

  @Description
    This defines the object in the i2c queue. Each entry is a composed
    of a list of TRBs, the number of the TRBs and the status of the
    currently processed TRB.
*/
typedef struct
{
    uint8_t                             count;          // a count of trb's in the trb list
    I2C2_TRANSACTION_REQUEST_BLOCK *ptrb_list;     // pointer to the trb list
    I2C2_MESSAGE_STATUS            *pTrFlag;       // set with the error of the last trb sent.
                                                        // if all trb's are sent successfully,
                                                        // then this is I2C2_MESSAGE_COMPLETE
} I2C_TR_QUEUE_ENTRY;

/**
  I2C Master Driver Object Type

  @Summary
    Defines the object that manages the i2c master.

  @Description
    This defines the object that manages the sending and receiving of
    i2c master transactions.
  */

typedef struct
{
    /* Read/Write Queue */
    I2C_TR_QUEUE_ENTRY          *pTrTail;       // tail of the queue
    I2C_TR_QUEUE_ENTRY          *pTrHead;       // head of the queue
    I2C_TR_QUEUE_STATUS         trStatus;       // status of the last transaction
    uint8_t                         i2cDoneFlag;    // flag to indicate the current
                                                    // transaction is done
    uint8_t                         i2cErrors;      // keeps track of errors


} I2C_OBJECT ;

/**
  I2C Master Driver State Enumeration

  @Summary
    Defines the different states of the i2c master.

  @Description
    This defines the different states that the i2c master
    used to process transactions on the i2c bus.
*/

typedef enum
{
    S_MASTER_IDLE,
    S_MASTER_RESTART,
    S_MASTER_SEND_ADDR,
    S_MASTER_SEND_DATA,
    S_MASTER_SEND_STOP,
    S_MASTER_ACK_ADDR,
    S_MASTER_RCV_DATA,
    S_MASTER_RCV_STOP,
    S_MASTER_ACK_RCV_DATA,
    S_MASTER_NOACK_STOP,
    S_MASTER_SEND_ADDR_10BIT_LSB,
    S_MASTER_10BIT_RESTART,
   
} I2C_MASTER_STATES;

/**
Section: Macro Definitions
*/

/* defined for I2C2 */

#ifndef I2C2_CONFIG_TR_QUEUE_LENGTH
        #define I2C2_CONFIG_TR_QUEUE_LENGTH 1
#endif

#define I2C2_TRANSMIT_REG                       SSP2BUF                 // Defines the transmit register used to send data.
#define I2C2_RECEIVE_REG                        SSP2BUF                 // Defines the receive register used to receive data.

// The following control bits are used in the I2C state machine to manage
// the I2C module and determine next states.
#define I2C2_WRITE_COLLISION_STATUS_BIT         SSP2CON1bits.WCOL     // Defines the write collision status bit.
#define I2C2_MODE_SELECT_BITS                   SSP2CON1bits.SSPM     // I2C Master Mode control bit.
#define I2C2_MASTER_ENABLE_CONTROL_BITS         SSP2CON1bits.SSPEN    // I2C port enable control bit.

#define I2C2_START_CONDITION_ENABLE_BIT         SSP2CON2bits.SEN      // I2C START control bit.
#define I2C2_REPEAT_START_CONDITION_ENABLE_BIT  SSP2CON2bits.RSEN     // I2C Repeated START control bit.
#define I2C2_RECEIVE_ENABLE_BIT                 SSP2CON2bits.RCEN     // I2C Receive enable control bit.
#define I2C2_STOP_CONDITION_ENABLE_BIT          SSP2CON2bits.PEN      // I2C STOP control bit.
#define I2C2_ACKNOWLEDGE_ENABLE_BIT             SSP2CON2bits.ACKEN    // I2C ACK start control bit.
#define I2C2_ACKNOWLEDGE_DATA_BIT               SSP2CON2bits.ACKDT    // I2C ACK data control bit.
#define I2C2_ACKNOWLEDGE_STATUS_BIT             SSP2CON2bits.ACKSTAT  // I2C ACK status bit.

#define I2C2_7bit    true
/**
Section: Local Functions
*/

void I2C2_FunctionComplete(void);
void I2C2_Stop(I2C2_MESSAGE_STATUS completion_code);

/**
Section: Local Variables
*/

static I2C_TR_QUEUE_ENTRY                  i2c2_tr_queue[I2C2_CONFIG_TR_QUEUE_LENGTH];
static I2C_OBJECT                          i2c2_object;
static I2C_MASTER_STATES                   i2c2_state = S_MASTER_IDLE;
static uint8_t                                 i2c2_trb_count = 0;

static I2C2_TRANSACTION_REQUEST_BLOCK       *p_i2c2_trb_current = NULL;
static I2C_TR_QUEUE_ENTRY                  *p_i2c2_current = NULL;


/**
  Section: Driver Interface
*/

void I2C2_Initialize(void)
{
    i2c2_object.pTrHead = i2c2_tr_queue;
    i2c2_object.pTrTail = i2c2_tr_queue;
    i2c2_object.trStatus.s.empty = true;
    i2c2_object.trStatus.s.full = false;

    i2c2_object.i2cErrors = 0;

    // R_nW write_noTX; P stopbit_notdetected; S startbit_notdetected; BF RCinprocess_TXcomplete; SMP High Speed; UA dontupdate; CKE enabled; D_nA lastbyte_address;
    SSP2STAT = 0x40;
    // SSPEN enabled; WCOL no_collision; CKP Idle:Low, Active:High; SSPM FOSC/4_SSPxADD_I2C; SSPOV no_overflow;
    SSP2CON1 = 0x28;
    // ACKTIM ackseq; SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 100ns; AHEN disabled;
    SSP2CON3 = 0x00;
    // SSPADD 3;
    SSP2ADD = 0x03;
   
    // clear the interrupt flags
    PIR4bits.SSP2IF = 0;
    PIR4bits.BCL2IF = 0;
   
    // enable the interrupts
    PIE4bits.SSP2IE = 1;
    PIE4bits.BCL2IE = 1;
   
}

       
uint8_t I2C2_ErrorCountGet(void)
{
    uint8_t ret;

    ret = i2c2_object.i2cErrors;
    return ret;
}

void I2C2_ISR ( void )
{
 
    static uint8_t  *pi2c_buf_ptr;
    static uint16_t i2c_address         = 0;
    static uint8_t  i2c_bytes_left      = 0;
    static uint8_t  i2c_10bit_address_restart = 0;

    PIR4bits.SSP2IF = 0;
   
    // Check first if there was a collision.
    // If we have a Write Collision, reset and go to idle state */
    if(I2C2_WRITE_COLLISION_STATUS_BIT)
    {
        // clear the Write colision
        I2C2_WRITE_COLLISION_STATUS_BIT = 0;
        i2c2_state = S_MASTER_IDLE;
        *(p_i2c2_current->pTrFlag) = I2C2_MESSAGE_FAIL;

        // reset the buffer pointer
        p_i2c2_current = NULL;

        return;
    }

    /* Handle the correct i2c state */
    switch(i2c2_state)
    {
        case S_MASTER_IDLE:    /* In reset state, waiting for data to send */

            if(i2c2_object.trStatus.s.empty != true)
            {
                // grab the item pointed by the head
                p_i2c2_current     = i2c2_object.pTrHead;
                i2c2_trb_count     = i2c2_object.pTrHead->count;
                p_i2c2_trb_current = i2c2_object.pTrHead->ptrb_list;

                i2c2_object.pTrHead++;

                // check if the end of the array is reached
                if(i2c2_object.pTrHead == (i2c2_tr_queue + I2C2_CONFIG_TR_QUEUE_LENGTH))
                {
                    // adjust to restart at the beginning of the array
                    i2c2_object.pTrHead = i2c2_tr_queue;
                }

                // since we moved one item to be processed, we know
                // it is not full, so set the full status to false
                i2c2_object.trStatus.s.full = false;

                // check if the queue is empty
                if(i2c2_object.pTrHead == i2c2_object.pTrTail)
                {
                    // it is empty so set the empty status to true
                    i2c2_object.trStatus.s.empty = true;
                }

                // send the start condition
                I2C2_START_CONDITION_ENABLE_BIT = 1;
               
                // start the i2c request
                i2c2_state = S_MASTER_SEND_ADDR;
            }

            break;

        case S_MASTER_RESTART:

            /* check for pending i2c Request */

            // ... trigger a REPEATED START
            I2C2_REPEAT_START_CONDITION_ENABLE_BIT = 1;

            // start the i2c request
            i2c2_state = S_MASTER_SEND_ADDR;

            break;

        case S_MASTER_SEND_ADDR_10BIT_LSB:

            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c2_object.i2cErrors++;
                I2C2_Stop(I2C2_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // Remove bit 0 as R/W is never sent here
                I2C2_TRANSMIT_REG = (i2c_address >> 1) & 0x00FF;

                // determine the next state, check R/W
                if(i2c_address & 0x01)
                {
                    // if this is a read we must repeat start
                    // the bus to perform a read
                    i2c2_state = S_MASTER_10BIT_RESTART;
                }
                else
                {
                    // this is a write continue writing data
                    i2c2_state = S_MASTER_SEND_DATA;
                }
            }

            break;

        case S_MASTER_10BIT_RESTART:

            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c2_object.i2cErrors++;
                I2C2_Stop(I2C2_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // ACK Status is good
                // restart the bus
                I2C2_REPEAT_START_CONDITION_ENABLE_BIT = 1;

                // fudge the address so S_MASTER_SEND_ADDR works correctly
                // we only do this on a 10-bit address resend
                i2c_address = 0x00F0 | ((i2c_address >> 8) & 0x0006);

                // set the R/W flag
                i2c_address |= 0x0001;

                // set the address restart flag so we do not change the address
                i2c_10bit_address_restart = 1;

                // Resend the address as a read
                i2c2_state = S_MASTER_SEND_ADDR;
            }

            break;

        case S_MASTER_SEND_ADDR:

            /* Start has been sent, send the address byte */

            /* Note:
                On a 10-bit address resend (done only during a 10-bit
                device read), the original i2c_address was modified in
                S_MASTER_10BIT_RESTART state. So the check if this is
                a 10-bit address will fail and a normal 7-bit address
                is sent with the R/W bit set to read. The flag
                i2c_10bit_address_restart prevents the  address to
                be re-written.
             */
            if(i2c_10bit_address_restart != 1)
            {
                // extract the information for this message
                i2c_address    = p_i2c2_trb_current->address;
                pi2c_buf_ptr   = p_i2c2_trb_current->pbuffer;
                i2c_bytes_left = p_i2c2_trb_current->length;
            }

            // check for 10-bit address
            if(!I2C2_7bit && (0x0 != i2c_address))
            { 
                if (0 == i2c_10bit_address_restart)
                {
                    // we have a 10 bit address
                    // send bits<9:8>
                    // mask bit 0 as this is always a write                   
                    I2C2_TRANSMIT_REG = 0xF0 | ((i2c_address >> 8) & 0x0006);
                    i2c2_state = S_MASTER_SEND_ADDR_10BIT_LSB;
                }
                else
                {
                    // resending address bits<9:8> to trigger read
                    I2C2_TRANSMIT_REG = i2c_address;
                    i2c2_state = S_MASTER_ACK_ADDR;
                    // reset the flag so the next access is ok
                    i2c_10bit_address_restart = 0;
                }
            }
            else
            {
                // Transmit the address
                I2C2_TRANSMIT_REG = i2c_address;
                if(i2c_address & 0x01)
                {
                    // Next state is to wait for address to be acked
                    i2c2_state = S_MASTER_ACK_ADDR;
                }
                else
                {
                    // Next state is transmit
                    i2c2_state = S_MASTER_SEND_DATA;
                }
            }
            break;

        case S_MASTER_SEND_DATA:

            // Make sure the previous byte was acknowledged
            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {
                // Transmission was not acknowledged
                i2c2_object.i2cErrors++;

                // Reset the Ack flag
                I2C2_ACKNOWLEDGE_STATUS_BIT = 0;

                // Send a stop flag and go back to idle
                I2C2_Stop(I2C2_DATA_NO_ACK);

            }
            else
            {
                // Did we send them all ?
                if(i2c_bytes_left-- == 0U)
                {
                    // yup sent them all!

                    // update the trb pointer
                    p_i2c2_trb_current++;

                    // are we done with this string of requests?
                    if(--i2c2_trb_count == 0)
                    {
                        I2C2_Stop(I2C2_MESSAGE_COMPLETE);
                    }
                    else
                    {
                        // no!, there are more TRB to be sent.
                        //I2C2_START_CONDITION_ENABLE_BIT = 1;

                        // In some cases, the slave may require
                        // a restart instead of a start. So use this one
                        // instead.
                        I2C2_REPEAT_START_CONDITION_ENABLE_BIT = 1;

                        // start the i2c request
                        i2c2_state = S_MASTER_SEND_ADDR;

                    }
                }
                else
                {
                    // Grab the next data to transmit
                    I2C2_TRANSMIT_REG = *pi2c_buf_ptr++;
                }
            }
            break;

        case S_MASTER_ACK_ADDR:

            /* Make sure the previous byte was acknowledged */
            if(I2C2_ACKNOWLEDGE_STATUS_BIT)
            {

                // Transmission was not acknowledged
                i2c2_object.i2cErrors++;

                // Send a stop flag and go back to idle
                I2C2_Stop(I2C2_MESSAGE_ADDRESS_NO_ACK);

                // Reset the Ack flag
                I2C2_ACKNOWLEDGE_STATUS_BIT = 0;
            }
            else
            {
                I2C2_RECEIVE_ENABLE_BIT = 1;
                i2c2_state = S_MASTER_ACK_RCV_DATA;
            }
            break;

        case S_MASTER_RCV_DATA:

            /* Acknowledge is completed.  Time for more data */

            // Next thing is to ack the data
            i2c2_state = S_MASTER_ACK_RCV_DATA;

            // Set up to receive a byte of data
            I2C2_RECEIVE_ENABLE_BIT = 1;

            break;

        case S_MASTER_ACK_RCV_DATA:

            // Grab the byte of data received and acknowledge it
            *pi2c_buf_ptr++ = I2C2_RECEIVE_REG;

            // Check if we received them all?
            if(--i2c_bytes_left)
            {

                /* No, there's more to receive */

                // No, bit 7 is clear.  Data is ok
                // Set the flag to acknowledge the data
                I2C2_ACKNOWLEDGE_DATA_BIT = 0;

                // Wait for the acknowledge to complete, then get more
                i2c2_state = S_MASTER_RCV_DATA;
            }
            else
            {

                // Yes, it's the last byte.  Don't ack it
                // Flag that we will nak the data
                I2C2_ACKNOWLEDGE_DATA_BIT = 1;

                I2C2_FunctionComplete();
            }

            // Initiate the acknowledge
            I2C2_ACKNOWLEDGE_ENABLE_BIT = 1;
            break;

        case S_MASTER_RCV_STOP:               
        case S_MASTER_SEND_STOP:

            // Send the stop flag
            I2C2_Stop(I2C2_MESSAGE_COMPLETE);
            break;

        default:

            // This case should not happen, if it does then
            // terminate the transfer
            i2c2_object.i2cErrors++;
            I2C2_Stop(I2C2_LOST_STATE);
            break;

    }
}

void I2C2_FunctionComplete(void)
{

    // update the trb pointer
    p_i2c2_trb_current++;

    // are we done with this string of requests?
    if(--i2c2_trb_count == 0)
    {
        i2c2_state = S_MASTER_SEND_STOP;
    }
    else
    {
        i2c2_state = S_MASTER_RESTART;
    }

}

void I2C2_Stop(I2C2_MESSAGE_STATUS completion_code)
{
    // then send a stop
    I2C2_STOP_CONDITION_ENABLE_BIT = 1;

    // make sure the flag pointer is not NULL
    if (p_i2c2_current->pTrFlag != NULL)
    {
        // update the flag with the completion code
        *(p_i2c2_current->pTrFlag) = completion_code;
    }

    // Done, back to idle
    i2c2_state = S_MASTER_IDLE;
   
}

void I2C2_MasterWrite(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pflag)
{
    static I2C2_TRANSACTION_REQUEST_BLOCK   trBlock;

    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {
        I2C2_MasterWriteTRBBuild(&trBlock, pdata, length, address);
        I2C2_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
    }

}

void I2C2_MasterRead(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C2_MESSAGE_STATUS *pflag)
{
    static I2C2_TRANSACTION_REQUEST_BLOCK   trBlock;


    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {
        I2C2_MasterReadTRBBuild(&trBlock, pdata, length, address);
        I2C2_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
    }

}


inline void I2C2_WaitForLastPacketToComplete()
{
    while(i2c2_state != S_MASTER_IDLE)
    {
        // If your code gets stuck here it is because the last packet is never completing
        // Most likely cause is that your interrupt is not firing as it should. Check if you have
        //   correctly enabled all MSSP, Peripheral and GIE interrupt settings.
    }
}

void I2C2_MasterTRBInsert(
                                uint8_t count,
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb_list,
                                I2C2_MESSAGE_STATUS *pflag)
{

    // check if there is space in the queue
    if (i2c2_object.trStatus.s.full != true)
    {
        *pflag = I2C2_MESSAGE_PENDING;

        i2c2_object.pTrTail->ptrb_list = ptrb_list;
        i2c2_object.pTrTail->count     = count;
        i2c2_object.pTrTail->pTrFlag   = pflag;
        i2c2_object.pTrTail++;

        // check if the end of the array is reached
        if (i2c2_object.pTrTail == (i2c2_tr_queue + I2C2_CONFIG_TR_QUEUE_LENGTH))
        {
            // adjust to restart at the beginning of the array
            i2c2_object.pTrTail = i2c2_tr_queue;
        }

        // since we added one item to be processed, we know
        // it is not empty, so set the empty status to false
        i2c2_object.trStatus.s.empty = false;

        // check if full
        if (i2c2_object.pTrHead == i2c2_object.pTrTail)
        {
            // it is full, set the full status to true
            i2c2_object.trStatus.s.full = true;
        }

    }
    else
    {
        *pflag = I2C2_MESSAGE_FAIL;
    }

    // for interrupt based
    if (*pflag == I2C2_MESSAGE_PENDING)
    {
        I2C2_WaitForLastPacketToComplete();
       
        // The state machine has to be started manually because it runs only in the ISR.
        // If we called the ISR function here function duplication would double the code size
        //    because this function would be called both from interrupt and from mainline code.
        PIR4bits.SSP2IF = true;

    }   // block until request is complete

}

void I2C2_MasterReadTRBBuild(
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address)
{
    ptrb->address  = address << 1;
    // make this a read
    ptrb->address |= 0x01;
    ptrb->length   = length;
    ptrb->pbuffer  = pdata;
}

void I2C2_MasterWriteTRBBuild(
                                I2C2_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address)
{
    ptrb->address = address << 1;
    ptrb->length  = length;
    ptrb->pbuffer = pdata;
}

bool I2C2_MasterQueueIsEmpty(void)
{
    return(i2c2_object.trStatus.s.empty);
}

bool I2C2_MasterQueueIsFull(void)
{
    return(i2c2_object.trStatus.s.full);
}       
       
void I2C2_BusCollisionISR( void )
{
    // enter bus collision handling code here
   PIR4bits.BCL2IF = 0;
}       
       
       
/**
End of File
*/


На първо време искам да видя, че нещо се чете от RTC модула, като си мисля, че с подаването на захранването трябва да започне броенето и да видя поне секундите да се променят.

За целта в основния ми цикъл съм вкарал:

Код:
void main(void)
{
    // initialize the device
    SYSTEM_Initialize();

    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:

    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();

uint8_t RXbuffer_forslave_1[50];
I2C2_MESSAGE_STATUS statusReadSlave1;
         

    while (1)
    {
    RXbuffer_forslave_1[0]=0xEE;
   
I2C2_MasterRead(&RXbuffer_forslave_1,10,0x57,&statusReadSlave1);
.
.
.
.
.


В чаршафа на RTC чипа пише че I2C адресът му е 68h а китаецът е написал в описанието на модула, че той е 57h

С 57h има комуникация, но осцилограмата на шината показва, че всички байтове са със стойност FF и нищо не се променя.

В случая се чете поредица от байтове, но дали са тези, които съдържат данните, не знам.
Това, което не ми е много ясно от кода на MCC е как да адресирам за четене регистрите на модула (00h - 12h).

Моля за вашите насоки.


Чет Мар 14, 2019 4:52 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 10, 2005 2:25 pm
Мнения: 4974
Местоположение: София
Мнение Re: I2C малко помощ
Цитат:
The slave address byte is the first byte received after the master generates a START condition. The slave address byte contains the 7-bit DS3231 address, which is 1101000, followed by the direction bit (R/W), which is 1 for a read.


и какво е МСС?


Чет Мар 14, 2019 5:53 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
MCC е вграденият в MplabXIDE инструмент "Mplab Code Configurator"

Със slave address = 68h нищо не се случва по шината. Няма "start condition" (SDA и SCL седят в "1") и не разбирам, защо е така.
С други стойности - примерно 67h има "start condition" но няма отговор от slave.
С 57h има "start condition" и slave отговаря.


Чет Мар 14, 2019 6:00 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 10, 2005 2:25 pm
Мнения: 4974
Местоположение: София
Мнение Re: I2C малко помощ
Пробвай:
start
ack = i2c_write(0xD0)
stop
и виж дали ack = 0.


Чет Мар 14, 2019 6:13 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 11:48 am
Мнения: 4671
Мнение Re: I2C малко помощ
по принцип някъде slave address го дават 8 битов другаде 7 битов
така че трябва да се нагоди/шифтне спрямо MCU-то

в "световната практика" I2C се свежда до "поток"(стриим) - read/write buffer
най-лесно ще го разбереш ако разгледаш SDK и библиотеки от ардуино

_________________
main[-1u]={1};


Чет Мар 14, 2019 7:33 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
Този код, който генерира MCC сигурно е безупречно изпипан, но за такива, като мен е трудно разбираем.

Тук намирам нещо, което ми е доста по-понятно. Утре ще го тествам в частта му I2C.


Чет Мар 14, 2019 8:52 pm
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Съб Май 21, 2016 8:47 pm
Мнения: 472
Местоположение: Бургас
Мнение Re: I2C малко помощ
lcr написа:
MCC е вграденият в MplabXIDE инструмент "Mplab Code Configurator"

Със slave address = 68h нищо не се случва по шината. Няма "start condition" (SDA и SCL седят в "1") и не разбирам, защо е така.
С други стойности - примерно 67h има "start condition" но няма отговор от slave.
С 57h има "start condition" и slave отговаря.


C0h и C1h са адресите са запис/четене:

The slave address byte contains the 7-bit DS3231 address, which is 1101000, followed by the direction bit (R/W), т.е.

1101 0000 -> С0h запис
1101 0001 -> C1h четене

ПП: Виждал съм в кодове за Ардуино да ползват адреса, който е показан (68h), но преди обръщение към шината го изместват 1 бит наляво и тогава установяват бита за четене/запис.


Пет Мар 15, 2019 9:48 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
Историята с I2C адреса на модула я разгадах.

На платката има EEPROM AT24C32 и изведени 3 пина (A0,A1 и A2) посредством които се задава адреса му.

Изображение

В случая въпросните пинове са висящи и като така адресът на паметта е 1010111, демек 57h.

Накратко - китаецът е посочил този адрес, като дефолтен, откъдето и объркването ми, че иде реч за адреса на RTC модула. Това обяснява и защо на този адрес се четат само празни байтове.

По въпроса с адреса на RTC модула (68h).....

Упорито шината стоеше във високо ниво докато не настроих скоростта на 100 kHz (беше на 400 kHz).

Сега има комуникация, но пак греда. Съдържанието на всички байтове, които се четат се променя непрекъснато а си мисля, че не следва да е така.


Пет Мар 15, 2019 2:00 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Юни 05, 2006 12:48 pm
Мнения: 4393
Местоположение: където небето среща земята, ракията е Jameson, а бирата Guinness
Мнение Re: I2C малко помощ
lcr написа:
Историята с I2C адреса на модула я разгадах.


Сега има комуникация, но пак греда. Съдържанието на всички байтове, които се четат се променя непрекъснато а си мисля, че не следва да е така.

дали тогава не четеш РТЦ модула?

_________________
... ако трети ден не ти се работи... това означава, че е сряда !


Пет Мар 15, 2019 2:48 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
MYXATA написа:
дали тогава не четеш РТЦ модула?


Точно RTC модула чета, но си мисля, че байтовете за минутите, часовете...... не би трябвало да си променят съдържанието по няколко пъти в секунда.


Пет Мар 15, 2019 2:55 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Юни 05, 2006 12:48 pm
Мнения: 4393
Местоположение: където небето среща земята, ракията е Jameson, а бирата Guinness
Мнение Re: I2C малко помощ
а кой е този РТЦ модул.... пусни някой линк към чаршафа.
щото може да си мислиш, че четеш дни пък да четеш секунди.... не е като да не се е случвало

_________________
... ако трети ден не ти се работи... това означава, че е сряда !


Пет Мар 15, 2019 3:16 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Май 12, 2014 10:49 pm
Мнения: 4379
Местоположение: София
Мнение Re: I2C малко помощ
https://datasheets.maximintegrated.com/en/ds/DS3231.pdf

Чета на куп определен брой байтове, като си мисля, че при всеки старт на I2C , пойнтерът сочи един и същи адрес.


Пет Мар 15, 2019 3:19 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 255 мнения ]  Отиди на страница Предишна  1 ... 13, 14, 15, 16, 17  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 4 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни