Problem med PIC18F46K22 "LÖST"

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PIC18F46K22

Inlägg av sodjan »

Det där med SSP1EN_bit och SSPEN_bit känns som en bug i MikroC miljön.
Finns det några specifika "device" filer där alla register är definierade?
Man kan kolla direkt där och se om SSP1EN finns med. Ingen #include
som lyfter in fel fil? O.s.v...

Ingen mening att gå vidare innan detta är utrett, något är fel...
Användarvisningsbild
SeniorLemuren
Inlägg: 8397
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med PIC18F46K22

Inlägg av SeniorLemuren »

janno skrev:Ursäkta att jag missade det, ändå gick jag tillbaka och sökte den informationen, men missade den.
Jag försöker bara systematiskt utesluta fel som man enkelt kan göra.
En annan sak som jag funderade över men inte hittat i tråden tidigare, hur talar man om för MikroC Pro's bibliotek vilken PIC man använder.
Eftersom du skrev så här:
Skriver man t.ex : SSP1CON1 = 0b00100000 (Enables the serial port) så är det godkänt.
om man däremot försöker sätta bara bit 5 "SSP1EN_bit = 1 ;" så får man rött streck under. Däremot går det att skriva: SSPEN_bit = 1 ; Som ju är för tex PIC18F2545 som bara har en SPI-modul?
Så kanske omgivningen tror att du har en annan processor än den som sitter i labbkortet.
Intressant att du reagerade på informationen om SSP1EN_bit = 1. eftersom alla mina tidigare programmeringar med olika µC har tillåtit formen XXXX_bit = utom denna. Som däremot godkänner ett uttryck som är till en µC som bara har en MSSP-modul. Det kan ju tyda på en bugg i mikroC PRO för just denna µC.
Användarvisningsbild
SeniorLemuren
Inlägg: 8397
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med PIC18F46K22

Inlägg av SeniorLemuren »

Det här är vad jag kan hitta i mikroC i en mapp DEFS
P18F46K22.C
sbit SSPEN_bit at SSP2CON1.B5; Finns
sbit SSPEN_bit at SSP1CON1.B5; Finns ej

sbit SSPEN_SSP1CON1_bit at SSP1CON1.B5; finns
sbit SSPEN_SSP2CON1_bit at SSP1CON1.B5; finns ej

P18F46K22.CP
sbit SSPEN_SSP1CON1_bit at SSP1CON1.B5; Finns
sbit SSPEN_SSP2CON1_bit at SSP2CON1.B5; Finns ej

sbit SSPEN_bit at SSP2CON1.B5; Finns
sbit SSPEN_bit at SSP1CON1.B5; Finns ej
Jag vet inte hur detta är tänkt, men i mina ögon tycker jag att det borede heta

sbit SSP2EN_bit at SSP2CON1.B5;
sbit SSP1EN_bit at SSP1CON1.B5;

skriver man bara SSPEN_bit = 1 så vet man ju inte om det är SSP1CON1 eller SSP2CON1 som gäller.

dessutom så fattas ju "sbit SSPEN_bit at SSP1CON1.B5;" och "sbit SSPEN_SSP2CON1_bit at SSP2CON1.B5;"

Som sagt jag vet inte hur det hänger ihop.

i REGISTER 15-2: SSPxCON1: SSPx CONTROL REGISTER 1 finns biten SSPxEN som då borde heta
SSP1EN eller SSP2EN ?
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PIC18F46K22

Inlägg av sodjan »

Om felen är helt uppenbara så kan man kanske rätta till dom själv.

Fjärde raden ovan "sbit SSPEN_SSP2CON1_bit at SSP1CON1.B5;"
borde väl inte finnas !? Man det kanske skulle vara:
"sbit SSPEN_SSP2CON1_bit at SSP2CON1.B5; finns ej"

Sen så kan man väl även skriva "registrer.bit" direkt i koden också
som en work-around.
Användarvisningsbild
SeniorLemuren
Inlägg: 8397
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med PIC18F46K22

Inlägg av SeniorLemuren »

Jo detta kanske man kan rätta själv. Men biblioteksrutinen för I2C är kompilerad och mikroC släpper inte källkoderna till sina lib-funktioner. Att skriva en egen I2C-funktion vet jag inte om jag fixar. Det verkar riktigt rörigt att få alla register rätt.
janno
Inlägg: 430
Blev medlem: 11 oktober 2009, 07:34:45
Ort: Västerås

Re: Problem med PIC18F46K22

Inlägg av janno »

Du hade installerat MPLABX såg jag tidigare, prövade du pluginen code configurator?
Code configurator
MPLABX code configurator.JPG
Där kan du sätta upp enheten du vill använda och få källkoden genererad, det kan ju vara värt att pröva den, bara för att kopiera källkoden för att få koll på vad som verkligen händer istället för dolda biblioteksrutiner.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
SeniorLemuren
Inlägg: 8397
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med PIC18F46K22

Inlägg av SeniorLemuren »

Intressant. Skall kolla. Även om MPLAB X ger mig mardrömmar. :)
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PIC18F46K22

Inlägg av sodjan »

Testade Janos förslag med standard inställningar för I1C för MSSP1 modulen.
Fick koden nedan. Snyggt med automatgenererade kommentarer... :-)
Sen så bygger ju deras lösning på ett kösystem för meddelanden o.s.v,
så jag vet inte hur lätt det är att bygga in i en MikroC lösning.

Ett alternativ är ju att "köra" I2C själv direkt utan "libbar"...

Kod: Markera allt

/**
  I2C1 Generated Driver File

  @Company
    Microchip Technology Inc.

  @File Name
    i2c1.c

  @Summary
    This is the generated header file for the I2C1 driver using MPLAB® Code Configurator

  @Description
    This header file provides APIs for driver for I2C1.
    Generation Information :
        Product Revision  :  MPLAB® Code Configurator - v2.25.2
        Device            :  PIC18F46K22
        Driver Version    :  2.00
    The generated drivers are tested against the following:
        Compiler          :  XC8 v1.34
        MPLAB 	          :  MPLAB X v2.35 or v3.00
*/

/*
Copyright (c) 2013 - 2015 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*/

/**
  Section: Included Files
*/

#include "i2c1.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
    I2C1_TRANSACTION_REQUEST_BLOCK *ptrb_list;     // pointer to the trb list
    I2C1_MESSAGE_STATUS            *pTrFlag;       // set with the error of the last trb sent.
                                                        // if all trb's are sent successfully,
                                                        // then this is I2C1_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 I2C1 */

#ifndef I2C1_CONFIG_TR_QUEUE_LENGTH
        #define I2C1_CONFIG_TR_QUEUE_LENGTH 1
#endif

#define I2C1_TRANSMIT_REG                       SSP1BUF                 // Defines the transmit register used to send data.
#define I2C1_RECEIVE_REG                        SSP1BUF                 // 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 I2C1_WRITE_COLLISION_STATUS_BIT         SSP1CON1bits.WCOL     // Defines the write collision status bit.
#define I2C1_MODE_SELECT_BITS                   SSP1CON1bits.SSPM     // I2C Master Mode control bit.
#define I2C1_MASTER_ENABLE_CONTROL_BITS         SSP1CON1bits.SSPEN    // I2C port enable control bit.

#define I2C1_START_CONDITION_ENABLE_BIT         SSP1CON2bits.SEN      // I2C START control bit.
#define I2C1_REPEAT_START_CONDITION_ENABLE_BIT  SSP1CON2bits.RSEN     // I2C Repeated START control bit.
#define I2C1_RECEIVE_ENABLE_BIT                 SSP1CON2bits.RCEN     // I2C Receive enable control bit.
#define I2C1_STOP_CONDITION_ENABLE_BIT          SSP1CON2bits.PEN      // I2C STOP control bit.
#define I2C1_ACKNOWLEDGE_ENABLE_BIT             SSP1CON2bits.ACKEN    // I2C ACK start control bit.
#define I2C1_ACKNOWLEDGE_DATA_BIT               SSP1CON2bits.ACKDT    // I2C ACK data control bit.
#define I2C1_ACKNOWLEDGE_STATUS_BIT             SSP1CON2bits.ACKSTAT  // I2C ACK status bit.

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

void I2C1_FunctionComplete(void);
void I2C1_Stop(I2C1_MESSAGE_STATUS completion_code);

/**
 Section: Local Variables
*/

static I2C_TR_QUEUE_ENTRY                  i2c1_tr_queue[I2C1_CONFIG_TR_QUEUE_LENGTH];
static I2C_OBJECT                          i2c1_object;
static I2C_MASTER_STATES                   i2c1_state = S_MASTER_IDLE;
static uint8_t                                 i2c1_trb_count = 0;

static I2C1_TRANSACTION_REQUEST_BLOCK       *p_i2c1_trb_current = NULL;
static I2C_TR_QUEUE_ENTRY                  *p_i2c1_current = NULL;


/**
  Section: Driver Interface
*/


void I2C1_Initialize(void)
{
    i2c1_object.pTrHead = i2c1_tr_queue;
    i2c1_object.pTrTail = i2c1_tr_queue;
    i2c1_object.trStatus.s.empty = true;
    i2c1_object.trStatus.s.full = false;

    i2c1_object.i2cErrors = 0;

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

    /* Byte sent or received */
    // clear the master interrupt flag
    PIR1bits.SSP1IF = 0;
    // enable the master interrupt
    PIE1bits.SSP1IE = 1;
    
}

        
uint8_t I2C1_ErrorCountGet(void)
{
    uint8_t ret;

    ret = i2c1_object.i2cErrors;
    return ret;
}

void I2C1_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;

    PIR1bits.SSP1IF = 0;

    // Check first if there was a collision.
    // If we have a Write Collision, reset and go to idle state */
    if(I2C1_WRITE_COLLISION_STATUS_BIT)
    {
        // clear the Write colision
        I2C1_WRITE_COLLISION_STATUS_BIT = 0;
        i2c1_state = S_MASTER_IDLE;
        *(p_i2c1_current->pTrFlag) = I2C1_MESSAGE_FAIL;

        // reset the buffer pointer
        p_i2c1_current = NULL;

        return;
    }

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

            if(i2c1_object.trStatus.s.empty != true)
            {
                // grab the item pointed by the head
                p_i2c1_current     = i2c1_object.pTrHead;
                i2c1_trb_count     = i2c1_object.pTrHead->count;
                p_i2c1_trb_current = i2c1_object.pTrHead->ptrb_list;

                i2c1_object.pTrHead++;

                // check if the end of the array is reached
                if(i2c1_object.pTrHead == (i2c1_tr_queue + I2C1_CONFIG_TR_QUEUE_LENGTH))
                {
                    // adjust to restart at the beginning of the array
                    i2c1_object.pTrHead = i2c1_tr_queue;
                }

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

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

                // send the start condition
                I2C1_START_CONDITION_ENABLE_BIT = 1;
                
                // start the i2c request
                i2c1_state = S_MASTER_SEND_ADDR;
            }

            break;

        case S_MASTER_RESTART:

            /* check for pending i2c Request */

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

            // start the i2c request
            i2c1_state = S_MASTER_SEND_ADDR;

            break;

        case S_MASTER_SEND_ADDR_10BIT_LSB:

            if(I2C1_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c1_object.i2cErrors++;
                I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // Remove bit 0 as R/W is never sent here
                I2C1_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
                    i2c1_state = S_MASTER_10BIT_RESTART;
                }
                else
                {
                    // this is a write continue writing data
                    i2c1_state = S_MASTER_SEND_DATA;
                }
            }

            break;

        case S_MASTER_10BIT_RESTART:

            if(I2C1_ACKNOWLEDGE_STATUS_BIT)
            {
                i2c1_object.i2cErrors++;
                I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK);
            }
            else
            {
                // ACK Status is good
                // restart the bus
                I2C1_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
                i2c1_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_i2c1_trb_current->address;
                pi2c_buf_ptr   = p_i2c1_trb_current->pbuffer;
                i2c_bytes_left = p_i2c1_trb_current->length;
            }

            // check for 10-bit address
            if(!I2C1_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                    
                    I2C1_TRANSMIT_REG = 0xF0 | ((i2c_address >> 8) & 0x0006);
                    i2c1_state = S_MASTER_SEND_ADDR_10BIT_LSB;
                }
                else
                {
                    // resending address bits<9:8> to trigger read
                    I2C1_TRANSMIT_REG = i2c_address;
                    i2c1_state = S_MASTER_ACK_ADDR;
                    // reset the flag so the next access is ok
                    i2c_10bit_address_restart = 0;
                }
            }
            else
            {
                // Transmit the address
                I2C1_TRANSMIT_REG = i2c_address;
                if(i2c_address & 0x01)
                {
                    // Next state is to wait for address to be acked
                    i2c1_state = S_MASTER_ACK_ADDR;
                }
                else
                {
                    // Next state is transmit
                    i2c1_state = S_MASTER_SEND_DATA;
                }
            }
            break;

        case S_MASTER_SEND_DATA:

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

                // Reset the Ack flag
                I2C1_ACKNOWLEDGE_STATUS_BIT = 0;

                // Send a stop flag and go back to idle
                I2C1_Stop(I2C1_DATA_NO_ACK);

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

                    // update the trb pointer
                    p_i2c1_trb_current++;

                    // are we done with this string of requests?
                    if(--i2c1_trb_count == 0)
                    {
                        I2C1_Stop(I2C1_MESSAGE_COMPLETE);
                    }
                    else
                    {
                        // no!, there are more TRB to be sent.
                        //I2C1_START_CONDITION_ENABLE_BIT = 1;

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

                        // start the i2c request
                        i2c1_state = S_MASTER_SEND_ADDR;

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

        case S_MASTER_ACK_ADDR:

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

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

                // Send a stop flag and go back to idle
                I2C1_Stop(I2C1_MESSAGE_ADDRESS_NO_ACK);

                // Reset the Ack flag
                I2C1_ACKNOWLEDGE_STATUS_BIT = 0;
            }
            else
            {
                I2C1_RECEIVE_ENABLE_BIT = 1;
                i2c1_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
            i2c1_state = S_MASTER_ACK_RCV_DATA;

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

            break;

        case S_MASTER_ACK_RCV_DATA:

            // Grab the byte of data received and acknowledge it
            *pi2c_buf_ptr++ = I2C1_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
                I2C1_ACKNOWLEDGE_DATA_BIT = 0;

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

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

                I2C1_FunctionComplete();
            }

            // Initiate the acknowledge
            I2C1_ACKNOWLEDGE_ENABLE_BIT = 1;
            break;

        case S_MASTER_RCV_STOP:                
        case S_MASTER_SEND_STOP:

            // Send the stop flag
            I2C1_Stop(I2C1_MESSAGE_COMPLETE);
            break;

        default:

            // This case should not happen, if it does then
            // terminate the transfer
            i2c1_object.i2cErrors++;
            I2C1_Stop(I2C1_LOST_STATE);
            break;

    }
}

void I2C1_FunctionComplete(void)
{

    // update the trb pointer
    p_i2c1_trb_current++;

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

}

void I2C1_Stop(I2C1_MESSAGE_STATUS completion_code)
{
    // then send a stop
    I2C1_STOP_CONDITION_ENABLE_BIT = 1;

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

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

void I2C1_MasterWrite(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C1_MESSAGE_STATUS *pflag)
{
    static I2C1_TRANSACTION_REQUEST_BLOCK   trBlock;

    // check if there is space in the queue
    if (i2c1_object.trStatus.s.full != true)
    {
        I2C1_MasterWriteTRBBuild(&trBlock, pdata, length, address);
        I2C1_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C1_MESSAGE_FAIL;
    }

}

void I2C1_MasterRead(
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address,
                                I2C1_MESSAGE_STATUS *pflag)
{
    static I2C1_TRANSACTION_REQUEST_BLOCK   trBlock;


    // check if there is space in the queue
    if (i2c1_object.trStatus.s.full != true)
    {
        I2C1_MasterReadTRBBuild(&trBlock, pdata, length, address);
        I2C1_MasterTRBInsert(1, &trBlock, pflag);
    }
    else
    {
        *pflag = I2C1_MESSAGE_FAIL;
    }

}

void I2C1_MasterTRBInsert(
                                uint8_t count,
                                I2C1_TRANSACTION_REQUEST_BLOCK *ptrb_list,
                                I2C1_MESSAGE_STATUS *pflag)
{

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

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

        // check if the end of the array is reached
        if (i2c1_object.pTrTail == (i2c1_tr_queue + I2C1_CONFIG_TR_QUEUE_LENGTH))
        {
            // adjust to restart at the beginning of the array
            i2c1_object.pTrTail = i2c1_tr_queue;
        }

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

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

    }
    else
    {
        *pflag = I2C1_MESSAGE_FAIL;
    }

    // for interrupt based
    if (*pflag == I2C1_MESSAGE_PENDING)
    {
        while(i2c1_state != S_MASTER_IDLE);
        {
            // force the task to run since we know that the queue has
            // something that needs to be sent
            PIR1bits.SSP1IF = true;
        }
    }   // block until request is complete

}

void I2C1_MasterReadTRBBuild(
                                I2C1_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 I2C1_MasterWriteTRBBuild(
                                I2C1_TRANSACTION_REQUEST_BLOCK *ptrb,
                                uint8_t *pdata,
                                uint8_t length,
                                uint16_t address)
{
    ptrb->address = address << 1;
    ptrb->length  = length;
    ptrb->pbuffer = pdata;
}

bool I2C1_MasterQueueIsEmpty(void)
{
    return(i2c1_object.trStatus.s.empty);
}

bool I2C1_MasterQueueIsFull(void)
{
    return(i2c1_object.trStatus.s.full);
}        
        
void I2C1_BusCollisionISR( void )
{
    // enter bus collision handling code here
}        
        
        
/**
 End of File
*/
Användarvisningsbild
SeniorLemuren
Inlägg: 8397
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med PIC18F46K22

Inlägg av SeniorLemuren »

Ja, jag har också genererat kod. Om det ser bra ut med kommentarerna vet jag inte för jag kan inte läsa dessa. Om det är något som gör mig förb. i datavärlden så är det korkade programmerare som lägger ljusgrå text på vit bakgrund. När jag råkar ut för slikt så stänger jag programmet direkt.

Det är säkert ingen konst att gå någonstans och ändra editor-inställningarna om man kan läsa den förb. texten för att ta sig dit. De som sitter bakom spakarna och tillverkar dylika program är säkert yngre förmågor som ser som örnar, men redan vid 40 års ålder så har ögats förmåga att urskilja gråskalor försämrats med flera hundra %.

Vad förväntar sig dessa förmågor av en en gubbe som jag, 70 år nästa år. Det finns väl förmodligen inte ens i deras medvetande att gammla gubbar och kärringar ens använder datorer. :(

Så, neej något mer försök i MPLAB-världen blir inte aktuella. :jimmyhacker:
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PIC18F46K22

Inlägg av sodjan »

Lite futtigt om det enbart handlar om att ställa om färgerna.
Aja, skit samma... :-)
janno
Inlägg: 430
Blev medlem: 11 oktober 2009, 07:34:45
Ort: Västerås

Re: Problem med PIC18F46K22

Inlägg av janno »

Om du då går in i Menyn
Tools -> Options
Väljer fliken "Fonts & Colors"
Och profilen "City Lights" så får du en högkontrast färgsättning.
Lika så kan du gå till "Appearence" fliken och "Look and feel" o välja hur du vill att användargränssnittet ska se ut.
Användarvisningsbild
SeniorLemuren
Inlägg: 8397
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med PIC18F46K22 "LÖST"

Inlägg av SeniorLemuren »

SeniorLemuren skrev:Nu har jag kört i diket.
Jag har ändrat om ett lib för OLED (SDD1303 SPI) skrivet i MPLAB X för PIC18F2550 till mikroC PRO och PIC 18F4550 för I2C i stället för SPI. Det var inga problem, funkade direkt.

Nu ville jag byta till en PIC18F46K22 och där är det tvärstopp. Jag har kopplat SDA1 till RC4 och SCL1 RC3 på IC18F46K22. Jag har även testat med SDA2 på RD1 och SCL2 på RD0.

Jag har testat att sätta
OSCCON = 0b01100010 ;
OSCTUNE.PLLEN=0;
för att köra på samma klockfrekvens som PIC18F4550 men icke. Vad har jag missat som skiljer de båda PIC:arna åt mer än interna klockan 8 resp 16 MHz och pinnarna för SDA/SCL

Jag har gjort ett kort testprogram som ser ut så här:

Kod: Markera allt

#include "font.h"
#include "SSD1306.h"


#define led_On       LATD5_bit = 1 ;
#define led_Off      LATD5_bit = 0 ;



void main() {
     ADCON1 = 0b00001111 ;          // Configure AN pins as digital I/O
     TRISA  = 0b00100000 ;
     TRISB  = 0b00000000 ;
     TRISC  = 0b00000000 ;
     TRISD  = 0b00000000 ;
     TRISE  = 0b00000000 ;
     LATE   = 0b00000000 ;
     LATB   = 0b00000000 ;
     LATC   = 0b00000000 ;
     LATD   = 0b00000000 ;
     ANSELC = 0b00000000 ;     
     OSCCON = 0b01110010 ; // Alternativt OSCCON = 0b01100010 ;(8MHz)
     OSCTUNE.PLLEN=0;
     while (OSCCON.HFIOFS==0); // wait stable oscillator
     I2C1_Init(100000);
     Oled_Init(); //***** SSD1306.h *****
     Oled_FillScreen(0x00);
     Oled_SetFont(Terminal12x16, 12, 16, 32,127);
     Oled_FillScreen(0x00);// Clear display
     Oled_ConstText("*TROTTLE*  ", 0,0) ;

     
do {

      led_On;
      delay_ms(500) ;
      led_Off;
      delay_ms(500) ;

      }while(1);
}
led har jag satt med för att se om det snurrar och det gör det så länge jag inte försöker göra write. Se slutet på den medskickade header-filen. Den hänger sig vid första writen:

Kod: Markera allt

#ifndef SSD1306_H
#define        SSD1306_H

//12C_ADDRESS    0x78

 //Declaration of global variables.
//------------------------------------------------------------------------------
typedef char                     schar;
typedef unsigned char            uchar;
typedef const char               cschar;
typedef const unsigned char      cuchar;
typedef int                      sint;
typedef unsigned int             uint;

cuchar *font, *font2;
uchar width, height, minimum, maximum;

// Function Prototypes.
//------------------------------------------------------------------------------
void Oled_Init(void);
void Oled_Command(uchar cmd);
void Oled_WriteRam(uchar dat);
void Oled_SetPointer(uchar seg, uchar pag);
void Oled_SetFont(cuchar *_font, uchar _width, uchar _height, uchar _min, uchar _max);
void Oled_WriteChar(uchar c, uchar seg, uchar pag);
void Oled_ConstText(cschar *buffer, uchar seg, uchar pag);
void Oled_Text(schar *buffer, uchar seg, uchar pag);
void Oled_FillScreen(uchar pattern);
void Oled_Image(cuchar *buffer);
void Right_HorizontalScroll(uchar start_page, uchar end_page, uchar set_time);
void Left_HorizontalScroll(uchar start_page, uchar end_page, uchar set_time);
void VerticalRight_HorizontalScroll(uchar start_page, uchar end_page, uchar set_time);
void VerticalLeft_HorizontalScroll(uchar start_page, uchar end_page, uchar set_time);
void Deactivate_Scroll(void);
void Activate_Scroll(void);
//------------------------------------------------------------------------------

// Initializes the OLED module.
//------------------------------------------------------------------------------
void Oled_Init(void){
Delay_ms(500);

Oled_Command(0xAE);                     // Set Display OFF
Oled_Command(0x81); Oled_Command(0xCF); // Set Contrast Control
Oled_Command(0xA4);                     // Entire Display ON
Oled_Command(0xA6);                     // Set Normal

Oled_Command(0x20); Oled_Command(0x02); // Set Memory Addressing Mode
Oled_Command(0x00);                     // Set Lower Column
Oled_Command(0x10);                     // Set Higher Column
Oled_Command(0xB0);                     // Set Page Start

Oled_Command(0x40);                     // Set Display Start Line
Oled_Command(0xA1);                     // Set Segment Re-map
Oled_Command(0xA8); Oled_Command(0x3F); // Set Multiplex Ratio
Oled_Command(0xC8);                     // Set COM Output
Oled_Command(0xD3); Oled_Command(0x00); // Set Display Offset
Oled_Command(0xDA); Oled_Command(0x12); // Set COM Pins Hardware Configuration

Oled_Command(0xD5); Oled_Command(0x80); // Set Display Clock
Oled_Command(0xD9); Oled_Command(0xF1); // Set Pre-charge Period
Oled_Command(0xDB); Oled_Command(0x40); // Set VCOMH Deselect Level
Oled_Command(0x8D); Oled_Command(0x14); // Charge Pump Setting

Oled_Command(0xAF);                     // Set Display ON
Oled_FillScreen(0x00);                  // Clear screen 
}

// Write command.
//------------------------------------------------------------------------------
void Oled_Command(uchar cmd){
I2C1_Start();
I2C1_Wr(0x78);  // ******************Här hänger det sig ******************
I2C1_Wr(0x00);  // Co = 0, D/C = 0
I2C1_Wr(cmd);
I2C1_Stop();
}
//------------------------------------------------------------------------------
// Headerfilen fortsätter här men jag klippte här eftersom man inte kommer längre än hit.
Användarvisningsbild
SeniorLemuren
Inlägg: 8397
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Problem med PIC18F46K22

Inlägg av SeniorLemuren »

Värsta amatörfelet. Missade detta

ANSELC = 0x00;
LATC = 0b00011000 ;

I och för sig så skulle ju detta kunna sättas i libfunktionen eftersom den ändå sätter alla andra parametrar, pinnar m.m. Där ser man lurigheten med att använda färdiga rutiner. :) Tack alla för hjälpen.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PIC18F46K22

Inlägg av sodjan »

Ah, vad skönt att det löste sig! Jag var orolig
att hela "båt-tråden" skulle stanna av... :-)
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Re: Problem med PIC18F46K22

Inlägg av vfr »

SeniorLemuren skrev:"stanna av... :-)
Eller sjunka får man kanske säga om en båttråd. Nej, det hade verkligen varit synd. Det är trevliga små uppgraderingar som görs, herr Lemuren. :D
Skriv svar