1
0
Fork 0

Additions from 11/12/2022: Using interruptions for ADC, Added Updated version of USI driver for I2C.

This commit is contained in:
Yohan Boujon 2022-04-05 20:30:35 +02:00
parent 900988633e
commit 8730b36933
11 changed files with 1042 additions and 122 deletions

749
att/usiTwiSlave.c Executable file
View file

@ -0,0 +1,749 @@
/********************************************************************************
USI TWI Slave driver.
Created by Donald R. Blake. donblake at worldnet.att.net
Adapted by Jochen Toppe, jochen.toppe at jtoee.com
---------------------------------------------------------------------------------
Created from Atmel source files for Application Note AVR312: Using the USI Module
as an I2C slave.
This program is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
---------------------------------------------------------------------------------
Change Activity:
Date Description
------ -------------
16 Mar 2007 Created.
27 Mar 2007 Added support for ATtiny261, 461 and 861.
26 Apr 2007 Fixed ACK of slave address on a read.
04 Jul 2007 Fixed USISIF in ATtiny45 def
12 Dev 2009 Added callback functions for data requests
06 Feb 2016 Minor change to allow mutli-byte requestFrom() from master.
10 Feb 2016 Simplied RX/TX buffer code and allowed use of full buffer.
13 Feb 2016 Made USI_RECEIVE_CALLBACK() callback fully interrupt-driven
12 Dec 2016 Added support for ATtiny167
23 Dec 2017 Fixed repeated restart (which broke when making receive callback
interrupt-driven)
********************************************************************************/
/********************************************************************************
includes
********************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "usiTwiSlave.h"
//#include "../common/util.h"
/********************************************************************************
device dependent defines
********************************************************************************/
#if defined( __AVR_ATtiny167__ )
# 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
# define USI_START_VECTOR USI_START_vect
# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
#endif
#if defined( __AVR_ATtiny2313__ )
# define DDR_USI DDRB
# define PORT_USI PORTB
# define PIN_USI PINB
# define PORT_USI_SDA PB5
# define PORT_USI_SCL PB7
# 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(__AVR_ATtiny84__) | \
defined(__AVR_ATtiny44__)
# define DDR_USI DDRA
# define PORT_USI PORTA
# define PIN_USI PINA
# define PORT_USI_SDA PORTA6
# define PORT_USI_SCL PORTA4
# define PIN_USI_SDA PINA6
# define PIN_USI_SCL PINA4
# define USI_START_COND_INT USISIF
# define USI_START_VECTOR USI_START_vect
# define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif
#if defined( __AVR_ATtiny25__ ) | \
defined( __AVR_ATtiny45__ ) | \
defined( __AVR_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
# define USI_START_VECTOR USI_START_vect
# define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif
#if defined( __AVR_ATtiny26__ )
# 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
# define USI_START_VECTOR USI_STRT_vect
# define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif
#if defined( __AVR_ATtiny261__ ) | \
defined( __AVR_ATtiny461__ ) | \
defined( __AVR_ATtiny861__ )
# 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
# define USI_START_VECTOR USI_START_vect
# define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif
#if defined( __AVR_ATmega165__ ) | \
defined( __AVR_ATmega325__ ) | \
defined( __AVR_ATmega3250__ ) | \
defined( __AVR_ATmega645__ ) | \
defined( __AVR_ATmega6450__ ) | \
defined( __AVR_ATmega329__ ) | \
defined( __AVR_ATmega3290__ )
# define DDR_USI DDRE
# define PORT_USI PORTE
# define PIN_USI PINE
# define PORT_USI_SDA PE5
# define PORT_USI_SCL PE4
# 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( __AVR_ATmega169__ )
# define DDR_USI DDRE
# define PORT_USI PORTE
# define PIN_USI PINE
# define PORT_USI_SDA PE5
# define PORT_USI_SCL PE4
# 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
// These macros make the stop condition detection code more readable.
#define USI_PINS_SCL_SDA ( ( 1 << PIN_USI_SDA ) | ( 1 << PIN_USI_SCL ) )
#define USI_PINS_SDA ( 1 << PIN_USI_SDA )
#define USI_PINS_SCL ( 1 << PIN_USI_SCL )
/********************************************************************************
functions implemented as macros
********************************************************************************/
#define SET_USI_TO_SEND_ACK( ) \
{ \
/* prepare ACK, ack is a zero */ \
USIDR = 0; \
/* set SDA as output */ \
DDR_USI |= ( 1 << PORT_USI_SDA ); \
/* clear all interrupt flags, except Start Cond */ \
USISR = \
( 0 << USI_START_COND_INT ) | \
( 1 << USIOIF ) | ( 1 << USIPF ) | \
( 1 << USIDC )| \
/* set USI counter to shift 1 bit */ \
( 0x0E << USICNT0 ); \
}
#define SET_USI_TO_READ_ACK( ) \
{ \
/* set SDA as input */ \
DDR_USI &= ~( 1 << PORT_USI_SDA ); \
/* prepare ACK */ \
USIDR = 0; \
/* clear all interrupt flags, except Start Cond */ \
USISR = \
( 0 << USI_START_COND_INT ) | \
( 1 << USIOIF ) | \
( 1 << USIPF ) | \
( 1 << USIDC ) | \
/* set USI counter to shift 1 bit */ \
( 0x0E << USICNT0 ); \
}
#define SET_USI_TO_TWI_START_CONDITION_MODE( ) \
{ \
USICR = \
/* enable Start Condition Interrupt, disable Overflow Interrupt */ \
( 1 << USISIE ) | ( 0 << USIOIE ) | \
/* set USI in Two-wire mode, no USI Counter overflow hold */ \
( 1 << USIWM1 ) | ( 0 << USIWM0 ) | \
/* Shift Register Clock Source = External, positive edge */ \
/* 4-Bit Counter Source = external, both edges */ \
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) | \
/* no toggle clock-port pin */ \
( 0 << USITC ); \
USISR = \
/* clear all interrupt flags, except Start Cond */ \
( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \
( 1 << USIDC ) | ( 0x0 << USICNT0 ); \
}
#define SET_USI_TO_SEND_DATA( ) \
{ \
/* set SDA as output */ \
DDR_USI |= ( 1 << PORT_USI_SDA ); \
/* clear all interrupt flags, except Start Cond */ \
USISR = \
( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \
( 1 << USIDC) | \
/* set USI to shift out 8 bits */ \
( 0x0 << USICNT0 ); \
}
#define SET_USI_TO_READ_DATA( ) \
{ \
/* set SDA as input */ \
DDR_USI &= ~( 1 << PORT_USI_SDA ); \
/* clear all interrupt flags, except Start Cond */ \
USISR = \
( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | \
( 1 << USIPF ) | ( 1 << USIDC ) | \
/* set USI to shift out 8 bits */ \
( 0x0 << USICNT0 ); \
}
#define USI_RECEIVE_CALLBACK() \
{ \
if (usi_onReceiverPtr) \
{ \
if (usiTwiAmountDataInReceiveBuffer()) \
{ \
usi_onReceiverPtr(usiTwiAmountDataInReceiveBuffer()); \
} \
} \
}
#define USI_REQUEST_CALLBACK() \
{ \
if(usi_onRequestPtr) usi_onRequestPtr(); \
}
/********************************************************************************
typedef's
********************************************************************************/
typedef enum
{
USI_SLAVE_CHECK_ADDRESS = 0x00,
USI_SLAVE_SEND_DATA = 0x01,
USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA = 0x02,
USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA = 0x03,
USI_SLAVE_REQUEST_DATA = 0x04,
USI_SLAVE_GET_DATA_AND_SEND_ACK = 0x05
} overflowState_t;
/********************************************************************************
local variables
********************************************************************************/
static uint8_t slaveAddress;
static uint8_t sleep_enable_bit;
static uint8_t in_transaction;
static volatile overflowState_t overflowState;
static uint8_t rxBuf[ TWI_RX_BUFFER_SIZE ];
static volatile uint8_t rxHead;
static volatile uint8_t rxTail;
static volatile uint8_t rxCount;
static uint8_t txBuf[ TWI_TX_BUFFER_SIZE ];
static volatile uint8_t txHead;
static volatile uint8_t txTail;
static volatile uint8_t txCount;
/********************************************************************************
local functions
********************************************************************************/
// flushes the TWI buffers
static void flushTwiBuffers( void )
{
rxTail = 0;
rxHead = 0;
rxCount = 0;
txTail = 0;
txHead = 0;
txCount = 0;
} // end flushTwiBuffers
/********************************************************************************
public functions
********************************************************************************/
// initialise USI for TWI slave mode
void usiTwiSlaveInit( uint8_t ownAddress )
{
// initialize the TX and RX buffers to empty
flushTwiBuffers( );
slaveAddress = ownAddress;
// In Two Wire mode (USIWM1, USIWM0 = 1X), the slave USI will pull SCL
// low when a start condition is detected or a counter overflow (only
// for USIWM1, USIWM0 = 11). This inserts a wait state. SCL is released
// by the ISRs (USI_START_vect and USI_OVERFLOW_vect).
// Set SCL and SDA as output
DDR_USI |= ( 1 << PORT_USI_SCL ) | ( 1 << PORT_USI_SDA );
// set SCL high
PORT_USI |= ( 1 << PORT_USI_SCL );
// set SDA high
PORT_USI |= ( 1 << PORT_USI_SDA );
// Set SDA and SCL as input
DDR_USI &= ~( 1 << PORT_USI_SDA );
DDR_USI &= ~( 1 << PORT_USI_SCL );
USICR =
// enable Start Condition Interrupt
( 1 << USISIE ) |
// disable Overflow Interrupt
( 0 << USIOIE ) |
// set USI in Two-wire mode, no USI Counter overflow hold
( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
// Shift Register Clock Source = external, positive edge
// 4-Bit Counter Source = external, both edges
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
// no toggle clock-port pin
( 0 << USITC );
// clear all interrupt flags and reset overflow counter
USISR = ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | ( 1 << USIDC );
// The 'in_transaction' variable remembers if the usiTwiSlave driver is in the middle of
// an i2c transaction. Initialize it to zero
in_transaction = 0;
} // end usiTwiSlaveInit
bool usiTwiDataInTransmitBuffer(void)
{
// return 0 (false) if the receive buffer is empty
return txCount;
} // end usiTwiDataInTransmitBuffer
// put data in the transmission buffer, wait if buffer is full
void usiTwiTransmitByte( uint8_t data )
{
// wait for free space in buffer
while ( txCount == TWI_TX_BUFFER_SIZE) ;
// store data in buffer
txBuf[ txHead ] = data;
txHead = ( txHead + 1 ) & TWI_TX_BUFFER_MASK;
txCount++;
} // end usiTwiTransmitByte
// return a byte from the receive buffer, wait if buffer is empty
uint8_t usiTwiReceiveByte( void )
{
uint8_t rtn_byte;
// wait for Rx data
while ( !rxCount );
rtn_byte = rxBuf [ rxTail ];
// calculate buffer index
rxTail = ( rxTail + 1 ) & TWI_RX_BUFFER_MASK;
rxCount--;
// return data from the buffer.
return rtn_byte;
} // end usiTwiReceiveByte
uint8_t usiTwiAmountDataInReceiveBuffer(void)
{
return rxCount;
}
/********************************************************************************
USI Start Condition ISR
********************************************************************************/
ISR( USI_START_VECTOR )
{
uint8_t usi_pins;
// http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html
// Notes about ISR. The compiler in the Arduino IDE handles some of the
// basic ISR plumbing (unless the "ISR_NAKED" attribute is applied).
// * The AVR processor resets the SREG.I bit when jumping into an ISR
// * The compiler automatically adds code to save SREG
// * < user's ISR code goes here >
// * The compiler automatically adds code to restore SREG
// * The compiler automatically uses the RETI instruction to return from the ISR.
// The RETI instruction enables interrupts after the return from ISR.
// The compiler behavior can be altered with attributes into the ISR declaration;
// however, the description above is the default.
// cli() call is not necessary. Processor disables interrupts when
// jumping to an ISR
// no need to save the SREG. The compiler does this automatically when using the
// ISR construct without modifying attributes.
if ( !in_transaction )
{
// remeber the sleep enable bit when entering the ISR
sleep_enable_bit = MCUCR & ( 1 << SE );
// clear the sleep enable bit to prevent the CPU from entering sleep mode while executing this ISR.
MCUCR &= ~( 1 << SE );
}
// set default starting conditions for new TWI package
overflowState = USI_SLAVE_CHECK_ADDRESS;
// set SDA as input
DDR_USI &= ~( 1 << PORT_USI_SDA );
// the start condition is that the master pulls SDA low.
// wait for SCL to go low to ensure the Start Condition has completed (the
// start detector will hold SCL low ) - if a Stop Condition arises then leave
// the interrupt to prevent waiting forever - don't use USISR to test for Stop
// Condition as in Application Note AVR312 because the Stop Condition Flag is
// going to be set from the last TWI sequence
// while SCL is high and SDA is low
while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL );
// if SDA line was low at SCL edge, then start condition occurred
if ( !( usi_pins & USI_PINS_SDA ) )
{
// a Stop Condition did not occur
// Execute callback if this is a repeated start
if (in_transaction)
{
USI_RECEIVE_CALLBACK();
}
USICR =
// keep Start Condition Interrupt enabled to detect RESTART
( 1 << USISIE ) |
// enable Overflow Interrupt
( 1 << USIOIE ) |
// set USI in Two-wire mode, hold SCL low on USI Counter overflow
( 1 << USIWM1 ) | ( 1 << USIWM0 ) |
// Shift Register Clock Source = External, positive edge
// 4-Bit Counter Source = external, both edges
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
// no toggle clock-port pin
( 0 << USITC );
//remember that the USI is in a valid i2c transaction
in_transaction = 1;
}
else
{
// a Stop Condition did occur
USICR =
// enable Start Condition Interrupt
( 1 << USISIE ) |
// disable Overflow Interrupt
( 0 << USIOIE ) |
// set USI in Two-wire mode, no USI Counter overflow hold
( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
// Shift Register Clock Source = external, positive edge
// 4-Bit Counter Source = external, both edges
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
// no toggle clock-port pin
( 0 << USITC );
//no longer in valid i2c transaction
in_transaction = 0;
// restore the sleep enable bit
MCUCR |= sleep_enable_bit;
} // end if
USISR =
// clear interrupt flags - resetting the Start Condition Flag will
// release SCL
( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) |
( 1 << USIPF ) |( 1 << USIDC ) |
// set USI to sample 8 bits (count 16 external SCL pin toggles)
( 0x0 << USICNT0);
// no need to restore the SREG. The compiler does this automatically when using the
// ISR construct without modifying attributes.
// The compiler automatically uses an RETI instruction to return when using the
// ISR construct without modifying attributes.
} // end ISR( USI_START_VECTOR )
/********************************************************************************
USI Overflow ISR
Handles all the communication.
Only disabled when waiting for a new Start Condition.
********************************************************************************/
ISR( USI_OVERFLOW_VECTOR )
{
uint8_t finished;
uint8_t usi_pins;
// http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html
// Notes about ISR. The compiler in the Arduino IDE handles some of the
// basic ISR plumbing.
// * The AVR processor resets the SREG.I bit when jumping into an ISR
// * The compiler automatically adds code to save the SREG
// * < user's ISR code goes here >
// * The compiler automatically adds code to restore the SREG
// * The compiler automatically uses the RETI instruction to return from the ISR.
// The RETI insturction enables interrupts after the return from ISR.
// The compiler behavior can be altered with attributes into the ISR declaration;
// however, the description above is the default.
// cli() call is not necessary. Processor disables interrupts when
// jumping to an ISR
// no need to save the SREG. The compiler does this automatically when using the
// ISR construct without modifying attributes.
// The ISR is only ever entered because the ISR(USI_START_VECTOR) interrupt
// routine ran first. That routine saved the sleep mode and disabled sleep.
// Most of the time this routine exits, it has setup the USI to shift in/out bits
// and is expected to re-entered because of the USI overflow interrupt. Track whether or
// not the transaction is completely finished.
finished = 0;
switch ( overflowState )
{
// 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 ) == slaveAddress) )
{
if ( USIDR & 0x01 )
{
overflowState = USI_SLAVE_SEND_DATA;
}
else
{
overflowState = USI_SLAVE_REQUEST_DATA;
} // end if
// ack the start frame
// sets up the USI to pull SDA low and clock one bit (two edges)
SET_USI_TO_SEND_ACK( );
}
else
{
SET_USI_TO_TWI_START_CONDITION_MODE( );
finished = 1;
}
break;
// master-read / slave-send: check reply and goto USI_SLAVE_SEND_DATA if OK,
// else reset USI
case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
// Execute request callback for each byte requested, as this is the intended
// behavior of this library
USI_REQUEST_CALLBACK();
if ( USIDR )
{
// if NACK, the master does not want more data
SET_USI_TO_TWI_START_CONDITION_MODE( );
finished = 1;
break;
}
// 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
if ( txCount )
{
USIDR = txBuf[ txTail ];
txTail = ( txTail + 1 ) & TWI_TX_BUFFER_MASK;
txCount--;
overflowState = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA;
SET_USI_TO_SEND_DATA( );
}
else
{
// the buffer is empty
SET_USI_TO_READ_ACK( ); // This might be neccessary sometimes see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=805227#805227
SET_USI_TO_TWI_START_CONDITION_MODE( );
} // end if
break;
// set USI to sample reply from master
// next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA
case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA:
overflowState = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA;
SET_USI_TO_READ_ACK( );
break;
// master-send / slave-receive: set USI to sample data from master, next
// USI_SLAVE_GET_DATA_AND_SEND_ACK
case USI_SLAVE_REQUEST_DATA:
overflowState = USI_SLAVE_GET_DATA_AND_SEND_ACK;
SET_USI_TO_READ_DATA( );
// with the SET_USI_TO_READ_DATA() macro call above, the USI has
// been setup to catch the next byte if the master sends one.
// while that's going on, look for a stop condition here which
// is when the SDA line goes high after the SCL line;
// wait until SCL goes high
while ( ! ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) & USI_PINS_SCL ) );
// if SDA line was high at SCL edge, then not a stop condition
if ( usi_pins & USI_PINS_SDA )
break;
// wait until SCL goes low or SDA goes high
while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL );
// if both SCL and SDA are high, then stop condition occurred
if ( usi_pins == USI_PINS_SCL_SDA )
{
USI_RECEIVE_CALLBACK();
SET_USI_TO_TWI_START_CONDITION_MODE( );
finished = 1;
}
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
// check buffer size
if ( rxCount < TWI_RX_BUFFER_SIZE )
{
rxBuf[ rxHead ] = USIDR;
rxHead = ( rxHead + 1 ) & TWI_RX_BUFFER_MASK;
rxCount++;
} else {
// overrun
// drop data
}
// next USI_SLAVE_REQUEST_DATA
overflowState = USI_SLAVE_REQUEST_DATA;
SET_USI_TO_SEND_ACK( );
break;
} // end switch
if (finished)
{
//no longer in valid i2c transaction
in_transaction = 0;
// restore the sleep enable bit
// note that this allows sleep -- it does not cause sleep
MCUCR |= sleep_enable_bit;
}
// no need to restore the SREG. The compiler does this automatically when using the
// ISR construct without modifying attributes.
// The compiler automatically uses an RETI instruction to return when using the
// ISR construct without modifying attributes.
} // end ISR( USI_OVERFLOW_VECTOR )

96
att/usiTwiSlave.h Executable file
View file

@ -0,0 +1,96 @@
/********************************************************************************
Header file for the USI TWI Slave driver.
Created by Donald R. Blake
donblake at worldnet.att.net
---------------------------------------------------------------------------------
Created from Atmel source files for Application Note AVR312: Using the USI Module
as an I2C slave.
This program is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
---------------------------------------------------------------------------------
Change Activity:
Date Description
------ -------------
15 Mar 2007 Created.
********************************************************************************/
#ifndef _USI_TWI_SLAVE_H_
#define _USI_TWI_SLAVE_H_
/********************************************************************************
includes
********************************************************************************/
#include <stdbool.h>
#include <avr/sleep.h>
/********************************************************************************
prototypes
********************************************************************************/
void usiTwiSlaveInit( uint8_t );
void usiTwiTransmitByte( uint8_t );
uint8_t usiTwiReceiveByte( void );
bool usiTwiDataInTransmitBuffer(void);
uint8_t usiTwiAmountDataInReceiveBuffer(void);
// on_XXX handler pointers
void (*usi_onRequestPtr)(void);
void (*usi_onReceiverPtr)(uint8_t);
/********************************************************************************
driver buffer definitions
********************************************************************************/
// permitted RX buffer sizes: 1, 2, 4, 8, 16, 32, 64, 128 or 256
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif
#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
// permitted TX buffer sizes: 1, 2, 4, 8, 16, 32, 64, 128 or 256
#ifndef TWI_TX_BUFFER_SIZE
#define TWI_TX_BUFFER_SIZE ( 16 )
#endif
#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
#endif // ifndef _USI_TWI_SLAVE_H_

View file

@ -20,9 +20,15 @@
*
****************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#if __GNUC__
#include <avr/io.h>
#include <avr/interrupt.h>
#else
#include <inavr.h>
#include <ioavr.h>
#endif
#include "USI_TWI_Slave.h"
#include "led_receptor.h"
/*! Static Variables
*/
@ -64,7 +70,8 @@ void USI_TWI_Slave_Initialise( unsigned char 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_SCL); // Set SCL as output
DDR_USI &= ~(1<<PORT_USI_SCL); // MODIF ::::::::::::::::: 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
@ -114,10 +121,13 @@ unsigned char USI_TWI_Data_In_Receive_Buffer( void )
* for reception of the "TWI Address" packet.
*/
/*#pragma vector=USI_START_VECTOR
__interrupt void USI_Start_Condition_ISR(void)*/
ISR(USI_START_VECTOR)
{
unsigned char tmpUSISR; // Temporary variable to store volatile
//********************************************************************************************************************************************************
//********************************************************************************************************************************************************
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;
@ -130,7 +140,6 @@ ISR(USI_START_VECTOR)
(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;
}
@ -138,13 +147,13 @@ ISR(USI_START_VECTOR)
* Handels all the comunication. Is disabled only when waiting
* for new Start Condition.
*/
/*#pragma vector=USI_OVERFLOW_VECTOR
__interrupt void USI_Counter_Overflow_ISR(void)*/
ISR(USI_OVERFLOW_VECTOR)
{
unsigned char tmpTxTail; // Temporary variables to store volatiles
unsigned char tmpUSIDR;
switch (USI_TWI_Overflow_State)
{
// ---------- Address mode ----------
@ -152,15 +161,16 @@ ISR(USI_OVERFLOW_VECTOR)
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;
if ( USIDR & 0x01 ){ // R/W
USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA; //Read => L'esclave doit envoyer une donn?e
}else{
USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA; //Write => L'esclave doit lire la demande
}
SET_USI_TO_SEND_ACK();
}
else
{
SET_USI_TO_TWI_START_CONDITION_MODE();
SET_USI_TO_TWI_START_CONDITION_MODE();
}
break;

View file

@ -63,9 +63,26 @@ typedef unsigned char uint8_t;
#define USI_SLAVE_REQUEST_DATA (0x04)
#define USI_SLAVE_GET_DATA_AND_SEND_ACK (0x05)
// AJOUT ########################################################################"
#if defined (__AVR_ATtiny24__) | \
defined (__AVR_ATtiny44__) | \
defined (__AVR_ATtiny84__)
#define DDR_USI DDRA
#define PORT_USI PORTA
#define PIN_USI PINA
#define PORT_USI_SDA PA6
#define PORT_USI_SCL PA4
#define PIN_USI_SDA PINA6
#define PIN_USI_SCL PINA4
#define USI_START_COND_INT USISIF
#define USI_START_VECTOR USI_STR_vect
#define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif
//###############################################################################
//! Device dependent defines
/*#if defined(__AT90tiny26__) | defined(__ATtiny26__)
#if defined(__AT90tiny26__) | defined(__ATtiny26__)
#define DDR_USI DDRB
#define PORT_USI PORTB
#define PIN_USI PINB
@ -76,9 +93,9 @@ typedef unsigned char uint8_t;
#define USI_START_COND_INT USISIF
#define USI_START_VECTOR USI_STRT_vect
#define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif*/
#endif
/*#if defined(__AT90Tiny2313__) | defined(__ATtiny2313__)
#if defined(__AT90Tiny2313__) | defined(__ATtiny2313__)
#define DDR_USI DDRB
#define PORT_USI PORTB
#define PIN_USI PINB
@ -87,11 +104,13 @@ typedef unsigned char uint8_t;
#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*/
#define USI_START_VECTOR USI_STRT_vect
#define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif
/*#if defined(__ATtiny25__) | defined(__ATtiny45__) | defined(__ATtiny85__)*/
#if defined( __AVR_ATtiny25__ ) | \
defined( __AVR_ATtiny45__ ) | \
defined( __AVR_ATtiny85__ )
#define DDR_USI DDRB
#define PORT_USI PORTB
#define PIN_USI PINB
@ -99,12 +118,12 @@ typedef unsigned char uint8_t;
#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_COND_INT USISIF
#define USI_START_VECTOR USI_START_vect
#define USI_OVERFLOW_VECTOR USI_OVF_vect
/*#endif*/
#endif
/*#if defined(__AT90Mega165__) | defined(__ATmega165__) | \
#if defined(__AT90Mega165__) | defined(__ATmega165__) | \
defined(__ATmega325__) | defined(__ATmega3250__) | \
defined(__ATmega645__) | defined(__ATmega6450__) | \
defined(__ATmega329__) | defined(__ATmega3290__) | \
@ -119,9 +138,10 @@ typedef unsigned char uint8_t;
#define USI_START_COND_INT USISIF
#define USI_START_VECTOR USI_START_vect
#define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
#endif*/
#endif
/*#if defined(__AT90Mega169__) | defined(__ATmega169__)
//#if defined(__AT90Mega169__) | defined(__ATmega169__)
#if defined(__AT90Mega169__) | defined(__AVR_ATmega169PA__)
#define DDR_USI DDRE
#define PORT_USI PORTE
#define PIN_USI PINE
@ -132,7 +152,7 @@ typedef unsigned char uint8_t;
#define USI_START_COND_INT USISIF
#define USI_START_VECTOR USI_STRT_vect
#define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif*/
#endif
//! Functions implemented as macros
#define SET_USI_TO_SEND_ACK() \
@ -153,14 +173,16 @@ typedef unsigned char uint8_t;
#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); \
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); \
ADCSRA |= (1<<ADEN)|(1<<ADIE)|(1<<ADSC); \
}
#define SET_USI_TO_SEND_DATA() \
{ \
DDR_USI |= (1<<PORT_USI_SDA); /* Set SDA as output */ \

View file

@ -9,57 +9,57 @@
<CSub></CSub>
<CVariant></CVariant>
<CVendor>Atmel</CVendor>
<CVersion>1.2.0</CVersion>
<DefaultRepoPath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs</DefaultRepoPath>
<CVersion>1.8.0</CVersion>
<DefaultRepoPath>D:/Programs\Atmelstudio\7.0\Packs</DefaultRepoPath>
<DependentComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<Description></Description>
<Files xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\include</AbsolutePath>
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\include\</AbsolutePath>
<Attribute></Attribute>
<Category>include</Category>
<Condition>C</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>include</Name>
<Name>include/</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\include\avr\iotn85.h</AbsolutePath>
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\include\avr\iotn85.h</AbsolutePath>
<Attribute></Attribute>
<Category>header</Category>
<Condition>C</Condition>
<FileContentHash>RcYmivGpgsCGGCzeWAIjcA==</FileContentHash>
<FileContentHash>T0lnJZ6iliUJCzU7ZHCMPQ==</FileContentHash>
<FileVersion></FileVersion>
<Name>include/avr/iotn85.h</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\templates\main.c</AbsolutePath>
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\templates\main.c</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>T6Fj/fIqJcOx0GrpJU4zHA==</FileContentHash>
<FileContentHash>KjvOcFWd++tbnsEMfVPd/w==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.c</Name>
<SelectString>Main file (.c)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\templates\main.cpp</AbsolutePath>
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\templates\main.cpp</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>YXFphlh0CtZJU+ebktABgQ==</FileContentHash>
<FileContentHash>mkKaE95TOoATsuBGv6jmxg==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.cpp</Name>
<SelectString>Main file (.cpp)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\gcc\dev\attiny85</AbsolutePath>
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny85</AbsolutePath>
<Attribute></Attribute>
<Category>libraryPrefix</Category>
<Condition>GCC</Condition>
@ -71,8 +71,8 @@
</d4p1:anyType>
</Files>
<PackName>ATtiny_DFP</PackName>
<PackPath>C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATtiny_DFP/1.2.118/Atmel.ATtiny_DFP.pdsc</PackPath>
<PackVersion>1.2.118</PackVersion>
<PackPath>D:/Programs/Atmelstudio/7.0/Packs/atmel/ATtiny_DFP/1.8.332/Atmel.ATtiny_DFP.pdsc</PackPath>
<PackVersion>1.8.332</PackVersion>
<PresentInProject>true</PresentInProject>
<ReferenceConditionId>ATtiny85</ReferenceConditionId>
<RteComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

View file

@ -27,24 +27,24 @@
<BootSegment>2</BootSegment>
<eraseonlaunchrule>0</eraseonlaunchrule>
<AsfFrameworkConfig>
<framework-data xmlns="">
<framework-data>
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.34.1" />
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.42.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
<avrtool>com.atmel.avrdbg.tool.stk500</avrtool>
<avrtool>com.atmel.avrdbg.tool.simulator</avrtool>
<avrtoolserialnumber />
<avrdeviceexpectedsignature>0x1E930B</avrdeviceexpectedsignature>
<com_atmel_avrdbg_tool_stk500>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
<IspClock>0</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
@ -54,12 +54,25 @@
<ToolName>STK500</ToolName>
</com_atmel_avrdbg_tool_stk500>
<avrtoolinterface>ISP</avrtoolinterface>
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
<avrtoolinterfaceclock>0</avrtoolinterfaceclock>
<ResetRule>0</ResetRule>
<EraseKey />
<com_atmel_avrdbg_tool_simulator>
<ToolOptions xmlns="">
<InterfaceProperties>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
<ToolNumber xmlns="">
</ToolNumber>
<ToolName xmlns="">Simulator</ToolName>
</com_atmel_avrdbg_tool_simulator>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
@ -74,7 +87,7 @@
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
@ -88,7 +101,7 @@
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
</AvrGcc>
@ -97,7 +110,7 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
@ -112,7 +125,7 @@
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
@ -127,7 +140,7 @@
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>

View file

@ -25,10 +25,12 @@ void led2_init(void)
void led1_stop(void)
{
DDRB &= ~(1<<PB1);
TCCR1 &= ~(1<<COM1A0);
}
void led2_stop(void)
{
DDRB &= ~(1<<PB4);
GTCCR &= ~(1<<COM1B0);
}

View file

@ -11,7 +11,17 @@ 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
ADCSRA|= (1<<ADEN)|(1<<ADPS2)|(1<<ADIE)|(1<<ADATE); //ADEN conversion autorisee
//On divise 1Mhz par 16 (62.5 KHz) < 200 KHz
//Interruptions autorisees
//Auto-Trigger autorise
ADCSRB &= ~(0b111<<ADTS0); //free-running mode
sei();
};
void ADC_start_conversion(void)
{
ADCSRA|=(1<<ADEN)|(1<<ADIE)|(1<<ADSC);
};
char ADC_read_value(void)
@ -21,13 +31,13 @@ char ADC_read_value(void)
return ADCH;
};
float ADC_averaging(void)
float ADC_averaging(unsigned char val_ana)
{
float valeur_finale=0;
char precision;
for(precision = 75; precision > 0 ; precision --)
{
valeur_finale = valeur_finale +(((ADC_read_value() * 0.01961) - valeur_finale) / 15);
valeur_finale = valeur_finale +(((val_ana * 0.01961) - valeur_finale) / 15);
}
return valeur_finale;
};
@ -35,30 +45,30 @@ float ADC_averaging(void)
float measureLed1(void)
{
float adcLed;
led2_stop();
led1_init();
_delay_ms(TIMING);
adcLed=ADC_averaging();
_delay_ms(TIMING);
_delay_us(TIMING);
adcLed=ADC_averaging(ADCH);
_delay_us(TIMING);
led1_stop();
return adcLed;
};
float measureLed2(void)
{
float adcLed;
led1_stop();
led2_init();
_delay_ms(TIMING);
adcLed=ADC_averaging();
_delay_ms(TIMING);
_delay_us(TIMING);
adcLed=ADC_averaging(ADCH);
_delay_us(TIMING);
led2_stop();
return adcLed;
};
char compareLed(void)
unsigned char compareLed(float led1,float led2)
{
float adcLed1 = measureLed1();
float adcLed2 = measureLed2();
float adcCompare = adcLed1 - adcLed2;
float adcLed1 = led1;
float adcLed2 = led2;
float adcCompare = led1 - led2;
if (adcCompare < -VOLTMIN) // adcLed2 > adcLed1
{
return LEFT;

View file

@ -10,8 +10,10 @@
#define LED_RECEPTOR_H_
#include "led_gen.h"
#define F_CPU 1000000
#include "USI_TWI_Slave.h"
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#define FRONT 0x51
#define RIGHT 0x52
@ -19,13 +21,14 @@
#define NOTHING 0x54
#define ERROR 0xF0
#define VOLTMIN 1
#define TIMING 250
#define TIMING 500
void ADC_init(void);
void ADC_start_conversion(void);
char ADC_read_value(void);
float ADC_averaging(void);
float ADC_averaging(unsigned char val_ana);
float measureLed1(void);
float measureLed2(void);
char compareLed(void);
unsigned char compareLed(float led1,float led2);
#endif /* LED_RECEPTOR_H_ */

View file

@ -9,7 +9,7 @@
void testLed(void)
{
char sendingData = compareLed();
char sendingData = compareLed(5,5);
switch(sendingData)
{
case NOTHING:

View file

@ -5,61 +5,76 @@
* Author : 40008304
*/
#if __GNUC__
#include <avr/io.h>
#include <avr/interrupt.h>
#else
#include <inavr.h>
#include <ioavr.h>
#endif
#include "led_gen.h"
#include "led_receptor.h"
#include "led_test.h"
#include "USI_TWI_Slave.h"
#define MSTR_TEST_WR 0x31
#define MSTR_TEST_RE 0x32
#define SLAVE_ADRESS 0x01
#define NOM_CONSTRUC 0x08
#define NOM_CAPTEUR 0x10
#define VALEUR_DEMAN 0x49
#define BASIC_MODE 0x42
int main(void)
{
unsigned char cmd, i, val;
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();
led1_init();
ADC_init();
while (1)
{
if( USI_TWI_Data_In_Receive_Buffer() )
{
cmd = USI_TWI_Receive_Byte();
volatile unsigned char rawVal;
volatile float adcled1;
volatile float adcled2;
volatile unsigned char recVal;
switch(cmd){
case MSTR_TEST_WR :
val=USI_TWI_Receive_Byte();
break;
case MSTR_TEST_RE :
USI_TWI_Transmit_Byte(0x0F);
break;
case NOM_CONSTRUC :
for (i=0;i<8;i++){USI_TWI_Transmit_Byte(nom_capteur[i]);}
break;
case NOM_CAPTEUR :
for (i=0;i<8;i++){USI_TWI_Transmit_Byte(sensor_type[i]);}
break;
case VALEUR_DEMAN :
USI_TWI_Transmit_Byte(0x45);
break;
case BASIC_MODE :
USI_TWI_Transmit_Byte(0x46);
break;
};
};
};
val++;
ISR (ADC_vect){//On récupère les données à chaque fin de conversion Analogique/Numérique
adcled1=measureLed1();
adcled2=measureLed2();
recVal=compareLed(adcled1,adcled2);
}
int main( void )
{
unsigned char slaveAdress, cmd,i=0;
unsigned char nom_capteur[8]= {'T','u','r','k','i','s','h','Z'};
unsigned char sensor_type[8]= {'C','a','t','c','h','E','y','e'};
slaveAdress = 0x01;
USI_TWI_Slave_Initialise(slaveAdress);
sei();
ADC_init();
ADC_start_conversion();
while(1)
{
if( USI_TWI_Data_In_Receive_Buffer() )
{
cmd = USI_TWI_Receive_Byte();
switch(cmd)
{
case NOM_CONSTRUC :
for (i=0; i<8; i++)
{
USI_TWI_Transmit_Byte(nom_capteur[i]);
}
break;
case NOM_CAPTEUR :
for (i=0; i<8; i++)
{
USI_TWI_Transmit_Byte(sensor_type[i]);
}
break;
case VALEUR_DEMAN :
USI_TWI_Transmit_Byte(recVal);
break;
case BASIC_MODE :
USI_TWI_Transmit_Byte(0x46);
break;
}
}
}
return 0;
}