📄 i2c_master.c
字号:
//******************************************************************************
//
// /|\ /|\
// MSP430F169 5k 5k MSP430F169
// slave | | master
// -----------------| | | -----------------
// 8Mhz--|XT2IN P2.0|<-|----+>|P3.1 |
// |XT2OUT | | | |
// | | | | XIN|-- 32768 Hz
// 32768Hz--|XIN P1.0|<-+----->|P3.3 XOUT|--
// |XOUT | | |
//
//
//******************************************************************************
#include <msp430x16x.h>
#define UART_TX_RETRY 10000
//#define DELTA 900 // target DCO = DELTA*(4096) = 3686400
#define DELTA 244 // target DCO = DELTA*(4096) = 1048576
//#define DELTA 70 // target DCO = DELTA*(4096) = 286720
#define DCO_FREQ ((double)DELTA * 4096) // DCO frequency
#define UART_BAUD_RATE 9600 // Baud Rate
#define DEBOUNCE_CNT 20
#define I2C_ADDR 0x23
#define EVENT_SW1 0x01
#define EVENT_SW2 0x02
#define EVENT_INT 0x04
//
// I2C Message Identifiers
//
#define SET_RTC_PARAMS 0
#define GET_RTC_PARAMS 1
#define SEND_IR_DATA 2
#define GET_LAST_IR_VALUE 3
#define GET_INPUT_STATE 4
#define GET_EVENT 5
//
// Event Flags for I2C getEvent message
//
#define EVENT_STATE_CHG 0x01 // Input signal state change
#define EVENT_IR_DATA 0x02 // IR data ready
void sysInit(void);
void setDCO(void);
void configUart1(void);
void configI2C(void);
void configWDT(void);
void iicSend(unsigned char addr, unsigned char bytes, unsigned char rwflag);
void sw1Options(void);
void sw2Options(void);
void txStr(const char* pStr);
void txByte(unsigned char byte);
void txWord(unsigned int word);
void setRTC(void);
void getRTC(void);
void getIRData(void);
void getIRVal(void);
void getInputState(void);
void getEvent(void);
unsigned char rxMsgLen;
unsigned char debounceCnt[3];
unsigned char Event = 0;
unsigned char rxIdx;
unsigned char RX_DATA[32];
unsigned char txIdx;
unsigned char TX_DATA[32];
//
// Low-level system initialization - called prior to main()
//
int __low_level_init(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
return (1); // Force initialization of RAM
// return (0); // Skip initialization of RAM
}
//
// Set DCO to selected frequency
//
void setDCO(void)
{
unsigned int Compare, Oldcapture = 0;
BCSCTL1 |= DIVA_3; // ACLK= LFXT1CLK/8
CCTL2 = CM_1 + CCIS_1 + CAP; // CAP, ACLK
TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear
while(1)
{
while (!(CCIFG & CCTL2)); // Wait until capture occured
CCTL2 &= ~CCIFG; // Capture occured, clear flag
Compare = CCR2; // Get current captured SMCLK
Compare = Compare - Oldcapture; // SMCLK difference
Oldcapture = CCR2; // Save current captured SMCLK
if (DELTA == Compare)
{
break; // If equal, leave "while(1)"
}
else if (DELTA < Compare) // DCO is too fast, slow it down
{
DCOCTL--;
if (DCOCTL == 0xFF)
{
if (!(BCSCTL1 == (XT2OFF + DIVA_3)))
BCSCTL1--; // Did DCO roll under?, Sel lower RSEL
}
}
else
{
DCOCTL++;
if (DCOCTL == 0x00)
{
if (!(BCSCTL1 == (XT2OFF + DIVA_3 + 0x07)))
BCSCTL1++; // Did DCO roll over? Sel higher RSEL
}
}
}
CCTL2 = 0; // Stop CCR2
TACTL = 0; // Stop Timer_A
}
//
// System Initialization
//
void sysInit(void)
{
setDCO(); // Set DCO
P1IES |= 0x30; // Set P1.5,4 for 1->0 interrupt
P1IFG = 0x00; // Clear P1 interrupt flags
P1IE |= 0x30; // Enable P1.5,4 interrupts
P5DIR |= 0x70; // P5.6,5,4 outputs
P5SEL |= 0x70; // P5.6,5,4 options
P2OUT = 0x00;
P2IES &= ~0x01; // Enable P2.0 interrupt
P2IFG &= ~0x01; // Enable P2.0 interrupt
P2IE |= 0x01; // Enable P2.0 interrupt
configI2C();
configUart1();
configWDT();
}
void configI2C(void)
{
P3SEL |= 0x0A; // Select I2C pins
U0CTL = SWRST; // Recommended init procedure
U0CTL |= I2C + SYNC; // Recommended init procedure
U0CTL &= ~I2CEN; // Recommended init procedure
I2COA = 0x30; // OWN ADDRESS
I2CPSC = 0;
I2CSCLH = 0;
I2CSCLL = 0;
I2CTCTL = I2CSSEL1+I2CRM; // SMCLK, repeat Mode
U0CTL |= I2CEN; // Enable I2C
}
//
// Configure USART1 for UART mode
//
void configUart1(void)
{
unsigned int rate;
// Calculate Buad Rate Clock divider values
rate = (DCO_FREQ/UART_BAUD_RATE);
P3SEL |= 0xC0; // P3.7,6 = URXD1/UTXD1
ME2 |= UTXE1 + URXE1; // Enable USART1 TXD/RXD
U1CTL |= (CHAR + SWRST); // 8-bit char, reset
U1TCTL |= SSEL1; // BRCLK = SMCLK
U1BR0 = (unsigned char)(rate & 0xff); // Lower 8 bits of BR clk divider
U1BR1 = (unsigned char)(rate >> 8); // Upper 8 bits of BR clk divider
U1MCTL = 0; // Modulation
U1CTL &= ~SWRST; // Initialize USART state machine
IE2 |= URXIE1; // Enable USART1 RX interrupt
}
//
// Configure Watchdog Timer
//
void configWDT(void)
{
WDTCTL = WDT_ADLY_1_9; // Clk source is ACLK,
// interval timer mode,
// clear, divide by 32768
}
//
// I2C Send
//
void iicSend(unsigned char addr, unsigned char bytes, unsigned char rwflag)
{
while( I2CDCTL & I2CBB ){} // Wait for I2C bus to stop being busy
if( rwflag ) // Read
{
I2CIE = 0; // Disable I2C interrupts
I2CIFG = 0;
rxIdx = 0; // Reset buffer index
I2CSA = addr; // Slave Address is 048h
U0CTL &= ~I2CEN; // Recommended init procedure
I2CTCTL = I2CSSEL1 + I2CRM; // SMCLK, repeat Mode
U0CTL |= I2CEN; // Enable I2C
I2CIE = RXRDYIE; // Enable RXRDYIFG interrupt
U0CTL |= MST;
I2CTCTL |= I2CSTT;
}
else // Write
{
I2CIE = 0; // Disable I2C interrupts
I2CIFG = 0;
txIdx = 0; // Reset buffer index
I2CSA = addr; // Slave Address is 048h
U0CTL &= ~I2CEN; // Recommended init procedure
I2CTCTL = I2CSSEL1; // SMCLK
U0CTL |= I2CEN; // Enable I2C
I2CNDAT = bytes; // Set number of bytes to write
I2CIE = TXRDYIE; // Enable I2C interrupts
U0CTL |= MST; // Master
I2CTCTL |= I2CTRX + I2CSTT + I2CSTP; // Transmit, start, stop
}
}
//
// Main
//
void main(void)
{
unsigned char x;
// Initialize System
sysInit();
txStr("\x1b[2JI2C Master\r\n\n");
while(1)
{
if( Event == 0 )
{
// Enter low-power mode 0 with interrupts enabled
_BIS_SR(LPM0_bits + GIE);
_NOP();
}
if( Event & EVENT_SW1 )
{
Event &= ~EVENT_SW1; // SW1 Event
sw1Options();
}
if( Event & EVENT_SW2 )
{
Event &= ~EVENT_SW2; // SW2 Event
sw2Options();
}
if( Event & EVENT_INT )
{
Event &= ~EVENT_INT; // Interrupt Event
txStr("\r\n\n\nInt - Get Interrupt Event");
getEvent();
iicSend(I2C_ADDR, TX_DATA[0], 0); // I2C write
iicSend(I2C_ADDR, 0, 1); // I2C read
txStr("\r\nInterrupt Event:");
for(x = 1; x < RX_DATA[0]; x++)
{
txStr(" ");
txByte(RX_DATA[x]);
}
if( RX_DATA[2] & EVENT_STATE_CHG )
{
txStr("\r\nInt - Get Input Pin State");
getInputState();
iicSend(I2C_ADDR, TX_DATA[0], 0); // I2C write
iicSend(I2C_ADDR, 0, 1); // I2C read
txStr("\r\nPin State:");
for(x = 1; x < RX_DATA[0]; x++)
{
txStr(" ");
txByte(RX_DATA[x]);
}
}
if( RX_DATA[2] & EVENT_IR_DATA )
{
txStr("\r\nInt - Get IR Data");
getIRData();
iicSend(I2C_ADDR, TX_DATA[0], 0); // I2C write
iicSend(I2C_ADDR, 0, 1); // I2C read
txStr("\r\nIR Data:");
for(x = 1; x < RX_DATA[0]; x++)
{
txStr(" ");
txByte(RX_DATA[x]);
}
}
P2IFG &= ~0x01; // Enable P2.0 interrupt
P2IE |= 0x01; // Enable P2.0 interrupt
if( P2IN & 0x01 )
{
Event |= EVENT_INT; // Interrupt Event
}
}
}
}
//
// USART0 I2C Interrupt Service Routine
//
#pragma vector=USART0TX_VECTOR
__interrupt void I2C_IV (void)
{
switch( I2CIV )
{
case 0x02: break; // ALIFG: n/a
case 0x04: // NACKIFG: n/a
break;
case 0x06: break; // OAIFG: n/a
case 0x08: break; // ARDYIFG: n/a
case 0x0A:
RX_DATA[rxIdx++] = I2CDRB;
if( rxIdx == 1 ) // RXRDYIFG
{
rxMsgLen = RX_DATA[0]-1; // Save message length
}
if( --rxMsgLen == 0 )
{
I2CTCTL |= I2CSTP;
}
break;
case 0x0C: // TXRDYIFG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -