Additions from 03/12/2021: Refactoring to multiple files.
This commit is contained in:
parent
f2c5b40d7d
commit
900988633e
11 changed files with 686 additions and 142 deletions
220
i2c_test_attiny85/USI_TWI_Slave.c
Executable file
220
i2c_test_attiny85/USI_TWI_Slave.c
Executable file
|
@ -0,0 +1,220 @@
|
||||||
|
// This file has been prepared for Doxygen automatic documentation generation.
|
||||||
|
/*! \file ********************************************************************
|
||||||
|
*
|
||||||
|
* Atmel Corporation
|
||||||
|
*
|
||||||
|
* File : USI_TWI_Slave.c
|
||||||
|
* Compiler : IAR EWAAVR 4.11A
|
||||||
|
* Revision : $Revision: 1.14 $
|
||||||
|
* Date : $Date: Friday, December 09, 2005 17:25:38 UTC $
|
||||||
|
* Updated by : $Author: jtyssoe $
|
||||||
|
*
|
||||||
|
* Support mail : avr@atmel.com
|
||||||
|
*
|
||||||
|
* Supported devices : All device with USI module can be used.
|
||||||
|
*
|
||||||
|
* AppNote : AVR312 - Using the USI module as a I2C slave
|
||||||
|
*
|
||||||
|
* Description : Functions for USI_TWI_receiver and USI_TWI_transmitter.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include "USI_TWI_Slave.h"
|
||||||
|
|
||||||
|
/*! Static Variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned char TWI_slaveAddress;
|
||||||
|
static volatile unsigned char USI_TWI_Overflow_State;
|
||||||
|
|
||||||
|
|
||||||
|
/*! Local variables
|
||||||
|
*/
|
||||||
|
static uint8_t TWI_RxBuf[TWI_RX_BUFFER_SIZE];
|
||||||
|
static volatile uint8_t TWI_RxHead;
|
||||||
|
static volatile uint8_t TWI_RxTail;
|
||||||
|
|
||||||
|
static uint8_t TWI_TxBuf[TWI_TX_BUFFER_SIZE];
|
||||||
|
static volatile uint8_t TWI_TxHead;
|
||||||
|
static volatile uint8_t TWI_TxTail;
|
||||||
|
|
||||||
|
/*! \brief Flushes the TWI buffers
|
||||||
|
*/
|
||||||
|
void Flush_TWI_Buffers(void)
|
||||||
|
{
|
||||||
|
TWI_RxTail = 0;
|
||||||
|
TWI_RxHead = 0;
|
||||||
|
TWI_TxTail = 0;
|
||||||
|
TWI_TxHead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//********** USI_TWI functions **********//
|
||||||
|
|
||||||
|
/*! \brief
|
||||||
|
* Initialise USI for TWI Slave mode.
|
||||||
|
*/
|
||||||
|
void USI_TWI_Slave_Initialise( unsigned char TWI_ownAddress )
|
||||||
|
{
|
||||||
|
Flush_TWI_Buffers();
|
||||||
|
|
||||||
|
TWI_slaveAddress = TWI_ownAddress;
|
||||||
|
|
||||||
|
PORT_USI |= (1<<PORT_USI_SCL); // Set SCL high
|
||||||
|
PORT_USI |= (1<<PORT_USI_SDA); // Set SDA high
|
||||||
|
DDR_USI &= ~(1<<PORT_USI_SCL); //modified // Set SCL as input
|
||||||
|
DDR_USI &= ~(1<<PORT_USI_SDA); // Set SDA as input
|
||||||
|
USICR = (1<<USISIE)|(0<<USIOIE)| // Enable Start Condition Interrupt. Disable Overflow Interrupt.
|
||||||
|
(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. No USI Counter overflow prior
|
||||||
|
// to first Start Condition (potentail failure)
|
||||||
|
(1<<USICS1)|(0<<USICS0)|(0<<USICLK)| // Shift Register Clock Source = External, positive edge
|
||||||
|
(0<<USITC);
|
||||||
|
USISR = 0xF0; // Clear all flags and reset overflow counter
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Puts data in the transmission buffer, Waits if buffer is full.
|
||||||
|
*/
|
||||||
|
void USI_TWI_Transmit_Byte( unsigned char data )
|
||||||
|
{
|
||||||
|
unsigned char tmphead;
|
||||||
|
|
||||||
|
tmphead = ( TWI_TxHead + 1 ) & TWI_TX_BUFFER_MASK; // Calculate buffer index.
|
||||||
|
while ( tmphead == TWI_TxTail ); // Wait for free space in buffer.
|
||||||
|
TWI_TxBuf[tmphead] = data; // Store data in buffer.
|
||||||
|
TWI_TxHead = tmphead; // Store new index.
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Returns a byte from the receive buffer. Waits if buffer is empty.
|
||||||
|
*/
|
||||||
|
unsigned char USI_TWI_Receive_Byte( void )
|
||||||
|
{
|
||||||
|
unsigned char tmptail;
|
||||||
|
unsigned char tmpRxTail; // Temporary variable to store volatile
|
||||||
|
tmpRxTail = TWI_RxTail; // Not necessary, but prevents warnings
|
||||||
|
while ( TWI_RxHead == tmpRxTail );
|
||||||
|
tmptail = ( TWI_RxTail + 1 ) & TWI_RX_BUFFER_MASK; // Calculate buffer index
|
||||||
|
TWI_RxTail = tmptail; // Store new index
|
||||||
|
return TWI_RxBuf[tmptail]; // Return data from the buffer.
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Check if there is data in the receive buffer.
|
||||||
|
*/
|
||||||
|
unsigned char USI_TWI_Data_In_Receive_Buffer( void )
|
||||||
|
{
|
||||||
|
unsigned char tmpRxTail; // Temporary variable to store volatile
|
||||||
|
tmpRxTail = TWI_RxTail; // Not necessary, but prevents warnings
|
||||||
|
return ( TWI_RxHead != tmpRxTail ); // Return 0 (FALSE) if the receive buffer is empty.
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Usi start condition ISR
|
||||||
|
* Detects the USI_TWI Start Condition and intialises the USI
|
||||||
|
* for reception of the "TWI Address" packet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
ISR(USI_START_VECTOR)
|
||||||
|
{
|
||||||
|
unsigned char tmpUSISR; // Temporary variable to store volatile
|
||||||
|
tmpUSISR = USISR; // Not necessary, but prevents warnings
|
||||||
|
// Set default starting conditions for new TWI package
|
||||||
|
USI_TWI_Overflow_State = USI_SLAVE_CHECK_ADDRESS;
|
||||||
|
DDR_USI &= ~(1<<PORT_USI_SDA); // Set SDA as input
|
||||||
|
while ( (PIN_USI & (1<<PORT_USI_SCL)) & !(tmpUSISR & (1<<USIPF)) ); // Wait for SCL to go low to ensure the "Start Condition" has completed.
|
||||||
|
// If a Stop condition arises then leave the interrupt to prevent waiting forever.
|
||||||
|
USICR = (1<<USISIE)|(1<<USIOIE)| // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
|
||||||
|
(1<<USIWM1)|(1<<USIWM0)| // Set USI in Two-wire mode.
|
||||||
|
(1<<USICS1)|(0<<USICS0)|(0<<USICLK)| // Shift Register Clock Source = External, positive edge
|
||||||
|
(0<<USITC);
|
||||||
|
USISR = (1<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags
|
||||||
|
(0x0<<USICNT0); // Set USI to sample 8 bits i.e. count 16 external pin toggles.
|
||||||
|
// RGB_DDR |= RED_LED_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief USI counter overflow ISR
|
||||||
|
* Handels all the comunication. Is disabled only when waiting
|
||||||
|
* for new Start Condition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ISR(USI_OVERFLOW_VECTOR)
|
||||||
|
{
|
||||||
|
unsigned char tmpTxTail; // Temporary variables to store volatiles
|
||||||
|
unsigned char tmpUSIDR;
|
||||||
|
|
||||||
|
|
||||||
|
switch (USI_TWI_Overflow_State)
|
||||||
|
{
|
||||||
|
// ---------- Address mode ----------
|
||||||
|
// Check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK, else reset USI.
|
||||||
|
case USI_SLAVE_CHECK_ADDRESS:
|
||||||
|
if ((USIDR == 0) || (( USIDR>>1 ) == TWI_slaveAddress))
|
||||||
|
{
|
||||||
|
if ( USIDR & 0x01 )
|
||||||
|
USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA;
|
||||||
|
else
|
||||||
|
USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA;
|
||||||
|
SET_USI_TO_SEND_ACK();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SET_USI_TO_TWI_START_CONDITION_MODE();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ----- Master write data mode ------
|
||||||
|
// Check reply and goto USI_SLAVE_SEND_DATA if OK, else reset USI.
|
||||||
|
case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
|
||||||
|
if ( USIDR ) // If NACK, the master does not want more data.
|
||||||
|
{
|
||||||
|
SET_USI_TO_TWI_START_CONDITION_MODE();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// From here we just drop straight into USI_SLAVE_SEND_DATA if the master sent an ACK
|
||||||
|
|
||||||
|
// Copy data from buffer to USIDR and set USI to shift byte. Next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA
|
||||||
|
case USI_SLAVE_SEND_DATA:
|
||||||
|
|
||||||
|
// Get data from Buffer
|
||||||
|
tmpTxTail = TWI_TxTail; // Not necessary, but prevents warnings
|
||||||
|
if ( TWI_TxHead != tmpTxTail )
|
||||||
|
{
|
||||||
|
TWI_TxTail = ( TWI_TxTail + 1 ) & TWI_TX_BUFFER_MASK;
|
||||||
|
USIDR = TWI_TxBuf[TWI_TxTail];
|
||||||
|
}
|
||||||
|
else // If the buffer is empty then:
|
||||||
|
{
|
||||||
|
SET_USI_TO_TWI_START_CONDITION_MODE();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
USI_TWI_Overflow_State = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA;
|
||||||
|
SET_USI_TO_SEND_DATA();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Set USI to sample reply from master. Next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA
|
||||||
|
case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA:
|
||||||
|
USI_TWI_Overflow_State = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA;
|
||||||
|
SET_USI_TO_READ_ACK();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ----- Master read data mode ------
|
||||||
|
// Set USI to sample data from master. Next USI_SLAVE_GET_DATA_AND_SEND_ACK.
|
||||||
|
case USI_SLAVE_REQUEST_DATA:
|
||||||
|
USI_TWI_Overflow_State = USI_SLAVE_GET_DATA_AND_SEND_ACK;
|
||||||
|
SET_USI_TO_READ_DATA();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Copy data from USIDR and send ACK. Next USI_SLAVE_REQUEST_DATA
|
||||||
|
case USI_SLAVE_GET_DATA_AND_SEND_ACK:
|
||||||
|
// Put data into Buffer
|
||||||
|
tmpUSIDR = USIDR; // Not necessary, but prevents warnings
|
||||||
|
TWI_RxHead = ( TWI_RxHead + 1 ) & TWI_RX_BUFFER_MASK;
|
||||||
|
TWI_RxBuf[TWI_RxHead] = tmpUSIDR;
|
||||||
|
|
||||||
|
USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA;
|
||||||
|
SET_USI_TO_SEND_ACK();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
176
i2c_test_attiny85/USI_TWI_Slave.h
Executable file
176
i2c_test_attiny85/USI_TWI_Slave.h
Executable file
|
@ -0,0 +1,176 @@
|
||||||
|
// This file has been prepared for Doxygen automatic documentation generation.
|
||||||
|
/*! \file ********************************************************************
|
||||||
|
*
|
||||||
|
* Atmel Corporation
|
||||||
|
*
|
||||||
|
* File : USI_TWI_Slave.h
|
||||||
|
* Compiler : IAR EWAAVR 4.11A
|
||||||
|
* Revision : $Revision: 1.14 $
|
||||||
|
* Date : $Date: Friday, December 09, 2005 17:25:38 UTC $
|
||||||
|
* Updated by : $Author: jtyssoe $
|
||||||
|
*
|
||||||
|
* Support mail : avr@atmel.com
|
||||||
|
*
|
||||||
|
* Supported devices : All device with USI module can be used.
|
||||||
|
* The example is written for the ATmega169, ATtiny26 & ATtiny2313
|
||||||
|
*
|
||||||
|
* AppNote : AVR312 - Using the USI module as a TWI slave
|
||||||
|
*
|
||||||
|
* Description : Header file for USI_TWI driver
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
//! Prototypes
|
||||||
|
void USI_TWI_Slave_Initialise( unsigned char );
|
||||||
|
void USI_TWI_Transmit_Byte( unsigned char );
|
||||||
|
unsigned char USI_TWI_Receive_Byte( void );
|
||||||
|
unsigned char USI_TWI_Data_In_Receive_Buffer( void );
|
||||||
|
void Timer_Init(void);
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
///////////////// Driver Buffer Definitions //////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes
|
||||||
|
|
||||||
|
#define TWI_RX_BUFFER_SIZE (8)
|
||||||
|
#define TWI_RX_BUFFER_MASK ( TWI_RX_BUFFER_SIZE - 1 )
|
||||||
|
|
||||||
|
#if ( TWI_RX_BUFFER_SIZE & TWI_RX_BUFFER_MASK )
|
||||||
|
#error TWI RX buffer size is not a power of 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes
|
||||||
|
|
||||||
|
#define TWI_TX_BUFFER_SIZE (8)
|
||||||
|
#define TWI_TX_BUFFER_MASK ( TWI_TX_BUFFER_SIZE - 1 )
|
||||||
|
|
||||||
|
#if ( TWI_TX_BUFFER_SIZE & TWI_TX_BUFFER_MASK )
|
||||||
|
#error TWI TX buffer size is not a power of 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define USI_SLAVE_CHECK_ADDRESS (0x00)
|
||||||
|
#define USI_SLAVE_SEND_DATA (0x01)
|
||||||
|
#define USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA (0x02)
|
||||||
|
#define USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA (0x03)
|
||||||
|
#define USI_SLAVE_REQUEST_DATA (0x04)
|
||||||
|
#define USI_SLAVE_GET_DATA_AND_SEND_ACK (0x05)
|
||||||
|
|
||||||
|
|
||||||
|
//! Device dependent defines
|
||||||
|
/*#if defined(__AT90tiny26__) | defined(__ATtiny26__)
|
||||||
|
#define DDR_USI DDRB
|
||||||
|
#define PORT_USI PORTB
|
||||||
|
#define PIN_USI PINB
|
||||||
|
#define PORT_USI_SDA PORTB0
|
||||||
|
#define PORT_USI_SCL PORTB2
|
||||||
|
#define PIN_USI_SDA PINB0
|
||||||
|
#define PIN_USI_SCL PINB2
|
||||||
|
#define USI_START_COND_INT USISIF
|
||||||
|
#define USI_START_VECTOR USI_STRT_vect
|
||||||
|
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
/*#if defined(__AT90Tiny2313__) | defined(__ATtiny2313__)
|
||||||
|
#define DDR_USI DDRB
|
||||||
|
#define PORT_USI PORTB
|
||||||
|
#define PIN_USI PINB
|
||||||
|
#define PORT_USI_SDA PORTB5
|
||||||
|
#define PORT_USI_SCL PORTB7
|
||||||
|
#define PIN_USI_SDA PINB5
|
||||||
|
#define PIN_USI_SCL PINB7
|
||||||
|
#define USI_START_COND_INT USISIF
|
||||||
|
#define USI_START_VECTOR USI_START_vect
|
||||||
|
#define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
/*#if defined(__ATtiny25__) | defined(__ATtiny45__) | defined(__ATtiny85__)*/
|
||||||
|
#define DDR_USI DDRB
|
||||||
|
#define PORT_USI PORTB
|
||||||
|
#define PIN_USI PINB
|
||||||
|
#define PORT_USI_SDA PB0
|
||||||
|
#define PORT_USI_SCL PB2
|
||||||
|
#define PIN_USI_SDA PINB0
|
||||||
|
#define PIN_USI_SCL PINB2
|
||||||
|
#define USI_START_COND_INT USISIF //soit USISIF ou USISIE
|
||||||
|
#define USI_START_VECTOR USI_START_vect
|
||||||
|
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||||
|
/*#endif*/
|
||||||
|
|
||||||
|
/*#if defined(__AT90Mega165__) | defined(__ATmega165__) | \
|
||||||
|
defined(__ATmega325__) | defined(__ATmega3250__) | \
|
||||||
|
defined(__ATmega645__) | defined(__ATmega6450__) | \
|
||||||
|
defined(__ATmega329__) | defined(__ATmega3290__) | \
|
||||||
|
defined(__ATmega649__) | defined(__ATmega6490__)
|
||||||
|
#define DDR_USI DDRE
|
||||||
|
#define PORT_USI PORTE
|
||||||
|
#define PIN_USI PINE
|
||||||
|
#define PORT_USI_SDA PORTE5
|
||||||
|
#define PORT_USI_SCL PORTE4
|
||||||
|
#define PIN_USI_SDA PINE5
|
||||||
|
#define PIN_USI_SCL PINE4
|
||||||
|
#define USI_START_COND_INT USISIF
|
||||||
|
#define USI_START_VECTOR USI_START_vect
|
||||||
|
#define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
/*#if defined(__AT90Mega169__) | defined(__ATmega169__)
|
||||||
|
#define DDR_USI DDRE
|
||||||
|
#define PORT_USI PORTE
|
||||||
|
#define PIN_USI PINE
|
||||||
|
#define PORT_USI_SDA PORTE5
|
||||||
|
#define PORT_USI_SCL PORTE4
|
||||||
|
#define PIN_USI_SDA PINE5
|
||||||
|
#define PIN_USI_SCL PINE4
|
||||||
|
#define USI_START_COND_INT USISIF
|
||||||
|
#define USI_START_VECTOR USI_STRT_vect
|
||||||
|
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
//! Functions implemented as macros
|
||||||
|
#define SET_USI_TO_SEND_ACK() \
|
||||||
|
{ \
|
||||||
|
USIDR = 0; /* Prepare ACK */ \
|
||||||
|
DDR_USI |= (1<<PORT_USI_SDA); /* Set SDA as output */ \
|
||||||
|
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \
|
||||||
|
(0x0E<<USICNT0); /* set USI counter to shift 1 bit. */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_USI_TO_READ_ACK() \
|
||||||
|
{ \
|
||||||
|
DDR_USI &= ~(1<<PORT_USI_SDA); /* Set SDA as intput */ \
|
||||||
|
USIDR = 0; /* Prepare ACK */ \
|
||||||
|
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \
|
||||||
|
(0x0E<<USICNT0); /* set USI counter to shift 1 bit. */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_USI_TO_TWI_START_CONDITION_MODE() \
|
||||||
|
{ \
|
||||||
|
USICR = (1<<USISIE)|(0<<USIOIE)| /* Enable Start Condition Interrupt. Disable Overflow Interrupt.*/ \
|
||||||
|
(1<<USIWM1)|(0<<USIWM0)| /* Set USI in Two-wire mode. No USI Counter overflow hold. */ \
|
||||||
|
(1<<USICS1)|(0<<USICS0)|(0<<USICLK)| /* Shift Register Clock Source = External, positive edge */ \
|
||||||
|
(0<<USITC); \
|
||||||
|
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \
|
||||||
|
(0x0<<USICNT0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_USI_TO_SEND_DATA() \
|
||||||
|
{ \
|
||||||
|
DDR_USI |= (1<<PORT_USI_SDA); /* Set SDA as output */ \
|
||||||
|
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \
|
||||||
|
(0x0<<USICNT0); /* set USI to shift out 8 bits */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_USI_TO_READ_DATA() \
|
||||||
|
{ \
|
||||||
|
DDR_USI &= ~(1<<PORT_USI_SDA); /* Set SDA as input */ \
|
||||||
|
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \
|
||||||
|
(0x0<<USICNT0); /* set USI to shift out 8 bits */ \
|
||||||
|
}
|
|
@ -135,9 +135,33 @@
|
||||||
</ToolchainSettings>
|
</ToolchainSettings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="led_gen.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="led_gen.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="led_receptor.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="led_receptor.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="led_test.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="led_test.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="main.c">
|
<Compile Include="main.c">
|
||||||
<SubType>compile</SubType>
|
<SubType>compile</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="USI_TWI_Slave.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="USI_TWI_Slave.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
|
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
|
||||||
</Project>
|
</Project>
|
34
i2c_test_attiny85/led_gen.c
Executable file
34
i2c_test_attiny85/led_gen.c
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* led_gen.c
|
||||||
|
*
|
||||||
|
* Created: 03/12/2021 14:25:05
|
||||||
|
* Author: 40008304
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "led_gen.h"
|
||||||
|
|
||||||
|
void led1_init(void)
|
||||||
|
{
|
||||||
|
DDRB |= (1<<PB1);
|
||||||
|
TCCR1|=(1<<CTC1)|(1<<COM1A0); //on active le mode CTC en comparant OCR1C, COM1A1 ? 1 pour desactiver /OC1A
|
||||||
|
OCR1C=16; //d'apres retroingenieurie OCR1C=16
|
||||||
|
TCCR1|=(1<<CS10); //on active la clock avec CS10 = 1, pas de prediv (plus precis pour haute freq)
|
||||||
|
}
|
||||||
|
|
||||||
|
void led2_init(void)
|
||||||
|
{
|
||||||
|
DDRB |= (1<<PB4);
|
||||||
|
GTCCR|=(1<<COM1B0); //COM1B0 a 1 pour desactiver /OC1A
|
||||||
|
OCR1B=16; //d'apres retroingenieurie OCR1B=16
|
||||||
|
TCCR1|=(1<<CS10); //on active la clock avec CS10 = 1, pas de prediv (plus precis pour haute freq)
|
||||||
|
}
|
||||||
|
|
||||||
|
void led1_stop(void)
|
||||||
|
{
|
||||||
|
TCCR1 &= ~(1<<COM1A0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void led2_stop(void)
|
||||||
|
{
|
||||||
|
GTCCR &= ~(1<<COM1B0);
|
||||||
|
}
|
19
i2c_test_attiny85/led_gen.h
Executable file
19
i2c_test_attiny85/led_gen.h
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* led_gen.h
|
||||||
|
*
|
||||||
|
* Created: 03/12/2021 14:25:45
|
||||||
|
* Author: 40008304
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LED_GEN_H_
|
||||||
|
#define LED_GEN_H_
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
void led1_init(void);
|
||||||
|
void led2_init(void);
|
||||||
|
void led1_stop(void);
|
||||||
|
void led2_stop(void);
|
||||||
|
|
||||||
|
#endif /* LED_GEN_H_ */
|
81
i2c_test_attiny85/led_receptor.c
Executable file
81
i2c_test_attiny85/led_receptor.c
Executable file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* led_receptor.c
|
||||||
|
*
|
||||||
|
* Created: 03/12/2021 14:29:43
|
||||||
|
* Author: 40008304
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "led_receptor.h"
|
||||||
|
|
||||||
|
void ADC_init(void)
|
||||||
|
{
|
||||||
|
DDRB &=~(1<<PB3); //Pin B3 en entree
|
||||||
|
ADMUX |= (1<<MUX1)|(1<<MUX0)|(1<<ADLAR); //MUX = 0010 donc sortie PB4 et ADLAR a 1 pour avoir les bits de poids fort en premier
|
||||||
|
ADCSRA |= (1<<ADEN)|(1<<ADPS2); //On divise 1Mhz par 16 (62.5 KHz) < 200 KHz, ADEN conversion autorisee
|
||||||
|
};
|
||||||
|
|
||||||
|
char ADC_read_value(void)
|
||||||
|
{
|
||||||
|
ADCSRA|=(1<<ADSC);
|
||||||
|
while(ADCSRA & (1<<ADSC));
|
||||||
|
return ADCH;
|
||||||
|
};
|
||||||
|
|
||||||
|
float ADC_averaging(void)
|
||||||
|
{
|
||||||
|
float valeur_finale=0;
|
||||||
|
char precision;
|
||||||
|
for(precision = 75; precision > 0 ; precision --)
|
||||||
|
{
|
||||||
|
valeur_finale = valeur_finale +(((ADC_read_value() * 0.01961) - valeur_finale) / 15);
|
||||||
|
}
|
||||||
|
return valeur_finale;
|
||||||
|
};
|
||||||
|
|
||||||
|
float measureLed1(void)
|
||||||
|
{
|
||||||
|
float adcLed;
|
||||||
|
led2_stop();
|
||||||
|
led1_init();
|
||||||
|
_delay_ms(TIMING);
|
||||||
|
adcLed=ADC_averaging();
|
||||||
|
_delay_ms(TIMING);
|
||||||
|
return adcLed;
|
||||||
|
};
|
||||||
|
|
||||||
|
float measureLed2(void)
|
||||||
|
{
|
||||||
|
float adcLed;
|
||||||
|
led1_stop();
|
||||||
|
led2_init();
|
||||||
|
_delay_ms(TIMING);
|
||||||
|
adcLed=ADC_averaging();
|
||||||
|
_delay_ms(TIMING);
|
||||||
|
return adcLed;
|
||||||
|
};
|
||||||
|
|
||||||
|
char compareLed(void)
|
||||||
|
{
|
||||||
|
float adcLed1 = measureLed1();
|
||||||
|
float adcLed2 = measureLed2();
|
||||||
|
float adcCompare = adcLed1 - adcLed2;
|
||||||
|
if (adcCompare < -VOLTMIN) // adcLed2 > adcLed1
|
||||||
|
{
|
||||||
|
return LEFT;
|
||||||
|
}
|
||||||
|
else if (adcCompare > VOLTMIN)
|
||||||
|
{
|
||||||
|
return RIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((adcLed1 > VOLTMIN) && (adcLed2 > VOLTMIN))
|
||||||
|
{
|
||||||
|
return FRONT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NOTHING;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
31
i2c_test_attiny85/led_receptor.h
Executable file
31
i2c_test_attiny85/led_receptor.h
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* led_receptor.h
|
||||||
|
*
|
||||||
|
* Created: 03/12/2021 14:29:30
|
||||||
|
* Author: 40008304
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LED_RECEPTOR_H_
|
||||||
|
#define LED_RECEPTOR_H_
|
||||||
|
|
||||||
|
#include "led_gen.h"
|
||||||
|
#define F_CPU 1000000
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#define FRONT 0x51
|
||||||
|
#define RIGHT 0x52
|
||||||
|
#define LEFT 0x53
|
||||||
|
#define NOTHING 0x54
|
||||||
|
#define ERROR 0xF0
|
||||||
|
#define VOLTMIN 1
|
||||||
|
#define TIMING 250
|
||||||
|
|
||||||
|
void ADC_init(void);
|
||||||
|
char ADC_read_value(void);
|
||||||
|
float ADC_averaging(void);
|
||||||
|
float measureLed1(void);
|
||||||
|
float measureLed2(void);
|
||||||
|
char compareLed(void);
|
||||||
|
|
||||||
|
#endif /* LED_RECEPTOR_H_ */
|
34
i2c_test_attiny85/led_test.c
Executable file
34
i2c_test_attiny85/led_test.c
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* led_test.c
|
||||||
|
*
|
||||||
|
* Created: 03/12/2021 15:28:35
|
||||||
|
* Author: 40008304
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "led_test.h"
|
||||||
|
|
||||||
|
void testLed(void)
|
||||||
|
{
|
||||||
|
char sendingData = compareLed();
|
||||||
|
switch(sendingData)
|
||||||
|
{
|
||||||
|
case NOTHING:
|
||||||
|
PORTB |= (1<<PINB0); //les deux sont eteintes
|
||||||
|
PORTB |= (1<<PINB2);
|
||||||
|
break;
|
||||||
|
case FRONT:
|
||||||
|
PORTB &= ~(1<<PINB0); //les deux sont allumees
|
||||||
|
PORTB &= ~(1<<PINB2);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
PORTB &= ~(1<<PINB0); //a droite allumee (led0)
|
||||||
|
PORTB |= (1<<PINB2);
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
PORTB |= (1<<PINB0); //a gauche allumee (led1)
|
||||||
|
PORTB &= ~(1<<PINB2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
16
i2c_test_attiny85/led_test.h
Executable file
16
i2c_test_attiny85/led_test.h
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* led_test.h
|
||||||
|
*
|
||||||
|
* Created: 03/12/2021 15:28:48
|
||||||
|
* Author: 40008304
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LED_TEST_H_
|
||||||
|
#define LED_TEST_H_
|
||||||
|
|
||||||
|
#include "led_receptor.h"
|
||||||
|
|
||||||
|
void testLed(void);
|
||||||
|
|
||||||
|
#endif /* LED_TEST_H_ */
|
|
@ -6,158 +6,60 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#define F_CPU 1000000
|
|
||||||
#include <util/delay.h>
|
|
||||||
|
|
||||||
#define FRONT 0x51
|
#include "led_gen.h"
|
||||||
#define RIGHT 0x52
|
#include "led_receptor.h"
|
||||||
#define LEFT 0x53
|
#include "led_test.h"
|
||||||
#define NOTHING 0x54
|
#include "USI_TWI_Slave.h"
|
||||||
#define ERROR 0xF0
|
|
||||||
#define VOLTMIN 1
|
|
||||||
|
|
||||||
void led1_init(void);
|
#define MSTR_TEST_WR 0x31
|
||||||
void led2_init(void);
|
#define MSTR_TEST_RE 0x32
|
||||||
void led1_stop(void);
|
|
||||||
void led2_stop(void);
|
#define SLAVE_ADRESS 0x01
|
||||||
void ADC_init(void);
|
#define NOM_CONSTRUC 0x08
|
||||||
char ADC_read_value(void);
|
#define NOM_CAPTEUR 0x10
|
||||||
float ADC_averaging(void);
|
#define VALEUR_DEMAN 0x49
|
||||||
float measureLed1(void);
|
#define BASIC_MODE 0x42
|
||||||
float measureLed2(void);
|
|
||||||
char compareLed(void);
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
DDRB |= (1<<PB0);
|
unsigned char cmd, i, val;
|
||||||
DDRB |= (1<<PB2);
|
unsigned char nom_capteur[9]={'I','U','T','V','i','D','A','v'};
|
||||||
|
unsigned char sensor_type[9]={'S','u','m','o','E','y','e','s'};
|
||||||
|
USI_TWI_Slave_Initialise(SLAVE_ADRESS);
|
||||||
led2_init();
|
led2_init();
|
||||||
led1_init();
|
led1_init();
|
||||||
ADC_init();
|
ADC_init();
|
||||||
char sendingData;
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
sendingData = compareLed();
|
if( USI_TWI_Data_In_Receive_Buffer() )
|
||||||
switch(sendingData)
|
|
||||||
{
|
{
|
||||||
case NOTHING:
|
cmd = USI_TWI_Receive_Byte();
|
||||||
PORTB |= (1<<PINB0); //les deux sont eteintes
|
|
||||||
PORTB |= (1<<PINB2);
|
switch(cmd){
|
||||||
break;
|
case MSTR_TEST_WR :
|
||||||
case FRONT:
|
val=USI_TWI_Receive_Byte();
|
||||||
PORTB &= ~(1<<PINB0); //les deux sont allumees
|
break;
|
||||||
PORTB &= ~(1<<PINB2);
|
|
||||||
break;
|
case MSTR_TEST_RE :
|
||||||
case RIGHT:
|
USI_TWI_Transmit_Byte(0x0F);
|
||||||
PORTB &= ~(1<<PINB0); //a droite allumee (led0)
|
break;
|
||||||
PORTB |= (1<<PINB2);
|
|
||||||
break;
|
case NOM_CONSTRUC :
|
||||||
case LEFT:
|
for (i=0;i<8;i++){USI_TWI_Transmit_Byte(nom_capteur[i]);}
|
||||||
PORTB |= (1<<PINB0); //a gauche allumee (led1)
|
break;
|
||||||
PORTB &= ~(1<<PINB2);
|
case NOM_CAPTEUR :
|
||||||
break;
|
for (i=0;i<8;i++){USI_TWI_Transmit_Byte(sensor_type[i]);}
|
||||||
default:
|
break;
|
||||||
break;
|
|
||||||
|
case VALEUR_DEMAN :
|
||||||
|
USI_TWI_Transmit_Byte(0x45);
|
||||||
|
break;
|
||||||
|
case BASIC_MODE :
|
||||||
|
USI_TWI_Transmit_Byte(0x46);
|
||||||
|
break;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
val++;
|
||||||
|
}
|
||||||
void led1_init(void)
|
|
||||||
{
|
|
||||||
DDRB |= (1<<PB1);
|
|
||||||
TCCR1|=(1<<CTC1)|(1<<COM1A0); //on active le mode CTC en comparant OCR1C, COM1A1 <20> 1 pour desactiver /OC1A
|
|
||||||
OCR1C=16; //d'apres retroingenieurie OCR1C=16
|
|
||||||
TCCR1|=(1<<CS10); //on active la clock avec CS10 = 1, pas de prediv (plus precis pour haute freq)
|
|
||||||
}
|
|
||||||
|
|
||||||
void led2_init(void)
|
|
||||||
{
|
|
||||||
DDRB |= (1<<PB4);
|
|
||||||
GTCCR|=(1<<COM1B0); //COM1B0 a 1 pour desactiver /OC1A
|
|
||||||
OCR1B=16; //d'apres retroingenieurie OCR1B=16
|
|
||||||
TCCR1|=(1<<CS10); //on active la clock avec CS10 = 1, pas de prediv (plus precis pour haute freq)
|
|
||||||
}
|
|
||||||
|
|
||||||
void led1_stop(void)
|
|
||||||
{
|
|
||||||
TCCR1 &= ~(1<<COM1A0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void led2_stop(void)
|
|
||||||
{
|
|
||||||
GTCCR &= ~(1<<COM1B0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADC_init(void)
|
|
||||||
{
|
|
||||||
DDRB &=~(1<<PB3); //Pin B3 en entree
|
|
||||||
ADMUX |= (1<<MUX1)|(1<<MUX0)|(1<<ADLAR); //MUX = 0010 donc sortie PB4 et ADLAR a 1 pour avoir les bits de poids fort en premier
|
|
||||||
ADCSRA |= (1<<ADEN)|(1<<ADPS2); //On divise 1Mhz par 16 (62.5 KHz) < 200 KHz, ADEN conversion autorisee
|
|
||||||
};
|
|
||||||
|
|
||||||
char ADC_read_value(void)
|
|
||||||
{
|
|
||||||
ADCSRA|=(1<<ADSC);
|
|
||||||
while(ADCSRA & (1<<ADSC));
|
|
||||||
return ADCH;
|
|
||||||
};
|
|
||||||
|
|
||||||
float ADC_averaging(void)
|
|
||||||
{
|
|
||||||
float valeur_finale=0;
|
|
||||||
char precision;
|
|
||||||
for(precision = 75; precision > 0 ; precision --)
|
|
||||||
{
|
|
||||||
valeur_finale = valeur_finale +(((ADC_read_value() * 0.01961) - valeur_finale) / 15);
|
|
||||||
}
|
|
||||||
return valeur_finale;
|
|
||||||
};
|
|
||||||
|
|
||||||
float measureLed1(void)
|
|
||||||
{
|
|
||||||
float adcLed;
|
|
||||||
led2_stop();
|
|
||||||
led1_init();
|
|
||||||
_delay_ms(250);
|
|
||||||
adcLed=ADC_averaging();
|
|
||||||
_delay_ms(250);
|
|
||||||
return adcLed;
|
|
||||||
};
|
|
||||||
|
|
||||||
float measureLed2(void)
|
|
||||||
{
|
|
||||||
float adcLed;
|
|
||||||
led1_stop();
|
|
||||||
led2_init();
|
|
||||||
_delay_ms(250);
|
|
||||||
adcLed=ADC_averaging();
|
|
||||||
_delay_ms(250);
|
|
||||||
return adcLed;
|
|
||||||
};
|
|
||||||
|
|
||||||
char compareLed(void)
|
|
||||||
{
|
|
||||||
float adcLed1 = measureLed1();
|
|
||||||
float adcLed2 = measureLed2();
|
|
||||||
float adcCompare = adcLed1 - adcLed2;
|
|
||||||
if (adcCompare < -VOLTMIN) // adcLed2 > adcLed1
|
|
||||||
{
|
|
||||||
return LEFT;
|
|
||||||
}
|
|
||||||
else if (adcCompare > VOLTMIN)
|
|
||||||
{
|
|
||||||
return RIGHT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if((adcLed1 > VOLTMIN) && (adcLed2 > VOLTMIN))
|
|
||||||
{
|
|
||||||
return FRONT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NOTHING;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
7
i2c_test_attiny85/test_led.c
Executable file
7
i2c_test_attiny85/test_led.c
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* test_led.c
|
||||||
|
*
|
||||||
|
* Created: 03/12/2021 15:25:24
|
||||||
|
* Author: 40008304
|
||||||
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue