This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

IIC更换系统主频后出现通讯异常(在线等)



程序之前一直在系统默认的1mhz频率下跑的,现在更改为11.0592Mhz之后,出现通讯异常。我把IIC的频率设置与原来的一样,170Khz左右,读操作包括两个部分,先写后读,程序大概如下,其中void UCSInit(void)之前没用,加上就有问题,不知道什么原因。下面为程序。

void UCSInit(void)
{
P7SEL |= (BIT0 + BIT1); //set P7.0 and P7.1 to XT1
SetVCore(PMMCOREV_2); // Set VCore = 1.75V
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFOCLK
UCSCTL4 |= SELA__REFOCLK; // Set ACLK = REFOCLK

UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_6; // Select DCO range 44.2368MHz operation
UCSCTL2 = FLLD_1 | 674; // Set DCO Multiplier for 22.1184MHz
__bic_SR_register(SCG0); // Enable the FLL control loop
__delay_cycles(375000);
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag

UCSCTL6 &= ~(XT1DRIVE_3); // Xtal is now stable, reduce drive
#if 1
// strength
//设置系统时钟为11.0592MHz
UCSCTL4 |=SELM_4; //MCLK选择DCO时钟分频
UCSCTL4 |=SELS_4; //SMCLK选择DCO时钟分频

UCSCTL5 |=DIVS_1; //进行如下操作SMCLK=SMCLK/2
UCSCTL5 |=DIVM_1; //进行如下操作MCLK=SMCLK/2
//UCSCTL5 |=DIVA__16; //进行如下操作ACLK=ACLK/32=32768HZ
#endif
}

void I2C_init(void)
{
//i2c--0
P3SEL |= BIT1 + BIT2; // 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 = CPU_SMAINCLK / 400000; // fSCL = SMCLK/12 = ~100kHz
UCB0BR0 = 62; // fSCL = SMCLK/12 = ~100kHz(内部1mhz)
UCB0BR1 = 0; //系统内部晶振 为06
UCB0I2CSA = 0x21; // Slave Address is 021h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
P2DIR |=BIT6;
P2SEL |=BIT6; // MCU ACLK(32.768Khz)时钟输出,QN8036 XCLK输入
P2SEL &= ~BIT2; //片选输出引脚
P2DIR |= BIT2;
P2OUT |= BIT2; //p2.2高电平有效
P2SEL &= ~BIT1; //p2.1MCU I/O中断输入
P2DIR &= ~BIT1; //QN8036中断输出(INT),MCU I/O 中断输入
stepValue = qnd_StepTbl[qnd_CH_STEP];
}

unsigned char QND_ReadReg(unsigned char Address)   //iic读操作
{
unsigned char adr_lo;
UCB0I2CSA = (0x21);
while (UCB0STAT & UCBUSY); // wait until I2C module has
// finished all operations
adr_lo = Address & 0xFF; // and low byte of address
I2CBufferArray[0] = adr_lo; // be sent in the I2CBuffer.
PTxData = (unsigned char *)I2CBufferArray; // TX array start address
TXByteCtr = 1; // set I2CBufferArray Pointer
I2CWriteInit();
UCB0CTL1 |= UCTXSTT; // start condition generation
// => I2C communication is started
__bis_SR_register(GIE); // Enter LPM0 w/ interrupts
I2CReadInit();
UCB0I2CSA = (0x21); // Slave Address is 048h
UCB0CTL1 |= UCTXSTT; // I2C start condition
while (UCB0CTL1 & UCTXSTT); // Ensure start condition got sent
UCB0CTL1 |= UCTXNACK; //baimahe
UCB0CTL1 |= UCTXSTP; // I2C stop condition
__bis_SR_register(GIE); // Enter LPM0 w/ interrupts
while(UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
return I2CBuffer;
}

#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
switch(__even_in_range(UCB0IV,12))
{
case 0: break; // Vector 0: No interrupts
case 2: break; // Vector 2: ALIFG
case 4: break; // Vector 4: NACKIFG
case 6: break; // Vector 6: STTIFG
case 8: break; // Vector 8: STPIFG
case 10: // Vector 10: RXIFG
I2CBuffer = UCB0RXBUF; // Get RX data
break;
case 12: // Vector 12: TXIFG
if (TXByteCtr--) // Check TX byte counter
{
UCB0TXBUF = *PTxData++; // Load TX buffer
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
}
break;
default: break;
}
}

这张为异常的图片

这张为正常的

  • 异常的那张图片本来是读的地址为0X0B的,但是结果是0xFF。请大牛们给点建议,到底是什么问题。

  • 你好,

    你注意到你异常波形和正常波形读取时的一个问题没有?

    正常波形在最后一个bit位上是高。

    说明发送的东西有问题啊。

    你把主频降到8M 或者4M同样的代码,再测试一下。

  • 楼主,

       时钟初始化应该问题不大.你的代码中发送和接受数据语句有一段:

    ......

    I2CWriteInit();
    UCB0CTL1 |= UCTXSTT; // start condition generation
    // => I2C communication is started
    __bis_SR_register(GIE); // Enter LPM0 w/ interrupts
    I2CReadInit();
    UCB0I2CSA = (0x21); // Slave Address is 048h
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    while (UCB0CTL1 & UCTXSTT); // Ensure start condition got sent

    .....

    这里面I2CWriteInit();和I2CReadInit();做了什么?

    因为这里的i2c数据发送是以中断的形式发送的,如果I2CReadInit();不具有等待发送完毕的功能的话,程序就会继续往下执行读取i2c数据的操作了.我怀疑是不是这个原因导致了发送和接收的冲突.

    建议在读取 i2c之前加入等待,保证数据发送完成之后再读取.

  • void I2CWriteInit(void)

     {   

       UCB0CTL1 |= UCTR;                         // UCTR=1 => Transmit Mode (R/W bit = 0)   

       UCB0IFG &= ~UCTXIFG;   

      UCB0IE &= ~UCRXIE;                         // disable Receive ready interrupt   

       UCB0IE |= UCTXIE;                          // enable Transmit ready interrupt

    }

    void I2CReadInit(void)

    {

       UCB0CTL1 &= ~UCTR;                        // UCTR=0 => Receive Mode (R/W bit = 1)   

       UCB0IFG &= ~UCRXIFG;                  // Clear USCI_B0 RX int flag   

       UCB0IE &= ~UCTXIE;                         // disable Transmit ready interrupt   

       UCB0IE |= UCRXIE;                          // enable Receive ready interrupt

     }

  • void I2CWriteInit(void)
    {
    UCB0CTL1 |= UCTR; // UCTR=1 => Transmit Mode (R/W bit = 0)
    UCB0IFG &= ~UCTXIFG;
    UCB0IE &= ~UCRXIE; // disable Receive ready interrupt
    UCB0IE |= UCTXIE; // enable Transmit ready interrupt
    }

    void I2CReadInit(void)
    {
    UCB0CTL1 &= ~UCTR; // UCTR=0 => Receive Mode (R/W bit = 1)
    UCB0IFG &= ~UCRXIFG; // Clear USCI_B0 RX int flag
    UCB0IE &= ~UCTXIE; // disable Transmit ready interrupt
    UCB0IE |= UCRXIE; // enable Receive ready interrupt
    }

  • 你好,

    请问,在1MHZ如果加上你自己的Init函数就业不行了吗,还是加上之后再1M HZ情况是ok的?

  • 1MHZ下是正常的,高频率下不行

  • 楼主,

        建议尝试一下在i2c发送和接收数据的代码之间加上延时等待,确保i2c发送操作完成了再进行接收操作。