<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=4&amp;t=12566&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2015-08-07T12:46:12+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=12566&amp;mode</id>
<entry>
<author><name><![CDATA[Rzeczek]]></name></author>
<updated>2015-08-07T12:46:12+01:00</updated>
<published>2015-08-07T12:46:12+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12566&amp;p=136685#p136685</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12566&amp;p=136685#p136685"/>
<title type="html"><![CDATA[I2C przerwaniowe]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12566&amp;p=136685#p136685"><![CDATA[
Od kilku dni próbuje obsłużyć i2c na przerwaniach. W końcu mi się udało.<br />Zmieniłem bibliotekę i2c na Prycon <a href="http://www.procyonengineering.com/embedded/avr/avrlib/"  class="postlink">http://www.procyonengineering.com/embedded/avr/avrlib/</a> i wprowadziłem zmiany w funkcji <strong>i2cMasterReceive(u08 deviceAddr, u08 length)</strong>; przerzucając z jej końca odczyt bufora danych do nowej funkcji <strong>i2cMasterReceiveBuffer(u08 length, u08* data)</strong>; a także napisałem funkcję <strong>MPU6050_Test_I2C()</strong> opierając się na kilkudniowych doświadczeniach z biblioteką avr315 atmel corporation.<br /><br />main.c<br />[syntax=c]#include &lt;stdlib.h&gt;<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;math.h&gt;  //include libm<br /><br />#include &quot;mkuart/mkuart.h&quot;<br />#include &quot;i2c_prycon/i2c_prycon.h&quot;<br /><br />#define MPU6050_RA_WHO_AM_I         0x75<br />#define MPU6050_ADDR (0x68 &lt;&lt;1)<br /><br />#define LED (1&lt;&lt;PB0)<br />#define LED_ON PORTB |= LED;<br />#define LED_OFF PORTB &amp;= ~LED;<br />#define LED_TOG PORTB ^= LED;<br /><br />typedef enum<br />{<br />TWI_IDLE = 0,<br />TWI_REQUEST_REGISTER = 1,<br />TWI_REQUEST_DATA = 2,<br />TWI_READ_DATA_FROM_BUFFER = 3,<br />TWI_SEND_DATA = 4,<br />} twiStateType;<br /><br />void brak_miejsca_na_znaki_TX()<br />{<br />LED_ON;<br />}<br /><br />int MPU6050_Test_I2C()<br />{<br />static twiStateType twiState = TWI_REQUEST_REGISTER;<br /><br />if(i2cGetState()) return 0;<br /><br />if(twiState == TWI_IDLE)<br />{<br />twiState = TWI_REQUEST_REGISTER;<br />return 1;<br /><br />}<br /><br />if(twiState == TWI_REQUEST_REGISTER)<br />{<br />//! send I2C data to a device on the bus<br />unsigned char dataOUT&#91;1&#93;;<br />dataOUT&#91;0&#93; = MPU6050_RA_WHO_AM_I;<br />i2cMasterSend(MPU6050_ADDR, 1, dataOUT);<br />twiState = TWI_REQUEST_DATA;<br />}<br />else if(twiState == TWI_REQUEST_DATA)<br />{<br />//! receive I2C data from a device on the bu<br />i2cMasterReceive(MPU6050_ADDR, 1);<br />twiState = TWI_READ_DATA_FROM_BUFFER;<br />}<br />else if(twiState == TWI_READ_DATA_FROM_BUFFER)<br />{<br />static char itmp&#91;10&#93;;<br />unsigned char dataIN&#91;1&#93;;<br /><br />i2cMasterReceiveBuffer(1, dataIN);<br /><br />uart_puts(&quot;MPU6050 Address: 0x&quot;);<br />ltoa(dataIN&#91;0&#93;, itmp, 16);<br />uart_puts(itmp);<br />uart_puts(&quot;\r\n&quot;);<br />twiState = TWI_IDLE;<br />}<br />return 0;<br />}<br /><br />int main(void) {<br />USART_Init( __UBRR );<br /><br />sei();<br /><br />i2cInit();<br /><br />uart_puts(&quot;Poczatek odczytu\r\n&quot;);<br /><br />while(1)<br />{<br />if(MPU6050_Test_I2C()) _delay_ms(3000);<br />}<br />}[/syntax]<br /><br />i2c_prycon.h<br />[syntax=c]/*! \file i2c.h \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */<br />//*****************************************************************************<br />//<br />// File Name: 'i2c.h'<br />// Title: I2C interface using AVR Two-Wire Interface (TWI) hardware<br />// Author: Pascal Stang - Copyright (C) 2002-2003<br />// Created: 2002.06.25<br />// Revised: 2003.03.03<br />// Version: 0.9<br />// Target MCU: Atmel AVR series<br />// Editor Tabs: 4<br />//<br />///\ingroup driver_avr<br />/// \defgroup i2c I2C Serial Interface Function Library (i2c.c)<br />/// \code #include &quot;i2c.h&quot; \endcode<br />/// \par Overview<br />///This library provides the high-level functions needed to use the I2C<br />///serial interface supported by the hardware of several AVR processors.<br />/// The library is functional but has not been exhaustively tested yet and is<br />/// still expanding.  Thanks to the standardization of the I2C protocol and<br />///register access, the send and receive commands are everything you need to<br />/// talk to thousands of different I2C devices including: EEPROMS, Flash memory,<br />/// MP3 players, A/D and D/A converters, electronic potentiometers, etc.<br />///<br />/// \par About I2C<br />///I2C (pronounced &quot;eye-squared-see&quot;) is a two-wire bidirectional<br />///network designed for easy transfer of information between a wide variety<br />///of intelligent devices.  Many of the Atmel AVR series processors have<br />///hardware support for transmitting and receiving using an I2C-type bus.<br />///In addition to the AVRs, there are thousands of other parts made by<br />///manufacturers like Philips, Maxim, National, TI, etc that use I2C as<br />///their primary means of communication and control.  Common device types<br />///are A/D &amp; D/A converters, temp sensors, intelligent battery monitors,<br />///MP3 decoder chips, EEPROM chips, multiplexing switches, etc.<br />///<br />///I2C uses only two wires (SDA and SCL) to communicate bidirectionally<br />///between devices.  I2C is a multidrop network, meaning that you can have<br />///several devices on a single bus.  Because I2C uses a 7-bit number to<br />///identify which device it wants to talk to, you cannot have more than<br />///127 devices on a single bus.<br />///<br />///I2C ordinarily requires two 4.7K pull-up resistors to power (one each on<br />///SDA and SCL), but for small numbers of devices (maybe 1-4), it is enough<br />///to activate the internal pull-up resistors in the AVR processor.  To do<br />///this, set the port pins, which correspond to the I2C pins SDA/SCL, high.<br />///For example, on the mega163, sbi(PORTC, 0); sbi(PORTC, 1);.<br />///<br />///For complete information about I2C, see the Philips Semiconductor<br />///website.  They created I2C and have the largest family of devices that<br />///work with I2C.<br />///<br />/// \Note: Many manufacturers market I2C bus devices under a different or generic<br />///bus name like &quot;Two-Wire Interface&quot;.  This is because Philips still holds<br />///&quot;I2C&quot; as a trademark.  For example, SMBus and SMBus devices are hardware<br />///compatible and closely related to I2C.  They can be directly connected<br />///to an I2C bus along with other I2C devices are are generally accessed in<br />///the same way as I2C devices.  SMBus is often found on modern motherboards<br />///for temp sensing and other low-level control tasks.<br />//<br />// This code is distributed under the GNU Public License<br />//which can be found at http://www.gnu.org/licenses/gpl.txt<br />//<br />//*****************************************************************************<br /><br />#ifndef I2C_H<br />#define I2C_H<br /><br />#include &quot;global.h&quot;<br /><br />// include project-specific configuration<br />#include &quot;i2cconf.h&quot;<br /><br />// TWSR values (not bits)<br />// (taken from avr-libc twi.h - thank you Marek Michalkiewicz)<br />// Master<br />#define TW_START0x08<br />#define TW_REP_START0x10<br />// Master Transmitter<br />#define TW_MT_SLA_ACK0x18<br />#define TW_MT_SLA_NACK0x20<br />#define TW_MT_DATA_ACK0x28<br />#define TW_MT_DATA_NACK0x30<br />#define TW_MT_ARB_LOST0x38<br />// Master Receiver<br />#define TW_MR_ARB_LOST0x38<br />#define TW_MR_SLA_ACK0x40<br />#define TW_MR_SLA_NACK0x48<br />#define TW_MR_DATA_ACK0x50<br />#define TW_MR_DATA_NACK0x58<br />// Slave Transmitter<br />#define TW_ST_SLA_ACK0xA8<br />#define TW_ST_ARB_LOST_SLA_ACK0xB0<br />#define TW_ST_DATA_ACK0xB8<br />#define TW_ST_DATA_NACK0xC0<br />#define TW_ST_LAST_DATA0xC8<br />// Slave Receiver<br />#define TW_SR_SLA_ACK0x60<br />#define TW_SR_ARB_LOST_SLA_ACK0x68<br />#define TW_SR_GCALL_ACK0x70<br />#define TW_SR_ARB_LOST_GCALL_ACK0x78<br />#define TW_SR_DATA_ACK0x80<br />#define TW_SR_DATA_NACK0x88<br />#define TW_SR_GCALL_DATA_ACK0x90<br />#define TW_SR_GCALL_DATA_NACK0x98<br />#define TW_SR_STOP0xA0<br />// Misc<br />#define TW_NO_INFO0xF8<br />#define TW_BUS_ERROR0x00<br /><br />// defines and constants<br />#define TWCR_CMD_MASK0x0F<br />#define TWSR_STATUS_MASK0xF8<br /><br />// return values<br />#define I2C_OK0x00<br />#define I2C_ERROR_NODEV0x01<br /><br />// types<br />typedef enum<br />{<br />I2C_IDLE = 0, I2C_BUSY = 1,<br />I2C_MASTER_TX = 2, I2C_MASTER_RX = 3,<br />I2C_SLAVE_TX = 4, I2C_SLAVE_RX = 5<br />} eI2cStateType;<br /><br />// functions<br /><br />//! Initialize I2C (TWI) interface<br />void i2cInit(void);<br /><br />//! Set the I2C transaction bitrate (in KHz)<br />void i2cSetBitrate(u16 bitrateKHz);<br /><br />// I2C setup and configurations commands<br />//! Set the local (AVR processor's) I2C device address<br />void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn);<br /><br />//! Set the user function which handles receiving (incoming) data as a slave<br />void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData));<br />//! Set the user function which handles transmitting (outgoing) data as a slave<br />void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData));<br /><br />// Low-level I2C transaction commands <br />//! Send an I2C start condition in Master mode<br />void i2cSendStart(void);<br />//! Send an I2C stop condition in Master mode<br />void i2cSendStop(void);<br />//! Wait for current I2C operation to complete<br />void i2cWaitForComplete(void);<br />//! Send an (address|R/W) combination or a data byte over I2C<br />void i2cSendByte(u08 data);<br />//! Receive a data byte over I2C  <br />// ackFlag = TRUE if recevied data should be ACK'ed<br />// ackFlag = FALSE if recevied data should be NACK'ed<br />void i2cReceiveByte(u08 ackFlag);<br />//! Pick up the data that was received with i2cReceiveByte()<br />u08 i2cGetReceivedByte(void);<br />//! Get current I2c bus status from TWSR<br />u08 i2cGetStatus(void);<br /><br />// high-level I2C transaction commands<br /><br />//! send I2C data to a device on the bus<br />void i2cMasterSend(u08 deviceAddr, u08 length, u08 *data);<br />//! receive I2C data from a device on the bus<br />void i2cMasterReceive(u08 deviceAddr, u08 length);<br />//! receive I2C data from buffer<br />void i2cMasterReceiveBuffer(u08 length, u08* data);<br /><br />//! send I2C data to a device on the bus (non-interrupt based)<br />u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data);<br />//! receive I2C data from a device on the bus (non-interrupt based)<br />u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data);<br /><br />//! Get the current high-level state of the I2C interface<br />eI2cStateType i2cGetState(void);<br /><br />#endif[/syntax]<br />i2c_prycon.c<br />[syntax=c]/*! \file i2c.c \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */<br />//*****************************************************************************<br />//<br />// File Name: 'i2c.c'<br />// Title: I2C interface using AVR Two-Wire Interface (TWI) hardware<br />// Author: Pascal Stang - Copyright (C) 2002-2003<br />// Created: 2002.06.25<br />// Revised: 2003.03.02<br />// Version: 0.9<br />// Target MCU: Atmel AVR series<br />// Editor Tabs: 4<br />//<br />// This code is distributed under the GNU Public License<br />//which can be found at http://www.gnu.org/licenses/gpl.txt<br />//<br />//*****************************************************************************<br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#include &quot;i2c_prycon.h&quot;<br />#include &quot;global.h&quot;<br />// include project-specific configuration<br />#include &quot;i2cconf.h&quot;<br /><br />#ifdef I2C_DEBUG<br />#include &quot;rprintf.h&quot;// include printf function library<br />#include &quot;uart2.h&quot;<br />#endif<br /><br />// Standard I2C bit rates are:<br />// 100KHz for slow speed<br />// 400KHz for high speed<br /><br />//#define I2C_DEBUG<br /><br />// I2C state and address variables<br />static volatile eI2cStateType I2cState;<br />static u08 I2cDeviceAddrRW;<br />// send/transmit buffer (outgoing data)<br />static u08 I2cSendData&#91;I2C_SEND_DATA_BUFFER_SIZE&#93;;<br />static u08 I2cSendDataIndex;<br />static u08 I2cSendDataLength;<br />// receive buffer (incoming data)<br />static u08 I2cReceiveData&#91;I2C_RECEIVE_DATA_BUFFER_SIZE&#93;;<br />static u08 I2cReceiveDataIndex;<br />static u08 I2cReceiveDataLength;<br /><br />// function pointer to i2c receive routine<br />//! I2cSlaveReceive is called when this processor<br />// is addressed as a slave for writing<br />static void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData);<br />//! I2cSlaveTransmit is called when this processor<br />// is addressed as a slave for reading<br />static u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData);<br /><br />// functions<br />void i2cInit(void)<br />{<br />// set pull-up resistors on I2C bus pins<br />// TODO: should #ifdef these<br />sbi(PORTC, 0);// i2c SCL on ATmega163,323,16,32,etc<br />sbi(PORTC, 1);// i2c SDA on ATmega163,323,16,32,etc<br />//sbi(PORTD, 0);// i2c SCL on ATmega128,64<br />//sbi(PORTD, 1);// i2c SDA on ATmega128,64<br /><br />// clear SlaveReceive and SlaveTransmit handler to null<br />i2cSlaveReceive = 0;<br />i2cSlaveTransmit = 0;<br />// set i2c bit rate to 100KHz<br />i2cSetBitrate(100);<br />// enable TWI (two-wire interface)<br />sbi(TWCR, TWEN);<br />// set state<br />I2cState = I2C_IDLE;<br />// enable TWI interrupt and slave address ACK<br />sbi(TWCR, TWIE);<br />sbi(TWCR, TWEA);<br />//outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));<br />// enable interrupts<br />sei();<br />}<br /><br />void i2cSetBitrate(u16 bitrateKHz)<br />{<br />u08 bitrate_div;<br />// set i2c bitrate<br />// SCL freq = F_CPU/(16+2*TWBR))<br />#ifdef TWPS0<br />// for processors with additional bitrate division (mega128)<br />// SCL freq = F_CPU/(16+2*TWBR*4^TWPS)<br />// set TWPS to zero<br />cbi(TWSR, TWPS0);<br />cbi(TWSR, TWPS1);<br />#endif<br />// calculate bitrate division<br />bitrate_div = ((F_CPU/1000l)/bitrateKHz);<br />if(bitrate_div &gt;= 16)<br />bitrate_div = (bitrate_div-16)/2;<br />outb(TWBR, bitrate_div);<br />}<br /><br />void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn)<br />{<br />// set local device address (used in slave mode only)<br />outb(TWAR, ((deviceAddr&amp;0xFE) | (genCallEn?1:0)) );<br />}<br /><br />void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData))<br />{<br />i2cSlaveReceive = i2cSlaveRx_func;<br />}<br /><br />void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData))<br />{<br />i2cSlaveTransmit = i2cSlaveTx_func;<br />}<br /><br />inline void i2cSendStart(void)<br />{<br />// send start condition<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));<br />}<br /><br />inline void i2cSendStop(void)<br />{<br />// transmit stop condition<br />// leave with TWEA on for slave receiving<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));<br />}<br /><br />inline void i2cWaitForComplete(void)<br />{<br />// wait for i2c interface to complete operation<br />while( !(inb(TWCR) &amp; BV(TWINT)) );<br />}<br /><br />inline void i2cSendByte(u08 data)<br />{<br />// save data to the TWDR<br />outb(TWDR, data);<br />// begin send<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT));<br />}<br /><br />inline void i2cReceiveByte(u08 ackFlag)<br />{<br />// begin receive over i2c<br />if( ackFlag )<br />{<br />// ackFlag = TRUE: ACK the recevied data<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));<br />}<br />else<br />{<br />// ackFlag = FALSE: NACK the recevied data<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT));<br />}<br />}<br /><br />inline u08 i2cGetReceivedByte(void)<br />{<br />// retieve received data byte from i2c TWDR<br />return( inb(TWDR) );<br />}<br /><br />inline u08 i2cGetStatus(void)<br />{<br />// retieve current i2c status from i2c TWSR<br />return( inb(TWSR) );<br />}<br /><br />void i2cMasterSend(u08 deviceAddr, u08 length, u08* data)<br />{<br />u08 i;<br />// wait for interface to be ready<br />while(I2cState);<br />// set state<br />I2cState = I2C_MASTER_TX;<br />// save data<br />I2cDeviceAddrRW = (deviceAddr &amp; 0xFE);// RW cleared: write operation<br />for(i=0; i&lt;length; i++)<br />I2cSendData&#91;i&#93; = *data++;<br />I2cSendDataIndex = 0;<br />I2cSendDataLength = length;<br />// send start condition<br />i2cSendStart();<br />}<br /><br />void i2cMasterReceive(u08 deviceAddr, u08 length)<br />{<br />// wait for interface to be ready<br />while(I2cState);<br />// set state<br />I2cState = I2C_MASTER_RX;<br />// save data<br />I2cDeviceAddrRW = (deviceAddr|0x01);// RW set: read operation<br />I2cReceiveDataIndex = 0;<br />I2cReceiveDataLength = length;<br />// send start condition<br />i2cSendStart();<br />}<br /><br />void i2cMasterReceiveBuffer(u08 length, u08* data)<br />{<br />u08 i;<br />// wait for data<br />while(I2cState);<br />// return data<br />for(i=0; i&lt;length; i++)<br />*data++ = I2cReceiveData&#91;i&#93;;<br />}<br /><br />u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data)<br />{<br />u08 retval = I2C_OK;<br /><br />// disable TWI interrupt<br />cbi(TWCR, TWIE);<br /><br />// send start condition<br />i2cSendStart();<br />i2cWaitForComplete();<br /><br />// send device address with write<br />i2cSendByte( deviceAddr &amp; 0xFE );<br />i2cWaitForComplete();<br /><br />// check if device is present and live<br />if( inb(TWSR) == TW_MT_SLA_ACK)<br />{<br />// send data<br />while(length)<br />{<br />i2cSendByte( *data++ );<br />i2cWaitForComplete();<br />length--;<br />}<br />}<br />else<br />{<br />// device did not ACK it's address,<br />// data will not be transferred<br />// return error<br />retval = I2C_ERROR_NODEV;<br />}<br /><br />// transmit stop condition<br />// leave with TWEA on for slave receiving<br />i2cSendStop();<br />while( !(inb(TWCR) &amp; BV(TWSTO)) );<br /><br />// enable TWI interrupt<br />sbi(TWCR, TWIE);<br /><br />return retval;<br />}<br /><br />u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data)<br />{<br />u08 retval = I2C_OK;<br /><br />// disable TWI interrupt<br />cbi(TWCR, TWIE);<br /><br />// send start condition<br />i2cSendStart();<br />i2cWaitForComplete();<br /><br />// send device address with read<br />i2cSendByte( deviceAddr | 0x01 );<br />i2cWaitForComplete();<br /><br />// check if device is present and live<br />if( inb(TWSR) == TW_MR_SLA_ACK)<br />{<br />// accept receive data and ack it<br />while(length &gt; 1)<br />{<br />i2cReceiveByte(TRUE);<br />i2cWaitForComplete();<br />*data++ = i2cGetReceivedByte();<br />// decrement length<br />length--;<br />}<br /><br />// accept receive data and nack it (last-byte signal)<br />i2cReceiveByte(FALSE);<br />i2cWaitForComplete();<br />*data++ = i2cGetReceivedByte();<br />}<br />else<br />{<br />// device did not ACK it's address,<br />// data will not be transferred<br />// return error<br />retval = I2C_ERROR_NODEV;<br />}<br /><br />// transmit stop condition<br />// leave with TWEA on for slave receiving<br />i2cSendStop();<br /><br />// enable TWI interrupt<br />sbi(TWCR, TWIE);<br /><br />return retval;<br />}<br />/*<br />void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata)<br />{<br />// disable TWI interrupt<br />cbi(TWCR, TWIE);<br /><br />// send start condition<br />i2cSendStart();<br />i2cWaitForComplete();<br /><br />// if there's data to be sent, do it<br />if(sendlength)<br />{<br />// send device address with write<br />i2cSendByte( deviceAddr &amp; 0xFE );<br />i2cWaitForComplete();<br /><br />// send data<br />while(sendlength)<br />{<br />i2cSendByte( *senddata++ );<br />i2cWaitForComplete();<br />sendlength--;<br />}<br />}<br /><br />// if there's data to be received, do it<br />if(receivelength)<br />{<br />// send repeated start condition<br />i2cSendStart();<br />i2cWaitForComplete();<br /><br />// send device address with read<br />i2cSendByte( deviceAddr | 0x01 );<br />i2cWaitForComplete();<br /><br />// accept receive data and ack it<br />while(receivelength &gt; 1)<br />{<br />i2cReceiveByte(TRUE);<br />i2cWaitForComplete();<br />*receivedata++ = i2cGetReceivedByte();<br />// decrement length<br />receivelength--;<br />}<br /><br />// accept receive data and nack it (last-byte signal)<br />i2cReceiveByte(TRUE);<br />i2cWaitForComplete();<br />*receivedata++ = i2cGetReceivedByte();<br />}<br /><br />// transmit stop condition<br />// leave with TWEA on for slave receiving<br />i2cSendStop();<br />while( !(inb(TWCR) &amp; BV(TWSTO)) );<br /><br />// enable TWI interrupt<br />sbi(TWCR, TWIE);<br />}<br />*/<br /><br />//! I2C (TWI) interrupt service routine<br />ISR(TWI_vect)<br />{<br />// read status bits<br />u08 status = inb(TWSR) &amp; TWSR_STATUS_MASK;<br /><br />switch(status)<br />{<br />// Master General<br />case TW_START:// 0x08: Sent start condition<br />case TW_REP_START:// 0x10: Sent repeated start condition<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: M-&gt;START\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// send device address<br />i2cSendByte(I2cDeviceAddrRW);<br />break;<br /><br />// Master Transmitter &amp; Receiver status codes<br />case TW_MT_SLA_ACK:// 0x18: Slave address acknowledged<br />case TW_MT_DATA_ACK:// 0x28: Data acknowledged<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: MT-&gt;SLA_ACK or DATA_ACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />if(I2cSendDataIndex &lt; I2cSendDataLength)<br />{<br />// send data<br />i2cSendByte( I2cSendData&#91;I2cSendDataIndex++&#93; );<br />}<br />else<br />{<br />// transmit stop condition, enable SLA ACK<br />i2cSendStop();<br />// set state<br />I2cState = I2C_IDLE;<br />}<br />break;<br />case TW_MR_DATA_NACK:// 0x58: Data received, NACK reply issued<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: MR-&gt;DATA_NACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// store final received data byte<br />I2cReceiveData&#91;I2cReceiveDataIndex++&#93; = inb(TWDR);<br />// continue to transmit STOP condition<br />case TW_MR_SLA_NACK:// 0x48: Slave address not acknowledged<br />case TW_MT_SLA_NACK:// 0x20: Slave address not acknowledged<br />case TW_MT_DATA_NACK:// 0x30: Data not acknowledged<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: MTR-&gt;SLA_NACK or MT-&gt;DATA_NACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// transmit stop condition, enable SLA ACK<br />i2cSendStop();<br />// set state<br />I2cState = I2C_IDLE;<br />break;<br />case TW_MT_ARB_LOST:// 0x38: Bus arbitration lost<br />//case TW_MR_ARB_LOST:// 0x38: Bus arbitration lost<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: MT-&gt;ARB_LOST\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// release bus<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT));<br />// set state<br />I2cState = I2C_IDLE;<br />// release bus and transmit start when bus is free<br />//outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));<br />break;<br />case TW_MR_DATA_ACK:// 0x50: Data acknowledged<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: MR-&gt;DATA_ACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// store received data byte<br />I2cReceiveData&#91;I2cReceiveDataIndex++&#93; = inb(TWDR);<br />// fall-through to see if more bytes will be received<br />case TW_MR_SLA_ACK:// 0x40: Slave address acknowledged<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: MR-&gt;SLA_ACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />if(I2cReceiveDataIndex &lt; (I2cReceiveDataLength-1))<br />// data byte will be received, reply with ACK (more bytes in transfer)<br />i2cReceiveByte(TRUE);<br />else<br />// data byte will be received, reply with NACK (final byte in transfer)<br />i2cReceiveByte(FALSE);<br />break;<br /><br />// Slave Receiver status codes<br />case TW_SR_SLA_ACK:// 0x60: own SLA+W has been received, ACK has been returned<br />case TW_SR_ARB_LOST_SLA_ACK:// 0x68: own SLA+W has been received, ACK has been returned<br />case TW_SR_GCALL_ACK:// 0x70:     GCA+W has been received, ACK has been returned<br />case TW_SR_ARB_LOST_GCALL_ACK:// 0x78:     GCA+W has been received, ACK has been returned<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: SR-&gt;SLA_ACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// we are being addressed as slave for writing (data will be received from master)<br />// set state<br />I2cState = I2C_SLAVE_RX;<br />// prepare buffer<br />I2cReceiveDataIndex = 0;<br />// receive data byte and return ACK<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));<br />break;<br />case TW_SR_DATA_ACK:// 0x80: data byte has been received, ACK has been returned<br />case TW_SR_GCALL_DATA_ACK:// 0x90: data byte has been received, ACK has been returned<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: SR-&gt;DATA_ACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// get previously received data byte<br />I2cReceiveData&#91;I2cReceiveDataIndex++&#93; = inb(TWDR);<br />// check receive buffer status<br />if(I2cReceiveDataIndex &lt; I2C_RECEIVE_DATA_BUFFER_SIZE)<br />{<br />// receive data byte and return ACK<br />i2cReceiveByte(TRUE);<br />//outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));<br />}<br />else<br />{<br />// receive data byte and return NACK<br />i2cReceiveByte(FALSE);<br />//outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT));<br />}<br />break;<br />case TW_SR_DATA_NACK:// 0x88: data byte has been received, NACK has been returned<br />case TW_SR_GCALL_DATA_NACK:// 0x98: data byte has been received, NACK has been returned<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: SR-&gt;DATA_NACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// receive data byte and return NACK<br />i2cReceiveByte(FALSE);<br />//outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT));<br />break;<br />case TW_SR_STOP:// 0xA0: STOP or REPEATED START has been received while addressed as slave<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: SR-&gt;SR_STOP\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// switch to SR mode with SLA ACK<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));<br />// i2c receive is complete, call i2cSlaveReceive<br />if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData);<br />// set state<br />I2cState = I2C_IDLE;<br />break;<br /><br />// Slave Transmitter<br />case TW_ST_SLA_ACK:// 0xA8: own SLA+R has been received, ACK has been returned<br />case TW_ST_ARB_LOST_SLA_ACK:// 0xB0:     GCA+R has been received, ACK has been returned<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: ST-&gt;SLA_ACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// we are being addressed as slave for reading (data must be transmitted back to master)<br />// set state<br />I2cState = I2C_SLAVE_TX;<br />// request data from application<br />if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData);<br />// reset data index<br />I2cSendDataIndex = 0;<br />// fall-through to transmit first data byte<br />case TW_ST_DATA_ACK:// 0xB8: data byte has been transmitted, ACK has been received<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: ST-&gt;DATA_ACK\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// transmit data byte<br />outb(TWDR, I2cSendData&#91;I2cSendDataIndex++&#93;);<br />if(I2cSendDataIndex &lt; I2cSendDataLength)<br />// expect ACK to data byte<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));<br />else<br />// expect NACK to data byte<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT));<br />break;<br />case TW_ST_DATA_NACK:// 0xC0: data byte has been transmitted, NACK has been received<br />case TW_ST_LAST_DATA:// 0xC8:<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: ST-&gt;DATA_NACK or LAST_DATA\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// all done<br />// switch to open slave<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));<br />// set state<br />I2cState = I2C_IDLE;<br />break;<br /><br />// Misc<br />case TW_NO_INFO:// 0xF8: No relevant state information<br />// do nothing<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: NO_INFO\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />break;<br />case TW_BUS_ERROR:// 0x00: Bus error due to illegal start or stop condition<br />#ifdef I2C_DEBUG<br />rprintfInit(uart1AddToTxBuffer);<br />rprintf(&quot;I2C: BUS_ERROR\r\n&quot;);<br />rprintfInit(uart1SendByte);<br />#endif<br />// reset internal hardware and release bus<br />outb(TWCR, (inb(TWCR)&amp;TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));<br />// set state<br />I2cState = I2C_IDLE;<br />break;<br />}<br />}<br /><br />eI2cStateType i2cGetState(void)<br />{<br />return I2cState;<br />}[/syntax]<br />Z biblioteki do projektu należy także dodać pliki prycona<br />avrlibdefs.h<br />avrlibtypes.h<br />global.h<br />i2cconf.h<br />a także MKUART z bluebooka.<br />(oryginalna obsługa i2c prycona nazywa się i2c.c oraz i2c.h w jego bibliotece)<br /><br />Tutaj otrzymany wynik <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><a href="https://obrazkiforum.atnel.pl/7234/ff2a14f6a4b442f47f482ba5ef82efd2.jpg"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/7234/ff2a14f6a4b442f47f482ba5ef82efd2.jpg" alt="Obrazek" /></a><br /><br />Aby obsłużyć urządzenie należy napisać sobie funkcję podobną do <strong>MPU6050_Test_I2C()</strong>, która podzieli zadania na zapis (tutaj wysłanie do urządzenia adresu komórki do odczytu), odczyt z urządzenia (odczyt n bitów do bufora) i odczyt z bufora I2C do własnego bufora i wyświetlenie go. Jeżeli i2c jest aktualnie zajęte <strong>i2cGetState()</strong> to wracamy do pętli głównej i wykonujemy inne zadania.<br /><br />Przez odpowiednią zmianę <strong>twiState</strong> sekwencyjnie dokonujemy zapisu, odczytu i odczytu z bufora. Następnie ustawiam twiState na TWI_IDLE aby ponownie zmienić stan na TWI_REQUEST_REGISTER i zwrócić funkcją wartość 1, która spowoduje 3 sekundowe opóźnienie w pętli głównej przed kolejnym odczytem.<br /><br />Jak obsłużę całkowicie żyroskop to zabiorę się za przerobienie biblioteki na atnelowską modę.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=7234">Rzeczek</a> — 7 sie 2015, o 12:46</p><hr />
]]></content>
</entry>
</feed>