Created
January 2, 2013 13:59
-
-
Save ossicode/4434782 to your computer and use it in GitHub Desktop.
temporary i2c master and slave all together. master mode is still working
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* i2c.c | |
* | |
* Created on: 2012. 12. 30. | |
* Author: OSSI | |
*/ | |
// we implement I2C as below: | |
// | |
// 7 bit addressing mode | |
// NO Multi-Master | |
#include "i2c.h" | |
// Master | |
// max buffer size | |
#define I2C_RX_BUFFER_SIZE 16 | |
#define I2C_TX_BUFFER_SIZE 16 | |
static uint16_t i2cRXIndex; | |
static uint16_t i2cTXIndex; | |
static uint8_t *rxData; | |
static uint8_t *txData; | |
// Slave | |
static uint16_t slaveRXIndex; | |
static uint16_t slaveTXIndex; | |
static uint8_t *slaveRXData; | |
static uint8_t *slaveTXData; | |
static uint8_t i2cTxFlag; | |
static uint8_t i2cRxFlag; | |
void i2c_setTxFlag(void) | |
{ | |
i2cTxFlag = 1; | |
} | |
void i2c_clearTxFlag(void) | |
{ | |
i2cTxFlag = 0; | |
} | |
uint8_t i2c_getTxFlag(void) | |
{ | |
return i2cTxFlag; | |
} | |
void i2c_setRxFlag(void) | |
{ | |
i2cRxFlag = 1; | |
} | |
void i2c_clearRxFlag(void) | |
{ | |
i2cRxFlag = 0; | |
} | |
uint8_t i2c_getRxFlag(void) | |
{ | |
return i2cRxFlag; | |
} | |
void i2c_portSetup(void) | |
{ | |
// For MSP430F2132, P3.1 = SDA, P3.2 = SCL | |
P3SEL |= 0x06; | |
} | |
// call this only when you need need master | |
void i2c_masterInit(uint8_t selctClockSource, uint16_t preScalerValue ,uint8_t modeSelect) | |
{ | |
ASSERT((selctClockSource == I2C_CLOCKSOURCE_ACLK)||(selctClockSource == I2C_CLOCKSOURCE_SMCLK)); | |
ASSERT((preScalerValue>=4) && (preScalerValue<=0xFFFF)); | |
ASSERT((modeSelect == I2C_TRANSMIT_MODE)||(modeSelect == I2C_RECEIVE_MODE)); | |
// reset I2C | |
UCB0CTL1 = UCSWRST; | |
// reset and set UCB0CTL0 for I2C mode | |
// UCA10 = 0 owe address 7 bit | |
// UCSLA10 = 0 slave address 7bit | |
// UCMM = 0 no multi-master | |
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; | |
// reset clock source while UCSWRST = 1 | |
UCB0CTL1 = selctClockSource + modeSelect + UCSWRST; | |
// fSCL = selctClockSource / preScalerValue | |
// for single master mode, minimum preScalerValue = 4 | |
UCB0BR0 = preScalerValue & 0xFF; | |
UCB0BR1 = (preScalerValue >> 8) & 0xFF; | |
UCB0CTL1 &= ~UCSWRST; | |
} | |
void i2c_setSlaveAddress(uint8_t slaveAddress) | |
{ | |
// slaveAddress is right justified. bit 6 is MSB for 7 bit address | |
// TODO:how to check whether we have valid 7 bit slaveAddress? | |
UCB0I2CSA = slaveAddress; | |
} | |
void i2c_enableRXInterrupt(void) | |
{ | |
IE2 |= UCB0RXIE; | |
} | |
void i2c_disableRXInterrupt(void) | |
{ | |
IE2 &= ~UCB0RXIE; | |
} | |
void i2c_enableTXInterrupt(void) | |
{ | |
IE2 |= UCB0TXIE; | |
} | |
void i2c_disableTXInterrupt(void) | |
{ | |
IE2 &= ~UCB0TXIE; | |
} | |
void i2c_masterReceive(uint8_t byteCount, uint8_t *data) | |
{ | |
ASSERT((byteCount >=1)&&(byteCount<=I2C_RX_BUFFER_SIZE)); | |
rxData = data; | |
if (byteCount == 1) | |
{ | |
i2cRXIndex = byteCount ; | |
__disable_interrupt(); | |
UCB0CTL1 |= UCTXSTT; // I2C start condition | |
while (UCB0CTL1 & UCTXSTT); // Start condition sent? | |
UCB0CTL1 |= UCTXSTP; // I2C stop condition | |
__enable_interrupt(); | |
} | |
else if (byteCount > 1) | |
{ | |
i2cRXIndex = byteCount ; | |
UCB0CTL1 |= UCTXSTT; // I2C start condition | |
} | |
} | |
void i2c_masterSend(uint8_t byteCount, uint8_t *data) | |
{ | |
ASSERT((byteCount >=1)&&(byteCount<=I2C_TX_BUFFER_SIZE)); | |
txData = data; | |
i2cTXIndex = byteCount; | |
UCB0CTL1 |= UCTXSTT; // I2C TX, start condition | |
} | |
void i2c_slaveInit(uint8_t rxByteCount, uint8_t *rxData, uint8_t txByteCount, uint8_t *txData) | |
{ | |
// initialize buffer and count | |
slaveRXData = rxData; | |
slaveTXData = txData; | |
slaveRXIndex = rxByteCount; | |
slaveTXIndex = txByteCount; | |
UCB0CTL1 |= UCSWRST; // Enable SW reset | |
UCB0CTL0 = UCMODE_3 + UCSYNC; // I2C Slave, synchronous mode | |
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation | |
IE2 |= UCB0TXIE + UCB0RXIE; // Enable TX interrupt | |
UCB0I2CIE |= UCSTTIE; // Enable STT interrupt | |
} | |
void i2c_setOwnAddress(uint8_t slaveAddress) | |
{ | |
UCB0I2COA = slaveAddress; | |
} | |
#pragma vector = USCIAB0RX_VECTOR | |
__interrupt void USCIAB0RX_ISR(void) | |
{ | |
// Master & Slave Mode: when NACK is detected | |
if (UCB0STAT & UCNACKIFG){ // send STOP if slave sends NACK | |
UCB0CTL1 |= UCTXSTP; | |
UCB0STAT &= ~UCNACKIFG; | |
// i2c_disableRXInterrupt(); | |
// TA0CCTL0 |= CCIE; | |
// __bic_SR_register_on_exit(LPM3_bits); | |
} | |
// Slave mode: when start condition is detected | |
if (UCB0STAT & UCSTTIFG) | |
{ | |
UCB0STAT &= ~UCSTTIFG; // Clear start condition int flag | |
// initialize something | |
// TI_start_callback(); | |
} | |
} | |
#pragma vector = USCIAB0TX_VECTOR | |
__interrupt void USCIAB0TX_ISR(void) | |
{ | |
// uart interrupt | |
if ((IFG2 & UCA0TXIFG) && (IE2 & UCA0TXIE)) | |
{ | |
IE2 &= ~UCA0TXIE; | |
} | |
// i2c RX interrupt | |
if (IFG2 & UCB0RXIFG) | |
{ | |
// Master | |
if (UCB0CTL0 & UCMST) | |
{ | |
//easier when we count down and compare for the one last byte to initiate STOP condition | |
i2cRXIndex--; | |
if (i2cRXIndex) | |
{ | |
*rxData = UCB0RXBUF; | |
rxData++; | |
if (i2cRXIndex == 1) | |
{ | |
UCB0CTL1 |= UCTXSTP; | |
} | |
} | |
else | |
{ | |
*rxData = UCB0RXBUF; | |
// when all bytes we want are received | |
// TODO: make separate process for the below | |
// i2c_disableRXInterrupt(); | |
// TA0CCTL0 |= CCIE; | |
// Back to Low Power Mode | |
__bic_SR_register_on_exit(LPM3_bits); | |
} | |
} | |
else | |
{ | |
// Slave | |
if(slaveRXIndex) | |
{ | |
*slaveRXData = UCB0RXBUF; | |
slaveRXData++; | |
slaveRXIndex --; | |
} | |
else | |
{ | |
// when we receive all data | |
} | |
} | |
} | |
// i2c TX interrupt | |
if (IFG2 & UCB0TXIFG) | |
{ | |
// Master | |
if (UCB0CTL0 & UCMST) | |
{ | |
//easier when we count down and compare for the one last byte to initiate STOP condition | |
if (i2cTXIndex) | |
{ | |
UCB0TXBUF=*txData; | |
txData++; | |
// When we send only one byte, do this after sending one byte | |
i2cTXIndex--; | |
} | |
else | |
{ | |
// When we send only one byte, do this after sending one byte | |
UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition right after sending last data | |
IFG2 &= ~UCB0TXIFG; | |
// send last byte | |
// UCB0TXBUF=*txData; | |
// i2c_disableTXInterrupt(); | |
// TA0CCTL0 |= CCIE; | |
// Back to Low Power Mode | |
// __bic_SR_register_on_exit(LPM3_bits); | |
} | |
} | |
else | |
{ | |
// Slave | |
if (slaveTXIndex) | |
{ | |
UCB0TXBUF = *slaveTXData; | |
slaveTXData++; | |
slaveTXIndex --; | |
} | |
else | |
{ | |
// when we transmit all the data | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment