Esp32到pic16lf18346 i2c通信问题



我在项目中使用了esp32和pic16lf18346。esp32是i2cc主机。我从图片中看到了错误的i2c数据。esp32每1秒进行一次多字节读取。图中主线程有while(1(和sleep。仅启用i2c isr。如果我从图片主线程中删除睡眠,我会得到正确的i2c数据。在逻辑分析器中,我看到i2c isr在睡眠期间运行,但SDA数据显示错误。

如有任何指导,我们将不胜感激
请参阅mcc生成的i2c代码。如果存在任何配置问题,请提供指导。

值得庆幸的是,马纳斯/**MSSP1生成的驱动程序文件

@Company
Microchip Technology Inc.
@File Name
i2c1.c
@Summary
This is the generated header file for the MSSP1 driver using
PIC10 / PIC12 / PIC16 / PIC18 MCUs
@Description
This header file provides APIs for driver for I2C1.
Generation Information :
Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.76
Device            :  PIC16LF18346
Driver Version    :  2.01
The generated drivers are tested against the following:
Compiler          :  XC8 2.00
MPLAB             :  MPLAB X 5.10
*/
/*
(c) 2018 Microchip Technology Inc. and its subsidiaries.
Subject to your compliance with these terms, you may use Microchip software and any
derivatives exclusively with Microchip products. It is your responsibility to comply with third party
license terms applicable to your use of third party software (including open source software) that
may accompany Microchip software.
THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
FOR A PARTICULAR PURPOSE.
IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
SOFTWARE.
*/
#include "i2c1.h"
#define I2C1_SLAVE_ADDRESS 0x08
#define I2C1_SLAVE_MASK    0x7F
typedef enum
{
SLAVE_NORMAL_DATA,
SLAVE_DATA_ADDRESS,
} SLAVE_WRITE_DATA_TYPE;
/**
Section: Global Variables
*/
volatile uint8_t    I2C1_slaveWriteData      = 0x55;
I2C1_RegisterWriteISR_t I2C1_RegisterWriteISR;
I2C1_RegisterReadISR_t I2C1_RegisterReadISR;
/**
Section: Local Functions
*/
void I2C1_StatusCallback(I2C1_SLAVE_DRIVER_STATUS i2c_bus_state);

/**
Prototype:        void I2C1_Initialize(void)
Input:            none
Output:           none
Description:      I2C1_Initialize is an
initialization routine that takes inputs from the GUI.
Comment:
Usage:            I2C1_Initialize();
*/
void I2C1_Initialize(void)
{
// initialize the hardware
// R_nW write_noTX; P stopbit_notdetected; S startbit_notdetected; BF RCinprocess_TXcomplete; SMP Standard Speed; UA dontupdate; CKE disabled; D_nA lastbyte_address;
SSP1STAT = 0x80;
// SSPEN enabled; WCOL no_collision; CKP disabled; SSPM 7 Bit Polling; SSPOV no_overflow;
SSP1CON1 = 0x26;
// ACKEN disabled; GCEN disabled; PEN disabled; ACKDT acknowledge; RSEN disabled; RCEN disabled; ACKSTAT received; SEN enabled;
SSP1CON2 = 0x01;
// ACKTIM ackseq; SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 300ns; AHEN disabled;
SSP1CON3 = 0x08;
// SSP1MSK 127;
SSP1MSK = (I2C1_SLAVE_MASK << 1);  // adjust UI mask for R/nW bit
// SSP1ADD 8;
SSP1ADD = (I2C1_SLAVE_ADDRESS << 1);  // adjust UI address for R/nW bit
// clear the slave interrupt flag
PIR1bits.SSP1IF = 0;
// enable the master interrupt
PIE1bits.SSP1IE = 1;
}
void I2C1_ISR ( void )
{
int readerr = 0;
uint8_t     i2c_data                = 0x55;
// NOTE: The slave driver will always acknowledge
//       any address match.
PIR1bits.SSP1IF = 0;        // clear the slave interrupt flag
i2c_data        = SSP1BUF;  // read SSPBUF to clear BF
if(1 == SSP1STATbits.R_nW)
{
if((1 == SSP1STATbits.D_nA) && (1 == SSP1CON2bits.ACKSTAT))
{
// callback routine can perform any post-read processing
I2C1_StatusCallback(I2C1_SLAVE_READ_COMPLETED);
}
else
{
// callback routine should write data into SSPBUF
I2C1_StatusCallback(I2C1_SLAVE_READ_REQUEST);
}
}
else if(0 == SSP1STATbits.D_nA)
{
// this is an I2C address
// callback routine should prepare to receive data from the master
I2C1_StatusCallback(I2C1_SLAVE_WRITE_REQUEST);
}
else
{
I2C1_slaveWriteData   = i2c_data;
// callback routine should process I2C1_slaveWriteData from the master
I2C1_StatusCallback(I2C1_SLAVE_WRITE_COMPLETED);
}
SSP1CON1bits.CKP    = 1;    // release SCL
} // end I2C1_ISR()

void I2C1_SetRegisterCallbackFunctions(I2C1_RegisterWriteISR_t write,
I2C1_RegisterReadISR_t read) {
I2C1_RegisterWriteISR = write;
I2C1_RegisterReadISR = read;
}
/**
Custom implementation of the callback
This slave driver emulates an command-driven Device.
Reads can be performed by writing a single byte as a command address
followed by 1 read.
Writes can be performed by writing a single byte address, followed by 1 data
write.
*/
void I2C1_StatusCallback(I2C1_SLAVE_DRIVER_STATUS i2c_bus_state)
{
static uint8_t registerAddress = 0;
static uint8_t slaveWriteType   = SLAVE_NORMAL_DATA;
switch (i2c_bus_state)
{
case I2C1_SLAVE_WRITE_REQUEST:
// the master will be sending the eeprom address next
slaveWriteType  = SLAVE_DATA_ADDRESS;
break;
case I2C1_SLAVE_WRITE_COMPLETED:
switch(slaveWriteType)
{
case SLAVE_DATA_ADDRESS:
registerAddress = I2C1_slaveWriteData;
break;
case SLAVE_NORMAL_DATA:
// the master has written data to store in the eeprom
if (I2C1_RegisterWriteISR) {
I2C1_RegisterWriteISR(registerAddress, I2C1_slaveWriteData);
}
break;
default:
break;
} // end switch(slaveWriteType)
slaveWriteType  = SLAVE_NORMAL_DATA;
break;
case I2C1_SLAVE_READ_REQUEST:
if (I2C1_RegisterReadISR) {
SSP1BUF = I2C1_RegisterReadISR(registerAddress);
}
break;
case I2C1_SLAVE_READ_COMPLETED:
if (I2C1_RegisterReadISR) {
I2C1_RegisterReadISR(-1); //indicate no more calls for this address
}
break;
default:
break;
} // end switch(i2c_bus_state)
}

每个GPIO上都有备用GPIO吗?当GPIO降到低位时唤醒PIC,PIC在while((中进行监测,直到线路回到高位时才返回睡眠状态。在进行I2C读取之前,您可以给予一点延迟。。。

最新更新