wip:
This commit is contained in:
@@ -35,84 +35,10 @@ extern "C"
|
|||||||
|
|
||||||
avr_err_t zh_avr_i2c_master_init(const bool pullup);
|
avr_err_t zh_avr_i2c_master_init(const bool pullup);
|
||||||
avr_err_t zh_avr_i2c_master_probe(const uint8_t addr, TickType_t xTicksToWait);
|
avr_err_t zh_avr_i2c_master_probe(const uint8_t addr, TickType_t xTicksToWait);
|
||||||
avr_err_t zh_avr_i2c_master_transmit(const uint8_t addr, uint8_t *data, uint8_t size, size_t delay);
|
avr_err_t zh_avr_i2c_master_transmit(const uint8_t addr, uint8_t *data, uint8_t size, TickType_t xTicksToWait);
|
||||||
avr_err_t zh_avr_i2c_master_receive(const uint8_t addr, uint8_t *data, uint8_t size, size_t delay);
|
avr_err_t zh_avr_i2c_master_receive(const uint8_t addr, uint8_t *data, uint8_t size, TickType_t xTicksToWait);
|
||||||
avr_err_t zh_avr_i2c_master_transmit_receive(const uint8_t addr, uint8_t *write_data, uint8_t write_size, uint8_t *read_data, uint8_t read_size, size_t delay);
|
avr_err_t zh_avr_i2c_master_transmit_receive(const uint8_t addr, uint8_t *write_data, uint8_t write_size, uint8_t *read_data, uint8_t read_size, size_t delay);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef IICULTIMATE_H
|
|
||||||
#define IICULTIMATE_H
|
|
||||||
|
|
||||||
|
|
||||||
// #include <avrlibtypes.h>
|
|
||||||
// #include <avrlibdefs.h>
|
|
||||||
|
|
||||||
#define i2c_PORT PORTC // Порт где сидит нога TWI
|
|
||||||
#define i2c_DDR DDRC
|
|
||||||
#define i2c_SCL 0 // Биты соответствующих выводов
|
|
||||||
#define i2c_SDA 1
|
|
||||||
|
|
||||||
#define i2c_MasterAddress 0x32 // Адрес на который будем отзываться
|
|
||||||
#define i2c_i_am_slave 1 // Если мы еще и слейвом работаем то 1. А то не услышит!
|
|
||||||
|
|
||||||
#define i2c_MasterBytesRX 1 // Величина принимающего буфера режима Slave, т.е. сколько байт жрем.
|
|
||||||
#define i2c_MasterBytesTX 1 // Величина Передающего буфера режима Slave , т.е. сколько байт отдаем за сессию.
|
|
||||||
|
|
||||||
#define i2c_MaxBuffer 3 // Величина буфера Master режима RX-TX. Зависит от того какой длины строки мы будем гонять
|
|
||||||
#define i2c_MaxPageAddrLgth 2 // Максимальная величина адреса страницы. Обычно адрес страницы это один или два байта.
|
|
||||||
// Зависит от типа ЕЕПРОМ или другой микросхемы.
|
|
||||||
|
|
||||||
#define i2c_type_msk 0b00001100 // Маска режима
|
|
||||||
#define i2c_sarp 0b00000000 // Start-Addr_R-Read-Stop Это режим простого чтения. Например из слейва или из епрома с текущего адреса
|
|
||||||
#define i2c_sawp 0b00000100 // Start-Addr_W-Write-Stop Это режим простой записи. В том числе и запись с адресом страницы.
|
|
||||||
#define i2c_sawsarp 0b00001000 // Start-Addr_W-WrPageAdr-rStart-Addr_R-Read-Stop Это режим с предварительной записью текущего адреса страницы
|
|
||||||
|
|
||||||
#define i2c_Err_msk 0b00110011 // Маска кода ошибок
|
|
||||||
#define i2c_Err_NO 0b00000000 // All Right! -- Все окей, передача успешна.
|
|
||||||
#define i2c_ERR_NA 0b00010000 // Device No Answer -- Слейв не отвечает. Т.к. либо занят, либо его нет на линии.
|
|
||||||
#define i2c_ERR_LP 0b00100000 // Low Priority -- нас перехватили собственным адресом, либо мы проиграли арбитраж
|
|
||||||
#define i2c_ERR_NK 0b00000010 // Received NACK. End Transmittion. -- Был получен NACK. Бывает и так.
|
|
||||||
#define i2c_ERR_BF 0b00000001 // BUS FAIL -- Автобус сломался. И этим все сказано. Можно попробовать сделать переинициализацию шины
|
|
||||||
|
|
||||||
#define i2c_Interrupted 0b10000000 // Transmiting Interrupted Битмаска установки флага занятости
|
|
||||||
#define i2c_NoInterrupted 0b01111111 // Transmiting No Interrupted Битмаска снятия флага занятости
|
|
||||||
|
|
||||||
#define i2c_Busy 0b01000000 // Trans is Busy Битмаска флага "Передатчик занят, руками не трогать".
|
|
||||||
#define i2c_Free 0b10111111 // Trans is Free Битмаска снятия флага занятости.
|
|
||||||
|
|
||||||
#define MACRO_i2c_WhatDo_MasterOut (MasterOutFunc)(); // Макросы для режимо выхода. Пока тут функция, но может быть что угодно
|
|
||||||
#define MACRO_i2c_WhatDo_SlaveOut (SlaveOutFunc)();
|
|
||||||
#define MACRO_i2c_WhatDo_ErrorOut (ErrorOutFunc)();
|
|
||||||
|
|
||||||
typedef void (*IIC_F)(void); // Тип указателя на функцию
|
|
||||||
|
|
||||||
extern IIC_F MasterOutFunc; // Подрбрости в сишнике.
|
|
||||||
extern IIC_F SlaveOutFunc;
|
|
||||||
extern IIC_F ErrorOutFunc;
|
|
||||||
|
|
||||||
extern uint8_t i2c_Do;
|
|
||||||
extern uint8_t i2c_InBuff[i2c_MasterBytesRX];
|
|
||||||
extern uint8_t i2c_OutBuff[i2c_MasterBytesTX];
|
|
||||||
|
|
||||||
extern uint8_t i2c_SlaveIndex;
|
|
||||||
|
|
||||||
extern uint8_t i2c_Buffer[i2c_MaxBuffer];
|
|
||||||
extern uint8_t i2c_index;
|
|
||||||
extern uint8_t i2c_ByteCount;
|
|
||||||
|
|
||||||
extern uint8_t i2c_SlaveAddress;
|
|
||||||
extern uint8_t i2c_PageAddress[i2c_MaxPageAddrLgth];
|
|
||||||
|
|
||||||
extern uint8_t i2c_PageAddrIndex;
|
|
||||||
extern uint8_t i2c_PageAddrCount;
|
|
||||||
|
|
||||||
void Init_i2c(void);
|
|
||||||
void Init_Slave_i2c(IIC_F Addr);
|
|
||||||
|
|
||||||
extern uint8_t WorkLog[100];
|
|
||||||
extern uint8_t WorkIndex;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
169
zh_avr_i2c.c
169
zh_avr_i2c.c
@@ -17,16 +17,23 @@
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
MASTER_TX,
|
MASTER_WRITE,
|
||||||
MASTER_RX,
|
MASTER_READ,
|
||||||
MASTER_TX_RX,
|
MASTER_WRITE_REG,
|
||||||
MASTER_PR
|
MASTER_READ_REG,
|
||||||
|
MASTER_PROBE
|
||||||
} _work_mode_t;
|
} _work_mode_t;
|
||||||
|
|
||||||
|
avr_err_t _zh_avr_i2c_master_start(TickType_t xTicksToWait);
|
||||||
|
|
||||||
static EventGroupHandle_t _event_group_handle = NULL;
|
static EventGroupHandle_t _event_group_handle = NULL;
|
||||||
static uint8_t _target_i2c_address = 0;
|
static uint8_t _target_i2c_address = 0;
|
||||||
volatile static uint8_t _work_mode = 0;
|
volatile static uint8_t _work_mode = 0;
|
||||||
|
|
||||||
|
volatile static uint8_t *_master_tx_data = NULL;
|
||||||
|
volatile static uint8_t _master_tx_data_size = 0;
|
||||||
|
volatile static uint8_t _master_tx_data_counter = 0;
|
||||||
|
|
||||||
avr_err_t zh_avr_i2c_master_init(const bool pullup)
|
avr_err_t zh_avr_i2c_master_init(const bool pullup)
|
||||||
{
|
{
|
||||||
_event_group_handle = xEventGroupCreate();
|
_event_group_handle = xEventGroupCreate();
|
||||||
@@ -45,8 +52,39 @@ avr_err_t zh_avr_i2c_master_init(const bool pullup)
|
|||||||
|
|
||||||
avr_err_t zh_avr_i2c_master_probe(const uint8_t addr, TickType_t xTicksToWait)
|
avr_err_t zh_avr_i2c_master_probe(const uint8_t addr, TickType_t xTicksToWait)
|
||||||
{
|
{
|
||||||
_work_mode = MASTER_PR;
|
_work_mode = MASTER_PROBE;
|
||||||
_target_i2c_address = addr;
|
_target_i2c_address = addr;
|
||||||
|
return _zh_avr_i2c_master_start(xTicksToWait);
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_err_t zh_avr_i2c_master_transmit(const uint8_t addr, uint8_t *data, uint8_t size, TickType_t xTicksToWait)
|
||||||
|
{
|
||||||
|
ZH_ERROR_CHECK(data != NULL || size > 0, AVR_ERR_INVALID_ARG);
|
||||||
|
_work_mode = MASTER_WRITE;
|
||||||
|
_target_i2c_address = addr;
|
||||||
|
_master_tx_data = data;
|
||||||
|
_master_tx_data_size = size;
|
||||||
|
_master_tx_data_counter = 0;
|
||||||
|
return _zh_avr_i2c_master_start(xTicksToWait);
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_err_t zh_avr_i2c_master_receive(const uint8_t addr, uint8_t *data, uint8_t size, TickType_t xTicksToWait)
|
||||||
|
{
|
||||||
|
ZH_ERROR_CHECK(data != NULL || size > 0, AVR_ERR_INVALID_ARG);
|
||||||
|
_work_mode = MASTER_READ;
|
||||||
|
_target_i2c_address = addr;
|
||||||
|
_master_tx_data_size = size;
|
||||||
|
_master_tx_data_counter = 0;
|
||||||
|
return _zh_avr_i2c_master_start(xTicksToWait);
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_err_t zh_avr_i2c_master_transmit_receive(const uint8_t addr, uint8_t *write_data, uint8_t write_size, uint8_t *read_data, uint8_t read_size, size_t delay)
|
||||||
|
{
|
||||||
|
return AVR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_err_t _zh_avr_i2c_master_start(TickType_t xTicksToWait)
|
||||||
|
{
|
||||||
TWCR = I2C_START | (1 << TWSTA);
|
TWCR = I2C_START | (1 << TWSTA);
|
||||||
EventBits_t bits = xEventGroupWaitBits(_event_group_handle, I2C_OK | I2C_NACK | I2C_COLLISION | I2C_BUS_FAIL, pdTRUE, pdFALSE, xTicksToWait);
|
EventBits_t bits = xEventGroupWaitBits(_event_group_handle, I2C_OK | I2C_NACK | I2C_COLLISION | I2C_BUS_FAIL, pdTRUE, pdFALSE, xTicksToWait);
|
||||||
if ((bits & I2C_OK) != 0)
|
if ((bits & I2C_OK) != 0)
|
||||||
@@ -63,48 +101,7 @@ avr_err_t zh_avr_i2c_master_probe(const uint8_t addr, TickType_t xTicksToWait)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
avr_err_t zh_avr_i2c_master_transmit(const uint8_t addr, uint8_t *data, uint8_t size, size_t delay)
|
ISR(TWI_vect)
|
||||||
{
|
|
||||||
TWCR = (1 << TWINT) | (0 << TWEA) | (1 << TWSTA) | (0 << TWSTO) | (0 << TWWC) | (1 << TWEN) | (1 << TWIE);
|
|
||||||
return AVR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
avr_err_t zh_avr_i2c_master_receive(const uint8_t addr, uint8_t *data, uint8_t size, size_t delay)
|
|
||||||
{
|
|
||||||
return AVR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
avr_err_t zh_avr_i2c_master_transmit_receive(const uint8_t addr, uint8_t *write_data, uint8_t write_size, uint8_t *read_data, uint8_t read_size, size_t delay)
|
|
||||||
{
|
|
||||||
return AVR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoNothing(void);
|
|
||||||
|
|
||||||
uint8_t i2c_Do; // Переменная состояния передатчика IIC
|
|
||||||
uint8_t i2c_InBuff[i2c_MasterBytesRX]; // Буфер прием при работе как Slave
|
|
||||||
uint8_t i2c_OutBuff[i2c_MasterBytesTX]; // Буфер передачи при работе как Slave
|
|
||||||
uint8_t i2c_SlaveIndex; // Индекс буфера Slave
|
|
||||||
|
|
||||||
uint8_t i2c_Buffer[i2c_MaxBuffer]; // Буфер для данных работы в режиме Master
|
|
||||||
uint8_t i2c_index; // Индекс этого буфера
|
|
||||||
uint8_t i2c_ByteCount; // Число байт передаваемых
|
|
||||||
|
|
||||||
uint8_t i2c_SlaveAddress; // Адрес подчиненного
|
|
||||||
|
|
||||||
uint8_t i2c_PageAddress[i2c_MaxPageAddrLgth]; // Буфер адреса страниц (для режима с sawsarp)
|
|
||||||
uint8_t i2c_PageAddrIndex; // Индекс буфера адреса страниц
|
|
||||||
uint8_t i2c_PageAddrCount; // Число байт в адресе страницы для текущего Slave
|
|
||||||
|
|
||||||
// Указатели выхода из автомата:
|
|
||||||
IIC_F MasterOutFunc = &DoNothing; // в Master режиме
|
|
||||||
IIC_F SlaveOutFunc = &DoNothing; // в режиме Slave
|
|
||||||
IIC_F ErrorOutFunc = &DoNothing; // в результате ошибки в режиме Master
|
|
||||||
|
|
||||||
uint8_t WorkLog[100]; // Лог пишем сюда
|
|
||||||
uint8_t WorkIndex = 0; // Индекс лога
|
|
||||||
|
|
||||||
ISR(TWI_vect) // Прерывание TWI Тут наше все.
|
|
||||||
{
|
{
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
switch (TWSR & 0xF8) // Отсекаем биты прескалера
|
switch (TWSR & 0xF8) // Отсекаем биты прескалера
|
||||||
@@ -118,35 +115,60 @@ ISR(TWI_vect) // Прерывание TWI Тут наше все.
|
|||||||
printf("08\n");
|
printf("08\n");
|
||||||
switch (_work_mode)
|
switch (_work_mode)
|
||||||
{
|
{
|
||||||
case MASTER_TX:
|
case MASTER_WRITE:
|
||||||
|
TWDR = (_target_i2c_address << 1) | I2C_MASTER_WRITE;
|
||||||
|
// TWCR = I2C_START;
|
||||||
break;
|
break;
|
||||||
case MASTER_RX:
|
case MASTER_READ:
|
||||||
break;
|
|
||||||
case MASTER_TX_RX:
|
|
||||||
break;
|
|
||||||
case MASTER_PR:
|
|
||||||
TWDR = (_target_i2c_address << 1) | I2C_MASTER_READ;
|
TWDR = (_target_i2c_address << 1) | I2C_MASTER_READ;
|
||||||
TWCR = I2C_START;
|
// TWCR = I2C_START;
|
||||||
|
break;
|
||||||
|
case MASTER_WRITE_REG:
|
||||||
|
break;
|
||||||
|
case MASTER_READ_REG:
|
||||||
|
break;
|
||||||
|
case MASTER_PROBE:
|
||||||
|
TWDR = (_target_i2c_address << 1) | I2C_MASTER_READ;
|
||||||
|
// TWCR = I2C_START;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
TWCR = I2C_START;
|
||||||
break;
|
break;
|
||||||
case 0x10: // A repeated START condition has been transmitted.
|
case 0x10: // A repeated START condition has been transmitted.
|
||||||
printf("10\n");
|
printf("10\n");
|
||||||
TWCR = I2C_START | (1 << TWSTO);
|
// TWCR = I2C_START | (1 << TWSTO);
|
||||||
break;
|
break;
|
||||||
case 0x18: // SLA+W has been transmitted. ACK has been received.
|
case 0x18: // SLA+W has been transmitted. ACK has been received.
|
||||||
printf("18\n");
|
printf("18\n");
|
||||||
|
TWDR = *(_master_tx_data++);
|
||||||
|
_master_tx_data_counter++;
|
||||||
|
TWCR = I2C_START;
|
||||||
break;
|
break;
|
||||||
case 0x20: // SLA+W has been transmitted. NOT ACK has been received.
|
case 0x20: // SLA+W has been transmitted. NOT ACK has been received.
|
||||||
printf("20\n");
|
printf("20\n");
|
||||||
|
TWCR = I2C_START | (1 << TWSTO);
|
||||||
|
xEventGroupSetBitsFromISR(_event_group_handle, I2C_NACK, &xHigherPriorityTaskWoken);
|
||||||
break;
|
break;
|
||||||
case 0x28: // Data byte has been transmitted. ACK has been received.
|
case 0x28: // Data byte has been transmitted. ACK has been received.
|
||||||
printf("28\n");
|
printf("28\n");
|
||||||
|
if (_master_tx_data_counter < _master_tx_data_size)
|
||||||
|
{
|
||||||
|
TWDR = *(_master_tx_data++);
|
||||||
|
_master_tx_data_counter++;
|
||||||
|
TWCR = I2C_START;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TWCR = I2C_START | (1 << TWSTO);
|
||||||
|
xEventGroupSetBitsFromISR(_event_group_handle, I2C_OK, &xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x30: // Data byte has been transmitted. NOT ACK has been received.
|
case 0x30: // Data byte has been transmitted. NOT ACK has been received.
|
||||||
printf("30\n");
|
printf("30\n");
|
||||||
|
TWCR = I2C_START | (1 << TWSTO);
|
||||||
|
xEventGroupSetBitsFromISR(_event_group_handle, I2C_NACK, &xHigherPriorityTaskWoken);
|
||||||
break;
|
break;
|
||||||
case 0x38: // Arbitration lost in SLA+W or data bytes. Arbitration lost in SLA+R or NOT ACK bit.
|
case 0x38: // Arbitration lost in SLA+W or data bytes. Arbitration lost in SLA+R or NOT ACK bit.
|
||||||
printf("38\n");
|
printf("38\n");
|
||||||
@@ -157,13 +179,15 @@ ISR(TWI_vect) // Прерывание TWI Тут наше все.
|
|||||||
printf("40\n");
|
printf("40\n");
|
||||||
switch (_work_mode)
|
switch (_work_mode)
|
||||||
{
|
{
|
||||||
case MASTER_TX:
|
case MASTER_WRITE:
|
||||||
break;
|
break;
|
||||||
case MASTER_RX:
|
case MASTER_READ:
|
||||||
break;
|
break;
|
||||||
case MASTER_TX_RX:
|
case MASTER_WRITE_REG:
|
||||||
break;
|
break;
|
||||||
case MASTER_PR:
|
case MASTER_READ_REG:
|
||||||
|
break;
|
||||||
|
case MASTER_PROBE:
|
||||||
TWCR = I2C_START | (1 << TWSTO);
|
TWCR = I2C_START | (1 << TWSTO);
|
||||||
xEventGroupSetBitsFromISR(_event_group_handle, I2C_OK, &xHigherPriorityTaskWoken);
|
xEventGroupSetBitsFromISR(_event_group_handle, I2C_OK, &xHigherPriorityTaskWoken);
|
||||||
break;
|
break;
|
||||||
@@ -675,31 +699,4 @@ ISR(TWI_vect) // Прерывание TWI Тут наше все.
|
|||||||
{
|
{
|
||||||
portYIELD();
|
portYIELD();
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
void DoNothing(void) // Функция пустышка, затыкать несуществующие ссылки
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// void Init_i2c(void) // Настройка режима мастера
|
|
||||||
// {
|
|
||||||
// i2c_PORT |= 1 << i2c_SCL | 1 << i2c_SDA; // Включим подтяжку на ноги, вдруг юзер на резисторы пожмотился
|
|
||||||
// i2c_DDR &= ~(1 << i2c_SCL | 1 << i2c_SDA);
|
|
||||||
|
|
||||||
// TWBR = 0x80; // Настроим битрейт
|
|
||||||
// TWSR = 0x00;
|
|
||||||
// }
|
|
||||||
|
|
||||||
void Init_Slave_i2c(IIC_F Addr) // Настройка режима слейва (если нужно)
|
|
||||||
{
|
|
||||||
TWAR = i2c_MasterAddress; // Внесем в регистр свой адрес, на который будем отзываться.
|
|
||||||
// 1 в нулевом бите означает, что мы отзываемся на широковещательные пакеты
|
|
||||||
SlaveOutFunc = Addr; // Присвоим указателю выхода по слейву функцию выхода
|
|
||||||
|
|
||||||
TWCR = 0 << TWSTA |
|
|
||||||
0 << TWSTO |
|
|
||||||
0 << TWINT |
|
|
||||||
1 << TWEA |
|
|
||||||
1 << TWEN |
|
|
||||||
1 << TWIE; // Включаем агрегат и начинаем слушать шину.
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user