В итоге, все сводиться к тому что запутываюсь в конечном автомате TWI.
Вот последние попытки:
Master:
Спойлер
Код: Выделить всё
/******************************************************************************/
Реализация TWI режим Master
/******************************************************************************/
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <avr/eeprom.h>
#include <stdlib.h>
#include <string.h>
/********************************Личные_Макросы********************************/
#define SET_BIT(port,bit) port|=(1<<bit)
#define CLR_BIT(port,bit) port&= ~(1<<bit)
#define INV_BIT(port,bit) port ^=(1<<bit)
#define BIT_IS_CLEAR(sfr,bit) (!(_SFR_BYTE(sfr) & (1<<(bit))))
#define BIT_IS_SET(sfr,bit) (_SFR_BYTE(sfr) & (1<<(bit) ))
/*********************** Статусные коды TWI модуля ****************************/
// Общие статусные коды.
#define TWI_START 0x08 //Состояние START сформировано.
#define TWI_REP_START 0x10 //Состояние повторный START сформировано.
#define TWI_ARB_LOST 0x38 //потерян приоритет.
// Статусные коды ведущего передатчика.
#define TWI_MTX_ADR_ACK 0x18 //передан пакет SLA+W, получено подтверждение.
#define TWI_MTX_ADR_NACK 0x20 //передан пакет SLA+W, не получено подтверждение.
#define TWI_MTX_DATA_ACK 0x28 //передан байт данных, получено подтверждение.
#define TWI_MTX_DATA_NACK 0x30 //передан байт данных, не получено подтверждение.
// Статусные коды ведущего приемника.
#define TWI_MRX_ADR_ACK 0x40 //передан пакет SLA+R, получено подтверждение.
#define TWI_MRX_ADR_NACK 0x48 //передан пакет SLA+R, не получено подтверждение.
#define TWI_MRX_DATA_ACK 0x50 //Байт данных принят, передано подтверждение.
#define TWI_MRX_DATA_NACK 0x58 //принят байт данных без подтверждения.
// Другие статусные коды.
#define TWI_NO_STATE 0xF8 //Неопределенное состояние (TWINT = "0").
#define TWI_BUS_ERROR 0x00 //Ошибка, из-за некоректных состояний СТАРТ или СТОП.
// Пользовательские коды.
#define TWI_SUCCESS 0xFF //Успешное завершение.
/************************ макросы получения байта адреса **********************/
#define TWI_SLAVE_ADDR 15
#define TWI_GET_READ_BYTE(ADDR) ((ADDR)<<1)|1;
#define TWI_GET_WRITE_BYTE(ADDR) ((ADDR)<<1)|0;
/************************ Переменные, константы TWI ***************************/
#define TWI_BUFFER_SIZE 19 // Размер буфера TWI модуля. (8*10+16*4+1)
#define TWI_READ_BIT 0 // Позиция R/W бита в адресном пакете.
#define TWSR_MASK 0xfc
#define TWI_SPEED 400UL
// Буфер для TWI.
uint8_t TWI_Buf[TWI_BUFFER_SIZE]={0};
// Размер получаемого/отправляемого пакета данных.
uint8_t TWI_MsgSize=0;
// Текущий статус TWI.
uint8_t TWI_State = TWI_NO_STATE;
/****************************************************************************
Инициализация и установка частоты сигнала
****************************************************************************/
uint8_t TWI_MasterInit(uint16_t fr)
{
static uint8_t i;
static uint16_t twbrValue;
static uint8_t pre[4] = {2, 8, 32, 128};
for(i = 0; i<4; i++){
twbrValue = (uint8_t)((((F_CPU)/1000UL)/fr)-16)/pre[i];
if ((twbrValue > 0)&& (twbrValue < 256)){
TWBR = twbrValue;
TWSR = i;
TWDR = 0xFF;
TWCR = (1<<TWEN);
return TWI_SUCCESS;
}
}
return 0;
}
// Ждем, пока модуль занят.
void TWI_TransceiverBusy(void)
{
while (TWCR & (1<<TWIE)){}
}
// Получить статус, работа с TWI завершена.
uint8_t TWI_GetFinishStep(void)
{
return (!(TWCR & (1<<TWIE)));
}
// Получить статус TWI модуля.
uint8_t TWI_GetState(void)
{
TWI_TransceiverBusy();
// Возвращаем статус TWI модуля.
return TWI_State;
}
// Передать данные.
void TWI_SendData(uint8_t *msg, uint8_t msgSize)
{
// Ждем, когда TWI модуль освободится.
TWI_TransceiverBusy();
// Сохряняем кол.байт для передачи.
TWI_MsgSize = msgSize;
// Сохряняем первый байт сообщения.
TWI_Buf[0] = msg[0];
// Если первый байт типа SLA+W.
if (!(msg[0] & (1<<TWI_READ_BIT)))
{
// Сохряняем остальную часть сообщения.
for (uint8_t i = (msgSize-1); i > 0; i--)
{
TWI_Buf[i] = msg[i];
}
}
// Обнуляем переменную, которая хранит статус операции.
TWI_State = TWI_NO_STATE;
// Разрешаем прерывание и формируем состояние старт.
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA);
}
// Отправляем запрос на чтение.
void TWI_ReadBytes(uint8_t address, uint8_t msgSize)
{
// Объявляем массив для отправки.
uint8_t msgBuf[2];
// Адресный пакет.
msgBuf[0] = TWI_GET_READ_BYTE(address);
// Передаем данные.
TWI_SendData(msgBuf, msgSize);
}
/******************************** Прерывания ********************************/
// Обработчик прерывания TWI модуля.
ISR(TWI_vect,ISR_BLOCK)
{
static uint8_t TWI_BufIndex;
uint8_t stat = TWSR & TWSR_MASK;
switch (stat)
{
// Состояние START сформировано.
case TWI_START:
// Состояние повторный START сформировано.
case TWI_REP_START:
TWI_BufIndex = 0;
// Был передан пакет SLA+W и получено подтверждение.
case TWI_MTX_ADR_ACK:
// Был передан байт данных и получено подтверждение.
case TWI_MTX_DATA_ACK:
if (TWI_BufIndex < TWI_MsgSize)
{
// Загружаем в регистр данных следующий байт.
// TWDR (TWI Data Register) - Регистр данных.
TWDR = TWI_Buf[TWI_BufIndex];
// Сбрасываем флаг TWINT.
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
TWI_BufIndex++;
}
else
{
TWI_State = TWI_SUCCESS;
// Формируем состояние СТОП, сбрасываем флаг, запрещаем прерывания.
TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWSTO)|(0<<TWIE);
}
break;
// Байт данных принят и передано подтверждение.
case TWI_MRX_DATA_ACK:
TWI_Buf[TWI_BufIndex] = TWDR;
TWI_BufIndex++;
// Был передан пакет SLA+R и получено подтвеждение.
case TWI_MRX_ADR_ACK:
if (TWI_BufIndex < (TWI_MsgSize-1))
{
// Если это не предпоследний принятый байт, формируем подтверждение.
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
}
else
{
// Если приняли предпоследний байт, подтверждение не формируем.
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
}
break;
// Был принят байт данных без подтверждения.
case TWI_MRX_DATA_NACK:
TWI_Buf[TWI_BufIndex] = TWDR;
TWI_State = TWI_SUCCESS;
// Формируем состояние стоп.
TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWSTO);
break;
// Был потерян приоритет.
case TWI_ARB_LOST:
// Сбрасываем флаг TWINT, формируем повторный СТАРТ.
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA);
break;
// Был передан пакет SLA+W и не получено подтверждение.
case TWI_MTX_ADR_NACK:
// Был передан пакет SLA+R и не получено подтверждение.
case TWI_MRX_ADR_NACK:
// Был передан байт данных и не получено подтверждение.
case TWI_MTX_DATA_NACK:
// Ошибка на шине из-за некоректных состояний СТАРТ или СТОП.
case TWI_BUS_ERROR:
default:
TWI_State = stat;
// Запретить прерывание.
TWCR = (1<<TWEN)|(0<<TWIE)|(0<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
break;
}
}
/***********************************************************/
union Byte
{
uint8_t Byte;
struct
{
uint8_t B0:1;
uint8_t B1:1;
uint8_t B2:1;
uint8_t B3:1;
uint8_t B4:1;
uint8_t B5:1;
uint8_t B6:1;
uint8_t B7:1;
}Bits;
};
union Byte OneOUT; // (Выход) U1
union Byte TwoOUT; // (Выход) U2
union Byte ThreeOUT; // (Выход) U3
union Byte FourOUT; // (Выход) U4
union Byte FifthOUT; // (Выход) U5
union Byte OneIN; // (Вход) U9
union Byte TwoIN; // (Вход) U10
union Byte ThreeIN; // (Вход) U11
union Byte FourIN; // (Вход) U12
union Byte FifthIN; // (Вход) U13
struct Time64{
uint16_t VarOne;
uint16_t VarTwo;
uint16_t VarThree;
uint16_t VarFour;
}Time;
void CpyVarToBuf()
{
memcpy(&TWI_Buf[1],&OneOUT.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[2],&TwoOUT.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[3],&ThreeOUT.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[4],&FourOUT.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[5],&FifthOUT.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[6],&OneIN.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[7],&TwoIN.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[8],&ThreeIN.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[9],&FourIN.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[10],&FifthIN.Byte,sizeof(uint8_t));
memcpy(&TWI_Buf[11],&Time,sizeof(Time));
}
uint8_t ttest=0;
int main(void)
{
TWI_MasterInit(TWI_SPEED);
sei();
//Заполним переменные значениям для теста.
Time.VarOne=255;
Time.VarTwo=2;
Time.VarThree=3;
Time.VarFour=60000;
OneOUT.Bits.B0=1;
FifthOUT.Bits.B0=1;
FifthIN.Bits.B7=1;
//Откопируем данные в буфер для отправки в TWI
CpyVarToBuf();
while(1)
{
//Пишем в TWI_Slave
//TWI_Buf[0]=TWI_GET_WRITE_BYTE(TWI_SLAVE_ADDR);
//TWI_SendData(TWI_Buf,TWI_BUFFER_SIZE);
//Читаем из TWI_SLAVE
TWI_ReadBytes(TWI_SLAVE_ADDR,TWI_BUFFER_SIZE);
asm volatile ("nop");
}
return 0;
}
Спойлер
Код: Выделить всё
/************************************************************************/
Реализация TWI режим Slave
/************************************************************************/
#define F_CPU 20000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/atomic.h>
#include <avr/sfr_defs.h>
#include <util/twi.h>
/********************************Макросы*********************************/
#define SET_BIT(port,bit) port|=(1<<bit)
#define CLR_BIT(port,bit) port&= ~(1<<bit)
#define INV_BIT(port,bit) port ^=(1<<bit)
#define BIT_IS_CLEAR(sfr,bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
#define BIT_IS_SET(sfr,bit) (_SFR_BYTE(sfr) & _BV(bit))
/************************************************************************/
#define I2C_ADDR 15
#define TWI_BUFFER_SIZE 18
uint8_t rxBuff[TWI_BUFFER_SIZE]={0};
uint8_t txBuff[TWI_BUFFER_SIZE]={0};
static void (*I2C_recv)(uint8_t,uint8_t*,uint8_t);
static void (*I2C_req)(uint8_t*,uint8_t);
void I2C_setCallbacks(void (*recv)(uint8_t,uint8_t*,uint8_t), void (*req)(uint8_t*,uint8_t))
{
I2C_recv = recv;
I2C_req = req;
}
void I2C_received(uint8_t msgRcv,uint8_t* msgBuf,uint8_t bufPtr)
{
msgBuf[bufPtr] = msgRcv;
}
void I2C_requested(uint8_t* msgBuf,uint8_t bufPtr)
{
TWDR = msgBuf[bufPtr]; //*(msgBuf+bufPtr);
}
void I2C_stop(void)
{
cli();
TWCR = 0;
TWAR = 0;
sei();
}
ISR(TWI_vect)
{
static uint8_t bufPtr;
switch(TW_STATUS)
{
case TW_ST_SLA_ACK:
bufPtr=0;
case TW_ST_DATA_ACK:
I2C_req(&txBuff[0],bufPtr++);
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_DATA_NACK:
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
break;
case TW_SR_SLA_ACK:
bufPtr = 0;
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
break;
case TW_SR_DATA_ACK:
I2C_recv(TWDR,&rxBuff[0],bufPtr++);
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_BUS_ERROR:
TWCR = 0;
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
default:
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
}
}
void I2C_init(uint8_t address)
{
cli();
TWAR = (address << 1);
TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
sei();
I2C_setCallbacks(I2C_received, I2C_requested);
}
int main()
{
I2C_init(I2C_ADDR);
for (uint8_t i=0;i<TWI_BUFFER_SIZE;i++){
txBuff[i]=((i*2)+2);
}
while(1)
{
}
return 0;
}
И вроде даже все нормально читается\пишется,как говориться приделывай в конце пакета CRC8 и радуйся жизни.
Ну я прям чувствую что где то у меня с этим TWI косяк. Мб кто чего посоветует ?



