📄 rp6i2cmastertwi.c
字号:
/* ****************************************************************************
* _______________________
* \| RP6 ROBOT SYSTEM |/
* \_-_-_-_-_-_-_-_-_-_/ >>> BASE CONTROLLER
* ----------------------------------------------------------------------------
* ------------------- [c]2006 / 2007 - AREXX ENGINEERING ---------------------
* -------------------------- http://www.arexx.com/ ---------------------------
* ****************************************************************************
* File: RP6I2CmasterTWI.c
* Version: 1.0
* Target: RP6 Base & Processor Expansion - ATMEGA32 @8.00 or 16.00MHz
* Author(s): Dominik S. Herwald
* ****************************************************************************
* Description:
* This is the I2C Bus Master Library.
*
* ****************************************************************************
* CHANGELOG AND LICENSING INFORMATION CAN BE FOUND AT THE END OF THIS FILE!
* ****************************************************************************
*/
/*****************************************************************************/
// Includes:
#include "RP6I2CmasterTWI.h"
/*
* This function initializes the TWI interface! You need
* to call this first before you use the TWI interface!
* You should better use the macro I2CTWI_initMaster without __ at the
* beginning. There you can specify the SCL frequency in kHz!
* Example:
* I2CTWI_initMaster(100); // I2C Master mode with 100kHz SCL frequency
* // This calculates TWBR value automatically.
*
* __I2CTWI_initMaster(32); // I2C Master mode also with 100kHz SCL frequency
* // but directly calculated with the formula in the
* // MEGA32 datasheet.
*/
void __I2CTWI_initMaster(uint8_t twi_bitrate)
{
cli();
TWBR = twi_bitrate;
TWSR = 0x00; // DO NOT USE PRESCALER! Otherwise you need to mask the
TWDR = 0xFF; // TWSR Prescaler bits everywhere TWSR is read!
TWCR = (1<<TWEN);
TWI_statusReg.lastTransOK = 1;
sei();
}
/*****************************************************************************/
// TWI Event handlers
// These functions are used to receive Data or react on errors.
void I2CTWI_requestedDataReady_DUMMY(uint8_t requestID){}
static void (*I2CTWI_requestedDataReadyHandler)(uint8_t) = I2CTWI_requestedDataReady_DUMMY;
void I2CTWI_setRequestedDataReadyHandler(void (*requestedDataReadyHandler)(uint8_t))
{
I2CTWI_requestedDataReadyHandler = requestedDataReadyHandler;
}
void I2CTWI_transmissionError_DUMMY(uint8_t requestID){}
static void (*I2CTWI_transmissionErrorHandler)(uint8_t) = I2CTWI_transmissionError_DUMMY;
void I2CTWI_setTransmissionErrorHandler(void (*transmissionErrorHandler)(uint8_t))
{
I2CTWI_transmissionErrorHandler = transmissionErrorHandler;
}
/*****************************************************************************/
// Delay
/**
* A small delay that is required between some transfers. Without this delay
* the transmission may fail.
*/
void I2CTWI_delay(void)
{
volatile uint8_t dly = 150;
while(dly--);
}
/*****************************************************************************/
// Control task
static uint8_t I2CTWI_buf[I2CTWI_BUFFER_SIZE];
static uint8_t I2CTWI_recbuf[I2CTWI_BUFFER_REC_SIZE];
static uint8_t TWI_msgSize;
volatile union TWI_statusReg TWI_statusReg = {0};
uint8_t TWI_TWSR_state = 0;
uint8_t I2CTWI_request_adr = 0;
uint8_t I2CTWI_request_reg = 0;
uint8_t I2CTWI_request_size = 0;
int16_t I2CTWI_requestID = 0;
uint8_t TWI_operation = I2CTWI_NO_OPERATION;
/**
* You have to call this functions frequently out of the
* main loop. It calls the event handlers above automatically if data has been received.
*/
void task_I2CTWI(void)
{
if (!I2CTWI_isBusy()) {
if (TWI_statusReg.lastTransOK) {
if(TWI_operation) {
if(TWI_operation == I2CTWI_SEND_REGISTER) {
I2CTWI_delay();
TWI_msgSize = 2;
I2CTWI_buf[0] = I2CTWI_request_adr;
I2CTWI_buf[1] = I2CTWI_request_reg;
TWI_statusReg.all = 0;
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(1<<TWSTA)|(0<<TWSTO);
TWI_operation = I2CTWI_REQUEST_BYTES;
}
else if (TWI_operation == I2CTWI_REQUEST_BYTES) {
I2CTWI_delay();
TWI_msgSize = I2CTWI_request_size + 1;
I2CTWI_request_adr = I2CTWI_request_adr | TWI_READ;
I2CTWI_buf[0] = I2CTWI_request_adr | TWI_READ;
TWI_statusReg.all = 0;
TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(1<<TWSTA)|(0<<TWSTO);
TWI_operation = I2CTWI_READ_BYTES_FROM_BUFFER;
}
else if (TWI_operation == I2CTWI_READ_BYTES_FROM_BUFFER) {
TWI_operation = I2CTWI_NO_OPERATION;
if(I2CTWI_requestID!=-1)
I2CTWI_requestedDataReadyHandler(I2CTWI_requestID);
}
}
}
else {
uint8_t errState = I2CTWI_getState();
if(errState != 0) {
TWI_operation = I2CTWI_NO_OPERATION;
TWI_statusReg.lastTransOK = 1;
I2CTWI_request_adr = 0;
I2CTWI_requestID = 0;
I2CTWI_request_size = 0;
I2CTWI_transmissionErrorHandler(errState);
}
}
}
}
/*****************************************************************************/
// Request functions - you need to use requestedDataReadyHandler to receive
// the requested data...
/**
* Requests a number of Bytes from the target device. You need to set a requestID
* to be able to identify the request after the data has been received and the
* "requestedDataReady" event handler is called.
*/
void I2CTWI_requestDataFromDevice(uint8_t targetAdr, uint8_t requestID, uint8_t numberOfBytes)
{
while(I2CTWI_isBusy() || TWI_operation != I2CTWI_NO_OPERATION) task_I2CTWI();
TWI_operation = I2CTWI_REQUEST_BYTES;
I2CTWI_request_adr = targetAdr;
I2CTWI_requestID = (int16_t)requestID;
I2CTWI_request_size = numberOfBytes;
}
/**
* Same as requestDataFromDevice, but this function first sets the register
* that has to be read and transmits the register number before!
* This is neccessary for the reaction on interrupt requests of slave devices as this
* function is non-blocking and thus very well suited for calls directly from ISRs.
*/
void I2CTWI_requestRegisterFromDevice(uint8_t targetAdr, uint8_t requestID, uint8_t reg, uint8_t numberOfBytes)
{
while(I2CTWI_isBusy() || TWI_operation != I2CTWI_NO_OPERATION) task_I2CTWI();
TWI_operation = I2CTWI_SEND_REGISTER;
I2CTWI_requestID = (int16_t)requestID;
I2CTWI_request_adr = targetAdr;
I2CTWI_request_reg = reg;
I2CTWI_request_size = numberOfBytes;
}
/**
* This function can be used in the requestedDataReady Handler to get the
* received data from the TWI Buffer. You need to provide a pointer to a
* buffer which is large enough to hold all received data.
* You can specify the number of bytes you want to read out of the buffer
* with the msgSize parameter.
* It does not make sense to use this function anywhere else as you
* can not guarantee what is in the reception buffer...
*/
void I2CTWI_getReceivedData(uint8_t *msg, uint8_t msgSize)
{
while(I2CTWI_isBusy());
uint8_t i = 0;
if(TWI_statusReg.lastTransOK)
for(; i < msgSize; i++)
msg[i] = I2CTWI_recbuf[i+1];
}
/**
* This function returns the last TWI State / Error State. It waits until
* TWI Module has completed last operation!
*/
uint8_t I2CTWI_getState(void)
{
while(I2CTWI_isBusy()); // Wait until TWI has completed the transmission.
return (TWI_TWSR_state); // Return error state.
}
/*****************************************************************************/
// Read functions:
/**
* Reads "numberOfBytes" from "targetAdr" Register "reg" into "messageBuffer".
* If the slave device supports auto increment, then it reads all subsequent registers of course!
*/
void I2CTWI_readRegisters(uint8_t targetAdr, uint8_t reg, uint8_t * messageBuffer, uint8_t numberOfBytes)
{
while(I2CTWI_isBusy() || TWI_operation != I2CTWI_NO_OPERATION) task_I2CTWI();
TWI_operation = I2CTWI_SEND_REGISTER;
I2CTWI_request_adr = targetAdr;
I2CTWI_requestID = -1;
I2CTWI_request_reg = reg;
I2CTWI_request_size = numberOfBytes;
while(I2CTWI_isBusy() || TWI_operation != I2CTWI_NO_OPERATION) task_I2CTWI();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -