Forum: Mikrocontroller und Digitale Elektronik BMP280 an PIC18F45K42 mit MPLAP und I2C


von Brom B. (schrori)


Lesenswert?

Hallo zusammen,

leider komme ich aktuell nicht wirklich weiter.
Ich möchte mit dem PIC18F45K42 via I2C auslesen. Leider finde ich zum 
BMP280 keine Bibliothek die für MPLAP geeignet ist und auch meine 
Versuche die anderen Bibliotheken umzuschreiben sind gescheitert.

Auch "Anleitungen" für den 18F4550 habe ich gefunden, doch nutzt diese 
nicht MCC sondern schreibt direkt in die Register welche sich von den 
Registern in meinem Controller stark unterscheiden.

Ich möchte lediglich den Luftdruck messen. es wäre toll wenn mir jemand 
helfen könnte. Bzw. würde es schon helfen wenn ich schaffe Bytes zu 
senden und zu empfangen. Ein paar code schnipsel wären toll!

Danke schonmal :)

Ausschnitt auf dem 18F4550
1
 
2
I2C_IDLE() //function checks the status of the bus. It checks either I2C bus is busy or free. is It completed the last operation successfully?
3
4
5
void I2C_IDLE()
6
{
7
  while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
8
}
9
I2C_Initialize_Master() //function enables master mode and generates clock frequency by uploading a value to the SSPADD register.
10
void I2C_Master_Init()
11
{
12
SSPCON = 0x28;  // enable I2C pins SCL and SDA for serial communication
13
SSPCON2 = 0x00; 
14
SSPSTAT = 0x00;  //slew rate enables for high speed control
15
SSPADD = ((_XTAL_FREQ/4)/I2C_BaudRate) - 1;
16
TRISC3 = 1;  //Set as a digital input 
17
TRISC4 = 1;  //Set as a digital input 
18
}
19
//This function should be called before using other functions.
20
void I2C_Start()
21
{
22
I2C_IDLE();
23
SSPCON2bits.SEN = 1;  // initial start condition on SDA line
24
}
25
//This function sends stops condition to end data transfer.
26
void I2C_Stop()
27
{
28
I2C_IDLE();
29
SSPCON2bits.PEN = 1; // Initiate Stop condition on SDA and SCL pins
30
}
31
//This function sends a  signal to a slave that the master wants to send more data. It will restart the data transfer.
32
void I2C_Restart()
33
{
34
I2C_IDLE();
35
SSPCON2bits.RSEN = 1; // Initiate Repeated Start condition on SDA and SCL pins.
36
}
37
//These two functions provide an ACK signal after sending a 7bit/10bit address or 8bit data.
38
void I2C_ACK(void)
39
{
40
  I2C_IDLE();
41
  SSPCON2bits.ACKDT = 0; //Acknowledge Data bit  
42
  SSPCON2bits.ACKEN = 1;  // Acknowledge Sequence Enable bit(
43
}
44
void I2C_NACK(void)
45
{
46
I2C_IDLE();
47
SSPCON2bits.ACKDT = 1; 
48
SSPCON2bits.ACKEN = 1; 
49
}
50
I2C_Write() //used to transmit address and data through the SDA wire.
51
// input parameter to this function can be a byte ( either address or data)
52
unsigned char I2C_Write(unsigned char Data)
53
{
54
I2C_IDLE();   // wait untill I2C_Bus of PIC18F4550 microcontroller becomes free 
55
SSPBUF = Data; // store data inside SSPBUF register of PIC18F4550 microcontroller
56
I2C_Wait();  
57
return ACKSTAT; //return status of data or address transmission
58
}
59
This I2C_Read_Byte() //routine reads a byte from the I2C_Bus and returns its value.
60
unsigned char I2C_Read_Byte(void)
61
{
62
SSPCON2bits.RCEN = 1; // Enable & Start Reception
63
while(!SSPIF); // Wait Until Completion
64
SSPIF = 0; // Clear The Interrupt Flag Bit
65
return SSPBUF; // Return The Received Byte
66
}

Example aus MPLapMCC
1
#ifndef I2C2_MASTER_EXAMPLE_H
2
#define I2C2_MASTER_EXAMPLE_H
3
4
#include <stdint.h>
5
#include <stdio.h>
6
#include "../i2c2_master.h"
7
8
uint8_t  I2C2_Read1ByteRegister(i2c2_address_t address, uint8_t reg);
9
uint16_t I2C2_Read2ByteRegister(i2c2_address_t address, uint8_t reg);
10
void I2C2_Write1ByteRegister(i2c2_address_t address, uint8_t reg, uint8_t data);
11
void I2C2_Write2ByteRegister(i2c2_address_t address, uint8_t reg, uint16_t data);
12
void I2C2_WriteNBytes(i2c2_address_t address, uint8_t *data, size_t len);
13
void I2C2_ReadNBytes(i2c2_address_t address, uint8_t *data, size_t len);
14
void I2C2_ReadDataBlock(i2c2_address_t address, uint8_t reg, uint8_t *data, size_t len);
15
16
#endif /* I2C2_MASTER_EXAMPLE_H */

Versuch der kombination
1
#include <stdint.h>
2
3
#if !defined BMP280_I2C
4
#define  BMP280_I2C2
5
#endif
6
7
8
#ifdef  BMP280_I2C2
9
#define BMP280_Start    I2C2_Start
10
#define BMP280_Write    I2C2_Wr
11
#define BMP280_Read     I2C2_Rd
12
#define BMP280_Stop     I2C2_Stop
13
#endif
14
15
#ifndef BMP280_I2C_ADDRESS
16
  #define BMP280_I2C_ADDRESS  0xEE
17
#endif
18
19
#define BMP280_CHIP_ID        0x58
20
21
#define BMP280_REG_DIG_T1     0x88
22
#define BMP280_REG_DIG_T2     0x8A
23
#define BMP280_REG_DIG_T3     0x8C
24
25
#define BMP280_REG_DIG_P1     0x8E
26
#define BMP280_REG_DIG_P2     0x90
27
#define BMP280_REG_DIG_P3     0x92
28
#define BMP280_REG_DIG_P4     0x94
29
#define BMP280_REG_DIG_P5     0x96
30
#define BMP280_REG_DIG_P6     0x98
31
#define BMP280_REG_DIG_P7     0x9A
32
#define BMP280_REG_DIG_P8     0x9C
33
#define BMP280_REG_DIG_P9     0x9E
34
35
#define BMP280_REG_CHIPID     0xD0
36
#define BMP280_REG_SOFTRESET  0xE0
37
38
#define BMP280_REG_STATUS     0xF3
39
#define BMP280_REG_CONTROL    0xF4
40
#define BMP280_REG_CONFIG     0xF5
41
#define BMP280_REG_PRESS_MSB  0xF7
42
43
int32_t adc_T, adc_P, t_fine;
44
45
//
46
void BMP280_Write8(uint8_t reg_addr, uint8_t _data);
47
48
49
50
51
//
52
// BMP280 sensor modes, register ctrl_meas mode[1:0]
53
typedef enum
54
{
55
  MODE_SLEEP  = 0x00,  // sleep mode
56
  MODE_FORCED = 0x01,  // forced mode
57
  MODE_NORMAL = 0x03   // normal mode
58
} BMP280_mode;
59
60
// oversampling setting. osrs_t[2:0], osrs_p[2:0]
61
typedef enum
62
{
63
  SAMPLING_SKIPPED = 0x00,  //skipped, output set to 0x80000
64
  SAMPLING_X1      = 0x01,  // oversampling x1
65
  SAMPLING_X2      = 0x02,  // oversampling x2
66
  SAMPLING_X4      = 0x03,  // oversampling x4
67
  SAMPLING_X8      = 0x04,  // oversampling x8
68
  SAMPLING_X16     = 0x05   // oversampling x16
69
} BMP280_sampling;
70
71
// filter setting filter[2:0]
72
typedef enum
73
{
74
  FILTER_OFF = 0x00,  // filter off
75
  FILTER_2   = 0x01,  // filter coefficient = 2
76
  FILTER_4   = 0x02,  // filter coefficient = 4
77
  FILTER_8   = 0x03,  // filter coefficient = 8
78
  FILTER_16  = 0x04   // filter coefficient = 16
79
} BMP280_filter;
80
81
// standby (inactive) time in ms (used in normal mode), t_sb[2:0]
82
typedef enum
83
{
84
  STANDBY_0_5   =  0x00,  // standby time = 0.5 ms
85
  STANDBY_62_5  =  0x01,  // standby time = 62.5 ms
86
  STANDBY_125   =  0x02,  // standby time = 125 ms
87
  STANDBY_250   =  0x03,  // standby time = 250 ms
88
  STANDBY_500   =  0x04,  // standby time = 500 ms
89
  STANDBY_1000  =  0x05,  // standby time = 1000 ms
90
  STANDBY_2000  =  0x06,  // standby time = 2000 ms
91
  STANDBY_4000  =  0x07   // standby time = 4000 ms
92
} standby_time;
93
94
struct
95
{
96
  uint16_t dig_T1;
97
  int16_t  dig_T2;
98
  int16_t  dig_T3;
99
100
  uint16_t dig_P1;
101
  int16_t  dig_P2;
102
  int16_t  dig_P3;
103
  int16_t  dig_P4;
104
  int16_t  dig_P5;
105
  int16_t  dig_P6;
106
  int16_t  dig_P7;
107
  int16_t  dig_P8;
108
  int16_t  dig_P9;
109
} BMP280_calib;
110
111
void I2C2_Write1ByteRegister(i2c2_address_t address, uint8_t reg, uint8_t data);
112
uint8_t  I2C2_Read1ByteRegister(i2c2_address_t address, uint8_t reg);
113
114
static i2c2_operations_t wr1RegCompleteHandler(void *ptr);
115
static i2c2_operations_t rd1RegCompleteHandler(void *ptr);
116
117
118
119
static i2c2_operations_t wr1RegCompleteHandler(void *ptr)
120
{
121
    I2C2_SetBuffer(ptr,1);
122
    I2C2_SetDataCompleteCallback(NULL,NULL);
123
    return I2C2_CONTINUE;
124
}
125
126
static i2c2_operations_t rd1RegCompleteHandler(void *ptr)
127
{
128
    I2C2_SetBuffer(ptr,1);
129
    I2C2_SetDataCompleteCallback(NULL,NULL);
130
    return I2C2_RESTART_READ;
131
}
132
133
134
135
136
// writes 1 byte '_data' to register 'reg_addr'
137
void BMP280_Write8(uint8_t reg_addr, uint8_t _data)
138
{
139
  while(!I2C2_Open(BMP280_I2C_ADDRESS)); // sit here until we get the bus..
140
  I2C2_SetDataCompleteCallback(wr1RegCompleteHandler,&_data);
141
  I2C2_SetBuffer(&reg_addr,1);
142
  I2C2_SetAddressNackCallback(NULL,NULL); //NACK polling?
143
  I2C2_MasterWrite();
144
  while(I2C2_BUSY == I2C2_Close()); // sit here until finished.
145
}
146
147
// reads 8 bits from register 'reg_addr'
148
uint8_t BMP280_Read8(uint8_t reg_addr)
149
{
150
151
152
    uint8_t ret = 0x00;
153
    
154
    while(!I2C2_Open(BMP280_I2C_ADDRESS)); // sit here until we get the bus..
155
    I2C2_SetDataCompleteCallback(rd1RegCompleteHandler,&ret);
156
    I2C2_SetBuffer(&reg_addr,1);
157
    I2C2_SetAddressNackCallback(NULL,NULL); //NACK polling?
158
    I2C2_MasterWrite();
159
    while(I2C2_BUSY == I2C2_Close()); // sit here until finished.
160
    
161
    return ret;
162
163
164
  /*uint8_t ret;
165
166
  BMP280_Start();
167
  BMP280_Write(BMP280_I2C_ADDRESS);
168
  BMP280_Write(reg_addr);
169
  BMP280_Start();
170
  BMP280_Write(BMP280_I2C_ADDRESS | 1);
171
  ret = BMP280_Read(0);
172
  BMP280_Stop();
173
174
  return ret;*/

MCC Master file
1
/**
2
  I2C2 Generated Driver File
3
4
  @Company
5
    Microchip Technology Inc.
6
7
  @File Name
8
    i2c2_master.c
9
10
  @Summary
11
    This is the generated driver implementation file for the I2C2 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs
12
13
  @Description
14
    This header file provides implementations for driver APIs for I2C2.
15
    Generation Information :
16
       ac Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.81.8
17
        Device            :  PIC18F45K42
18
        Driver Version    :  1.0.2
19
    The generated drivers are tested against the following:
20
        Compiler          :  XC8 2.36 and above or later
21
        MPLAB             :  MPLAB X 6.00
22
*/
23
24
/*
25
    (c) 2018 Microchip Technology Inc. and its subsidiaries. 
26
    
27
    Subject to your compliance with these terms, you may use Microchip software and any 
28
    derivatives exclusively with Microchip products. It is your responsibility to comply with third party 
29
    license terms applicable to your use of third party software (including open source software) that 
30
    may accompany Microchip software.
31
    
32
    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER 
33
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY 
34
    IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS 
35
    FOR A PARTICULAR PURPOSE.
36
    
37
    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, 
38
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND 
39
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP 
40
    HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO 
41
    THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL 
42
    CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT 
43
    OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS 
44
    SOFTWARE.
45
*/
46
47
#include "i2c2_master.h"
48
#include <xc.h>
49
50
// I2C2 STATES
51
typedef enum {
52
    I2C2_IDLE = 0,
53
    I2C2_SEND_ADR_READ,
54
    I2C2_SEND_ADR_WRITE,
55
    I2C2_TX,
56
    I2C2_RX,
57
    I2C2_TX_EMPTY,
58
    I2C2_RX_EMPTY,        
59
    I2C2_SEND_RESTART_READ,
60
    I2C2_SEND_RESTART_WRITE,
61
    I2C2_SEND_RESTART,
62
    I2C2_SEND_STOP,
63
    I2C2_RX_ACK,
64
    I2C2_TX_ACK,
65
    I2C2_RX_NACK_STOP,
66
    I2C2_RX_NACK_RESTART,
67
    I2C2_RESET,
68
    I2C2_ADDRESS_NACK,
69
    I2C2_BUS_COLLISION,
70
    I2C2_BUS_ERROR
71
} i2c2_fsm_states_t;
72
73
// I2C2 Event callBack List
74
typedef enum {
75
    I2C2_DATA_COMPLETE = 0,
76
    I2C2_WRITE_COLLISION,
77
    I2C2_ADDR_NACK,
78
    I2C2_DATA_NACK,
79
    I2C2_TIMEOUT,
80
    I2C2_NULL
81
} i2c2_callbackIndex_t;
82
83
// I2C2 Status Structure
84
typedef struct
85
{
86
    i2c2_callback_t callbackTable[6];
87
    void *callbackPayload[6];           //  each callBack can have a payload
88
    uint16_t time_out;                  // I2C2 Timeout Counter between I2C2 Events.
89
    uint16_t time_out_value;            // Reload value for the timeouts
90
    i2c2_address_t address;             // The I2C2 Address
91
    uint8_t *data_ptr;                  // pointer to a data buffer
92
    size_t data_length;                 // Bytes in the data buffer
93
    i2c2_fsm_states_t state;            // Driver State
94
    i2c2_error_t error;
95
    unsigned addressNackCheck:2;
96
    unsigned busy:1;
97
    unsigned inUse:1;
98
    unsigned bufferFree:1;
99
100
} i2c2_status_t;
101
102
static void I2C2_SetCallback(i2c2_callbackIndex_t idx, i2c2_callback_t cb, void *ptr);
103
static void I2C2_Poller(void);
104
static inline void I2C2_ClearInterruptFlags(void);
105
static inline void I2C2_MasterFsm(void);
106
107
/* I2C2 interfaces */
108
static inline bool I2C2_MasterOpen(void);
109
static inline void I2C2_MasterClose(void);    
110
static inline uint8_t I2C2_MasterGetRxData(void);
111
static inline void I2C2_MasterSendTxData(uint8_t data);
112
static inline void I2C2_MasterSetCounter(uint8_t counter);
113
static inline uint8_t I2C2_MasterGetCounter();
114
static inline void I2C2_MasterResetBus(void);
115
static inline void I2C2_MasterEnableRestart(void);
116
static inline void I2C2_MasterDisableRestart(void);
117
static inline void I2C2_MasterStop(void);
118
static inline bool I2C2_MasterIsNack(void);
119
static inline void I2C2_MasterSendAck(void);
120
static inline void I2C2_MasterSendNack(void);
121
static inline void I2C2_MasterClearBusCollision(void);
122
static inline bool I2C2_MasterIsRxBufFull(void);
123
static inline bool I2C2_MasterIsTxBufEmpty(void);
124
static inline bool I2C2_MasterIsStopFlagSet(void);
125
static inline bool I2C2_MasterIsCountFlagSet(void);
126
static inline bool I2C2_MasterIsNackFlagSet(void);
127
static inline void I2C2_MasterClearStopFlag(void);
128
static inline void I2C2_MasterClearCountFlag(void);
129
static inline void I2C2_MasterClearNackFlag(void);
130
131
/* Interrupt interfaces */
132
static inline void I2C2_MasterEnableIrq(void);
133
static inline bool I2C2_MasterIsIrqEnabled(void);
134
static inline void I2C2_MasterDisableIrq(void);
135
static inline void I2C2_MasterClearIrq(void);
136
static inline void I2C2_MasterWaitForEvent(void);
137
138
static i2c2_fsm_states_t I2C2_DO_IDLE(void);
139
static i2c2_fsm_states_t I2C2_DO_SEND_ADR_READ(void);
140
static i2c2_fsm_states_t I2C2_DO_SEND_ADR_WRITE(void);
141
static i2c2_fsm_states_t I2C2_DO_TX(void);
142
static i2c2_fsm_states_t I2C2_DO_RX(void);
143
static i2c2_fsm_states_t I2C2_DO_TX_EMPTY(void);
144
static i2c2_fsm_states_t I2C2_DO_RX_EMPTY(void);
145
static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_READ(void);
146
static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_WRITE(void);
147
static i2c2_fsm_states_t I2C2_DO_SEND_RESTART(void);
148
static i2c2_fsm_states_t I2C2_DO_SEND_STOP(void);
149
static i2c2_fsm_states_t I2C2_DO_RX_ACK(void);
150
static i2c2_fsm_states_t I2C2_DO_TX_ACK(void);
151
static i2c2_fsm_states_t I2C2_DO_RX_NACK_STOP(void);
152
static i2c2_fsm_states_t I2C2_DO_RX_NACK_RESTART(void);
153
static i2c2_fsm_states_t I2C2_DO_RESET(void);
154
static i2c2_fsm_states_t I2C2_DO_ADDRESS_NACK(void);
155
static i2c2_fsm_states_t I2C2_DO_BUS_COLLISION(void);
156
static i2c2_fsm_states_t I2C2_DO_BUS_ERROR(void);
157
158
typedef i2c2_fsm_states_t (*i2c2FsmHandler)(void);
159
const i2c2FsmHandler i2c2_fsmStateTable[] = {
160
    I2C2_DO_IDLE,
161
    I2C2_DO_SEND_ADR_READ,
162
    I2C2_DO_SEND_ADR_WRITE,
163
    I2C2_DO_TX,
164
    I2C2_DO_RX,
165
    I2C2_DO_TX_EMPTY,
166
    I2C2_DO_RX_EMPTY,
167
    I2C2_DO_SEND_RESTART_READ,
168
    I2C2_DO_SEND_RESTART_WRITE,
169
    I2C2_DO_SEND_RESTART,
170
    I2C2_DO_SEND_STOP,
171
    I2C2_DO_RX_ACK,
172
    I2C2_DO_TX_ACK,
173
    I2C2_DO_RX_NACK_STOP,
174
    I2C2_DO_RX_NACK_RESTART,
175
    I2C2_DO_RESET,
176
    I2C2_DO_ADDRESS_NACK,
177
    I2C2_DO_BUS_COLLISION,
178
    I2C2_DO_BUS_ERROR
179
};
180
181
i2c2_status_t I2C2_Status = {0};
182
183
void I2C2_Initialize()
184
{
185
    //EN disabled; RSEN disabled; S Cleared by hardware after Start; CSTR Enable clocking; MODE 7-bit address; 
186
    I2C2CON0 = 0x04;
187
    //ACKCNT Acknowledge; ACKDT Acknowledge; ACKSTAT ACK received; ACKT 0; RXO 0; TXU 0; CSD Clock Stretching enabled; 
188
    I2C2CON1 = 0x80;
189
    //ACNT disabled; GCEN disabled; FME disabled; ABD disabled; SDAHT 30 ns hold time; BFRET 8 I2C Clock pulses; 
190
    I2C2CON2 = 0x18;
191
    //CLK MFINTOSC; 
192
    I2C2CLK = 0x03;
193
    //CNTIF 0; ACKTIF 0; WRIF 0; ADRIF 0; PCIF 0; RSCIF 0; SCIF 0; 
194
    I2C2PIR = 0x00;
195
    //CNTIE disabled; ACKTIE disabled; WRIE disabled; ADRIE disabled; PCIE disabled; RSCIE disabled; SCIE disabled; 
196
    I2C2PIE = 0x00;
197
    //BTOIF No bus timout; BCLIF No bus collision detected; NACKIF No NACK/Error detected; BTOIE disabled; BCLIE disabled; NACKIE disabled; 
198
    I2C2ERR = 0x00;
199
    //Count register 
200
    I2C2CNT = 0xFF;
201
    return;
202
}
203
204
i2c2_error_t I2C2_Open(i2c2_address_t address)
205
{
206
    i2c2_error_t returnValue = I2C2_BUSY;
207
    
208
    if(!I2C2_Status.inUse)
209
    {
210
        I2C2_Status.address = address;
211
        I2C2_Status.busy = 0;
212
        I2C2_Status.inUse = 1;
213
        I2C2_Status.addressNackCheck = 0;
214
        I2C2_Status.state = I2C2_RESET;
215
        I2C2_Status.time_out_value = 500; // MCC should determine a reasonable starting value here.
216
        I2C2_Status.bufferFree = 1;
217
218
        // set all the call backs to a default of sending stop
219
        I2C2_Status.callbackTable[I2C2_DATA_COMPLETE]=I2C2_CallbackReturnStop;
220
        I2C2_Status.callbackPayload[I2C2_DATA_COMPLETE] = NULL;
221
        I2C2_Status.callbackTable[I2C2_WRITE_COLLISION]=I2C2_CallbackReturnStop;
222
        I2C2_Status.callbackPayload[I2C2_WRITE_COLLISION] = NULL;
223
        I2C2_Status.callbackTable[I2C2_ADDR_NACK]=I2C2_CallbackReturnStop;
224
        I2C2_Status.callbackPayload[I2C2_ADDR_NACK] = NULL;
225
        I2C2_Status.callbackTable[I2C2_DATA_NACK]=I2C2_CallbackReturnStop;
226
        I2C2_Status.callbackPayload[I2C2_DATA_NACK] = NULL;
227
        I2C2_Status.callbackTable[I2C2_TIMEOUT]=I2C2_CallbackReturnReset;
228
        I2C2_Status.callbackPayload[I2C2_TIMEOUT] = NULL;
229
        
230
        I2C2_MasterClearIrq();
231
        I2C2_MasterOpen();
232
        returnValue = I2C2_NOERR;
233
    }
234
    return returnValue;
235
}
236
237
i2c2_error_t I2C2_Close(void)
238
{
239
    i2c2_error_t returnValue = I2C2_BUSY;
240
    if(!I2C2_Status.busy)
241
    {
242
        I2C2_Status.inUse = 0;
243
        I2C2_Status.address = 0xff;
244
        I2C2_MasterClearIrq();
245
        I2C2_MasterDisableIrq();
246
        I2C2_MasterClose();
247
        returnValue = I2C2_Status.error;
248
    }
249
    return returnValue;
250
}
251
252
i2c2_error_t I2C2_MasterOperation(bool read)
253
{
254
    i2c2_error_t returnValue = I2C2_BUSY;
255
    if(!I2C2_Status.busy)
256
    {
257
        I2C2_Status.busy = true;
258
        returnValue = I2C2_NOERR;
259
        I2C2_MasterSetCounter((uint8_t) I2C2_Status.data_length);
260
261
        if(read)
262
        {
263
            I2C2_Status.state = I2C2_RX;
264
            I2C2_DO_SEND_ADR_READ();
265
        }
266
        else
267
        {
268
            I2C2_Status.state = I2C2_TX;
269
            I2C2_DO_SEND_ADR_WRITE();
270
        }
271
        I2C2_Poller();
272
    }
273
    return returnValue;
274
}
275
276
i2c2_error_t I2C2_MasterRead(void)
277
{
278
    return I2C2_MasterOperation(true);
279
}
280
281
i2c2_error_t I2C2_MasterWrite(void)
282
{
283
    return I2C2_MasterOperation(false);
284
}
285
286
void I2C2_SetTimeOut(uint8_t timeOutValue)
287
{
288
    I2C2_MasterDisableIrq();
289
    I2C2_Status.time_out_value = timeOutValue;
290
    I2C2_MasterEnableIrq();
291
}
292
293
void I2C2_SetBuffer(void *buffer, size_t bufferSize)
294
{
295
    if(I2C2_Status.bufferFree)
296
    {
297
        I2C2_Status.data_ptr = buffer;
298
        I2C2_Status.data_length = bufferSize;
299
        I2C2_Status.bufferFree = false;
300
    }
301
}
302
303
void I2C2_SetDataCompleteCallback(i2c2_callback_t cb, void *ptr)
304
{
305
    I2C2_SetCallback(I2C2_DATA_COMPLETE, cb, ptr);
306
}
307
308
void I2C2_SetWriteCollisionCallback(i2c2_callback_t cb, void *ptr)
309
{
310
    I2C2_SetCallback(I2C2_WRITE_COLLISION, cb, ptr);
311
}
312
313
void I2C2_SetAddressNackCallback(i2c2_callback_t cb, void *ptr)
314
{
315
    I2C2_SetCallback(I2C2_ADDR_NACK, cb, ptr);
316
}
317
318
void I2C2_SetDataNackCallback(i2c2_callback_t cb, void *ptr)
319
{
320
    I2C2_SetCallback(I2C2_DATA_NACK, cb, ptr);
321
}
322
323
void I2C2_SetTimeoutCallback(i2c2_callback_t cb, void *ptr)
324
{
325
    I2C2_SetCallback(I2C2_TIMEOUT, cb, ptr);
326
}
327
328
static void I2C2_SetCallback(i2c2_callbackIndex_t idx, i2c2_callback_t cb, void *ptr)
329
{
330
    if(cb)
331
    {
332
        I2C2_Status.callbackTable[idx] = cb;
333
        I2C2_Status.callbackPayload[idx] = ptr;
334
    }
335
    else
336
    {
337
        I2C2_Status.callbackTable[idx] = I2C2_CallbackReturnStop;
338
        I2C2_Status.callbackPayload[idx] = NULL;
339
    }
340
}
341
342
static void I2C2_Poller(void)
343
{
344
    while(I2C2_Status.busy)
345
    {
346
        I2C2_MasterWaitForEvent();
347
        I2C2_MasterFsm();
348
    }
349
}
350
351
static inline void I2C2_MasterFsm(void)
352
{
353
    I2C2_ClearInterruptFlags();
354
355
    if(I2C2_Status.addressNackCheck && I2C2_MasterIsNack())
356
    {
357
        I2C2_Status.state = I2C2_ADDRESS_NACK;
358
    }
359
    I2C2_Status.state = i2c2_fsmStateTable[I2C2_Status.state]();
360
}
361
362
static inline void I2C2_ClearInterruptFlags(void)
363
{
364
    if(I2C2_MasterIsCountFlagSet())
365
    {
366
        I2C2_MasterClearCountFlag();
367
    }
368
    else if(I2C2_MasterIsStopFlagSet())
369
    {
370
        I2C2_MasterClearStopFlag();
371
    }
372
    else if(I2C2_MasterIsNackFlagSet())
373
    {
374
        I2C2_MasterClearNackFlag();
375
    }
376
}
377
378
static i2c2_fsm_states_t I2C2_DO_IDLE(void)
379
{
380
    I2C2_Status.busy = false;
381
    I2C2_Status.error = I2C2_NOERR;
382
    return I2C2_RESET;
383
}
384
385
static i2c2_fsm_states_t I2C2_DO_SEND_ADR_READ(void)
386
{
387
    I2C2_Status.addressNackCheck = 2;
388
    if(I2C2_Status.data_length ==  1)
389
    {
390
        I2C2_DO_RX_EMPTY();
391
    }
392
    I2C2_MasterSendTxData((uint8_t) (I2C2_Status.address << 1 | 1));
393
    return I2C2_RX;
394
}
395
396
static i2c2_fsm_states_t I2C2_DO_SEND_ADR_WRITE(void)
397
{
398
    I2C2_Status.addressNackCheck = 2;
399
    I2C2_MasterSendTxData((uint8_t) (I2C2_Status.address << 1));
400
    return I2C2_TX;
401
}
402
403
static i2c2_fsm_states_t I2C2_DO_TX(void)
404
{
405
    if(I2C2_MasterIsNack())
406
    {
407
        switch(I2C2_Status.callbackTable[I2C2_DATA_NACK](I2C2_Status.callbackPayload[I2C2_DATA_NACK]))
408
        {
409
            case I2C2_RESTART_READ:
410
                return I2C2_DO_SEND_RESTART_READ();
411
            case I2C2_RESTART_WRITE:
412
                  return I2C2_DO_SEND_RESTART_WRITE();
413
            default:
414
            case I2C2_CONTINUE:
415
            case I2C2_STOP:
416
                return I2C2_IDLE;
417
        }
418
    }
419
    else if(I2C2_MasterIsTxBufEmpty())
420
    {
421
        if(I2C2_Status.addressNackCheck)
422
        {
423
            I2C2_Status.addressNackCheck--;
424
        }
425
        uint8_t dataTx = *I2C2_Status.data_ptr++;
426
        i2c2_fsm_states_t retFsmState = (--I2C2_Status.data_length)?I2C2_TX:I2C2_DO_TX_EMPTY();
427
        I2C2_MasterSendTxData(dataTx);
428
        return retFsmState;
429
    }
430
    else
431
    {
432
        return I2C2_TX;
433
    }
434
}
435
436
static i2c2_fsm_states_t I2C2_DO_RX(void)
437
{
438
    if(!I2C2_MasterIsRxBufFull())
439
    {
440
        return I2C2_RX;
441
    }
442
    if(I2C2_Status.addressNackCheck)
443
    {
444
        I2C2_Status.addressNackCheck--;
445
    }
446
447
    if(--I2C2_Status.data_length)
448
    {
449
        *I2C2_Status.data_ptr++ = I2C2_MasterGetRxData();
450
        return I2C2_RX;
451
    }
452
    else
453
    {
454
        i2c2_fsm_states_t retFsmState = I2C2_DO_RX_EMPTY();
455
        *I2C2_Status.data_ptr++ = I2C2_MasterGetRxData();
456
        return retFsmState;
457
    }
458
}
459
460
static i2c2_fsm_states_t I2C2_DO_TX_EMPTY(void)
461
{
462
    I2C2_Status.bufferFree = true;
463
    switch(I2C2_Status.callbackTable[I2C2_DATA_COMPLETE](I2C2_Status.callbackPayload[I2C2_DATA_COMPLETE]))
464
    {
465
        case I2C2_RESTART_READ:
466
            I2C2_MasterEnableRestart();
467
            return I2C2_SEND_RESTART_READ;
468
        case I2C2_CONTINUE:
469
            // Avoid the counter stop condition , Counter is incremented by 1
470
            I2C2_MasterSetCounter((uint8_t) I2C2_Status.data_length + 1);
471
            return I2C2_TX;
472
        default:
473
        case I2C2_STOP:
474
            I2C2_MasterDisableRestart();
475
            return I2C2_SEND_STOP;
476
    }
477
}
478
479
static i2c2_fsm_states_t I2C2_DO_RX_EMPTY(void)
480
{
481
    I2C2_Status.bufferFree = true;
482
    switch(I2C2_Status.callbackTable[I2C2_DATA_COMPLETE](I2C2_Status.callbackPayload[I2C2_DATA_COMPLETE]))
483
    {
484
        case I2C2_RESTART_WRITE:
485
            I2C2_MasterEnableRestart();
486
            return I2C2_SEND_RESTART_WRITE;
487
        case I2C2_RESTART_READ:
488
            I2C2_MasterEnableRestart();
489
            return I2C2_SEND_RESTART_READ;
490
        case I2C2_CONTINUE:
491
            // Avoid the counter stop condition , Counter is incremented by 1
492
            I2C2_MasterSetCounter((uint8_t) (I2C2_Status.data_length + 1));
493
            return I2C2_RX;
494
        default:
495
        case I2C2_STOP:
496
            if(I2C2_Status.state != I2C2_SEND_RESTART_READ)
497
            {
498
                I2C2_MasterDisableRestart();
499
            }
500
            return I2C2_RESET;
501
    }
502
}
503
504
static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_READ(void)
505
{
506
    I2C2_MasterSetCounter((uint8_t) I2C2_Status.data_length);
507
    return I2C2_DO_SEND_ADR_READ();
508
}
509
510
static i2c2_fsm_states_t I2C2_DO_SEND_RESTART_WRITE(void)
511
{
512
    return I2C2_SEND_ADR_WRITE;
513
}
514
515
516
static i2c2_fsm_states_t I2C2_DO_SEND_RESTART(void)
517
{
518
    return I2C2_SEND_ADR_READ;
519
}
520
521
static i2c2_fsm_states_t I2C2_DO_SEND_STOP(void)
522
{
523
    I2C2_MasterStop();
524
    if(I2C2_MasterGetCounter())
525
    {
526
        I2C2_MasterSetCounter(0);
527
        I2C2_MasterSendTxData(0);
528
    }
529
    return I2C2_IDLE;
530
}
531
532
static i2c2_fsm_states_t I2C2_DO_RX_ACK(void)
533
{
534
    I2C2_MasterSendAck();
535
    return I2C2_RX;
536
}
537
538
static i2c2_fsm_states_t I2C2_DO_TX_ACK(void)
539
{
540
    I2C2_MasterSendAck();
541
    return I2C2_TX;
542
}
543
544
static i2c2_fsm_states_t I2C2_DO_RX_NACK_STOP(void)
545
{
546
    I2C2_MasterSendNack();
547
    I2C2_MasterStop();
548
    return I2C2_DO_IDLE();
549
}
550
551
static i2c2_fsm_states_t I2C2_DO_RX_NACK_RESTART(void)
552
{
553
    I2C2_MasterSendNack();
554
    return I2C2_SEND_RESTART;
555
}
556
557
static i2c2_fsm_states_t I2C2_DO_RESET(void)
558
{
559
    I2C2_MasterResetBus();
560
    I2C2_Status.busy = false;
561
    I2C2_Status.error = I2C2_NOERR;
562
    return I2C2_RESET;
563
}
564
static i2c2_fsm_states_t I2C2_DO_ADDRESS_NACK(void)
565
{
566
    I2C2_Status.addressNackCheck = 0;
567
    I2C2_Status.error = I2C2_FAIL;
568
    I2C2_Status.busy = false;
569
    switch(I2C2_Status.callbackTable[I2C2_ADDR_NACK](I2C2_Status.callbackPayload[I2C2_ADDR_NACK]))
570
    {
571
        case I2C2_RESTART_READ:
572
        case I2C2_RESTART_WRITE:
573
            return I2C2_DO_SEND_RESTART();
574
        default:
575
            return I2C2_RESET;
576
    }
577
}
578
579
static i2c2_fsm_states_t I2C2_DO_BUS_COLLISION(void)
580
{
581
    // Clear bus collision status flag
582
    I2C2_MasterClearIrq();
583
584
    I2C2_Status.error = I2C2_FAIL;
585
    switch (I2C2_Status.callbackTable[I2C2_WRITE_COLLISION](I2C2_Status.callbackPayload[I2C2_WRITE_COLLISION])) {
586
    case I2C2_RESTART_READ:
587
        return I2C2_DO_SEND_RESTART_READ();
588
    case I2C2_RESTART_WRITE:
589
        return I2C2_DO_SEND_RESTART_WRITE();
590
    default:
591
        return I2C2_DO_RESET();
592
    }
593
}
594
595
static i2c2_fsm_states_t I2C2_DO_BUS_ERROR(void)
596
{
597
    I2C2_MasterResetBus();
598
    I2C2_Status.busy  = false;
599
    I2C2_Status.error = I2C2_FAIL;
600
    return I2C2_RESET;
601
}
602
603
void I2C2_BusCollisionIsr(void)
604
{
605
    I2C2_MasterClearBusCollision();
606
    I2C2_Status.state = I2C2_RESET;
607
}
608
609
i2c2_operations_t I2C2_CallbackReturnStop(void *funPtr)
610
{
611
    return I2C2_STOP;
612
}
613
614
i2c2_operations_t I2C2_CallbackReturnReset(void *funPtr)
615
{
616
    return I2C2_RESET_LINK;
617
}
618
619
i2c2_operations_t I2C2_CallbackRestartWrite(void *funPtr)
620
{
621
    return I2C2_RESTART_WRITE;
622
}
623
624
i2c2_operations_t I2C2_CallbackRestartRead(void *funPtr)
625
{
626
    return I2C2_RESTART_READ;
627
}
628
629
630
631
/* I2C2 Register Level interfaces */
632
static inline bool I2C2_MasterOpen(void)
633
{
634
    if(!I2C2CON0bits.EN)
635
    {
636
        //CNTIF 0; ACKTIF 0; WRIF 0; ADRIF 0; PCIF 0; RSCIF 0; SCIF 0; 
637
        I2C2PIR = 0x00;
638
        //CNTIE disabled; ACKTIE disabled; WRIE disabled; ADRIE disabled; PCIE disabled; RSCIE disabled; SCIE disabled; 
639
        I2C2PIE = 0x00;
640
        //BTOIF No bus timout; BCLIF No bus collision detected; NACKIF No NACK/Error detected; BTOIE disabled; BCLIE disabled; NACKIE disabled; 
641
        I2C2ERR = 0x00;
642
        //Count register 
643
        I2C2CNT = 0xFF;
644
        //Clock PadReg Configuration
645
        RB1I2C   = 0x51;
646
        //Data PadReg Configuration
647
        RB2I2C   = 0x51;
648
        //Enable I2C2
649
        I2C2CON0bits.EN = 1;
650
        return true;
651
    }
652
    return false;
653
}
654
655
static inline void I2C2_MasterClose(void)
656
{
657
    //Disable I2C2
658
    I2C2CON0bits.EN = 0;
659
    //CNTIF 0; ACKTIF 0; WRIF 0; ADRIF 0; PCIF 0; RSCIF 0; SCIF 0; 
660
    I2C2PIR = 0x00;
661
    //Set Clear Buffer Flag
662
    I2C2STAT1bits.CLRBF = 1;
663
}
664
665
static inline uint8_t I2C2_MasterGetRxData(void)
666
{
667
    return I2C2RXB;
668
}
669
670
static inline void I2C2_MasterSendTxData(uint8_t data)
671
{
672
    I2C2TXB  = data;
673
}
674
675
static inline uint8_t I2C2_MasterGetCounter()
676
{
677
    return I2C2CNT;
678
}
679
680
static inline void I2C2_MasterSetCounter(uint8_t counter)
681
{
682
    I2C2CNT = counter;
683
}
684
685
static inline void I2C2_MasterResetBus(void)
686
{
687
    //Disable I2C2
688
    I2C2CON0bits.EN = 0;
689
    //Set Clear Buffer Flag
690
    I2C2STAT1bits.CLRBF = 1;
691
    //Enable I2C2
692
    I2C2CON0bits.EN = 1;
693
}
694
695
static inline void I2C2_MasterEnableRestart(void)
696
{
697
    //Enable I2C2 Restart
698
    I2C2CON0bits.RSEN = 1;
699
}
700
701
static inline void I2C2_MasterDisableRestart(void)
702
{
703
    //Disable I2C2 Restart
704
    I2C2CON0bits.RSEN = 0;
705
}
706
707
static inline void I2C2_MasterStop(void)
708
{
709
    //Clear Start Bit
710
    I2C2CON0bits.S = 0;
711
}
712
713
static inline bool I2C2_MasterIsNack(void)
714
{
715
    return I2C2CON1bits.ACKSTAT;
716
}
717
718
static inline void I2C2_MasterSendAck(void)
719
{
720
    I2C2CON1bits.ACKDT = 0;
721
}
722
723
static inline void I2C2_MasterSendNack(void)
724
{
725
    I2C2CON1bits.ACKDT = 1;
726
}
727
728
static inline void I2C2_MasterClearBusCollision(void)
729
{
730
    I2C2ERRbits.BCLIF = 0;
731
    I2C2ERRbits.BTOIF = 0;
732
    I2C2ERRbits.NACKIF = 0;
733
}
734
735
static inline bool I2C2_MasterIsRxBufFull(void)
736
{
737
    return I2C2STAT1bits.RXBF;
738
}
739
740
static inline bool I2C2_MasterIsTxBufEmpty(void)
741
{
742
    return I2C2STAT1bits.TXBE;
743
}
744
745
static inline bool I2C2_MasterIsStopFlagSet(void)
746
{
747
    return I2C2PIRbits.PCIF;
748
}
749
750
static inline bool I2C2_MasterIsCountFlagSet(void)
751
{
752
    return I2C2PIRbits.CNTIF;
753
}
754
755
static inline bool I2C2_MasterIsNackFlagSet(void)
756
{
757
    return I2C2ERRbits.NACKIF;
758
}
759
760
static inline void I2C2_MasterClearStopFlag(void)
761
{
762
    I2C2PIRbits.PCIF = 0;
763
}
764
765
static inline void I2C2_MasterClearCountFlag(void)
766
{
767
    I2C2PIRbits.CNTIF = 0;
768
}
769
770
static inline void I2C2_MasterClearNackFlag(void)
771
{
772
    I2C2ERRbits.NACKIF = 0;
773
}
774
775
static inline void I2C2_MasterEnableIrq(void)
776
{
777
    PIE6bits.I2C2IE    = 1;
778
    PIE6bits.I2C2EIE    = 1;
779
    PIE5bits.I2C2RXIE  = 1;
780
    PIE5bits.I2C2TXIE  = 1;
781
782
    I2C2PIEbits.PCIE = 1; 
783
    I2C2PIEbits.CNTIE = 1; 
784
    I2C2ERRbits.NACKIE = 1; 
785
}
786
787
static inline bool I2C2_MasterIsIrqEnabled(void)
788
{
789
    return (PIE5bits.I2C2RXIE && PIE5bits.I2C2TXIE && PIE6bits.I2C2IE);
790
}
791
792
static inline void I2C2_MasterDisableIrq(void)
793
{
794
    PIE6bits.I2C2IE    = 0;
795
    PIE6bits.I2C2EIE    = 0;
796
    PIE5bits.I2C2RXIE  = 0;
797
    PIE5bits.I2C2TXIE  = 0;
798
    I2C2PIEbits.SCIE = 0;
799
    I2C2PIEbits.PCIE = 0;
800
    I2C2PIEbits.CNTIE = 0;
801
    I2C2PIEbits.ACKTIE = 0;
802
    I2C2PIEbits.RSCIE = 0;
803
    I2C2ERRbits.BCLIE = 0;
804
    I2C2ERRbits.BTOIE = 0;
805
    I2C2ERRbits.NACKIE = 0;
806
}
807
808
static inline void I2C2_MasterClearIrq(void)
809
{
810
    I2C2PIR = 0x00;
811
}
812
813
static inline void I2C2_MasterWaitForEvent(void)
814
{
815
    while(1)
816
    {
817
        if(PIR5bits.I2C2TXIF)
818
        {    
819
            break;
820
        }
821
        if(PIR5bits.I2C2RXIF)
822
        {  
823
            break;
824
        } 
825
        if(I2C2PIRbits.PCIF)
826
        {
827
            break;
828
        } 
829
        if(I2C2PIRbits.CNTIF)
830
        {
831
            break;
832
        }
833
        if(I2C2ERRbits.NACKIF)
834
        {
835
            break;
836
        }
837
    }
838
}

von Steve van de Grens (roehrmond)


Angehängte Dateien:

Lesenswert?

Du hast vergessen, zu beschreiben, wo es hakt. Hast du wenigstens einen 
logic analyzer? Wenn nicht, besorge dir einen (ab 10 Euro). Damit kannst 
du die Kommunikation untersuchen.

von Brom B. (schrori)


Lesenswert?

Hallo, tatsächlich stehe ich einfach volle Lotte auf dem schlauch...

Ich hatte gerade die idee die funktionen welche mcc generiert zu nutzen.

Als erstes die chip adresse, dann die Adresse des registers im BMP280 
und am ende binär was ich schreiben möchte.

Aber wie time ich das?

Also sagen wir ich sende das ich lesen möchte. Muss ich dann einfach nur 
warten und sag ihm dannach so jetz lies dieses register aus?

Ich hab so einen treiber noch nie selbst geschrieben daher weiß ich 
einfach nicht wo ich anfangen soll und woe der ablauf ist.

Sorry wegen des codes
Grüße

von Bratmaxxe (Gast)


Lesenswert?

Es gibt von Bosch eine C Bibliothek für den BMP280. Was du brauchst ist 
eine Wrappper-Funktion um deine eigentliche I2C Write und Read Funktion.

von Brom B. (schrori)


Lesenswert?

Hallo Bratmaxe,

Das hat geholfen dann weiß ich schonmal was ich brauche.

Byte weise lesen und schreiben stellt MCC aus mplap bereit.

Was ist ein wrapper? :D

Ich bastel später mal was zusammen mit der bitte um Prüfung 😄

von Vorname N. (mcu32)


Lesenswert?

Richard S. schrieb:
> Was ist ein wrapper? :D

Ein Wrapper ist eine Funktion, die um die eigentliche Driver Funktion 
"drum herum" geschrieben wird.
Weil verschiedene Controller unterschiedliche Bitadressen bzw. Treiber 
für die Verwendung der Peripherie wie I2C, SPI usw. besitzen, stellen 
Hersteller wie Bosch eine universelle API bereit, die dann noch 
entsprechend "gewrapped" werden muss.

Hier ein Beispiel auf einem STM32F103 mit der BME280 Bib von Bosch:
1
void BME280_Setup()
2
{
3
    //BME280
4
    bme280.intf_ptr = &dev_addr; //device address
5
    bme280.intf = BME280_I2C_INTF; //used interface (i2c)
6
7
    //Associate BME280 with I2C HAL
8
    //Typecast of I2C HAL receive/write function ptr to the suitable format for bme280 driver
9
    bme280.read =  (bme280_read_fptr_t)user_i2c_read;    //pointer to wrapper function for system specific i2c read
10
    bme280.write = (bme280_write_fptr_t)user_i2c_write;  //pointer to wrapper function for system specific i2c write
11
    bme280.delay_us = (bme280_delay_us_fptr_t)user_delay; //pointer to wrapper function for system specific delay
12
    bme280_status = bme280_init(&bme280);
13
}
1
int8_t user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len)
2
{
3
4
    HAL_StatusTypeDef status = HAL_OK;
5
6
    //initial value is usually zero
7
  int32_t iError = BME280_INIT_VALUE;
8
9
  uint8_t tempbuff[I2C_BUFFER_LEN] = {BME280_INIT_VALUE};
10
  uint8_t index = BME280_INIT_VALUE;
11
  tempbuff[BME280_INIT_VALUE] = reg_addr;
12
13
  uint8_t trials = 3;
14
  uint8_t timeout = 20;
15
16
  //check if I2C is ready to use, use the generated i2c instance
17
  while (HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(dev_addr<<1), trials, timeout) != HAL_OK) {}
18
19
    status = HAL_I2C_Mem_Read(&hi2c1,              // i2c handle
20
                  (uint16_t)(dev_addr<<1),      // i2c address, left aligned
21
                (uint16_t)reg_addr,        // register address
22
                (uint16_t)I2C_MEMADD_SIZE_8BIT,  // bme280 uses 8bit register addresses
23
                tempbuff,              // write returned data to this variable
24
                len,          // how many bytes to expect returned
25
                timeout);                // timeout
26
27
    if (status != HAL_OK)
28
    {
29
      // The BME280 API calls for 0 return value as a success, and -1 returned as failure
30
      iError = (-1);
31
    }
32
  for (index = BME280_INIT_VALUE; index < len; index++) {
33
    *(reg_data + index) = tempbuff[index];
34
  }
35
36
  return (int8_t)iError;
37
}

Einfach gesagt schreibst du eine Funktion, die beim Aufrufen auf die 
entsprechenden Funktionen der API zeigt.

In dem von mir geposteten Beispiel siehst du die Initialisierung der 
Wrapper und die Implementation der Usereigenen i2c_read Funktion.
Bei der Initialisierung lasse ich die Funktionen der Bosch API auf meine 
Wrapperfunktionen zeigen.

Hier noch der Link zur Bosch API:
https://github.com/BoschSensortec/BME280_driver

Ich hoffe es kam halbwegs rüber was ich meine :D

: Bearbeitet durch User
von Brom B. (schrori)


Lesenswert?

Danke für die umfangreiche Antwort:)

Also ich habe das jetz so verstanden das der Wrapper die API Funktionen 
aufgreift, und controller spezifische Parameter ergänzt. Sodass eine 
neue Funktion entsteht die einfach einfach ist oder?

Also man bastelt sich seine funktion aus den Funktionen der API und 
speichert das dann als zb. BMPWRITE

oder?

von Vorname N. (mcu32)


Lesenswert?

JA genau. Du lässt beim Aufruf der API Funktion die entsprechende 
Funktion deines Controllers aufrufen. In meinem Beispiel rufe ich mit 
der Bosch API über meine User Funktion die I2C Funktion der STM32 HAL 
auf.
1
bme280.read =  (bme280_read_fptr_t)user_i2c_read;//pointer to wrapper function for system specific i2c read
Die Funktion read vom struct bme280 zeigt mit dem Pointer 
bme280_read_ptr auf die UserFunktion i2c_read.

Du lässt die API Funktion also auf die entsprechenden Funktionen zeigen. 
Du kannst natürlich auch eine komplett eigene Funktion schreiben bei der 
du in die I2C Schnittstelle die entsprechenden Bytes für den Sensor 
schickst. Ich persönlich finde den Weg mit Wrappern allerdings elegante.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Offenbar hast du zu viele unbekannte Baustellen gleichzeitig.

Klar ist, dass du mit I²C Kommunizieren musst. Das beginnt mit dem 
Senden einer Slave Adresse und dem Einlesen des ACK im neunten 
Takt-Impuls. Programmiere das mal in einem neuen leeren(!) Projekt bis 
zu diesem Punkt.

Den Erfolg kannst du wunderbar ohne Sensor mit dem Logic Analyzer 
kontrollieren.

Lies dazu 
http://stefanfrings.de/mikrocontroller_buch/Einstieg%20in%20die%20Elektronik%20mit%20Mikrocontrollern%20-%20Band%202.pdf 
Kapitel 5.9 bis 5.9.4.

Wenn du soweit bist, schauen wir weiter.

Als nächstes käme dann:

- nach dem ACK 0..n Bytes zu senden und dann 0..n Bytes zu empfangen.
- das ganze in eine Funktion zu verpacken, die man so aufrufen kann:
1
/**
2
 * Perform an I²C transaction
3
 * which sends 0 or more data bytes, followed by receiving 0 or 
4
 * more data bytes.
5
 *
6
 * slave_addr     7 bit slave address
7
 * send_buffer    Buffer to send (may be 0 if not used)
8
 * send_size      Number of bytes to send
9
 * receive_buffer Buffer to receive (may be 0 if not used)
10
 * receive_size   Number of bytes to receive
11
 * returns        Number of received data bytes, or -1 if sending failed,
12
 *                for example did not receive an ACK.
13
 */
14
int i2c_communicate(
15
    uint8_t slave_addr,
16
    void* send_buffer, int send_size, 
17
    void* receive_buffer, int receive_size) {
18
   ...
19
}

Erst dann kommt der Punkt, wo man sich mit dem Sensor und seinen 
Registern befasst. Als erstes würde ich Register 0xD0 (chip id) 
auslesen.
1
uint8_t send[]={0xD0}; // Register "chip id"
2
uint8_t receive[1];    // Buffer to receive 1 Byte
3
i2c_communicate(0x76, send, 1, receive, 1);

Die Sache mit den beiden Puffern kommt dir jetzt vielleicht noch unnötig 
kompliziert vor, aber spätestens wenn du mehrere Bytes senden/empfangen 
musst wird das so sehr praktisch.

Danach schau mal was man sonst noch alles auslesen kann ohne vorher 
etwas zu initialisieren oder zu starten. Erst wenn du damit klar kommst, 
befasse dich mit den komplexeren Abläufen.

Die mir bekannten Bosch Sensoren sind alle sehr einfach zu benutzen und 
unmissverständlich dokumentiert. Eine fertige Library würde ich nur 
benutzen, wenn mir auf Anhieb klar ist, wie sie zu benutzen ist. 
Ansonsten lieber selbst neu schreiben.

Normalerweise rate ich davon ab, das Rad neu zu erfinden, aber in diesem 
Fall sehe ich das ausnahmsweise mal anders.

von Forist (Gast)


Lesenswert?

Richard S. schrieb:
> Ausschnitt auf dem 18F4550
> ...

Soory, nach der 5ten Seite habe ich aufgehört zu lesen, war mir zu dumm 
mit der Scrollerei.

Wichtige Regeln - erst lesen, dann posten!
...
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Brom B. (schrori)


Lesenswert?

Also erstmal vielen Dank an MCU und Stefan ich denke das hat wird mir 
sehr weiterhelfen vorallem die genauen Erklärungen zu den code passagen!

@Forist ja ich weiß sorry 😅

Die ganze ausführliche Materie werde ich mir auf jedenfall noch zu 
gemüte führen zu anfang werde ich jedoch versuchen den sensor mit den 
Befehlen aus mcc (erfordert doe slave adresse, das register und die Bit 
Belegung) zu triggern und im anschluss das readout register auslesen.

Da mich das aber generell interessiert interessiert mich schon alles von 
grund auf.

Vorallem möchte ich auch irgendwann RS485 nutzen 😄 danke euch ich 
berichte!

von Wolfgang (Gast)


Lesenswert?

Richard S. schrieb:
> Vorallem möchte ich auch irgendwann RS485 nutzen

Der BMP280 kann I2C und SPI. Mit RS485 weiß der nichts anzufangen.

von Brom B. (schrori)


Lesenswert?

Das weiß ich es geht darum das Ergebnis der Messung weiterzuleiten :)

von BesserWisser (Gast)


Lesenswert?

Richard S. schrieb:
> Das weiß ich es geht darum

Nachdem was du hier zeigst/fragst, weist du überhaupt nichts und bis 
umfangreich talent frei. Schlicht zu dämlich für dieses Hobby!

Wiederml das übliche Rumgesülze und Frage/Bitte an Dritte hins. macht 
doch mal schnell, dass was ich will/brauche aber nicht kann - zum 
kotzen!

von Brom B. (schrori)


Lesenswert?

BesserWisser schrieb:
> Richard S. schrieb:
>> Das weiß ich es geht darum
>
> Nachdem was du hier zeigst/fragst, weist du überhaupt nichts und bis
> umfangreich talent frei. Schlicht zu dämlich für dieses Hobby!
>
> Wiederml das übliche Rumgesülze und Frage/Bitte an Dritte hins. macht
> doch mal schnell, dass was ich will/brauche aber nicht kann - zum
> kotzen!


Traurig das es immer diese leute gibt die nichts besseres zu tun als 
blöd daher zu reden. Den Namen hast du dir sehr gut ausgesucht denn 
keiner kann solche leiden. Trotzdem tust du mir leid  traurig wenn man 
so drauf ist.

Man lernt nunmal am besten an beispielen und in diesem fall wäre das 
nunmal schritt für schritt erklärt.

Danke an die anderen nochmal die sinnvolle Beiträge leisten. Ich hatte 
auch bereits nach büchern zu PICs gesucht aber wirklich fündig geworden 
bin ich dabei auch nicht. Die meisten haben 2 3 Beispiele ala lasst die 
LED blinken aber wrapping oder gar treiber erstellen für Protokolle habe 
ich  och keine gefunden. Wenn ihr da was habt gern her damit:).

@besserwisser von dir bitte nicht such dir lieber einen Therapeuten 
menschen die nichts besseres zu tun haben als andere anonym zu 
beleidigen haben meist eine psychische störung die man behandeln sollte 
:)

Schönen abend den meisten! :)

von Brom B. (schrori)


Lesenswert?

Hallo hallöchen nochmal da bin ich wieder:)

Also ich habe einen Wrapper gebaut mithilfe der I2C Library aus MCC und 
dem C Treiber von Bosch, das ganze wird auch fehler frei kompiliert. 
(Kam noch nicht zum anschließen)

Nun ist mir aber aufgefallen das diese Protokolle insbesondere der Bosch 
treiber enorm viel Flash Speicher ziehen. Könntet Ihr mir eine 
Hilfestellung geben  diesen zu optimieren?

Macht es sinn ungenutzte Funktionen einfach zu löschen? Ich dachte immer 
der Compiler entfernt von haus aus alles was nicht genutzt wird.

Und dann habe ich noch beobachtet das Bei 99% Flashspeicher Belegung 
(wenn ich die Bosch Funktion nicht aufrufe bin ich bei 40% von 32k) der 
SPI clock in höheren Frequenzen nicht mehr arbeitet. Ich musste teils 
auf 500khz runter um ein Signal zu bekommen. Kann das wirklich zusammen 
hängen?

Mein RAM liegt bei 400/4000 bytes.

Bevor die Frage kommt, ich habe einen TFT Monitor am SPI und die Fonts / 
Logos sind in BMPHex. Wenn ich diese ausklammere fällt der 
Speicherbedarf enorm.

Kann man das auch effizienter gestalten? Wenn ja, wie?

Danke euch und viele Grüße :)

: Bearbeitet durch User
von Vorname N. (mcu32)


Lesenswert?

Wie hast du den Sensor denn verdrahtet? "Flying Wire" oder schön 
verdrillte Leitungen mit Schirmung? Wie lang sind diese?
Zum Optimieren: Das einfachste ist natürlich ein (meist kommerzieller) 
Compiler, mit entsprechendem Optimierungslevel. Aber da muss man häufig 
aufpassen das nichts essentielles wegoptimiert wird :)
Ansonsten die allgemeinen Regeln, unnötige Schleifen vermeiden, kein 
unnötiges Beleg von Speicher den man nie braucht. Speicher von 
temporären Variablen nach Gebrauch wieder frei geben usw.

Für eine speichereffiziente Ansteuerung von Displays gabs hier im Forum 
mal irgendwo einen Artikel wenn ich mich richtig erinnere.

: Bearbeitet durch User
von Brom B. (schrori)


Lesenswert?

Vorname N. schrieb:
> Wie hast du den Sensor denn verdrahtet? "Flying Wire" oder schön
> verdrillte Leitungen mit Schirmung? Wie lang sind diese?
> Zum Optimieren: Das einfachste ist natürlich ein (meist kommerzieller)
> Compiler, mit entsprechendem Optimierungslevel. Aber da muss man häufig
> aufpassen das nichts essentielles wegoptimiert wird :)
> Ansonsten die allgemeinen Regeln, unnötige Schleifen vermeiden, kein
> unnötiges Beleg von Speicher den man nie braucht. Speicher von
> temporären Variablen nach Gebrauch wieder frei geben usw.
>
> Für eine speichereffiziente Ansteuerung von Displays gabs hier im Forum
> mal irgendwo einen Artikel wenn ich mich richtig erinnere.



Hallo Vorname.N.,
Momentan ist alles noch auf dem Steckbrettmit jumperkabeln 20cm wenn die 
schaltung steht lasse ich eine Platine bestücken auf welcher der Sensor 
genauso verschaltet ist wie auf dem Shield.

Die Optimierungsstufe 2 Und 3 des xc8 kamen mit ascc nicht zurecht, als 
ich das entfernt hatte brachte Stufe 2 ca 5000byte und für stufe 3 
prognostiziert er mir 10000byte einsparung.

Bei mir hängt es wirklich am Flash speicher, wenn ich ein Bitmap nur 
einmal benötige (zb. BOOTlogo) und die Variable in der diese BMP als hex 
gespeichert wird auf zb 0 gesetzt wird (oder wie löscht man den speicher 
richtig?) Bevor der include des I2c und BMP kommt, spare ich mir dann 
wirklich Flash speicher? Und müssten schleifen nicht eigentlich gut 
sein? Denn am Arbeitsspeicher mangelts mir ja nicht sondern der Programm 
speicher ist zu gering. 😅

Nach der Display Geschichte werd ich mal suchen Danke!!

Achso und das SPI CLK problem konnte ich am oszi messen / sehen mit 
vollerem speicher konnte der hohe takt nicht mehr  gehalten werden.

von Vorname N. (mcu32)


Lesenswert?

Wie hast du die Kommunikation implementiert? Polst du die Buffer oder 
machst du es Interruptgesteuert?

von Brom B. (schrori)


Lesenswert?

Vorname N. schrieb:
> Wie hast du die Kommunikation implementiert? Polst du die Buffer oder
> machst du es Interruptgesteuert?


Interrupts habe ich keine hinterlegt soweit ich weiß. Ich habe lediglich 
die Read und Write kommandos des MCC in die Bosch samples an dem 
entsprechenden platzhalter eingefügt und die datentypen  bze so lange 
angepasst bis der compiler nicht mehr geneckert hat 😅

Also es wird ein Configurations byte gesendet und dannach wird der 
Ausgabe byte immer wieder abgefragt.

Beide geräte sowohl SPI TFT als auch I2C sensor sind 100% Slave und 
senden keine aktiven Signale

von Vorname N. (mcu32)


Lesenswert?

Mh ok. Das könnte zumindest mal dein Problem mit SPI erklären. Wenn du 
sowas Polst kann es bei höherer Auslastung der CPU gut möglich sein dass 
irgendwann das Timing nicht mehr eingehalten wird.

Bei der restlichen Optimierung kann ich dir leider wenig helfen - ich 
kenne deinen Code nicht. Aber verstehe ich das richtig, dass du 
sämtliche Bildformate / Grafiken auf deinem µC hinterlegt hast?

Oh und Glückwunsch dass es zumindest in einem gewissen Bereich gut 
funktioniert :)

: Bearbeitet durch User
von Brom B. (schrori)


Lesenswert?

Vorname N. schrieb:
> Mh ok. Das könnte zumindest mal dein Problem mit SPI erklären. Wenn du
> sowas Polst kann es bei höherer Auslastung der CPU gut möglich sein dass
> irgendwann das Timing nicht mehr eingehalten wird.
>
> Bei der restlichen Optimierung kann ich dir leider wenig helfen - ich
> kenne deinen Code nicht. Aber verstehe ich das richtig, dass du
> sämtliche Bildformate / Grafiken auf deinem µC hinterlegt hast?
>
> Oh und Glückwunsch dass es zumindest in einem gewissen Bereich gut
> funktioniert :)


Vielen Dank :D

Naja der Bildschirm ist ein ST7735 und reagiert einfach auf Signale die 
er empfängt. Er bekommt also pixel für pixel via spi gesendet.

Spi und I2c triggere ich aber nacheinander also nie beide parallel.

Spi kann den hohen takt sehr gut halten bis der Flashspeicher sich 
füllt.

Ob der Sensor wirklich macht was er soll erfahre ich erst wenn ich den 
levelshifter angebracht habe 😁

"Sämtliche bildformate und grafiken" sind in meinem Fall 1 Logo ca 
100x80px alt binär BMP in Hex, und 2 Fonts (A-Z a-z 0-9 und 
Sonderzeichen.

Ich habe das in eine eigene Header gepackt und dementsprechend ist es im 
Programmcode hinterlegt als Char.

Wie könnte ich es denn sonst noch speichern?
Ist ein Zusätzlicher speicherchip sehr aufwendig?

Der Code ist noch recht wüst im Grunde habe ich mich nach und nach an 
die Funktionen herangetastet die funktionen neu orientiert und dann 
weiterverarbeitet.

Vg

von Brom B. (schrori)


Lesenswert?

Addr W2812 Rgbs steuere ich noch mit 1 2 Bitbanging schleifen aber das 
läuft alles für 2-3 for Geschichten sollte doch harmlos sein oder?

von Vorname N. (mcu32)


Lesenswert?

Ich muss gestehen das ich mit "größeren" Images bisher nur mit TouchGFX 
o.ä. gearbeitet habe. Bei den Displays, die ich dafür verwendet habe ist 
ein separater Slot für eine microSD Karte eingebaut, Zugriff erfolgt 
durch den µC dann durch DMA.

von Brom B. (schrori)


Lesenswert?

Vorname N. schrieb:
> Ich muss gestehen das ich mit "größeren" Images bisher nur mit TouchGFX
> o.ä. gearbeitet habe. Bei den Displays, die ich dafür verwendet habe ist
> ein separater Slot für eine microSD Karte eingebaut, Zugriff erfolgt
> durch den µC dann durch DMA.

Diese Möglichkeit habe ich eine MicroSd karte befindet sich ebenso am 
bildschirm und ist für späteres datenlogging ohnehin vorgesehen.
Mit DMA habe ich bisher 0 befasst ich weis aber das der uC das kann,

Könntedt du mir hier eine kurze Erklärung abgeben? Soweit ich weiß 
/dachte klappt das mit der SD Karte nur via spi 🤔

von Vorname N. (mcu32)


Lesenswert?

Puh. Also ich bin da auch kein Experte darin, ich kann nur sagen dass du 
die Daten auf der Karte dann nicht per CPU "holst" sondern du diese 
quasi direkt per SPI buffern kannst. Das hat den Vorteil, dass die CPU 
währenddessen alles andere erledigen kann und die Übertragung deiner 
Bilddaten beispielswiese in Hardware implementiert abläuft.

Der Beispielcode den ich dir zum Thema Wrapper gepostet habe ist aus 
einem Projekt, das ich vor 2 Jahren mal angefangen habe - seit dem mache 
ich eigentlich nur noch Hardware und bin größtenteils raus aus dem Thema 
Embedded Software :D
Mein Wissen dazu ist also nicht mehr ganz so direkt verfügbar.

von Brom B. (schrori)


Lesenswert?

Ok dann werd ich mal belesen :)

Aber zum generellen einbinden, würde ich sozusagen alles speichern und 
dann die ganzen benötigten Bitmaps (oder pixel hex wie immer das heisst) 
von der SD In den RAM buffern und diesen nach verwendung wieder 
freigeben richtig?

Wie genau lösche ich in C eine Variable so das der speicher wirklich 
woeder frei ist?

VG

von Brom B. (schrori)


Lesenswert?

Bzw. Könnte ich den inhalt (zumindest die großen Bitmaps) als locale 
variable laden dann müsste nach abschluss der Speicher wieder frei sein 
richtig? Das klingt schonmal alles sehr super duper :D

Lässt sich mit DMA auch ein txt file auf die Sd schreiben? :)

von Stefan F. (Gast)


Lesenswert?

Richard S. schrieb:
> Wie genau lösche ich in C eine Variable so das der speicher wirklich
> woeder frei ist?

Gar nicht.

Globale und statische Variablen sind immer da. Sie haben eine feste 
Adresse.

Lokale Variablen in Funktionen liegen auf dem Stack, welcher beim 
Verlassen der Funktion freigegeben wird.

Wenn du mit malloc() dynamischen Speicher im Heap belegst, gibst du ihn 
mit free() wieder frei.

von Brom B. (schrori)


Lesenswert?

Stefan F. schrieb:
> Richard S. schrieb:
>> Wie genau lösche ich in C eine Variable so das der speicher wirklich
>> woeder frei ist?
>
> Gar nicht.
>
> Globale und statische Variablen sind immer da. Sie haben eine feste
> Adresse.
>
> Lokale Variablen in Funktionen liegen auf dem Stack, welcher beim
> Verlassen der Funktion freigegeben wird.
>
> Wenn du mit malloc() dynamischen Speicher im Heap belegst, gibst du ihn
> mit free() wieder frei.

Hi Steffen danke für die Antwort,
Wie kann ich mir das vorstellen? Erzeuge ich dann eine char Variable die 
bewusst im dynamischen speicher liegt?

Vg

von Stefan F. (Gast)


Lesenswert?

Richard S. schrieb:
> Erzeuge ich dann eine char Variable die
> bewusst im dynamischen speicher liegt?

Es ist primitiver: Du reservierst eine gewisse Anzahl Bytes und bekommst 
einen Zeiger auf den Speicherbereich. Was du wie darin speicherst bleibt 
dir überlassen

https://www.c-howto.de/tutorial/arrays-felder/speicherverwaltung/

Prüfe aber vorher, ob malloc() von deiner C Bibliothek überhaupt 
unterstützt wird. Bei machen Mikrocontrollern muss man diese Funktion 
selbst implementieren.

von Brom B. (schrori)


Lesenswert?

Verstehe aber der dynamische speicher ist dann trotzdem futsch...
Im falle der SD Karte könnte ich also zb. (Manuell) eine char mit länge 
500 erstellen und deren Wert immer wieder neu beschreiben.
Im grunde wäre das doch das gleiche oder?

Mit der Ausnahme das im falle der char jedes file die gleiche größe 
haben muss während es im dynamischen speicher nur die selbige anfangs 
adresse hat oder?

Hab icj das richtig verstanden?

von Stefan F. (Gast)


Lesenswert?

Richard S. schrieb:
> Im grunde wäre das doch das gleiche oder?

Ja. Bei Mikrocontrollern macht es relativ selten Sinn, Speicher 
dynamisch zu belegen. Bei PC schon eher, weil man möglichst viel 
ungenutzten Speicher anderen Programmen überlassen will.

Richard S. schrieb:
> Mit der Ausnahme das im falle der char jedes file die gleiche größe
> haben muss während es im dynamischen speicher nur die selbige anfangs
> adresse hat oder?

Wenn dein Puffer z.B. 500 Bytes groß ist heißt das nicht, dass jede 
Datei ihn komplett mit 500 Bytes ausnutzen muss. Man kann darin auch 
kleinere Dateien ablegen, wenn du dir die tatsächliche Größe woanders 
(in einer int Variable) merkst.

von RS (Gast)


Lesenswert?

Stefan F. schrieb:
> Wenn dein Puffer z.B. 500 Bytes groß ist heißt das nicht, dass jede
> Datei ihn komplett mit 500 Bytes ausnutzen muss. Man kann darin auch
> kleinere Dateien ablegen, wenn du dir die tatsächliche Größe woanders
> (in einer int Variable) merkst.

Beispielsweise dann so?

char puffer[500];
int Datenlänge = 300;
char Filler = "0";
for (int i = 0; i<500 - Datenlänge; i++)
{
Filler = Filler + "0"
}

puffer = "Irgendwas mit 300 bytes" + Filter;

... = Puffer[0:300];

das ist bestimmt 100000 mal umständlicher als es sein müsste xD

oder meinst du jetzt in der malloc() Methode?

Ich hab ursprünglich mit Python da ist das alles etwas lockerer :D


PS hat mich irgendwie nicht eingeloggt

von Bratmaxxe (Gast)


Lesenswert?

Da würde ich dann doch lieber direkt mit malloc() arbeiten.
Die Idee bei C ist ja, dass du mit beispielswiese
1
uint16_t meineVarible
 einen Speicherbereich von 2 Byte reservierst, egal ob da nun 2 Byte 
rein kommt oder nicht.
Mit malloc() hingegen kannst du gezielt bytewise Speicher belegen.

von Brom B. (schrori)


Lesenswert?

Bratmaxxe schrieb:
> Da würde ich dann doch lieber direkt mit malloc() arbeiten.
> Die Idee bei C ist ja, dass du mit beispielswiese
1
uint16_t 
2
> meineVarible
 einen Speicherbereich von 2 Byte reservierst, egal ob
> da nun 2 Byte rein kommt oder nicht.
> Mit malloc() hingegen kannst du gezielt bytewise Speicher belegen.


Das ist wieder ein typisches Beispiel warum ich foren so schätze das 
sind infos die normale bücher einfach nicht deutlich hergeben.

Kurzes update btw, ich bekomme zahlen aus dem BMP. Die bosch library hat 
nicht funktioniert daher habe ich komplett eigene Funktionen geschrieben 
welche die bits aktiv senden und empfangen.

Für meine zwecke genügt das vollkommen :)

Jetz muss ich das wirr warr nurnoch entwirren xD

von Duckundweg (Gast)


Lesenswert?

an  BesserWisser (Gast)

wenn dir das zu blöde ist, dann sei' doch das nächstemal einfach still 
und blättere über diesen Thread hinweg.
Dieses Forum krankt leider unerträglich an diesen besch.. 
Möchtegern-Motzern

von Brom B. (schrori)


Lesenswert?

@Duckundweg danke für die Deckung :)

So also ich kann ihn Configurieren Werte auslesen usw.

Nun stehe ich vor dem Problem das ich total wirre nonsens zahlen habe...

Hat MPLap die Möglichkeit Print befehle auszugeben?

Ich habe meinen Bildschirm bzw. Sprintf im verdacht.

von Bernd (Gast)


Lesenswert?

Jetzt musst du nur noch dig_T1 bis dig_T3 und dig_P1 bis dig_P9 auslesen 
und abspeichern. Daraus und aus den aktuellen Messwerten kannst du dann 
Temperatur und Druck berechnen. Weist du wie das geht? Ansonsten habe 
ich hier ein PDF-Dokument, wo das beschrieben ist, auch ein Beispiel als 
C-Programm. Ich weiß nicht mehr, wo ich das runtergeladen habe, sonst 
würde ich dir den Link schicken. Anhängen darf ich es wohl nicht, aber 
ich könnte es dir per PN schicken.

Bernd

von Brom B. (schrori)


Lesenswert?

Bernd schrieb:
> Jetzt musst du nur noch dig_T1 bis dig_T3 und dig_P1 bis dig_P9 auslesen
> und abspeichern. Daraus und aus den aktuellen Messwerten kannst du dann
> Temperatur und Druck berechnen. Weist du wie das geht? Ansonsten habe
> ich hier ein PDF-Dokument, wo das beschrieben ist, auch ein Beispiel als
> C-Programm. Ich weiß nicht mehr, wo ich das runtergeladen habe, sonst
> würde ich dir den Link schicken. Anhängen darf ich es wohl nicht, aber
> ich könnte es dir per PN schicken.
>
> Bernd
6

Hallo Bernd,

Danke für den Hinweis das habe ich bereits gemacht:) das Problem lag 
tatsächlich darin das mein Tft treiber keine Doubles verarbeiten kann. 
Ich habe diese nun als float abgespeichert und habe präzise und 
sinnhafte werte! :)

Vielen Dank an alle!!

Für den nächsten der dannach sucht, ich habe einfach die Befehle aus dem 
MCC example genommen und die register aus dem datenblatt so beschrieben 
wie es dort steht.

Im Nachhinein eigentlich total einfach die formatiererei mit den 
datentypen ist viel schlimmer :D

von Vorname N. (mcu32)


Lesenswert?

Brom B. schrieb:
> Im Nachhinein eigentlich total einfach die formatiererei mit den
> datentypen ist viel schlimmer :D

Das stimmt allerdings. Oft ist es mangels guter Doku Rumprobiererei wie 
man casten muss :)

von Brom B. (schrori)


Lesenswert?

Jetz muss ich trotzdem nochmal einhaken was DMA angeht, funktioniert das 
das ich via SPI und DMA aud eine microSD zugreife obwohl ich den selben 
SPI für den TFT nutze?

Eigentlich ja kein Problem durch CS aber DMA läufz ja im Hintergrund 
wenn ich das richtig verstanden habe

von Akira (akari222023)


Lesenswert?

Hallo du kannst Daten in ein serial flash ic schreiben.

Wenn die Daten in dem ich sind, klammerst du den source Code hierfür 
aus.

SD Card Braucht Recht viel Speicher für fat32

von Steve van de Grens (roehrmond)


Lesenswert?

Brom B. schrieb:
> Nun stehe ich vor dem Problem das ich total wirre nonsens zahlen habe...

Deswegen hatte ich dir empfohlen, zuerst die Chip ID auslesen. Klappt 
das korrekt? Wenn nicht, funktioniert die Kommunikation schon in den 
Grundzügen nicht. Das würdest du dann auch mit dem Logic Analyzer sehen.

OK, in deinem Fall war die Ursache etwas anderes. Aber behalte das 
trotzdem mal im Hinterkopf.

Brom B. schrieb:
> Im Nachhinein eigentlich total einfach

Siehst du, die gleiche Erfahrung habe ich mit anderen Sensoren von Bosch 
gemacht. Deswegen hatte ich in deinem Fall so schnell empfohlen, es 
selbst zu programmieren anstatt die Bibliothek zu benutzen.

Brom B. schrieb:
> Jetz muss ich trotzdem nochmal einhaken was DMA angeht, funktioniert das
> das ich via SPI und DMA aud eine microSD zugreife obwohl ich den selben
> SPI für den TFT nutze?

Wenn du sicher stellst, dass die beiden Peripherien immer nur 
abwechselnd angesprochen werden sollte das gehen. Wer auf das Display 
zugreifen will muss halt warten, bis die Kommunikation mit der SD Karte 
abgeschlossen ist (oder umgekehrt).

: Bearbeitet durch User
von Brom B. (schrori)


Lesenswert?

Steve van de Grens schrieb:
> Brom B. schrieb:
>> Nun stehe ich vor dem Problem das ich total wirre nonsens zahlen habe...
>
> Deswegen hatte ich dir empfohlen, zuerst die Chip ID auslesen. Klappt
> das korrekt? Wenn nicht, funktioniert die Kommunikation schon in den
> Grundzügen nicht. Das wirst du dann auch mit dem Logic Analyzer sehen.



Der Sesor funktioniert auch mit Anzeige die werte passen, ich hatte zu 
wenig speicher zum bitshiften reserviert.

Akira schrieb:
> Hallo du kannst Daten in ein serial flash ic schreiben.
> Wenn die Daten in dem ich sind, klammerst du den source Code hierfür aus

Eignet sich das für ein Logfile? Kann ich das später dann auslesen bei 
bedarf? Falls ja würde ich gerne mehr erfahren welches IC wäre zb 
geeignet?

Beitrag #7219366 wurde von einem Moderator gelöscht.
von Brom B. (schrori)


Lesenswert?

Vorname N. schrieb:
> Brom B. schrieb:
>> Im Nachhinein eigentlich total einfach die formatiererei mit den
>> datentypen ist viel schlimmer :D
>
> Das stimmt allerdings. Oft ist es mangels guter Doku Rumprobiererei wie
> man casten muss :)

Steve van de Grens schrieb:
> Deswegen hatte ich dir empfohlen, zuerst die Chip ID auslesen. Klappt
> das korrekt? Wenn nicht, funktioniert die Kommunikation schon in den
> Grundzügen nicht. Das würdest du dann auch mit dem Logic Analyzer sehen.
> OK, in deinem Fall war die Ursache etwas anderes. Aber behalte das
> trotzdem mal im Hinterkopf.

Ist bestimmt generell gut für den code zu prüfen ob alles geht um 
aufhänger zu meiden :)

Steve van de Grens schrieb:
> Siehst du, die gleiche Erfahrung habe ich mit anderen Sensoren von Bosch
> gemacht. Deswegen hatte ich in deinem Fall so schnell empfohlen, es
> selbst zu programmieren anstatt die Bibliothek zu benutzen.


Ja jetzt weiß ich was du meintest xD totsl simpel eigentlich:D

Steve van de Grens schrieb:
> Wenn du sicher stellst, dass die beiden Peripherien immer nur
> abwechselnd angesprochen werden sollte das gehen. Wer auf das Display
> zugreifen will muss halt warten, bis die Kommunikation mit der SD Karte
> abgeschlossen ist (oder umgekehrt).



So war das ursprünglich auch gedacht.
Allerdings läuft ja DMA Permanent im Hintergrund bzw immer wenn ich es 
aufrufe. Die Bildschirm Aktualisierung dauert über SPI auch immer ein 
weilchen im Gegensatz zu den restlichen abläufen. Wenn ich dann noch 
warten muss bis spi von der Karte frei ist... wäre es nicht möglich 
ssgen wir die Anzahl der Messungen als doublelong im eeprom oder so zu 
speichern und diese bei bedarf mit dem pickit auszulesen?

Vg

von Steve van de Grens (roehrmond)


Lesenswert?

Brom B. schrieb:
> wäre es nicht möglich
> ssgen wir die Anzahl der Messungen als doublelong im eeprom oder so zu
> speichern und diese bei bedarf mit dem pickit auszulesen?

Ich verstehe die Frage nicht, insbesondere wie damit Zugriffskonflikte 
auf dem Bus vermieden werden könnten.

Willst du die Ergebnisse der Messung im EEProm speichern? Bedenke das 
man das EEprom nicht unbegrenzt oft beschrieben kann. Ich kenne PIC 
nicht, aber ich gehe mal davon aus, dass man das EEprom über den 
Programmieradapter nicht im laufenden Betrieb auslesen kann.

Bin jetzt nicht sicher, ob deine Frage so gemeint war.

: Bearbeitet durch User
von Brom B. (schrori)


Lesenswert?

Steve van de Grens schrieb:
> Brom B. schrieb:
>> wäre es nicht möglich
>> ssgen wir die Anzahl der Messungen als doublelong im eeprom oder so zu
>> speichern und diese bei bedarf mit dem pickit auszulesen?
>
> Ich verstehe die Frage nicht, insbesondere wie damit Zugriffskonflikte
> auf dem Bus vermieden werden könnten.
>
> Willst du die Ergebnisse der Messung im EEProm speichern? Bedenke das
> man das EEprom nicht unbegrenzt oft beschrieben kann. Ich kenne PIC
> nicht, aber ich gehe mal davon aus, dass man das EEprom über den
> Programmieradapter nicht im laufenden Betrieb auslesen kann.
>
> Bin jetzt nicht sicher, ob deine Frage so gemeint war.

Im Grunde möchte ich daten speichern zb. Anzahl der Messungen über die 
zeit etc. Am liebsten als txt. Wenn ich das ganze dann abstecke möchte 
ich es auslesen.

von Steve van de Grens (roehrmond)


Lesenswert?

Brom B. schrieb:
> Im Grunde möchte ich daten speichern zb. Anzahl der Messungen über die
> zeit etc. Am liebsten als txt. Wenn ich das ganze dann abstecke möchte
> ich es auslesen.

OK. Dann rechne dir aus wie lange das EEPROM halten wird. Ein "Wear 
Levelling" Algorithmus kann helfen, die Lebensdauer des EEPROM erheblich 
zu erhöhen.

Alternativ würde sich anbieten, anstelle des PIC einen ESP8266 zu 
verwenden und die Messwerte per WLAN an einen Webserver oder MQTT Broker 
zu senden, der sie dann speichert. Dann brauchst du in deinem 
Mikrocontroller keine Uhr.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.