1
0
Fork 0

Additions from 07/01/2022: Added back interruptions, Renamed library.

This commit is contained in:
Yohan Boujon 2022-04-05 20:36:14 +02:00
parent 2b1327994c
commit 4504b6121b
10 changed files with 1404 additions and 119 deletions

View file

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

View file

@ -28,15 +28,15 @@
<eraseonlaunchrule>0</eraseonlaunchrule> <eraseonlaunchrule>0</eraseonlaunchrule>
<AsfFrameworkConfig> <AsfFrameworkConfig>
<framework-data> <framework-data>
<options /> <options />
<configurations /> <configurations />
<files /> <files />
<documentation help="" /> <documentation help="" />
<offline-documentation help="" /> <offline-documentation help="" />
<dependencies> <dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.25.0" /> <content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.25.0" />
</dependencies> </dependencies>
</framework-data> </framework-data>
</AsfFrameworkConfig> </AsfFrameworkConfig>
<avrtool>com.atmel.avrdbg.tool.stk500</avrtool> <avrtool>com.atmel.avrdbg.tool.stk500</avrtool>
<avrtoolserialnumber /> <avrtoolserialnumber />
@ -72,79 +72,79 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings> <ToolchainSettings>
<AvrGcc> <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.2.118\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec> <avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols> <avrgcc.compiler.symbols.DefSymbols>
<ListValues> <ListValues>
<Value>NDEBUG</Value> <Value>NDEBUG</Value>
</ListValues> </ListValues>
</avrgcc.compiler.symbols.DefSymbols> </avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths> <avrgcc.compiler.directories.IncludePaths>
<ListValues> <ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value> <Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
</ListValues> </ListValues>
</avrgcc.compiler.directories.IncludePaths> </avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level> <avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.linker.libraries.Libraries> <avrgcc.linker.libraries.Libraries>
<ListValues> <ListValues>
<Value>libm</Value> <Value>libm</Value>
</ListValues> </ListValues>
</avrgcc.linker.libraries.Libraries> </avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths> <avrgcc.assembler.general.IncludePaths>
<ListValues> <ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value> <Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
</ListValues> </ListValues>
</avrgcc.assembler.general.IncludePaths> </avrgcc.assembler.general.IncludePaths>
</AvrGcc> </AvrGcc>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings> <ToolchainSettings>
<AvrGcc> <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.2.118\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec> <avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols> <avrgcc.compiler.symbols.DefSymbols>
<ListValues> <ListValues>
<Value>DEBUG</Value> <Value>DEBUG</Value>
</ListValues> </ListValues>
</avrgcc.compiler.symbols.DefSymbols> </avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths> <avrgcc.compiler.directories.IncludePaths>
<ListValues> <ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value> <Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
</ListValues> </ListValues>
</avrgcc.compiler.directories.IncludePaths> </avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level> <avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel> <avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.linker.libraries.Libraries> <avrgcc.linker.libraries.Libraries>
<ListValues> <ListValues>
<Value>libm</Value> <Value>libm</Value>
</ListValues> </ListValues>
</avrgcc.linker.libraries.Libraries> </avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths> <avrgcc.assembler.general.IncludePaths>
<ListValues> <ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value> <Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
</ListValues> </ListValues>
</avrgcc.assembler.general.IncludePaths> </avrgcc.assembler.general.IncludePaths>
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel> <avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
</AvrGcc> </AvrGcc>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -163,10 +163,10 @@
<Compile Include="main.c"> <Compile Include="main.c">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
<Compile Include="USI_TWI_Slave.c"> <Compile Include="usiTwiSlave.c">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
<Compile Include="USI_TWI_Slave.h"> <Compile Include="usiTwiSlave.h">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
</ItemGroup> </ItemGroup>

View file

@ -11,16 +11,16 @@ void led1_init(void)
{ {
DDRB |= (1<<PB1); DDRB |= (1<<PB1);
TCCR1|=(1<<CTC1)|(1<<COM1A0); //on active le mode CTC en comparant OCR1C, COM1A0 : mode toggle TCCR1|=(1<<CTC1)|(1<<COM1A0); //on active le mode CTC en comparant OCR1C, COM1A0 : mode toggle
OCR1C=16; //d'apres retroingenieurie OCR1C=16 OCR1C=34; //d'apres retroingenieurie OCR1C=16
TCCR1|=(1<<CS10); //on active la clock avec CS10 = 1, pas de prediv (plus precis pour haute freq) TCCR1|=(1<<CS10)|(1<<CS11); //on active la clock, prediv de 4
} }
void led2_init(void) void led2_init(void)
{ {
DDRB |= (1<<PB4); DDRB |= (1<<PB4);
GTCCR|=(1<<COM1B0); //COM1B0 : mode toggle GTCCR|=(1<<COM1B0); //COM1B0 : mode toggle
OCR1C=16; //d'apres retroingenieurie OCR1C=16 OCR1C=34; //d'apres retroingenieurie OCR1C=16
TCCR1|=(1<<CS10); //on active la clock avec CS10 = 1, pas de prediv (plus precis pour haute freq) TCCR1|=(1<<CS10)|(1<<CS11); //on active la clock, prediv de 4
} }
void led1_stop(void) void led1_stop(void)

View file

@ -44,23 +44,23 @@ float ADC_averaging(unsigned char val_ana)
float measureLed1(void) float measureLed1(void)
{ {
float adcLed; float adcLed=69;
//led1_init(); led1_init();
//_delay_ms(TIMING); _delay_ms(TIMING);
adcLed=ADC_averaging(ADCH); //adcLed=ADC_averaging(ADCH);
//_delay_ms(TIMING); _delay_ms(TIMING);
//led1_stop(); led1_stop();
return adcLed; return adcLed;
}; };
float measureLed2(void) float measureLed2(void)
{ {
float adcLed; float adcLed=69;
//led2_init(); led2_init();
//_delay_ms(TIMING); _delay_ms(TIMING);
adcLed=ADC_averaging(ADCH); //adcLed=ADC_averaging(ADCH);
//_delay_ms(TIMING); _delay_ms(TIMING);
//led2_stop(); led2_stop();
return adcLed; return adcLed;
}; };

View file

@ -10,7 +10,7 @@
#define LED_RECEPTOR_H_ #define LED_RECEPTOR_H_
#include "led_gen.h" #include "led_gen.h"
#include "USI_TWI_Slave.h" #include "usiTwiSlave.h"
#define F_CPU 8000000 #define F_CPU 8000000
#include <util/delay.h> #include <util/delay.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
@ -21,7 +21,7 @@
#define NOTHING 0x54 #define NOTHING 0x54
#define ERROR 0xF0 #define ERROR 0xF0
#define VOLTMIN 1 #define VOLTMIN 1
#define TIMING 100 #define TIMING 5
void ADC_init(void); void ADC_init(void);
void ADC_start_conversion(void); void ADC_start_conversion(void);

View file

@ -15,7 +15,7 @@
#include "led_gen.h" #include "led_gen.h"
#include "led_receptor.h" #include "led_receptor.h"
#include "USI_TWI_Slave.h" #include "usiTwiSlave.h"
//#define F_CPU 1000000 //#define F_CPU 1000000
#define NOM_CONSTRUC 0x08 #define NOM_CONSTRUC 0x08
#define NOM_CAPTEUR 0x10 #define NOM_CAPTEUR 0x10
@ -35,44 +35,52 @@ volatile unsigned char recVal;
int main( void ) int main( void )
{ {
unsigned char slaveAdress, cmd,i=0; float test1,test2;
unsigned char cmd,i=0;
unsigned char nom_capteur[8]= {'T','u','r','k','i','s','h','Z'}; 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'}; unsigned char sensor_type[8]= {'C','a','t','c','h','E','y','e'};
uint8_t slaveAdress;//data = 0x45;
slaveAdress = 0x01; slaveAdress = 0x01;
MCUCR |= (1<<PUD); MCUCR |= (1<<PUD);
//led1_init();
//led2_init();
//USI_TWI_Slave_Initialise(slaveAdress);
usiTwiSlaveInit(slaveAdress);
USI_TWI_Slave_Initialise(slaveAdress);
sei(); sei();
//ADC_init(); //ADC_init();
//ADC_start_conversion(); //ADC_start_conversion();
while(1) while(1)
{ {
if( USI_TWI_Data_In_Receive_Buffer() ) test1=measureLed1();
test2=measureLed2();
if( usiTwiDataInTransmitBuffer() )
{ {
cmd = USI_TWI_Receive_Byte(); cmd = usiTwiReceiveByte();
switch(cmd) switch(cmd)
{ {
case NOM_CONSTRUC : case NOM_CONSTRUC :
for (i=0; i<8; i++) for (i=0; i<8; i++)
{ {
USI_TWI_Transmit_Byte(nom_capteur[i]); usiTwiTransmitByte(nom_capteur[i]);
} }
break; break;
case NOM_CAPTEUR : case NOM_CAPTEUR :
for (i=0; i<8; i++) for (i=0; i<8; i++)
{ {
USI_TWI_Transmit_Byte(sensor_type[i]); usiTwiTransmitByte(sensor_type[i]);
} }
break; break;
case VALEUR_DEMAN : case VALEUR_DEMAN :
USI_TWI_Transmit_Byte(0x45/*recVal*/); usiTwiTransmitByte(0x45/*recVal*/);
break; break;
case BASIC_MODE : case BASIC_MODE :
USI_TWI_Transmit_Byte(0x46); usiTwiTransmitByte(0x45);
break; break;
} }
} }

View file

@ -0,0 +1,230 @@
// 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.
*
*
****************************************************************************/
#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
*/
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); // 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
// 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.
*/
/*#pragma vector=USI_START_VECTOR
__interrupt void USI_Start_Condition_ISR(void)*/
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.
}
/*! \brief USI counter overflow ISR
* 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 ----------
// 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 ){ // 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();
}
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;
}
}

View file

@ -0,0 +1,203 @@
// 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: 6351 $
* Date : $Date: 2010-01-29 20:15:43 +0800 (Fri, 29 Jan 2010) $
* Updated by : $Author: hskinnemoen $
*
* 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 **********//
#include <avr/io.h>
#ifndef TWDR
void USI_TWI_Slave_Initialise(unsigned char);
void USI_TWI_Slave_Disable();
void USI_TWI_Transmit_Byte(unsigned char);
unsigned char USI_TWI_Receive_Byte(void);
unsigned char USI_TWI_Peek_Receive_Byte(void);
unsigned char USI_TWI_Data_In_Receive_Buffer(void);
unsigned char USI_TWI_Space_In_Transmission_Buffer(void);
unsigned char USI_TWI_Slave_Is_Active();
void (*USI_TWI_On_Slave_Transmit)(void);
void (*USI_TWI_On_Slave_Receive)(int);
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
extern uint8_t TWI_Buffer[];
#define TWI_RX_BUFFER_SIZE (16)
#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 (16)
#if (TWI_TX_BUFFER_SIZE & TWI_TX_BUFFER_MASK)
#error TWI TX buffer size is not a power of 2
#endif
#define TWI_BUFFER_SIZE (TWI_RX_BUFFER_SIZE + TWI_TX_BUFFER_SIZE)
//////////////////////////////////////////////////////////////////
#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_STRT_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(__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__)
#if defined(__AT90Mega169__) | defined(__AVR_ATmega169PA__)
#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
#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_SEND_NACK() \
{ \
DDR_USI &= ~(1 << PORT_USI_SDA); /* Set SDA as input, NACK is SDA high */ \
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 input */ \
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() \
{ \
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 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 */ \
}
#endif

748
i2c_test_attiny85/usiTwiSlave.c Executable file
View file

@ -0,0 +1,748 @@
/********************************************************************************
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() \
{ \
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( ) \
{ \
/* 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 as input
DDR_USI &= ~( 1 << PORT_USI_SDA );
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) //Fonction modif : affiche 255 constamment
{ //Solution : creer une variable temporaire recuperant rxTail et la comparant avec rxHead
unsigned char tmpRxTail; // Creation d'une variable temporaire pour stocker rxTail au moment present
tmpRxTail = rxTail; // on recupere rxTail dans la variable temporaire
return ( rxHead != tmpRxTail ); // Renvoi 0 si aucune donnee n'est envoyee
// renvoi 0 mais perturbe la transmission
//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
i2c_test_attiny85/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 ( 1 )
#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_