Без телепатов такой код не разберешь.
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено mandigit 22 ноября 2006 г. 14:18
В ответ на: А можно код привести, телепаты в отпуске, а код нам не снится. отправлено Russ 22 ноября 2006 г. 14:02

#include
#include

#include "ProjDefs.h"
#include "USI_TWI_Slave.h"

#include "mysystypes.h"

#if defined(__AT90S2313__)
#define TCCR0 TCCR0B
#define TIMER0_OVF_vect TIMER0_OVF0_vect
#endif

#ifdef USI_NOINT
INT8U myUSICR;
#endif
INT8U TWI_slaveAddress;
INT8U *TWI_RxBuf, TWI_RxBufMaxSize, TWI_RxMsgLen;
INT8U *TWI_TxBuf, TWI_bufPtr;
#ifdef USI_CRC8
INT8U TWI_crc8, tmpTWI_crc8;
INT8U TWI_TxMsgLen, tmpTWI_TxMsgLen;
#endif

#pragma location = 4
__no_init __regvar volatile union USI_TWI_StatusReg USI_TWI_statusReg; // USI_TWI_S_statusRegister is defined in USI_TWI_Slave_config.h

#ifdef USI_TIME_OUT
#define SetTimeOut(x) \
{ \
TCCR0 = 0; \
TIFR = (1 << TOV0); \
TCNT0 = 0xFF - ((x * (XTAL / 1000000L)) / 64) + 1;\
TCCR0 = \
(0 << CS02) | (1 << CS01) | (1 << CS00); \
}
#endif

void USI_TWI_Disable(void)
{
#ifdef PROTECT_INT
my_sreg = __save_interrupt();
#endif
DDR_USI &= ~((1 << PIN_USI_SCL) | (1 << PIN_USI_SDA));
PORT_USI &= ~((1 << PIN_USI_SCL) | (1 << PIN_USI_SDA));
#ifdef PROTECT_INT
__restore_interrupt(my_sreg);
#endif

#ifdef USI_NOINT
myUSICR =
#endif
USICR = 0;
}

void USI_TWI_Init(void)
{
USI_TWI_statusReg.all = 0;

#ifdef PROTECT_INT
my_sreg = __save_interrupt();
#endif
PORT_USI |= ((1 << PIN_USI_SCL) | (1 << PIN_USI_SDA));
#ifdef PROTECT_INT
__restore_interrupt(my_sreg);
#endif

#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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);

#ifdef PROTECT_INT
my_sreg = __save_interrupt();
#endif
DDR_USI = (DDR_USI | (1 << PIN_USI_SCL)) & ~(1 << PIN_USI_SDA);
#ifdef PROTECT_INT
__restore_interrupt(my_sreg);
#endif

USISR =
(1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC) | // Clear flags
0x0; // Set USI to sample 8 bits i.e. count 16 external pin toggles.

#ifndef USI_NOINT
#ifdef PROTECT_INT
my_sreg = __save_interrupt();
#endif
TIMSK |= (1 << TOIE0);
#ifdef PROTECT_INT
__restore_interrupt(my_sreg);
#endif
#endif
}

void USI_TWI_Slave_Initialise(INT8U addr, void *rxBuf, INT8U bufMaxSize)
{
TWI_slaveAddress = addr;
TWI_RxBuf = rxBuf;
TWI_RxBufMaxSize = bufMaxSize;
USI_TWI_Init();
}

void USI_TWI_SndPkt(
void *msg
#ifdef USE_USI_CRC8
,INT8U msgSize
#endif
)
{
#ifndef USI_NOINT
__disable_interrupt();
#endif
#ifdef USE_USI_CRC8
tmpTWI_crc8 = CRC8(msg, msgSize);
tmpTWI_TxMsgLen = msgSize;
#endif
TWI_TxBuf = msg;
#ifndef USI_NOINT
__enable_interrupt();
#endif
}

INT8U USI_ProcessRcvPkt(void)
{
#ifdef USE_USI_CRC8
INT8U tmp;
#endif
if(USI_TWI_statusReg.DataInRxBuf)
{
USI_TWI_statusReg.DataInRxBuf = 0;
#ifdef USE_USI_CRC8
tmp = TWI_RxMsgLen;
tmp--;
if(TWI_RxBuf[tmp] == CRC8(TWI_RxBuf, tmp))
return(tmp)
else
return(0);
#else
return(TWI_RxMsgLen);
#endif
}
return(0);
}

#ifdef USI_NOINT
void USI_Start_Condition_ISR(void)
#else
#pragma vector=USI_STRT_vect
__interrupt void USI_Start_Condition_ISR(void)
#endif
{
#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI &= ~(1 << PIN_USI_SDA); // Set SDA as input
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

USI_TWI_statusReg.AddressMode = 1; // Expect TWI address on buss
/* Set default starting conditions for new TWI package */
/* Enable TWI Coutner overflow and interrupts*/
#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (1 << USIOIE); // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (1 << USIOIE) | // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC) | // Clear flags
0x0; // Set USI to sample 8 bits i.e. count 16 external pin toggles.
}

#ifdef USI_NOINT
void USI_Counter_Overflow_ISR(void)
#else
#pragma vector=USI_OVF_vect
__interrupt void USI_Counter_Overflow_ISR(void)
#endif
{
/* Inspect Address and R/W bit and set flags accordingly; ACK knowledge on address if able to comply
to the type of operation requested by the master (read or write) - depends on whether data are
available. for transmission/ if there is room for received data*/
if (USI_TWI_statusReg.AddressMode)
{
USI_TWI_statusReg.AddressMode = 0;

if((USIDR & 0xFE) == TWI_slaveAddress) // If expecting address packet
{
/*if (USIDR == 0)
USI_TWI_statusReg.genAddressCall = 1;
else
USI_TWI_statusReg.genAddressCall = 0;*/
USI_TWI_statusReg.MasterReadDataMode = (USIDR & 0x01); // USIDR_LSB = R/W Mode. 0 => masterWriteDataMode

if(!USI_TWI_statusReg.MasterReadDataMode)
USI_TWI_statusReg.DataInRxBuf = 0;

#ifdef USE_USI_CRC8
else
{
TWI_TxMsgLen = tmpTWI_TxMsgLen;
TWI_crc8 = tmpTWI_crc8;
}
#endif

TWI_bufPtr = 0; // Initialize Buffer to receive/transmit data

USIDR = 0; // Prepare ACK

#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI |= (1 << PIN_USI_SDA); // Set SDA as output
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

USISR =
(0 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0xE; // Set USI to shift out 1 bit

#ifdef USI_TIME_OUT
SetTimeOut(USI_TIME_OUT);
while(IsBitClear(TIFR, TOV0) && !(USISR & ((1 << USISIF) | (1 << USIOIF)))); // Wait until ACK sent. (Pass if Start Cond.)
TCCR0 = 0;

#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI &= ~(1 << PIN_USI_SDA); // Set SDA as input
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

if(IsBitSet(TIFR, TOV0))
{
TIFR = (1 << TOV0); //Clear TimeOut Flag
#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0x0;
return;
}
#else
while(!(USISR & ((1 << USISIF) | (1 << USIOIF)))); // Wait until ACK sent. (Pass if Start Cond.)

#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI &= ~(1 << PIN_USI_SDA); // Set SDA as input
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

#endif
}
// If received address did not match own address - ignore package. Wait for new Start Condition */
else
{ // Set USI in TWI Start Condition Mode
#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0x0;
return;
}
}
/* Address accepted - handle R/W byte and (N)ACK*/
else
{
/* One or more bytes transmitted by slave (Master Read); Read NACK if
transmission completed or ACK to continue */
if (USI_TWI_statusReg.MasterReadDataMode)
{
#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI &= ~(1 << PIN_USI_SDA); // Set SDA as input
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

USIDR = 0;
USISR =
(0 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0xE; // Set USI to sample 1 bit

#ifdef USI_TIME_OUT
SetTimeOut(USI_TIME_OUT);
while(IsBitClear(TIFR, TOV0) && !(USISR & ((1 << USISIF) | (1 << USIOIF)))); // Wait until (N)ACK received. (Pass if Start Cond.)
TCCR0 = 0;
if(IsBitSet(TIFR, TOV0))
{
TIFR = (1 << TOV0); //Clear TimeOut Flag
#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0x0;
return;
}
#else
while(!(USISR & ((1 << USISIF) | (1 << USIOIF)))); // Wait until (N)ACK received. (Pass if Start Cond.)
#endif

if (USIDR) // If NACK (USIDR_LSB=1) re-init the Start Cond detector
{
#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0x0;
return;
}
}
/* "masterWriteDataMode" - Slave receive. Store the
sampled data and send an ACK to the Master.*/
else
{
if(TWI_bufPtr < TWI_RxBufMaxSize)
{
TWI_RxBuf[TWI_bufPtr++] = USIDR;
USIDR = 0; // Send ACK
}
else
USIDR = 0x80; // send NACK

#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI |= (1 << PIN_USI_SDA); // Set SDA as output
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

USISR =
(0 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0xE; // Set USI to shift out 1 bit

#ifdef USI_TIME_OUT
SetTimeOut(USI_TIME_OUT);
while (IsBitClear(TIFR, TOV0) && !(USISR & ((1 << USISIF) | (1 << USIOIF)))); // Wait until (N)ACK sent. (Pass if Start Cond.)
TCCR0 = 0;
#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI &= ~(1 << PIN_USI_SDA); // Set SDA as intput
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

if(IsBitSet(TIFR, TOV0))
{
TIFR = (1 << TOV0); //Clear TimeOut Flag
#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0x0;
return;
}
#else
while (!(USISR & ((1 << USISIF) | (1 << USIOIF)))); // Wait until (N)ACK sent. (Pass if Start Cond.)

#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI &= ~(1 << PIN_USI_SDA); // Set SDA as intput
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

#endif
}
}
/* If The TWI master has initiated a read cycle (slave transmit) copy data from buffer to USIDR*/
if (USI_TWI_statusReg.MasterReadDataMode)
{
#ifdef USI_CRC8
if(TWI_bufPtr == TWI_TxMsgLen)
USIDR = TWI_crc8;
else
#endif
USIDR = TWI_TxBuf[TWI_bufPtr++]; // Put data in USI Data Register.

#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI |= (1 << PIN_USI_SDA); // Set SDA as output
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

#ifdef USI_TIME_OUT
SetTimeOut(USI_TIME_OUT * 8);
#endif
USISR =
(0 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0x0; // Set USI to shift out 8 bits
}
// "masterWriteDataMode". I.e. prepare to sample a data byte. (Or stop condition.)
else
{
#ifdef PROTECT_INT
#ifdef USI_NOINT
my_sreg = __save_interrupt();
#endif
#endif
DDR_USI &= ~(1 << PIN_USI_SDA); // Set SDA as intput
#ifdef PROTECT_INT
#ifdef USI_NOINT
__restore_interrupt(my_sreg);
#endif
#endif

USISR =
(0 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC) | // Clear all flags, except Start Cond
0xE; // Set USI to sample 1 bit

#ifdef USI_TIME_OUT
SetTimeOut(USI_TIME_OUT);
while (IsBitClear(TIFR, TOV0) && !(USISR & ((1 << USISIF) | (1 << USIOIF) | (1 << USIPF)))); // Wait until 1 bit sampled or STOP condition. (Pass if Start Cond.) OR TimeOut Expired
TCCR0 = 0;
if(IsBitSet(TIFR, TOV0))
{
TIFR = (1 << TOV0); //Clear TimeOut Flag
#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC)| // Clear all flags, except Start Cond
0x0;
return;
}
#else
while (!(USISR & ((1 << USISIF) | (1 << USIOIF) | (1 << USIPF)))); // Wait until 1 bit sampled or STOP condition. (Pass if Start Cond.) OR TimeOut Expired
#endif

if (USISR & (1 << USIPF)) // If STOP Cond then set USI in START Cond Mode
{
USI_TWI_statusReg.DataInRxBuf = 1; // Transmition complete i.e. valid data in RxBuf
TWI_RxMsgLen = TWI_bufPtr;

#ifdef USI_NOINT
myUSICR =
(1 << USISIE) | (0 << USIOIE); // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
USICR =
#ifndef USI_NOINT
(1 << USISIE) | (0 << USIOIE) | // Enable Start Condition Interrupt. Disable Overflow Interrupt.
#endif
(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 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC) | // Clear all flags, except Start Cond
0x0;
return;
}
else
{
USISR =
(0 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC) | // Clear all flags, except Start Cond
0x2; // Set USI to sample last 7 bits
}
}
}

#ifdef USI_NOINT
void USI_ISR(void)
{
if(IsBitSet(myUSICR, USISIE) && IsBitSet(USISR, USISIF))
{
#ifdef USI_TIME_OUT
TCCR0 = 0; //Stop TimeOut Timer
TIFR = (1 << TOV0);
#endif //Clear TimeOut Flag
USI_Start_Condition_ISR();
}
else
{
if(IsBitSet(myUSICR, USIOIE) && IsBitSet(USISR, USIOIF))
{
#ifdef USI_TIME_OUT
TCCR0 = 0; //Stop TimeOut Timer
TIFR = (1 << TOV0);
#endif //Clear TimeOut Flag
USI_Counter_Overflow_ISR();
}
}

#ifdef USI_TIME_OUT
if(IsBitSet(TIFR, TOV0))
{
TCCR0 = 0;
TIFR = (1 << TOV0); //Clear TimeOut Flag
USI_TWI_Disable();
USI_TWI_Init();
}
#endif
}
#else
#ifdef USI_TIME_OUT
#pragma vector = TIMER0_OVF_vect
__interrupt void TIMER0_OVF_vect_(void)
{
TCCR0 = 0;
USI_TWI_Disable();
USI_TWI_Init();}
}
#endif
#endif

Составить ответ  |||  Конференция  |||  Архив

Ответы


Отправка ответа
Имя (обязательно): 
Пароль: 
E-mail: 

Тема (обязательно):
Сообщение:

Ссылка на URL: 
URL изображения: 


Rambler's Top100 Рейтинг@Mail.ru
Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание