如何从传感器进行调试?(GCC)

ljsrvy3e  于 2023-03-12  发布在  其他
关注(0)|答案(1)|浏览(152)

正在尝试从adafruit传感器(sht31d)检索数据。
编译使用GCC的Fio,微控制器是一个atmega328p.
原始Arduino Implementation using Wire,在readTempHum()中:

for (uint8_t i=0; i<6; i++) 
{
  readbuffer[i] = Wire.read();
}

因为GCC不使用Wire,所以我尝试自己使用fleury i2c填充缓冲区:

for (uint8_t i=0; i<6; i++)
  {
    if (i==0) //Activate device
    {
      readbuffer[i] = read8(SHT31_DEFAULT_ADDR);
    }
    else if (i2c_readAck())
    {
      readbuffer[i] = i2c_readAck();
    }
    else
    {
      readbuffer[i] = i2c_readNak();
    }
  }

我对read8的意图只是开始接收数据:

uint16_t read8(uint8_t reg)
{
  uint16_t val = -1;

  if (i2c_start(SHT31_DEFAULT_ADDR<<1 | I2C_WRITE) == 0) //Section 4.2 of datasheet
  {

    i2c_write((uint8_t)reg);
    i2c_stop();

    if (i2c_start(SHT31_DEFAULT_ADDR<<1 | I2C_READ) == 0) //Section 4.4 of datasheet
    {

      val |= ((uint16_t)i2c_readAck());

    }
  }
  return val;
}

这真的很难调试。我几乎不知道这是在哪里,即使在彻底审查了datasheet。输出通过UART使用FTDI是什么。
另外,我用Arduino库测试了这个,在那里它工作得完美无缺,所以一切都连接得很好。
Currently digging through the Wire TWI library to better understand where I'm going wrong..

rseugnpd

rseugnpd1#

如果它有助于有类似的问题,今天我需要I2C为我的ATMega328P和没有I2C支持在我的ASF为8位AVR(我习惯了AVR32 UC3平台,那里是所有容易得多),所以我决定写我自己的I2C库,因为我发现没有工作或可靠的库...
以下是I2C.h库:

//-----------------------------------------------------------------------------
//--- I2C lib for ATMega328P ver: 1.00 ----------------------------------------
//-----------------------------------------------------------------------------
#ifndef _I2C_h
#define _I2C_h
//-----------------------------------------------------------------------------
void I2C_init(U32 clk_i2c)  // init I2C with clk_i2c baudrate
    {
    // clk_i2c=clk_cpu/(16+2*TWBR*prescaler)
    U32 d=((clk_cpu>>1)/clk_i2c)-8; // TWBR*prescaler
    U32 p=d>>8; if (d&255!=0) p++;  // prescaler = ceil(d/256)
    if (p>3){ p=3; d=255; } // too low freq, set lowest possible
     else if (p) d/=p;  
    TWSR = (d>>8)&3;    // set prescaler, clear flags
    TWBR = d&255;       // set clock
    TWCR = (1<<TWEN);   // enable TWI
    }
//-----------------------------------------------------------------------------
void TWIStart(void)
    {
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while ((TWCR & (1<<TWINT)) == 0);
    }
//-----------------------------------------------------------------------------
void TWIStop(void)
    {
    TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
    cpu_delay_us(10,clk_cpu);   // some recover wait
    }
//-----------------------------------------------------------------------------
void TWIWrite(U8 u8data)
    {
    TWDR = u8data;
    TWCR = (1<<TWINT)|(1<<TWEN);
    while ((TWCR & (1<<TWINT)) == 0);
    }
//-----------------------------------------------------------------------------
U8 TWIReadACK(void)
    {
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
    while ((TWCR & (1<<TWINT)) == 0);
    return TWDR;
    }
//-----------------------------------------------------------------------------
U8 TWIReadNACK(void)
    {
    TWCR = (1<<TWINT)|(1<<TWEN);
    while ((TWCR & (1<<TWINT)) == 0);
    return TWDR;
    }
//-----------------------------------------------------------------------------
#define TWIGetStatus (TWSR&0xF8)
//-----------------------------------------------------------------------------
bool I2C_probe(U8 adr)      // probe slave with address adr return true if present.
    {
    bool ret=true;
    TWIStart();             if (TWIGetStatus!=0x08) ret=false;  // Start OK?
    TWIWrite((adr<<1)|0);   if (TWIGetStatus!=0x18) ret=false;  // ACK received after address+R/W passed?
    TWIStop();
    return ret;
    }
//-----------------------------------------------------------------------------
bool I2C_write(U8 adr,U8 *dat,U8 siz) // send dat[siz] data to slave adr
    {
    TWIStart(); if (TWIGetStatus!=0x08) return false;
    TWIWrite((adr<<1)|0); if (TWIGetStatus != 0x18) return false;
    for (;siz;dat++,siz--)
        {
        TWIWrite(*dat); if (TWIGetStatus != 0x28) return false;
        }
    TWIStop();
    return true;
    }
//----------------------------------------------------------------------------- 
U8 I2C_read(U8 adr,U8 *dat,U8 siz)  // read dat[siz] data from slave adr (untested yet!!!)
    {
    TWIStart(); if (TWIGetStatus!=0x08) return false;
    TWIWrite((adr<<1)|1); if (TWIGetStatus != 0x40) return false;
    for (;siz;dat++,siz--)
        {
        *dat=TWIReadNACK(); if (TWIGetStatus != 0x58) return false;
        }
    TWIStop();
    return true;
    }
//-----------------------------------------------------------------------------
#endif
//-----------------------------------------------------------------------------

它需要cpu_delay_us例程(添加它与ASF向导),也使用CPU时钟定义之前,包括这个例如我的:

#define clk_cpu 16000000
#include "I2C.h"

我用AVR32的LCD1602库测试了它,它工作正常(我花了相当长的时间才让它工作,不得不在停止后添加等待状态,否则I2C失败),所以探测和发送数据到从机正在工作,但我没有I2C传感器可供使用,所以我还不能测试接收...
以下是典型用法:

// init I2C to 400KHz baudrate
I2C_init(400000);

// probe first I2C device (and obtain its address)
volatile U8 LCD_I2C_adr=0;
for (LCD_I2C_adr=1;LCD_I2C_adr<128;LCD_I2C_adr++)
 if (I2C_probe(LCD_I2C_adr))
  break;

// send some packet
U8 packet[]={1,2,3,4,5}; // some packet
I2C_write(LCD_I2C_adr,packet,sizeof(packet));

// read some packet
I2C_read(LCD_I2C_adr,packet,sizeof(packet));

库本身是简单的阻塞,不使用中断,但它是一个很好的起点。

相关问题