TWI Waveform

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have been using SAMDxx processors for a while, but I am just about to start a project which needs TWI and I realize that  I have not used it since I moved from 8 bit processors.  In order to practise using TWI I attached an I/O Xplained board to a SAMD21 Xplained.  The I/O board has a AT30TSE752 temp sensor which has the address 0x9E and I have managed to get the program reading it successfully but there is an odd element to it which I would like to clarify.  I am using the ASF calls which occasionally have their quirks.

The configuration part of the program looks like this:  (I am sorry not putting code using the add code button, but it does not seem to work)

#define DATA_LENGTH 10
#define SLAVE_ADDRESS 0x4F; 

struct i2c_master_module i2c_master_instance;

struct i2c_master_packet register_packet;  // Sets up correct address for register
uint8_t TempReg[1] = {
 0x00
};

struct i2c_master_packet temp_ture_packet; // Ready to read temperature
uint8_t temperature[2] = {
  0x00, 0x00
};

void fill_structs(void){
 register_packet.address = SLAVE_ADDRESS;
 register_packet.data_length = 1;
 register_packet.data  = TempReg;

 temp_ture_packet.address = SLAVE_ADDRESS;
 temp_ture_packet.data_length = 2;
 temp_ture_packet.data = temperature;
}

void configure_i2c_master(void){
 struct i2c_master_config config_i2c_master;
 i2c_master_get_config_defaults(&config_i2c_master);
 config_i2c_master.pinmux_pad0 = PINMUX_PA08D_SERCOM2_PAD0; //SCL
 config_i2c_master.pinmux_pad1 = PINMUX_PA09D_SERCOM2_PAD1;   //sda
 config_i2c_master.baud_rate_high_speed = I2C_MASTER_BAUD_RATE_3400KHZ;
 while(i2c_master_init(&i2c_master_instance, SERCOM2, &config_i2c_master)!= STATUS_OK);
 i2c_master_enable(&i2c_master_instance);
}

And writing  to the TWI looks like this:

 i2c_master_write_packet_wait_no_stop(&i2c_master_instance, &register_packet);
 i2c_master_read_packet_wait(&i2c_master_instance, &temp_ture_packet); //
 printf("Temperature in 2 bytes: %d  %d\r\n", temperature[0],temperature[1] );

I have got this working but you will have seen that I have set the Slave Address at 0x4F. 

0x4F is of course 0x9E>>1.

In the logic analyser screenshot you will that see that the address is coming out as 0x9E.  It appears as if there is a timing error.

Do I just stop being pedantic and adjust numbers by bit shifting or have I got something wrong?

By the way does the SAMD21 have the ability to do a clock stretch and does this have anything to do with my other question?  I have seen it suggested that the mcu does not have that facility.

Thanks for any help.

Regards

MikeFW

 

 

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nothing wrong, 0x9E or 0x4F is just the address as 8 bits (including the R/W bit) or as 7 bits. I notice there is a quick start example for AT30TSE75x, sure enough it has this:

#define AT30TSE_TEMPERATURE_TWI_ADDR    0x4F //0b1001111

meaning ASF i2c expects the address without the R/W bit (which makes sense since there are separate write and read functions).

 

BTW, don't put ';' in your defines as you have here

#define SLAVE_ADDRESS 0x4F; 

that will give you problems sooner or later

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the answer.  I now see what is going on.

Could you answer my second part:  - Does the SAMD21 have the ability to stretch its SCL line?  I know I should be able to read the data and see for myself, but I don't really understand what the data sheet is saying or even whether it is saying it.  There does not seem to be a configuration property offering this but the manual is clearly saying something about stretch:

26.6.2.6 I2C Master Operation...The I2C master has two interrupt strategies. When SCL Stretch Mode (CTRLA.SCLSM) is set to zero, SCL is stretched
before or after the acknowledge bit . In this mode the I2C master operates according to the behavior diagram shown in
Figure 26-6.

If I need to configure the property, how do I do it using the ASF approach?

Regards

MikeFW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes it can stretch SCL. The CTRLA.SCLSM bit is not about if the SCL will be streched but when, in ASF you have

    /** Set to enable SCL stretch only after ACK bit (required for high speed) */
    bool scl_stretch_only_after_ack_bit;

The practical difference (apart from the requirement for high speed) is if the master can look at incoming data before sending ACK/NACK. With the default CTRLA.SCLSM = 0 it is possible to look at data while with CTRLA.SCLSM = 1 the ACK/NACK decision has to be made beforehand.

It is similar for a slave but with added ability to NACK a matched address (CTRLA.SCLSM = 0 needed for that). It could be useful if you set up a range or mask such that multiple addresses will be matched while you intend to respond only to some subset of them. I never got that to work when I tried it however.

/Lars

Last Edited: Sun. Feb 26, 2017 - 03:07 PM