4

我是嵌入式编程的新手,正在尝试让我的第一个 I2C 项目工作。我正在使用 PIC32MX795F512L。我非常关注 PIC32 上 I2C 的微芯片数据表。我遇到的问题是从未从 I2C1STAT 寄存器中清除 S 位。我实际上不清楚我是否必须这样做,或者它是否在 Start 事件结束时自动完成,但现在我正在尝试手动清除它。但是,我所做的任何事情似乎都没有效果。如果需要更多信息以便更容易理解正在发生的事情,请告诉我。我正在使用 PICKIT3,所以我也可以获得调试信息。我知道主中断发生,S 位被设置,我退出中断代码并挂在 while 语句检查 I2C1STATbits.S。

编辑:我正在编辑这篇文章以使用我的新代码而不是旧代码。我现在使用的是 20MHZ 外设时钟。只是我今天尝试的许多事情中的一件不起作用。延迟只是 256 毫秒的延迟。我知道超长,但很快。

main()
{
//Setup I2C1CON

I2C1CONbits.SIDL = 0;   //Continue to run while in Idle
I2C1CONbits.SCLREL = 1; //Release the clock (Unsure of this)
I2C1CONbits.A10M = 0;   //Using a 7 bit slave address
I2C1CONbits.DISSLW = 1; //Slew rate control disabled because running at 100 KHZ

I2C1ADD = 0x1E;         //Slave address without read or write bit
I2C1BRG = 0x060;        //Set the BRG clock rate - Based on Page 24-19

I2C1CONbits.ON = 1;     //Turn on the I2C module

delay();

I2C1CONbits.SEN = 1;    //Initiate a start event

while(I2C1CONbits.SEN == 1);    //Wait until Start event is done

I2C1TRN = 0x3C;                 //Load the address into the Transmit register

while(I2C1STATbits.TRSTAT == 1);
while(I2C1STATbits.ACKSTAT == 0);    //Wait for a ACK from the device

I2C1TRN = 0x00;

while(I2C1STATbits.TRSTAT == 1);
while(I2C1STATbits.ACKSTAT == 0);

I2C1TRN = 0x70;

while(I2C1STATbits.TRSTAT == 1);
while(I2C1STATbits.ACKSTAT == 0);


while(1);

}

谢谢你的帮助。

4

2 回答 2

1

我也刚开始使用 PIC32MZ 系列,设置 I2C 以与各种存储芯片通信。我使用了您的代码并对其进行了修改,以使其正常工作。由于我使用的是 PIC32MZ 系列,我相信 I2C 寄存器应该是相同的。

I2C 配置:

I2C1CONbits.SIDL = 0;       // Stop in Idle Mode bit                        -> Continue module operation when the device enters Idle mode
I2C1CONbits.A10M = 0;       // 10-bit Slave Address Flag bit                -> I2CxADD register is a 7-bit slave address
I2C1CONbits.DISSLW = 1;     // Slew Rate Control Disable bit                -> Slew rate control disabled for Standard Speed mode (100 kHz)
I2C1CONbits.ACKDT = 0;      // Acknowledge Data bit                         -> ~ACK is sent
I2C1BRG = 0x0F3;            // Baud Rate Generator set to provide 100KHz for SCL with 50 MHz xtal. 

我遵循了 I2C 数据表中提供的传输步骤,因此很容易遵循这些步骤以及 pdf 和我对代码的评论。

I2C 数据传输:

// 1. Turn on the I2C module by setting the ON bit (I2CxCON<15>) to ‘1’.
I2C1CONbits.ON = 1;         // I2C Enable bit                               -> Enables the I2C module and configures the SDAx and SCLx pins as serial port pins

//------------- WRITE begins here ------------
// 2. Assert a Start condition on SDAx and SCLx.
I2C1CONbits.PEN = 0;        // Stop Condition Enable Bit                    -> Stop Condition Idle 
I2C1CONbits.SEN = 1;        // Start Condition Enable bit                   -> Initiate Start condition on SDAx and SCLx pins; cleared by module
while(I2C1CONbits.SEN == 1);            // SEN is to be cleared when I2C Start procedure has been completed 

// 3. Load the Data on the bus
I2C1TRN = 0b10100000 ;          // Write the slave address to the transmit register for I2C WRITE 
while(I2C1STATbits.TRSTAT == 1);        // MASTER Transmit still in progress
while(I2C1STATbits.ACKSTAT == 1);       // Master should receive the ACK from Slave, which will clear the I2C1STAT<ACKSTAT> bit. 

I2C1TRN = 0xCE;                 // Register Address 
while(I2C1STATbits.TRSTAT == 1);
while(I2C1STATbits.ACKSTAT == 1);

I2C1TRN = 0xCF;                 // Register Value 
while(I2C1STATbits.TRSTAT == 1);
while(I2C1STATbits.ACKSTAT == 1);
I2C1CONbits.PEN = 1;        // Stop Condition Enable Bit                    -> Initiate Stop condition on SDAx and SCLx pins; cleared by module

//-------------- WRITE ends here -------------

此代码运行良好,因为我使用了几个 LED 来切换指示成功的写入过程。

于 2017-04-25T15:10:16.197 回答
-1

while(!(I2C1STATbits.ACKSTAT == 0)); 我猜是正确的方式。如果您将 I2C 用作从机,则使用 I2C1ADD 设置当前 PIC mc 的从机地址。如果任何主请求以该从机地址开头,PIC 将作为从机响应该地址。

阅读此 pdf,其中最初他们已指定在 PIC 中将 I2C 配置为主机和从机,并且主机请求由同一个 PIC 与 I2C1ADD 值中的从机地址进行检查。 http://ww1.microchip.com/downloads/en/DeviceDoc/61116F.pdf

于 2014-09-25T13:58:16.103 回答