Estoy trabajando con un sensor MSP430G2553 y un BMP180. tengo la siguiente funcion en mi programa
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;
}
Que llama a esta otra función
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();
}
código I2C
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) {}
}
Obviamente, se supone que temp[0] almacenará el byte más significativo mientras que temp[1] almacenará el byte menos significativo, pero sucede lo contrario: temp[0] está guardando LSB y temp[1] está guardando MSB. Ya verifiqué los datos I2C con un analizador lógico pero la secuencia es la opuesta a la que imprime mi función.
Hubo un problema con la condición STOP. En la hoja de datos dice que en caso de que quiera leer un solo byte, envíe la condición STOP antes de leer, pero no explica qué hacer cuando está leyendo más de un byte, y es por eso que estaba enviando el STOP después de leer el último byte en este caso. Entonces, aparentemente el sensor enviaba un byte adicional después de cada ciclo I2C. Este byte no se guardaba en una variable, sino que se guardaba en el registro RXBUF, y cada vez que comenzaba un nuevo ciclo se le asignaba este valor a v[0], mientras que a v[1] se le asignaba el byte que se suponía que era el primero. one.Esta es la única función que necesitaba cambiar
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);
}
Envío un valor verdadero a recepcionI2C para indicar que este es el último byte que se leerá y eliminé finI2C porque la condición STOP se envía en la última llamada de recepcionI2C .
No puedo ver ningún defecto evidente. Probaría una función read_uint16() que usa un idioma diferente para comparar los resultados:
uint16_t val = read_byte();
val <<= 8;
val |= read_byte();
También aconseje usar 0x%x
como formato printf para depurar problemas de orden de bytes.
Kartman
EmTor
brahans
EmTor
Kartman
damiend
damiend
recepcionI2C
se supone que produce un byte a la vez en el orden en que son enviados por el sensor, que es MSB primero.EmTor
damiend
EmTor
damiend
EmTor
damiend
EmTor
damiend