⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rp6i2cmastertwi.c

📁 RP6机器人范例程序。包括移动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ****************************************************************************
 *                           _______________________
 *                           \| 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 + -