Ich arbeite mit einem MSP430G2553 und einem BMP180-Sensor. Ich habe folgende Funktion in meinem Programm
uint16_t leer_temp_des() {
unsigned char temp[2];
escribir_com_bmp180(CTRL_MEAS, LEER_TEMP);
retardo_ms(RET_LEC_TEMP);
leer_2_bytes_bmp180(OUT_MSB, temp);
printf("t0 %u\n", (uint16_t) temp[0]);
printf("t1 %u\n", (uint16_t) temp[1]);
uint16_t temperatura = ((uint16_t) (temp[0] << 8) | (uint16_t) temp[1]);
printf("t %u\n", temperatura);
//temperatura <<= 8;
//temperatura |= temp[1];
return temperatura;
}
Was diese andere Funktion aufruft
void leer_2_bytes_bmp180(uint8_t reg, uint8_t *v) {
inicioI2C(DIR_I2C_BMP180);
envioI2C(reg);
reinicioI2C(DIR_I2C_BMP180, false);
*v = recepcionI2C(false);
*(v + 1) = recepcionI2C(false);
finI2C();
}
I2C-Code
void inicializarI2C() {
UCB0CTL1 |= UCSWRST;
UCB0CTL0 &= ~(UCA10 | UCSLA10 | UCMM);
UCB0CTL0 |= (UCMST | UCMODE1 | UCMODE0 | UCSYNC);
UCB0CTL1 |= UCSSEL1 | UCSSEL0;
UCB0CTL1 |= UCTR;
UCB0STAT = 0;
UCB0BR0 = 160;
UCB0BR1 = 0;
UCB0I2COA = 0x1A;
UCB0I2CSA = 0x77;
P1DIR |= BIT6;
P1SEL |= BIT6;
P1SEL2 |= BIT6;
P1SEL |= BIT7;
P1SEL2 |= BIT7;
UCB0CTL1 &= ~UCSWRST;
}
void inicioI2C(uint8_t dir) {
UCB0I2CSA = dir;
UCB0CTL1 |= UCTR;
UCB0CTL1 |= UCTXSTT;
while((IFG2 & UCB0TXIFG) == 0) {}
//while((UCB0STAT & UCNACKIFG) == 0) {}
}
void reinicioI2C(uint8_t dir, bool rw) {
UCB0I2CSA = dir;
if(rw) {
UCB0CTL1 |= UCTR;
}
else {
UCB0CTL1 &= ~UCTR;
}
//UCB0CTL1 |= UCTR;
UCB0CTL1 |= UCTXSTT;
while((UCB0CTL1 & UCTXSTT) != 0) {
if((UCB0STAT & UCNACKIFG) != 0) {
break;
/*UCB0STAT &= ~UCNACKIFG;
UCB0CTL1 |= UCTXSTP;
while((UCB0CTL1 & UCTXSTP) != 0) {}*/
}
}
}
uint8_t envioI2C(uint8_t dato) {
//UCB0CTL1 |= UCTR;
//UCB0I2CSA = dir;
//UCB0CTL1 |= UCTXSTT;
UCB0TXBUF = dato;
while((UCB0CTL1 & UCTXSTT) != 0) {}
if((UCB0STAT & UCNACKIFG) != 0) {
UCB0STAT &= ~UCNACKIFG;
UCB0CTL1 |= UCTXSTP;
//while((UCB0CTL1 & UCTXSTP) != 0);
return 0;
}
while((IFG2 & UCB0TXIFG) == 0);
return 1;
//retardo_ms(1);
}
uint8_t recepcionI2C(bool parar) {
//UCB0CTL1 =& ~UCTR;
//UCB0I2CSA = dir;
//UCB0CTL1 |= UCTXSTT;
if(parar) {
if((UCB0STAT & UCNACKIFG) != 0) {
UCB0STAT &= ~UCNACKIFG;
}
UCB0CTL1 |= UCTXSTP;
}
while(!(IFG2 & UCB0RXIFG));
uint8_t dato = UCB0RXBUF;
//while(!(IFG2 & UCB0RXIFG));
if(parar) {
while((UCB0CTL1 & UCTXSTP) != 0) {}
}
return dato;
}
void finI2C() {
if((UCB0STAT & UCNACKIFG) != 0) {
UCB0STAT &= ~UCNACKIFG;
}
UCB0CTL1 |= UCTXSTP;
while((UCB0CTL1 & UCTXSTP) != 0) {}
}
Offensichtlich soll temp[0] das höchstwertige Byte speichern, während temp[1] das niedrigstwertige Byte speichern wird, aber das Gegenteil passiert: temp[0] speichert LSB und temp[1] speichert MSB. Ich habe die I2C-Daten bereits mit einem Logikanalysator überprüft, aber die Sequenz ist das Gegenteil von dem, was meine Funktion druckt.
Es gab ein Problem mit der STOP-Bedingung. Im Datenblatt heißt es, dass Sie, falls Sie ein einzelnes Byte lesen möchten, vor dem Lesen die STOP-Bedingung senden, aber es erklärt nicht, was zu tun ist, wenn Sie mehr als ein Byte lesen, und deshalb habe ich das gesendet STOP nach dem Lesen des letzten Bytes in diesem Fall. Anscheinend hat der Sensor also nach jedem I2C-Zyklus ein zusätzliches Byte gesendet. Dieses Byte wurde nicht in einer Variablen gespeichert, sondern im RXBUF-Register, und jedes Mal, wenn ein neuer Zyklus begann, wurde v[0] dieser Wert zugewiesen, während v[1] das Byte zugewiesen wurde, das das erste sein sollte one.This ist die einzige Funktion, die ich ändern musste
void leer_2_bytes_bmp180(uint8_t reg, uint8_t *v) {
inicioI2C(DIR_I2C_BMP180);
envioI2C(reg);
reinicioI2C(DIR_I2C_BMP180, false);
*v = recepcionI2C(false);
*(v + 1) = recepcionI2C(true);
}
Ich sende einen wahren Wert an recepcionI2C, um anzuzeigen, dass dies das letzte Byte ist, das gelesen wird, und ich habe finI2C entfernt , da die STOP-Bedingung im letzten recepcionI2C -Aufruf gesendet wird.
Kann keinen offensichtlichen Mangel erkennen. Ich würde eine read_uint16 () -Funktion ausprobieren, die ein anderes Idiom verwendet, um die Ergebnisse zu vergleichen:
uint16_t val = read_byte();
val <<= 8;
val |= read_byte();
Empfehlen Sie auch die Verwendung 0x%x
als printf-Format, um Probleme mit der Byte-Reihenfolge zu beheben.
Kartmann
EmTor
brhans
EmTor
Kartmann
DamienD
DamienD
recepcionI2C
jeweils ein Byte in der Reihenfolge liefern soll, in der sie vom Sensor gesendet werden, der zuerst MSB ist.EmTor
DamienD
EmTor
DamienD
EmTor
DamienD
EmTor
DamienD