Phạm Thành Danh
Thành Viên PIF
Hiện em muốn kết nối I2C giữa con g2553 và con g2452 (vì k mua được g2553 nữa ) nhưng không biết làm sao cả, code I2C của con g2452 khác nhau quá. Em muốn dùng g2553 làm master , g2452 làm slave để gửi một mảng 2 số từ master tới slave.Anh chị nào từng dùng qua thì giúp em với nhé!!. Em có thử code như thế này nhưng không thành công, nó bị treo ở dòng while ở master.
Master code:
Slave code
Master code:
Code:
{
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x58; // Slave Address is 058h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
//IE2 |= UCB0TXIE;
// _BIS_SR(GIE);
TxData[0]=hour;
TxData[1]=min;
PTxData = (unsigned char *)TxData; // TX array start address
TXByteCtr = sizeof TxData; // Load TX byte counter
/*while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT;
_BIS_SR(GIE);*/
while (UCB0CTL1 & UCTXSTP); // Loop until I2C STT is sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
while (!(IFG2&UCB0TXIFG));
unsigned char i;
for( i=0;i<TXByteCtr;i++)
{
UCB0TXBUF= *(PTxData+i) ;
while (!(IFG2&UCB0TXIFG));
}
UCB0CTL1 |= UCTXSTP; // I2C stop condition after 1st TX
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
Code:
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
{
while(1); // If calibration constants erased
// do not load, trap CPU!!
}
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
P2SEL &= ~(BIT6 +BIT0+ BIT7+BIT1 +BIT2 +BIT3 +BIT4); // 2.6,2.7 are GPIO
P2SEL2 &= ~(BIT6 + BIT0+ BIT7+BIT1 +BIT2 +BIT3 +BIT4);
P1SEL &= ~(d1+d2+d3+d4);
P1SEL2 &= ~(d1+d2+d3+d4);
P1DIR |=(d1+d2+d3+d4);
P2DIR |=( BIT0 + BIT1 + BIT2+BIT3 +BIT4);
while(1)
{
Setup_USI_Slave();
PRxData = (unsigned char *)data;
#pragma vector = USI_VECTOR
__interrupt void USI_TXRX (void)
{
if (USICTL1 & USISTTIFG) // Start entry?
{
//P1OUT |= 0x01; // LED on: sequence start
I2C_State = 2; // Enter 1st state on start
}
switch(__even_in_range(I2C_State,14))
{
case 0: // Idle, should not get here
break;
case 2: // RX Address
USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX address
USICTL1 &= ~USISTTIFG; // Clear start flag
I2C_State = 4; // Go to next state: check address
break;
case 4: // Process Address and send (N)Ack
if (USISRL & 0x01){ // If master read...
SLV_Addr = 0xB1; // Save R/W bit
transmit = 1;}
else{transmit = 0;
SLV_Addr = 0xB0;}
USICTL0 |= USIOE; // SDA = output
if (USISRL == SLV_Addr) // Address match?
{
USISRL = 0x00; // Send Ack
// P1OUT &= ~0x01; // LED off
if (transmit == 0){
I2C_State = 6;} // Go to next state: RX data
if (transmit == 1){
I2C_State = 10;} // Else go to next state: TX data
}
else
{
USISRL = 0xFF; // Send NAck
// P1OUT |= 0x01; // LED on: error
I2C_State = 8; // next state: prep for next Start
}
USICNT |= 0x01; // Bit counter = 1, send (N)Ack bit
break;
case 6: // Receive data byte
Data_RX();
break;
case 8:// Check Data & TX (N)Ack
USICTL0 |= USIOE; // SDA = output
if (Bytecount <= (Number_of_Bytes-2))
// If not last byte
{
*PRxData++ = USISRL;
USISRL = 0x00; // Send Ack
I2C_State = 6; // Rcv another byte
Bytecount++;
USICNT |= 0x01; // Bit counter = 1, send (N)Ack bit
}
else // Last Byte
{
USISRL = 0xFF; // Send NAck
USICTL0 &= ~USIOE; // SDA = input
SLV_Addr = 0xB0; // Reset slave address
I2C_State = 0; // Reset state machine
Bytecount =0; // Reset counter for next TX/RX
}
break;
case 10: // Send Data byte
TX_Data();
break;
case 12:// Receive Data (N)Ack
USICTL0 &= ~USIOE; // SDA = input
USICNT |= 0x01; // Bit counter = 1, receive (N)Ack
I2C_State = 14; // Go to next state: check (N)Ack
break;
case 14:// Process Data Ack/NAck
if (USISRL & 0x01) // If Nack received...
{
USICTL0 &= ~USIOE; // SDA = input
SLV_Addr = 0xB0; // Reset slave address
I2C_State = 0; // Reset state machine
Bytecount = 0;
// LPM0_EXIT; // Exit active for next transfer
}
else // Ack received
{
//P1OUT &= ~0x01; // LED off
TX_Data(); // TX next byte
}
break;
}
USICTL1 &= ~USIIFG; // Clear pending flags
}
void Data_RX(void){
USICTL0 &= ~USIOE; // SDA = input
USICNT |= 0x08; // Bit counter = 8, RX data
I2C_State = 8; // next state: Test data and (N)Ack
}
void TX_Data(void){
USICTL0 |= USIOE; // SDA = output
USISRL = SLV_Data++;
USICNT |= 0x08; // Bit counter = 8, TX data
I2C_State = 12; // Go to next state: receive (N)Ack
}
void Setup_USI_Slave(void){
//P1OUT = 0xC0; // P1.6 & P1.7 Pullups
//P1REN |= 0xC0; // P1.6 & P1.7 Pullups
//P1DIR = 0xFF; // Unused pins as outputs
//P2OUT = 0;
//P2DIR = 0xFF;
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7;
USICTL0 = USIPE6+USIPE7+USISWRST; // Port & USI mode setup
USICTL1 = USII2C+USIIE+USISTTIE; // Enable I2C mode & USI interrupts
USICKCTL = USICKPL; // Setup clock polarity
USICNT |= USIIFGCC; // Disable automatic clear control
USICTL0 &= ~USISWRST; // Enable USI
USICTL1 &= ~USIIFG; // Clear pending flag
transmit = 0;
_EINT();
}