He estado intentando configurar I2C en el microcontrolador PIC16F1618. Estoy usando MPLAB X IDE, junto con el compilador xc8. El código MSSP se está generando a través del configurador de códigos MPLAB. He configurado la configuración para que sea la interrupción maestra I2C, la frecuencia de reloj sea 62.5KHz. La velocidad de giro es la velocidad estándar, el tiempo de retención SDA es de 300 ns. La dirección del esclavo será de 7 bits. He configurado RC0 para que sea SDA y RC1 para que sea SCL. Así que mi inicialización I2C generada se ve así,
void I2C_Initialize(void) {
i2c_object.pTrHead = i2c_tr_queue;
i2c_object.pTrTail = i2c_tr_queue;
i2c_object.trStatus.s.empty = true;
i2c_object.trStatus.s.full = false;
i2c_object.i2cErrors = 0;
// R_nW write_noTX; P stopbit_notdetected; S startbit_notdetected; BF RCinprocess_TXcomplete; SMP Standard Speed; UA dontupdate; CKE Idle to Active; D_nA lastbyte_address;
SSP1STAT = 0x80;
// SSPEN enabled; WCOL no_collision; CKP Idle:Low, Active:High; SSPM FOSC/4_SSPxADD; SSPOV no_overflow;
SSP1CON1 = 0x28;
// ACKTIM ackseq; SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 300ns; AHEN disabled;
SSP1CON3 = 0x08;
// Baud Rate Generator Value: SSP1ADD 3;
SSP1ADD = 0x03;
/* Byte sent or received */
// clear the master interrupt flag
PIR1bits.SSP1IF = 0;
// enable the master interrupt
PIE1bits.SSP1IE = 1;
}
Soy muy nuevo en los microcontroladores PIC, ¿podría ayudarme donde está el problema? Estoy usando PIC16F1618. No puedo ver ninguna forma de onda cuando conecto mi osciloscopio al pin SCL. La salida es siempre BAJA. Si conecto una resistencia de pull up, el pin siempre estará en HIGH lógico. También he intentado enviar algunos comandos de lectura / escritura para comprobar si el reloj se inicia, pero lamentablemente no lo hace. He trabajado con controladores ARM y en eso, después de la inicialización, podré observar las señales del reloj.
en main.c
I2C_Initialize();
bmp280.dev_addr = 0x77;
init_check = bmp280_init(&bmp280);
while (1) {
bmp280_read_uncomp_pressure(&tempVar);
}
bmp280.c
BMP280_RETURN_FUNCTION_TYPE bmp280_init(bmp280_t *temp_bmp280)
{
/* variable used to return communication result*/
BMP280_RETURN_FUNCTION_TYPE com_rslt = ERROR;
uint8_t v_data_u8 = BMP280_INIT_VALUE;
p_bmp280 = temp_bmp280;/* assign BMP280 ptr */
/* read chip id */
com_rslt = i2cbus_read(p_bmp280->dev_addr,
BMP280_CHIP_ID_REG, &v_data_u8,
BMP280_GEN_READ_WRITE_DATA_LENGTH);
//com_rslt = p_bmp280->BMP280_BUS_READ_FUNC(p_bmp280->dev_addr,
//BMP280_CHIP_ID_REG, &v_data_u8,
//BMP280_GEN_READ_WRITE_DATA_LENGTH);/* read Chip Id */
p_bmp280->chip_id = v_data_u8;
/* readout bmp280 calibparam structure */
com_rslt += bmp280_get_calib_param();
return com_rslt;
}
BMP280_RETURN_FUNCTION_TYPE bmp280_read_uncomp_pressure(int32_t *v_uncomp_pressure_s32)
{
/* variable used to return communication result*/
BMP280_RETURN_FUNCTION_TYPE com_rslt = ERROR;
/* Array holding the MSB and LSb value
a_data_u8[0] - Pressure MSB
a_data_u8[1] - Pressure LSB
a_data_u8[2] - Pressure LSB
*/
uint8_t a_data_u8[BMP280_PRESSURE_DATA_SIZE] = {BMP280_INIT_VALUE, BMP280_INIT_VALUE, BMP280_INIT_VALUE};
/* check the p_bmp280 struct pointer as NULL*/
if (p_bmp280 == BMP280_NULL) {
return E_BMP280_NULL_PTR;
} else {
com_rslt = i2cbus_read(p_bmp280->dev_addr,
BMP280_PRESSURE_MSB_REG,
a_data_u8, BMP280_PRESSURE_DATA_LENGTH);
*v_uncomp_pressure_s32 = (int32_t)(
(((uint32_t)(a_data_u8[BMP280_PRESSURE_MSB_DATA]))
<< BMP280_SHIFT_BIT_POSITION_BY_12_BITS) |
(((uint32_t)(a_data_u8[BMP280_PRESSURE_LSB_DATA]))
<< BMP280_SHIFT_BIT_POSITION_BY_04_BITS) |
((uint32_t)a_data_u8[BMP280_PRESSURE_XLSB_DATA] >>
BMP280_SHIFT_BIT_POSITION_BY_04_BITS));
}
return com_rslt;
}
estructura bmp280_t utilizada
typedef struct {
struct bmp280_calib_param_t calib_param;/**<calibration data*/
uint8_t chip_id;/**< chip id of the sensor*/
uint8_t dev_addr;/**< device address of the sensor*/
uint8_t oversamp_temperature;/**< temperature over sampling*/
uint8_t oversamp_pressure;/**< pressure over sampling*/
}bmp280_t;
en i2c_wrapper.c
int8_t i2cbus_read(uint8_t device_addr, uint8_t register_addr, uint8_t* register_data, uint8_t rd_len)
{
I2C_MESSAGE_STATUS status;
uint16_t timeOut;
uint16_t counter;
uint8_t *pD;
int8_t ret = 0;
pD = register_data;
for (counter = 0; counter < rd_len; counter++)
{
// Now it is possible that the slave device will be slow.
// As a work around on these slaves, the application can
// retry sending the transaction
timeOut = 0;
while(status != I2C_MESSAGE_FAIL)
{
// write one byte to slave i2c device, which is the register address
I2C_MasterWrite(®ister_addr, 1, device_addr, &status);
// wait for the message to be sent or status has changed.
while(status == I2C_MESSAGE_PENDING);
if (status == I2C_MESSAGE_COMPLETE)
break;
// if status is I2C_MESSAGE_ADDRESS_NO_ACK,
// or I2C_DATA_NO_ACK,
// The device may be busy and needs more time for the last
// write so we can retry writing the data, this is why we
// use a while loop here
// check for max retry and skip this byte
if (timeOut == MAX_RETRY)
break;
else
timeOut++;
}
if (status == I2C_MESSAGE_COMPLETE)
{
// this portion will read the byte from the memory location.
timeOut = 0;
while(status != I2C_MESSAGE_FAIL)
{
// read from the slave device
I2C_MasterRead(pD, 1, device_addr, &status);
// wait for the message to be sent or status has changed.
while(status == I2C_MESSAGE_PENDING);
if (status == I2C_MESSAGE_COMPLETE)
break;
// if status is I2C_MESSAGE_ADDRESS_NO_ACK,
// or I2C_DATA_NO_ACK,
// The device may be busy and needs more time for the last
// write so we can retry writing the data, this is why we
// use a while loop here
// check for max retry and skip this byte
if (timeOut == MAX_RETRY)
break;
else
timeOut++;
}
}
// exit if the last transaction failed
if (status == I2C_MESSAGE_FAIL)
{
ret = -1;
break;
}
pD++;
register_addr++;
}
return (ret);
}
I2C_MasterWrite y I2C_MasterRead es generado por el configurador de códigos que está presente en i2c.c