Problem med PIC18F46K22 "LÖST"
Re: Problem med PIC18F46K22
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...
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...
- SeniorLemuren
- Inlägg: 8397
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Problem med PIC18F46K22
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.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:Så kanske omgivningen tror att du har en annan processor än den som sitter i labbkortet.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?
- SeniorLemuren
- Inlägg: 8397
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Problem med PIC18F46K22
Det här är vad jag kan hitta i mikroC i en mapp DEFS
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 ?
Jag vet inte hur detta är tänkt, men i mina ögon tycker jag att det borede hetaP18F46K22.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
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 ?
Re: Problem med PIC18F46K22
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.
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.
- SeniorLemuren
- Inlägg: 8397
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Problem med PIC18F46K22
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.
Re: Problem med PIC18F46K22
Du hade installerat MPLABX såg jag tidigare, prövade du pluginen code configurator?
Code configurator 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.
Code configurator 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.
- SeniorLemuren
- Inlägg: 8397
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Problem med PIC18F46K22
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"...
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
*/
- SeniorLemuren
- Inlägg: 8397
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Problem med PIC18F46K22
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.
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.

Re: Problem med PIC18F46K22
Lite futtigt om det enbart handlar om att ställa om färgerna.
Aja, skit samma...
Aja, skit samma...

Re: Problem med PIC18F46K22
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.
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.
- SeniorLemuren
- Inlägg: 8397
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Problem med PIC18F46K22 "LÖST"
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: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
#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); }
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.
- SeniorLemuren
- Inlägg: 8397
- Blev medlem: 26 maj 2009, 12:20:37
- Ort: Kristinehamn
Re: Problem med PIC18F46K22
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.
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.

Re: Problem med PIC18F46K22
Ah, vad skönt att det löste sig! Jag var orolig
att hela "båt-tråden" skulle stanna av...
att hela "båt-tråden" skulle stanna av...

Re: Problem med PIC18F46K22
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.SeniorLemuren skrev:"stanna av...
