BMP280 an PIC18F45K42 mit MPLAP und I2C

OP #7214241
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
}
OP #7214320
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
#7214338
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
OP #7214368
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?
#7214374
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.
Gast #7214393
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.
OP #7214681
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!
Gast #7214956
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!
OP #7215505
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! :)
OP #7217312
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 :)
#7217352
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.
OP #7217374
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.
OP #7217382
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
#7217385
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 :)
OP #7217412
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
OP #7217418
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 🤔
#7217428
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.
OP #7217435
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
Gast #7217438
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.
OP #7217440
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
Gast #7217446
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.
OP #7217451
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?
Gast #7217465
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.
Gast #7217619
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
Gast #7218056
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.
OP #7218067
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
Gast #7218075
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
OP #7218262
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.
Gast #7218268
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
OP #7218300
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
OP #7218372
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
Gast #7218689
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).
OP #7218694
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.
OP #7219695
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
Gast #7219699
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.
OP #7219704
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.
Gast #7219733
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren