
[MSPM0G5187 SM] 보드에는 UART, I2C 모듈들을 연결할 수 있는 커넥터가 있어 I2C 센서들을 쉽게 연결하고 Serial FND과 같은 디버깅 모듈로 간단히 표시할 수 있다.

간단히 I2C 거리 감지 모듈(VL53L0X)로 거리 출력값을 표시 해보자.
SysConfig로 I2C를 추가 하고 핀맵을 할당한다.

I2C로 거리 감지 센서의 데이터를 읽으려고 기존에 사용했던 Read/Write 함수를 사용 하는데... 에러가 발생한다.
void HAL_I2C_Master_Transmit(I2C_Regs *i2c, uint8_t addr, uint8_t *buf, uint16_t len, uint16_t timeout)
{
volatile uint32_t waitCount;
DL_I2C_fillControllerTXFIFO(i2c, buf, len);
/* Wait for I2C to be Idle */
waitCount = timeout * 10;
while (!(
DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_IDLE));
/* Send the packet to the controller.
* This function will send Start + Stop automatically.
*/
DL_I2C_startControllerTransfer(i2c, addr>>1, DL_I2C_CONTROLLER_DIRECTION_TX, len);
/* Poll until the Controller writes all bytes */
while (
DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_BUSY)
;
/* Trap if there was an error */
if (DL_I2C_getControllerStatus(i2c) &
DL_I2C_CONTROLLER_STATUS_ERROR) {
/* LED will remain high if there is an error */
__BKPT(0);
}
/* Wait for I2C to be Idle */
while (!(
DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_IDLE));
}
확인 결과MSPM05178은 최신 출시된 칩셋이고 SDK 버전도 업데이트 되면서 I2C부분에서 수정된것이 많은것 같다.
기존 I2C 코드에서 Read시 문제가 있었는데 수정이 좀 되었으려나?
일단 최신 코드 기준으로 I2C관련 코드를 다시 작성했다.
void HAL_I2C_Master_Transmit(I2C_Regs *i2c, uint8_t addr, uint8_t *buf, uint16_t len, uint16_t timeout)
{
DL_I2CC_fillTXFIFO(i2c, buf, len);
/* Wait for I2C to be Idle */
while (!(
DL_I2CC_getStatus(i2c) & DL_I2CC_STATUS_IDLE))
;
/* Send the packet to the controller.
* This function will send Start + Stop automatically.
*/
DL_I2CC_startTransfer(i2c, addr>>1, DL_I2CC_DIRECTION_TX, len);
/* Workaround for errata I2C_ERR_13 */
delay_cycles(32000);
/* Poll until the Controller writes all bytes */
while (
DL_I2CC_getStatus(i2c) & DL_I2CC_STATUS_BUSY)
;
/* Trap if there was an error */
if (DL_I2CC_getStatus(i2c) &
DL_I2CC_STATUS_ERROR) {
/* LED will remain high if there is an error */
//__BKPT(0);
}
/* Wait for I2C to be Idle */
while (!(
DL_I2CC_getStatus(i2c) & DL_I2CC_STATUS_IDLE))
;
#endif
}
기존에 테스트 했던 LTR559 거리 감지 센서는 10mm 내외의 짧은 거리만 측정이 가능한데 이번에는 VL53L0X 센서를 이용해서 2000mm 까지 감지 가능하도록 해 보자.
최대한 간한하게 거리 값만 출력하는 예제 코드를 작성했다. 거리 값을 좀더 정밀하고 안정되게 출력하려면 센서 내부 MCU의 설정을 최신 코드로 해 주어야 한다고 한다. 우선 MSPM0G5187의 I2C가 정상동작 하는지 간단히 값이 출력되는지만 확인해 보자.
#define I2C_INST I2C_0_INST
#define I2C_TIMEOUT_COUNT 1000
#define VL53L0X_ADDR (0x29 << 1)
#define REG_SYSRANGE_START 0x00
#define REG_SYSTEM_SEQUENCE_CONFIG 0x01
#define REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x0A
#define REG_SYSTEM_INTERRUPT_CLEAR 0x0B
#define REG_RESULT_INTERRUPT_STATUS 0x13
#define REG_RESULT_RANGE_STATUS 0x14
#define REG_GPIO_HV_MUX_ACTIVE_HIGH 0x84
uint8_t VL53L0X_Init()
{
uint8_t id;
id = i2c_read_reg(VL53L0X_ADDR, 0xC0);
if(id != 0xEE)
return 0;
// 기본 설정
i2c_write_reg(VL53L0X_ADDR, 0x88, 0x00);
i2c_write_reg(VL53L0X_ADDR, 0x80, 0x01);
i2c_write_reg(VL53L0X_ADDR, 0xFF, 0x01);
i2c_write_reg(VL53L0X_ADDR, 0x00, 0x00);
uint8_t stop_variable = i2c_read_reg(VL53L0X_ADDR, 0x91);
i2c_write_reg(VL53L0X_ADDR, 0x00, 0x01);
i2c_write_reg(VL53L0X_ADDR, 0xFF, 0x00);
i2c_write_reg(VL53L0X_ADDR, 0x80, 0x00);
i2c_write_reg(VL53L0X_ADDR, REG_SYSTEM_INTERRUPT_CONFIG_GPIO, 0x04);
i2c_write_reg(VL53L0X_ADDR, REG_GPIO_HV_MUX_ACTIVE_HIGH, i2c_read_reg(VL53L0X_ADDR, REG_GPIO_HV_MUX_ACTIVE_HIGH) & ~0x10); // Active Low
i2c_write_reg(VL53L0X_ADDR, REG_SYSTEM_INTERRUPT_CLEAR, 0x01);
i2c_write_reg(VL53L0X_ADDR, REG_SYSRANGE_START, 0x02);
return 1;
}
uint16_t VL53L0X_ReadDistance(void) {
uint8_t high, low;
uint16_t distance = 0;
uint32_t timeout = 0;
while ((i2c_read_reg(VL53L0X_ADDR, REG_RESULT_INTERRUPT_STATUS) & 0x07) == 0) {
timeout++;
if (timeout > 50000) return 0xFFFF;
}
high = i2c_read_reg(VL53L0X_ADDR, 0x1E);
low = i2c_read_reg(VL53L0X_ADDR, 0x1F);
distance = (high << 8) | low;
i2c_write_reg(VL53L0X_ADDR, REG_SYSTEM_INTERRUPT_CLEAR, 0x01);
return distance;
}
int main(void)
{
uint8_t id = 0;
unsigned int distance = 0;
uint8_t led_mask;
SYSCFG_DL_init();
Led1On();
delay_ms(1000);
VL53L0X_Init();
while (1) {
distance = VL53L0X_ReadDistance();
PrintFND(distance);
delay_ms(50);
}
}