Author Topic: ATSAMD21G18A I2C slave  (Read 2560 times)

0 Members and 1 Guest are viewing this topic.

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
ATSAMD21G18A I2C slave
« on: February 01, 2022, 01:49:25 pm »
Ok so I have a I2C master another ATSAMD21G18A but it uses arduino bootloder / code to drive the master. To learn how I2C works I wanted to write the slave on my own without the arduino code, however I am not doing something correctly. I know this is vague but before I start posting a bunch of code and asking someone to find the problem I want to check if there is a working bare bones slave implementation available that I could use as a guide and check with the datasheet what has and has not been used. The only thing I found is this https://www.avrfreaks.net/sites/default/files/forum_attachments/Atmel-42631-SAM-D21-SERCOM-I2C-Configura.pdf, however if I use this slave and an I2C scanner code https://playground.arduino.cc/Main/I2cScanner/ to see if any slaves exist I get nothing. Any advice is appreciated
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #1 on: February 01, 2022, 05:23:21 pm »
Here is a simple implementation. This one answers to two different addresses. It was taken from a real project, you can remote parts that deal with 2 addresses.
Alex
 
The following users thanked this post: WILDERNESSBAGEL

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #2 on: February 01, 2022, 05:27:40 pm »
Here a bare minimum example. It sends an incrementing counter and ignores any received bytes.
Alex
 
The following users thanked this post: WILDERNESSBAGEL

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #3 on: February 02, 2022, 07:43:30 am »
I tried this bare minimum example first but I still don't get anything when I run the scanner. I understand that it ignores any received bytes so maybe that's the reason. But I tried putting a print statement in the I2C_SERCOM_IRQ_HANDLER and it never gets printed. I used your samd21 starter to set up the UART, here is the code even tho it's basically your UART example with the copy pasted minimum example. But maybe I did something silly when putting them together.

Code: [Select]
/*
 * Copyright (c) 2015, Alex Taradov <alex@taradov.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "samd21.h"
#include "hal_gpio.h"

//-----------------------------------------------------------------------------
#define PERIOD_FAST     100
#define PERIOD_SLOW     500

HAL_GPIO_PIN(UART_TX,  B, 22)
HAL_GPIO_PIN(UART_RX,  B, 23)

//-----------------------------------------------------------------------------
HAL_GPIO_PIN(SDA,      A, 8)
HAL_GPIO_PIN(SCL,      A, 9)

#define I2C_BASE_ADDRESS       0x52// 8-bit address
#define I2C_SERCOM             SERCOM0
#define I2C_SERCOM_PMUX        HAL_GPIO_PMUX_C
#define I2C_SERCOM_APBCMASK    PM_APBCMASK_SERCOM0
#define I2C_SERCOM_GCLK_ID     SERCOM0_GCLK_ID_CORE
#define I2C_SERCOM_IRQ_HANDLER irq_handler_sercom0
#define I2C_SERCOM_IRQ         SERCOM0_IRQn

#define DelayTicks(ticks)              {volatile uint32_t n=ticks; while(n--);}    //takes 8 cycles
#define DelayMs(ms)                    DelayTicks(MS_TO_DLYTICKS(ms))
#define F_CPU 8000000
#define CYCLES_IN_DLYTICKS_FUNC        8
#define MS_TO_DLYTICKS(ms)    (uint32_t)(F_CPU / 1000 * ms / CYCLES_IN_DLYTICKS_FUNC) // ((float)(F_CPU)) / 1000.0

//-----------------------------------------------------------------------------
static void timer_set_period(uint16_t i)
{
  TC3->COUNT16.CC[0].reg = (F_CPU / 1000ul / 256) * i;
  TC3->COUNT16.COUNT.reg = 0;
}

//-----------------------------------------------------------------------------
void irq_handler_tc3(void)
{
  if (TC3->COUNT16.INTFLAG.reg & TC_INTFLAG_MC(1))
  {
    TC3->COUNT16.INTFLAG.reg = TC_INTFLAG_MC(1);
  }
}

//-----------------------------------------------------------------------------
static void timer_init(void)
{
  PM->APBCMASK.reg |= PM_APBCMASK_TC3;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(TC3_GCLK_ID) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  TC3->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ |
      TC_CTRLA_PRESCALER_DIV256 | TC_CTRLA_PRESCSYNC_RESYNC;

  TC3->COUNT16.COUNT.reg = 0;

  timer_set_period(PERIOD_SLOW);

  TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;

  TC3->COUNT16.INTENSET.reg = TC_INTENSET_MC(1);
  NVIC_EnableIRQ(TC3_IRQn);
}

//-----------------------------------------------------------------------------
static void uart_init(uint32_t baud)
{
  uint64_t br = (uint64_t)65536 * (F_CPU - 16 * baud) / F_CPU;

  HAL_GPIO_UART_TX_out();
  HAL_GPIO_UART_TX_pmuxen(PORT_PMUX_PMUXE_D_Val);
  HAL_GPIO_UART_RX_in();
  HAL_GPIO_UART_RX_pmuxen(PORT_PMUX_PMUXE_D_Val);

  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM5_GCLK_ID_CORE) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  SERCOM5->USART.CTRLA.reg =
      SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK |
      SERCOM_USART_CTRLA_RXPO(3/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(1/*PAD0*/);

  SERCOM5->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN |
      SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/);

  SERCOM5->USART.BAUD.reg = (uint16_t)br;

  SERCOM5->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
}

//-----------------------------------------------------------------------------
static void uart_putc(char c)
{
  while (!(SERCOM5->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE));
  SERCOM5->USART.DATA.reg = c;
}

//-----------------------------------------------------------------------------
static void uart_puts(char *s)
{
  while (*s)
    uart_putc(*s++);
}

//-----------------------------------------------------------------------------
static void sys_init(void)
{
  // Switch to 8MHz clock (disable prescaler)
  SYSCTRL->OSC8M.bit.PRESC = 0;
}

static void i2c_init(void)
{
HAL_GPIO_SDA_pmuxen(I2C_SERCOM_PMUX);
HAL_GPIO_SCL_pmuxen(I2C_SERCOM_PMUX);

PM->APBCMASK.reg |= I2C_SERCOM_APBCMASK;

GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(I2C_SERCOM_GCLK_ID) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

I2C_SERCOM->I2CS.ADDR.reg = I2C_BASE_ADDRESS;
I2C_SERCOM->I2CS.CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN;

I2C_SERCOM->I2CS.CTRLA.reg = SERCOM_I2CS_CTRLA_ENABLE | SERCOM_I2CS_CTRLA_MODE_I2C_SLAVE;

I2C_SERCOM->I2CS.INTENSET.reg = SERCOM_I2CS_INTENCLR_PREC | SERCOM_I2CS_INTENCLR_AMATCH |
SERCOM_I2CS_INTENCLR_DRDY;

NVIC_EnableIRQ(I2C_SERCOM_IRQ);
}

//-----------------------------------------------------------------------------
void I2C_SERCOM_IRQ_HANDLER(void)
{
uart_puts("\r\n Interrupt!\r\n");
int flags;

flags = I2C_SERCOM->I2CS.INTFLAG.reg;

if (flags & SERCOM_I2CS_INTFLAG_AMATCH)
{
I2C_SERCOM->I2CS.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
I2C_SERCOM->I2CS.CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(3);
}

if (flags & SERCOM_I2CS_INTFLAG_PREC)
{
I2C_SERCOM->I2CS.INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
}

if (flags & SERCOM_I2CS_INTFLAG_DRDY)
{
if (I2C_SERCOM->I2CS.STATUS.reg & SERCOM_I2CS_STATUS_DIR)
{
static int cnt = 0;
I2C_SERCOM->I2CS.DATA.reg = cnt++;
}
else
{
I2C_SERCOM->I2CS.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;

int data = I2C_SERCOM->I2CS.DATA.reg;
(void)data;
}

I2C_SERCOM->I2CS.INTFLAG.reg = SERCOM_I2CS_INTFLAG_DRDY;
}
}


//-----------------------------------------------------------------------------
int main(void)
{
  uint32_t cnt = 0;
  bool fast = false;

  sys_init();
  timer_init();
  uart_init(115200);
  i2c_init();
  DelayMs(1000);
  uart_puts("\r\nHello, world!\r\n");
  DelayMs(1000);


  while (1)
  {



  }

  return 0;
}


Could it be something on the arduino side of the exchange? I am reading the correct sensor addresses so I assumed everything is working properly.
« Last Edit: February 02, 2022, 07:47:05 am by WILDERNESSBAGEL »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #4 on: February 02, 2022, 07:53:09 am »
Do you have pull-ups on the bus? Why not capture the bus with a logic analyzer and see what is going on?
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #5 on: February 02, 2022, 08:36:52 am »
I don't have a logic analyzer, I only have a scope. I changed the arduino code to make it easier to capture it now looks like this:

Code: [Select]
#include<Wire.h>
int x = 0;
void setup() {
  // Start the I2C Bus as Master
  Wire.begin();
  Serial1.begin(115200);
}
void loop() {
  Wire.beginTransmission(0x52); // transmit to device #9
  Wire.write(x);              // sends x
  Wire.endTransmission();    // stop transmitting
  x++; // Increment x
  if (x > 5) x = 0; // `reset x once it gets 6
  Serial1.println("Write");
  delay(500);
}

The slave code stayed the same.
Here is an image of clock and data. As far as I can tell the address part is good. Aren't there supposed to be some stop and start bits between the address part and the slave part.

https://imgur.com/a/xdIustA

« Last Edit: February 02, 2022, 08:38:26 am by WILDERNESSBAGEL »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #6 on: February 02, 2022, 08:42:08 am »
 Wire.beginTransmission(); takes 7-bit address, so you need to provide 0x29 as an address.

Also, at least capture clock and data on two different traces at the same time. It is hard to interpret the results.

And get a logic analyzer. $15 will save you a ton of time.
« Last Edit: February 02, 2022, 08:43:58 am by ataradov »
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #7 on: February 02, 2022, 09:02:27 am »
I changed the address in the arduino code to 0x29 but no dice there is still no print on the slave. I'm not really sure if I understand the addressing part I see your comment that 0x52 is an 8 bit address (in the code) and if I understand 0x29 is just 0x52 shifted once. I see that the SAMD21 has 7 bit and 10 bit addressing so I thought the code uses 10 bit version but I don't see ADDR.TENBITEN=1 being set anywhere? Or is it ok because 0x52 == 0b1010010 (only 7 bits needed to represent the number) but why do I need to shift the address in wire begin then? I'm a bit confused  |O . Here is a picture of clock and data when the address is 0x29. https://imgur.com/a/sXz2bvq. And thank you for the quick responses and patience with this.  Do i need to change the slave address to 0x29 aswell (I tried but it didn't help)?
« Last Edit: February 02, 2022, 09:08:30 am by WILDERNESSBAGEL »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #8 on: February 02, 2022, 09:13:38 am »
It has 7 bit address, but the register that holds is shifted by 1. So, you either need to shift 7-bit value before writing to the register, or specify 8-bit value. I always use 8-bit addresses.

According to this, scanner actually uses 8-bit addresses too. I'm not sure if there is a difference between different Arduino implementations or their documentation is wrong. But you can return the address back to 0x52 on Ardiuno side.

And just to double check, you use my startup code as well? So your interrupt handler in the vector table is also called  irq_handler_sercom0?

And double check that you have connected SCL/SDA correctly on the D21 side.
« Last Edit: February 02, 2022, 09:17:20 am by ataradov »
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #9 on: February 02, 2022, 09:24:14 am »
I see the addresses are starting to make more sense :). Yeah the arduino is wonky to to say the least, if there is a master slave example for samd I could try that just to make sure it's not some random arduino problem.
If this is the vector table then I guess it's correct. I checked the wiring it seems ok.

Code: [Select]
void (* const vectors[])(void) =
{
  &_stack_top,                   // 0 - Initial Stack Pointer Value

  // Cortex-M0+ handlers
  irq_handler_reset,             // 1 - Reset
  irq_handler_nmi,               // 2 - NMI
  irq_handler_hard_fault,        // 3 - Hard Fault
  0,                             // 4 - Reserved
  0,                             // 5 - Reserved
  0,                             // 6 - Reserved
  0,                             // 7 - Reserved
  0,                             // 8 - Reserved
  0,                             // 9 - Reserved
  0,                             // 10 - Reserved
  irq_handler_sv_call,           // 11 - SVCall
  0,                             // 12 - Reserved
  0,                             // 13 - Reserved
  irq_handler_pend_sv,           // 14 - PendSV
  irq_handler_sys_tick,          // 15 - SysTick

  // Peripheral handlers
  irq_handler_pm,                // 0 - Power Manager
  irq_handler_sysctrl,           // 1 - System Controller
  irq_handler_wdt,               // 2 - Watchdog Timer
  irq_handler_rtc,               // 3 - Real Time Counter
  irq_handler_eic,               // 4 - External Interrupt Controller
  irq_handler_nvmctrl,           // 5 - Non-Volatile Memory Controller
  irq_handler_dmac,              // 6 - Direct Memory Access Controller
  irq_handler_usb,               // 7 - Universal Serial Bus Controller
  irq_handler_evsys,             // 8 - Event System
  irq_handler_sercom0,           // 9 - Serial Communication Interface 0
  irq_handler_sercom1,           // 10 - Serial Communication Interface 1
  irq_handler_sercom2,           // 11 - Serial Communication Interface 2
  irq_handler_sercom3,           // 12 - Serial Communication Interface 3
  irq_handler_sercom4,           // 13 - Serial Communication Interface 4
  irq_handler_sercom5,           // 14 - Serial Communication Interface 5
  irq_handler_tcc0,              // 15 - Timer/Counter for Control 0
  irq_handler_tcc1,              // 16 - Timer/Counter for Control 1
  irq_handler_tcc2,              // 17 - Timer/Counter for Control 2
  irq_handler_tc3,               // 18 - Timer/Counter 3
  irq_handler_tc4,               // 19 - Timer/Counter 4
  irq_handler_tc5,               // 20 - Timer/Counter 5
  irq_handler_tc6,               // 21 - Timer/Counter 6
  irq_handler_tc7,               // 22 - Timer/Counter 7
  irq_handler_adc,               // 23 - Analog-to-Digital Converter
  irq_handler_ac,                // 24 - Analog Comparator
  irq_handler_dac,               // 25 - Digital-to-Analog Converter
  irq_handler_ptc,               // 26 - Peripheral Touch Controller
  irq_handler_i2s,               // 27 - Inter-IC Sound Interface
};
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #10 on: February 02, 2022, 09:37:26 am »
Here is I2C master example https://github.com/ataradov/dgw/blob/master/embedded/i2c_master.c

I see no other obvious reasons for it not to work.
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #11 on: February 02, 2022, 02:17:40 pm »
Sorry for the late response, I tried to use the master code and the slave code. The i2c_start(0x52) function returns 0 if I understand correctly this means that there is no slave detected. Here are both complete codes just in case I messed something up.

MASTER:

Code: [Select]
/*
 * Copyright (c) 2016, Alex Taradov <alex@taradov.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
/*MASTER*/
/*- Includes ----------------------------------------------------------------*/
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "samd21.h"
#include "hal_gpio.h"


/*- Prototypes --------------------------------------------------------------*/
int i2c_init(int freq);
bool i2c_start(int addr);
bool i2c_stop(void);
bool i2c_read_byte(uint8_t *byte, bool last);
bool i2c_write_byte(uint8_t byte);
bool i2c_busy(int addr);
void i2c_pins(int mask, int value);


HAL_GPIO_PIN(UART_TX,  B, 22)
HAL_GPIO_PIN(UART_RX,  B, 23)

/*- Definitions -------------------------------------------------------------*/
HAL_GPIO_PIN(SDA,             A, 8);
HAL_GPIO_PIN(SCL,             A, 9);
#define I2C_SERCOM            SERCOM2
#define I2C_SERCOM_PMUX       PORT_PMUX_PMUXE_D_Val
#define I2C_SERCOM_GCLK_ID    SERCOM2_GCLK_ID_CORE
#define I2C_SERCOM_CLK_GEN    0
#define I2C_SERCOM_APBCMASK   PM_APBCMASK_SERCOM2

#define T_RISE                215e-9 // Depends on the board, actually


#define DelayTicks(ticks)              {volatile uint32_t n=ticks; while(n--);}    //takes 8 cycles
#define DelayMs(ms)                    DelayTicks(MS_TO_DLYTICKS(ms))
#define CYCLES_IN_DLYTICKS_FUNC        8
#define MS_TO_DLYTICKS(ms)    (uint32_t)(F_CPU / 1000 * ms / CYCLES_IN_DLYTICKS_FUNC) // ((float)(F_CPU)) / 1000.0

enum
{
  I2C_TRANSFER_WRITE = 0,
  I2C_TRANSFER_READ  = 1,
};

enum
{
  I2C_PINS_SDA = (1 << 0),
  I2C_PINS_SCL = (1 << 1),
};




/*-----------------------------------UART------------------------------------*/
#define PERIOD_SLOW     500
//-----------------------------------------------------------------------------
static void timer_set_period(uint16_t i)
{
TC3->COUNT16.CC[0].reg = (F_CPU / 1000ul / 256) * i;
TC3->COUNT16.COUNT.reg = 0;
}

//-----------------------------------------------------------------------------
void irq_handler_tc3(void)
{
if (TC3->COUNT16.INTFLAG.reg & TC_INTFLAG_MC(1))
{
TC3->COUNT16.INTFLAG.reg = TC_INTFLAG_MC(1);
}
}

//-----------------------------------------------------------------------------
static void timer_init(void)
{
PM->APBCMASK.reg |= PM_APBCMASK_TC3;

GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(TC3_GCLK_ID) |
GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

TC3->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ |
TC_CTRLA_PRESCALER_DIV256 | TC_CTRLA_PRESCSYNC_RESYNC;

TC3->COUNT16.COUNT.reg = 0;

timer_set_period(PERIOD_SLOW);

TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;

TC3->COUNT16.INTENSET.reg = TC_INTENSET_MC(1);
NVIC_EnableIRQ(TC3_IRQn);
}

//-----------------------------------------------------------------------------
static void uart_init(uint32_t baud)
{
uint64_t br = (uint64_t)65536 * (F_CPU - 16 * baud) / F_CPU;

HAL_GPIO_UART_TX_out();
HAL_GPIO_UART_TX_pmuxen(PORT_PMUX_PMUXE_D_Val);
HAL_GPIO_UART_RX_in();
HAL_GPIO_UART_RX_pmuxen(PORT_PMUX_PMUXE_D_Val);

PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5;

GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM5_GCLK_ID_CORE) |
GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

SERCOM5->USART.CTRLA.reg =
SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK |
SERCOM_USART_CTRLA_RXPO(3/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(1/*PAD0*/);

SERCOM5->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN |
SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/);

SERCOM5->USART.BAUD.reg = (uint16_t)br;

SERCOM5->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
}

//-----------------------------------------------------------------------------
static void uart_putc(char c)
{
while (!(SERCOM5->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE));
SERCOM5->USART.DATA.reg = c;
}

//-----------------------------------------------------------------------------
static void uart_puts(char *s)
{
while (*s)
uart_putc(*s++);
}

//-----------------------------------------------------------------------------
static void sys_init(void)
{
// Switch to 8MHz clock (disable prescaler)
SYSCTRL->OSC8M.bit.PRESC = 0;
}
/*----------------------------------I2C--------------------------------------*/
/*- Implementations ---------------------------------------------------------*/

//-----------------------------------------------------------------------------
int i2c_init(int freq)
{
  int baud = ((float)F_CPU / freq - (float)F_CPU * T_RISE - 10.0) / 2.0;

  if (baud < 0)
    baud = 0;
  else if (baud > 255)
    baud = 255;

  freq = (float)F_CPU / (2.0 * (5.0 + baud) + (float)F_CPU * T_RISE);

  PM->APBCMASK.reg |= I2C_SERCOM_APBCMASK;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(I2C_SERCOM_GCLK_ID) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(I2C_SERCOM_CLK_GEN);

  I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST;
  while (I2C_SERCOM->I2CM.CTRLA.reg & SERCOM_I2CM_CTRLA_SWRST);

  I2C_SERCOM->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
  while (I2C_SERCOM->I2CM.SYNCBUSY.reg);

  I2C_SERCOM->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud);
  while (I2C_SERCOM->I2CM.SYNCBUSY.reg);

  I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_ENABLE |
      SERCOM_I2CM_CTRLA_MODE_I2C_MASTER |
      SERCOM_I2CM_CTRLA_SDAHOLD(3);
  while (I2C_SERCOM->I2CM.SYNCBUSY.reg);

  I2C_SERCOM->I2CM.STATUS.reg |= SERCOM_I2CM_STATUS_BUSSTATE(1);

  HAL_GPIO_SDA_in();
  HAL_GPIO_SDA_clr();
  HAL_GPIO_SDA_pmuxen(I2C_SERCOM_PMUX);

  HAL_GPIO_SCL_in();
  HAL_GPIO_SCL_clr();
  HAL_GPIO_SCL_pmuxen(I2C_SERCOM_PMUX);

  return freq;
}

//-----------------------------------------------------------------------------
bool i2c_start(int addr)
{
  I2C_SERCOM->I2CM.INTFLAG.reg = SERCOM_I2CM_INTFLAG_ERROR;

  I2C_SERCOM->I2CM.ADDR.reg = addr;
  while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) &&
         0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));
  if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK ||
      I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_ERROR)
  {
    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
    return false;
  }

  return true;
}

//-----------------------------------------------------------------------------
bool i2c_stop(void)
{
  if ((I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) ||
      (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB))
  {
    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
  }

  return true;
}

//-----------------------------------------------------------------------------
bool i2c_read_byte(uint8_t *byte, bool last)
{
  while (1)
  {
    int flags = I2C_SERCOM->I2CM.INTFLAG.reg;

    if (flags & SERCOM_I2CM_INTFLAG_SB)
      break;

    if (flags & (SERCOM_I2CM_INTFLAG_MB | SERCOM_I2CM_INTFLAG_ERROR))
      return false;
  }

  if (last)
    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT | SERCOM_I2CM_CTRLB_CMD(3);
  else
    I2C_SERCOM->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;

  *byte = I2C_SERCOM->I2CM.DATA.reg;

  return true;
}

//-----------------------------------------------------------------------------
bool i2c_write_byte(uint8_t byte)
{
  I2C_SERCOM->I2CM.DATA.reg = byte;
  uart_puts("\r\n Written in data reg \r\n");

  while (1)
  {
    int flags = I2C_SERCOM->I2CM.INTFLAG.reg;

    if (flags & SERCOM_I2CM_INTFLAG_MB)
      break;

    if (flags & (SERCOM_I2CM_INTFLAG_SB | SERCOM_I2CM_INTFLAG_ERROR))
      return false;
// uart_puts("\r\n Stuck in while \r\n");
  }

  if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK)
  {
    I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
    return false;
  }

  return true;
}

//-----------------------------------------------------------------------------
bool i2c_busy(int addr)
{
  bool busy;

  I2C_SERCOM->I2CM.ADDR.reg = addr | I2C_TRANSFER_WRITE;

  while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));

  busy = (0 != (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK));

  I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);

  return busy;
}

//-----------------------------------------------------------------------------
void i2c_pins(int mask, int value)
{
  if (mask & I2C_PINS_SDA)
  {
    HAL_GPIO_SDA_out();
    HAL_GPIO_SDA_write(value & I2C_PINS_SDA);
  }
  else
  {
    HAL_GPIO_SDA_in();
    HAL_GPIO_SDA_clr();
  }

  if (mask & I2C_PINS_SCL)
  {
    HAL_GPIO_SCL_out();
    HAL_GPIO_SCL_write(value & I2C_PINS_SCL);
  }
  else
  {
    HAL_GPIO_SCL_in();
    HAL_GPIO_SCL_clr();
  }

  HAL_GPIO_SDA_pmuxdis();
  HAL_GPIO_SCL_pmuxdis();
}





int main(){

sys_init();
timer_init();
uart_init(115200);
DelayMs(3000);
i2c_init(100000);
uart_puts("\r\n uart done \r\n");
uart_puts("\r\n i2c init done \r\n");
uart_putc(i2c_start(0x52) + 48);

while(1){
uart_puts("\r\n before write \r\n");
i2c_write_byte(2);
uart_puts("\r\n data written\r\n");
DelayMs(200);
}


return 0;
}


SLAVE:

Code: [Select]
/*
 * Copyright (c) 2015, Alex Taradov <alex@taradov.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "samd21.h"
#include "hal_gpio.h"

//-----------------------------------------------------------------------------
#define PERIOD_FAST     100
#define PERIOD_SLOW     500

HAL_GPIO_PIN(UART_TX,  B, 22)
HAL_GPIO_PIN(UART_RX,  B, 23)

//-----------------------------------------------------------------------------
HAL_GPIO_PIN(SDA,      A, 8)
HAL_GPIO_PIN(SCL,      A, 9)

#define I2C_BASE_ADDRESS       0x52// 8-bit address
#define I2C_SERCOM             SERCOM0
#define I2C_SERCOM_PMUX        HAL_GPIO_PMUX_C
#define I2C_SERCOM_APBCMASK    PM_APBCMASK_SERCOM0
#define I2C_SERCOM_GCLK_ID     SERCOM0_GCLK_ID_CORE
#define I2C_SERCOM_IRQ_HANDLER irq_handler_sercom0
#define I2C_SERCOM_IRQ         SERCOM0_IRQn

#define DelayTicks(ticks)              {volatile uint32_t n=ticks; while(n--);}    //takes 8 cycles
#define DelayMs(ms)                    DelayTicks(MS_TO_DLYTICKS(ms))
#define FCPU 8000000
#define CYCLES_IN_DLYTICKS_FUNC        8
#define MS_TO_DLYTICKS(ms)    (uint32_t)(FCPU / 1000 * ms / CYCLES_IN_DLYTICKS_FUNC) // ((float)(F_CPU)) / 1000.0

//-----------------------------------------------------------------------------
static void timer_set_period(uint16_t i)
{
  TC3->COUNT16.CC[0].reg = (F_CPU / 1000ul / 256) * i;
  TC3->COUNT16.COUNT.reg = 0;
}

//-----------------------------------------------------------------------------
void irq_handler_tc3(void)
{
  if (TC3->COUNT16.INTFLAG.reg & TC_INTFLAG_MC(1))
  {
    TC3->COUNT16.INTFLAG.reg = TC_INTFLAG_MC(1);
  }
}

//-----------------------------------------------------------------------------
static void timer_init(void)
{
  PM->APBCMASK.reg |= PM_APBCMASK_TC3;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(TC3_GCLK_ID) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  TC3->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ |
      TC_CTRLA_PRESCALER_DIV256 | TC_CTRLA_PRESCSYNC_RESYNC;

  TC3->COUNT16.COUNT.reg = 0;

  timer_set_period(PERIOD_SLOW);

  TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;

  TC3->COUNT16.INTENSET.reg = TC_INTENSET_MC(1);
  NVIC_EnableIRQ(TC3_IRQn);
}

//-----------------------------------------------------------------------------
static void uart_init(uint32_t baud)
{
  uint64_t br = (uint64_t)65536 * (F_CPU - 16 * baud) / F_CPU;

  HAL_GPIO_UART_TX_out();
  HAL_GPIO_UART_TX_pmuxen(PORT_PMUX_PMUXE_D_Val);
  HAL_GPIO_UART_RX_in();
  HAL_GPIO_UART_RX_pmuxen(PORT_PMUX_PMUXE_D_Val);

  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM5_GCLK_ID_CORE) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  SERCOM5->USART.CTRLA.reg =
      SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK |
      SERCOM_USART_CTRLA_RXPO(3/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(1/*PAD0*/);

  SERCOM5->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN |
      SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/);

  SERCOM5->USART.BAUD.reg = (uint16_t)br;

  SERCOM5->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
}

//-----------------------------------------------------------------------------
static void uart_putc(char c)
{
  while (!(SERCOM5->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE));
  SERCOM5->USART.DATA.reg = c;
}

//-----------------------------------------------------------------------------
static void uart_puts(char *s)
{
  while (*s)
    uart_putc(*s++);
}

//-----------------------------------------------------------------------------
static void sys_init(void)
{
  // Switch to 8MHz clock (disable prescaler)
  SYSCTRL->OSC8M.bit.PRESC = 0;
}

static void i2c_init(void)
{
HAL_GPIO_SDA_pmuxen(I2C_SERCOM_PMUX);
HAL_GPIO_SCL_pmuxen(I2C_SERCOM_PMUX);

PM->APBCMASK.reg |= I2C_SERCOM_APBCMASK;

GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(I2C_SERCOM_GCLK_ID) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

I2C_SERCOM->I2CS.ADDR.reg = I2C_BASE_ADDRESS;
I2C_SERCOM->I2CS.CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN;

I2C_SERCOM->I2CS.CTRLA.reg = SERCOM_I2CS_CTRLA_ENABLE | SERCOM_I2CS_CTRLA_MODE_I2C_SLAVE;

I2C_SERCOM->I2CS.INTENSET.reg = SERCOM_I2CS_INTENCLR_PREC | SERCOM_I2CS_INTENCLR_AMATCH |
SERCOM_I2CS_INTENCLR_DRDY;

NVIC_EnableIRQ(I2C_SERCOM_IRQ);
}

//-----------------------------------------------------------------------------
void I2C_SERCOM_IRQ_HANDLER(void)
{
uart_puts("\r\n Interrupt!\r\n");
int flags;

flags = I2C_SERCOM->I2CS.INTFLAG.reg;

if (flags & SERCOM_I2CS_INTFLAG_AMATCH)
{
I2C_SERCOM->I2CS.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
I2C_SERCOM->I2CS.CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(3);
}

if (flags & SERCOM_I2CS_INTFLAG_PREC)
{
I2C_SERCOM->I2CS.INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
}

if (flags & SERCOM_I2CS_INTFLAG_DRDY)
{
if (I2C_SERCOM->I2CS.STATUS.reg & SERCOM_I2CS_STATUS_DIR)
{
static int cnt = 0;
I2C_SERCOM->I2CS.DATA.reg = cnt++;
}
else
{
I2C_SERCOM->I2CS.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;

int data = I2C_SERCOM->I2CS.DATA.reg;
(void)data;
}

I2C_SERCOM->I2CS.INTFLAG.reg = SERCOM_I2CS_INTFLAG_DRDY;
}
}


//-----------------------------------------------------------------------------
int main(void)
{
  uint32_t cnt = 0;
  bool fast = false;

  sys_init();
  timer_init();
  uart_init(115200);
  i2c_init();
  DelayMs(1000);
  uart_puts("\r\nHello, world!\r\n");
  DelayMs(1000);


  while (1)
  {



  }

  return 0;
}


How important are resistor values for I2C? I used 10k to pullup both lines can this maybe be the reason, I see a lot of different values on the internet so not sure if this is good. I'll try to connect the master to a random sensor and see if it responds.

UPDATE:

It doesn't recognize the sensor either the sensor I used was tcn75 https://ww1.microchip.com/downloads/en/DeviceDoc/21490D.pdf address should be 0x48.
« Last Edit: February 02, 2022, 02:40:57 pm by WILDERNESSBAGEL »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #12 on: February 02, 2022, 04:48:55 pm »
0x48 is the 7-bit address. 8-bit address would be 0x90.
Alex
 
The following users thanked this post: WILDERNESSBAGEL

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #13 on: February 03, 2022, 08:35:55 am »
Ok so I guess it's something with the MCU. The one I used as a master works and returns true when testing with the sensor, the other one gets false with the same code. Any ideas what could be the problem could it be the crystal or something along those lines? In your opinion how hard would it be to figure it out? Also thanks for all the help, best help I had on any of the forums.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #14 on: February 03, 2022, 08:40:56 am »
You have the scope, you can check is the crystal is running. But you can also disable all clock initialization just to be sure.

And also, put some pin toggling in he main loop. If the loop runs, then the clock is fine. Plus you have debug prints, check them and if they show up, then the clock must be good.

The pins may be damaged too, which is also easy enough to test.
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #15 on: February 03, 2022, 01:30:49 pm »
Thanks for the suggestions, I tried everything and everything worked as expected, I even tried generating PWM on random pins and it's fine. I'm out of ideas :(. It looks like everything besides I2C is ok :D

UPDATE:

I continued to mess around doing simple things to see if anything brakes and now it randomly can't find the device signature. When I try to read it it reads it every 5th time and the same is for uploading the code. I tried to erase the chip (found this as a solution on another form post) but it didn't help.
« Last Edit: February 03, 2022, 02:32:53 pm by WILDERNESSBAGEL »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #16 on: February 03, 2022, 05:08:15 pm »
Can you show your schematics and board layout?
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #17 on: February 07, 2022, 12:27:21 pm »
Once again sorry for the late response, a friend of mine designed the board so I had to wait for him to send me the schematics. This is the schematic of the one that doesn't respond.. Board layout is in the attachment.

P.S. I found another MKRGSM and the communication between two MKRs works as expected so the code is for sure good.
« Last Edit: February 07, 2022, 12:38:50 pm by WILDERNESSBAGEL »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #18 on: February 07, 2022, 05:00:53 pm »
There is no schematic attached.
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #19 on: February 07, 2022, 08:10:31 pm »
Whoops my bad I accidentally removed it when I edited the message. I will post it now.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #20 on: February 07, 2022, 09:29:06 pm »
Why is VDDCORE connected to 3.3 V? You are not supposed to connect anything to it, except for decoupling capacitors. This pin is an output of the internal voltage regulator, and it is 1.2 V.
Alex
 
The following users thanked this post: WILDERNESSBAGEL

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #21 on: February 08, 2022, 12:03:56 pm »
Yep it's just a mistake, I'll give it back to get it fixed, is there anything else that should be changed? And could this have caused any damage to the MCU is there a way to check?

I tested various things and now it seems like everything works fine. Thanks once again for all the help.
« Last Edit: February 08, 2022, 03:08:37 pm by WILDERNESSBAGEL »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11721
  • Country: us
    • Personal site
Re: ATSAMD21G18A I2C slave
« Reply #22 on: February 08, 2022, 04:39:24 pm »
It could have damaged the device, so if possible I would replace it. There is no simple way to check it. If you leave it and something else does not work, then you will always have to doubt that it is because of the previous damage.

The values for R9 and R10 are strange. They should be 5.1K.
Alex
 

Offline WILDERNESSBAGELTopic starter

  • Contributor
  • Posts: 28
  • Country: hr
Re: ATSAMD21G18A I2C slave
« Reply #23 on: February 11, 2022, 08:10:10 am »
Thank you I'll have those changed as well for the next design.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf