Another one. Can someone check my code?

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

This code consists of twi, usart and gpio. For AT32UC3B0512.

/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/**
 * \mainpage User Application template doxygen documentation
 *
 * \par Empty user application template
 *
 * Bare minimum empty user application template
 *
 * \par Content
 *
 * -# Include the ASF header files (through asf.h)
 * -# "Insert system clock initialization code here" comment
 * -# Minimal main function that starts with a call to board_init()
 * -# "Insert application code here" comment
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#include <avr32/io.h>
#include <asf.h>

#define USART_SERIAL                     &AVR32_USART0
#define USART_SERIAL_BAUDRATE            9600
#define USART_SERIAL_CHAR_LENGTH         8
#define USART_SERIAL_PARITY              USART_NO_PARITY
#define USART_SERIAL_STOP_BIT            USART_1_STOPBIT

void twi_init(void)
{
	twi_master_options_t opt = {
		.speed = 50000,
		.chip  = 0x68
	};
	
	static const gpio_map_t twi_gpio = {
		{9,0},
		{10,0}
	};
	
	gpio_enable_module(twi_gpio, sizeof(twi_gpio) / sizeof(twi_gpio[0]));

	twi_master_setup(&AVR32_TWI, &opt);
}

void RS232_init(void)
{
	static usart_serial_options_t usart_options = {
		.baudrate = USART_SERIAL_BAUDRATE,
		.charlength = USART_SERIAL_CHAR_LENGTH,
		.paritytype = USART_SERIAL_PARITY,
		.stopbits = USART_SERIAL_STOP_BIT
	};
	
	static const gpio_map_t rs232_gpio = {
		{18,0},
		{19,0}
	};
	
	gpio_enable_module(rs232_gpio,sizeof(rs232_gpio) / sizeof(rs232_gpio[0]));
	
	usart_serial_init(USART_SERIAL, &usart_options);
}


int main (void)
{
	/* Insert system clock initialization code here (sysclk_init()). */

	sysclk_init();
	board_init();
	twi_init();
	RS232_init();
	
	uint8_t data_received[10];

	twi_package_t packet_read = {
		.addr         = 0x75,      // TWI slave memory address data
		.addr_length  = sizeof (uint16_t),    // TWI slave memory address data size
		.chip         = 0x68,      // TWI slave bus address
		.buffer       = data_received,        // transfer data destination buffer
		.length       = 10                    // transfer data size (bytes)
	};
	
	//Enter loop
	while(1)
	{
		// Perform a multi-byte read access then check the result.
		if(twi_master_read(&AVR32_TWI, &packet_read) == TWI_SUCCESS){
		
			usart_serial_write_packet(USART_SERIAL, &data_received[0], sizeof(data_received[0]));
		}
	}
	

	/* Insert application code here, after the board has been initialized. */
}

The  I2C slave device I use is MPU6050, according to the register map, 0x75 is 'wh am i' register, so the usart should print '0x68' in PUTTY. However, when I connected the RS232 USB to my computer and open the correct COM port in PUTTY, it seemed to have no output.

Is there any problem with this code? THANKS!

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

I really wish that manufacturers would agree on a standard when describing I2C device addresses.
The confusion is caused by bit-0.
Shift the slave device address leftwards by 1 to 0xD0 and see if it works.

Last Edited: Tue. Sep 19, 2017 - 11:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mikech wrote:
I really wish that manufacturers would agree on a standard when describing I2C device addresses.

It's not just device manufacturers - it's software writers who also get this wrong.

 

The I2C Specification is very clear that the address is a 7-bit number.

 

But device manufacturers and software writers confuse the issue by including the R/W bit in what they call the "address" (sic).

 

angry

 

See: http://www.avrfreaks.net/comment...

 

#I2CAddress

 

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

I understand. So what I lack is the last R/W word, which is '0' for R? So for different operations i.e. Read or Write, the address will be different.

And what about the address for registers inside slave devices? Will it need for 8-bit?

Last Edited: Wed. Sep 20, 2017 - 05:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrAn wrote:
 R/W word

R/W is a single bit - not a word.

 

which is '0' for R

No. It's 1 for R

 

So for different operations i.e. Read or Write, the address will be different.

No!

 

The address and the R/W bit are entirely independent:

 

I2C Specification: https://www.nxp.com/docs/en/user-guide/UM10204.pdf

 

The address is 7 bits[1]; it is always the same - it is what identifies the particular Slave.

 

The R/W is an additional bit which distinguishes read from write.

 

And what about the address for registers inside slave devices? Will it need for 8-bit?

That is an entirely different matter.

 

That is purely down to the particular Slave - RTFM for details.

 

 

[1] I2C does also support 10-bit addresses; but, in the same way, the R/W bit is still a separate bit - quite distinct from the address.

 

Last Edited: Wed. Sep 20, 2017 - 05:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@MrAn wrote:

so the usart should print '0x68' in PUTTY.

I don't think so.  It will print the char whose code is 0x68: 'h'.

 

If you want to print binary data as text, you must convert it to text prior to printing.

 

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10

 

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

Oh, yeah, get it. That's my error.

I am changing that into putchar...

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

Greg_Muth wrote:
If you want to print binary data as text, you must convert it to text prior to printing

That is, to spell it out:

 

If you want "0x68" - a four-character text string - to appear on your PuTTY (or other terminal) screen, then you must send a character '0' (ASCII code 0x30), then send a character 'x' (ASCII code 0x78), then send a character '6' (ASCII code 0x36), then send a character '8' (ASCII code 0x38).

 

 

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

Now it's the adjusted code here.

/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/**
 * \mainpage User Application template doxygen documentation
 *
 * \par Empty user application template
 *
 * Bare minimum empty user application template
 *
 * \par Content
 *
 * -# Include the ASF header files (through asf.h)
 * -# "Insert system clock initialization code here" comment
 * -# Minimal main function that starts with a call to board_init()
 * -# "Insert application code here" comment
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#include <avr32/io.h>
#include <asf.h>

#define USART_SERIAL                     &AVR32_USART0
#define USART_SERIAL_BAUDRATE            9600
#define USART_SERIAL_CHAR_LENGTH         8
#define USART_SERIAL_PARITY              USART_NO_PARITY
#define USART_SERIAL_STOP_BIT            USART_1_STOPBIT

static void twi_init(void)
{
	twi_master_options_t opt = {
		.speed = 50000,
		.chip  = 0x68
	};
	
	static const gpio_map_t twi_gpio = {
		{9,0},
		{10,0}
	};
	
	gpio_enable_module(twi_gpio, sizeof(twi_gpio) / sizeof(twi_gpio[0]));

	twi_master_setup(&AVR32_TWI, &opt);
}

static void RS232_init(void)
{
	static usart_serial_options_t usart_options = {
		.baudrate = USART_SERIAL_BAUDRATE,
		.charlength = USART_SERIAL_CHAR_LENGTH,
		.paritytype = USART_SERIAL_PARITY,
		.stopbits = USART_SERIAL_STOP_BIT
	};
	
	static const gpio_map_t rs232_gpio = {
		{18,0},
		{19,0}
	};
	
	gpio_enable_module(rs232_gpio,sizeof(rs232_gpio) / sizeof(rs232_gpio[0]));
	
	usart_serial_init(USART_SERIAL, &usart_options);
}


int main (void)
{
	/* Insert system clock initialization code here (sysclk_init()). */

	sysclk_init();
	board_init();
	twi_init();
	RS232_init();
	
	uint8_t data_received[8];

	twi_package_t packet_read = {
		.addr         = 0x75,      // TWI slave memory address data
		.addr_length  = sizeof (uint16_t),    // TWI slave memory address data size
		.chip         = (0x68 << 1) | 1,      // TWI slave bus address with read
		.buffer       = data_received,        // transfer data destination buffer
		.length       = 8                    // transfer data size (bytes)
	};
	
	//Enter loop
	while(1)
	{
		// Perform a multi-byte read access then check the result.
		if(twi_master_read(&AVR32_TWI, &packet_read) == TWI_SUCCESS){
			int i;
			usart_if usart0 = &AVR32_USART0;
			for (i=0;i<8;i++){
				usart_serial_putchar(usart0,data_received[i]);
			}
			
		}
	}
	

	/* Insert application code here, after the board has been initialized. */
}

What I want is to print the data received from slave device onto PUTTY through uart. Now it seems not working. Any suggestions?

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

Did you not read #6 and #8?

 

The values in data_received[] are just raw bytes - if you want them to appear as stings like "0x68", then you need to convert them!

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

Also note that your code will print nothing at all when twi_master_read() returns anything other than TWI_SUCCESS

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
/*Code before has few changes to suit the needs*/
	while(1)
	{
		// Perform a multi-byte read access then check the result.
		twi_master_read(&AVR32_TWI, &packet_read);
		char buffer[10];
		int data = (int)data_received;
		sprintf(buffer,"%d",data);
		usart_write_line(&AVR32_USART0,buffer);
		delay_s(1);
		
	}

It doesn't print any outputs. Any suggestion? Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
char buffer[10];
int data = (int)data_received;
sprintf(buffer,"%d",data);

That is going to output the address of data_received[0] as a decimal number.

Greg Muth

Portland, OR, US

Xplained Boards mostly

Atmel Studio 7.0 on Windows 10