如何使用MCC生成的i2c驱动程序处理读取的数据?

如何解决如何使用MCC生成的i2c驱动程序处理读取的数据?

我正在尝试将新的(?)i2c驱动程序用于PIC18F45Q10。我不了解如何不经修改就可以使用它。我只想将自己的函数与状态机一起设置为回调以处理传入的字节。

我正在从Linux机器向微控制器发送2个字节。

i2cset 1 0x12 0x01 0x02

位置:

  • 1是Linux I2C总线号
  • 0x12是7位i2c地址(我的微控制器)
  • 0x01是数据的第一个字节
  • 0x02是数据的第二个字节

我的问题是I2C2_SlaveRdCallBack();从未被调用(因为rx缓冲区始终为空)。

MCC中的I2C配置似乎很好,因为当我在if(I2C2_SlaveIsRxBufFull())行上放置一个断点时-停在那儿,我看到i2c2RdData变量包含数据的第一个字节。 Linux机器可以使用i2cdetect命令发现我的微控制器(i2cdetect发送所有可能的设备地址,并且在接收到ACK时会显示发现的设备)。

如何使用此驱动程序?该代码应该正常工作,还是只是一些脚手架/示例?

此驱动程序的主要ISR处理程序:

static void I2C2_Isr() 
{ 
    I2C2_SlaveClearIrq();

    // read SSPBUF to clear BF
    i2c2RdData = I2C2_SlaveGetRxData(); //  <- but there is my first ! (it reads hardware register)

    if(I2C2_SlaveIsRead())
    {
        i2c2State = I2C2_TX;
    }
    else
    {
        i2c2State = I2C2_RX;
    }
    
    switch(i2c2State)
    {
        case I2C2_TX:
            if(!I2C2_SlaveIsWriteCollision())
            {
                I2C2_SlaveWrCallBack();
            }
            else
            {
                I2C2_SlaveWrColCallBack();
                I2C2_SlaveRestart();
            }
            i2c2NextState = I2C2_ADDR;
            break;
           
        case I2C2_RX:
            if (I2C2_SlaveIsData())              <--    I have problem here
            {
                if(I2C2_SlaveIsRxBufFull())      <--    when the buffer is not full 
                { 
                    I2C2_SlaveRdCallBack();      <--    read callback is not called
                }
            }
            else
            {
                I2C2_SlaveAddrCallBack();       
                i2c2NextState = I2C2_ADDR;
            }
            break;
        default:          
            break;
    }
    i2c2State = i2c2NextState;
    I2C2_SlaveReleaseClock();
}

完整的驱动程序代码:

/**
  I2C2 Generated Driver File

  @Company
    Microchip Technology Inc.

  @File Name
    i2c2.c

  @Summary
    This is the generated driver implementation file for the I2C2 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  @Description
    This header file provides implementations for driver APIs for I2C2.
    Generation Information :
        Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.78.1
        Device            :  PIC18F45Q10
        Driver Version    :  1.0.0
    The generated drivers are tested against the following:
        Compiler          :  XC8 2.10 and above or later
        MPLAB             :  MPLAB X 5.30
*/

/*
    (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 "i2c2_slave.h"
#include <xc.h>

#define I2C2_SLAVE_ADDRESS      18
#define I2C2_SLAVE_MASK         127

/**
 Section: Global Variables
 */
typedef enum 
{
    I2C2_ADDR,I2C2_TX,I2C2_RX
} i2c2_state_t;

static void I2C2_Isr(void);
static void I2C2_SlaveDefRdInterruptHandler(void);
static void I2C2_SlaveDefWrInterruptHandler(void);
static void I2C2_SlaveDefAddrInterruptHandler(void);
static void I2C2_SlaveDefWrColInterruptHandler(void);
static void I2C2_SlaveDefBusColInterruptHandler(void);

static void I2C2_SlaveRdCallBack(void);
static void I2C2_SlaveWrCallBack(void);
static void I2C2_SlaveAddrCallBack(void);
static void I2C2_SlaveWrColCallBack(void);
static void I2C2_SlaveBusColCallBack(void);

static inline bool I2C2_SlaveOpen();
static inline void I2C2_SlaveClose();
static inline void I2C2_SlaveSetSlaveAddr(uint8_t slaveAddr);
static inline void I2C2_SlaveSetSlaveMask(uint8_t maskAddr);
static inline void I2C2_SlaveEnableIrq(void);
static inline bool I2C2_SlaveIsAddr(void);
static inline bool I2C2_SlaveIsRead(void);
static inline void I2C2_SlaveClearBuff(void);
static inline void I2C2_SlaveClearIrq(void);
static inline void I2C2_SlaveReleaseClock(void);
static inline bool I2C2_SlaveIsWriteCollision(void);
static inline bool I2C2_SlaveIsTxBufEmpty(void);
static inline bool I2C2_SlaveIsData(void);
static inline void I2C2_SlaveRestart(void);
static inline bool I2C2_SlaveIsRxBufFull(void);
static inline void I2C2_SlaveSendTxData(uint8_t data);
static inline uint8_t I2C2_SlaveGetRxData(void);
static inline uint8_t I2C2_SlaveGetAddr(void);
static inline void I2C2_SlaveSendAck(void);
static inline void I2C2_SlaveSendNack(void);


static volatile i2c2_state_t i2c2State = I2C2_ADDR;
static volatile i2c2_state_t i2c2NextState = I2C2_ADDR;
volatile uint8_t i2c2WrData;
volatile uint8_t i2c2RdData;
volatile uint8_t i2c2SlaveAddr;

void I2C2_Initialize()
{
    SSP2STAT  = 0x40;
    SSP2CON1 |= 0x06;
    SSP2CON2  = 0x10;
    SSP2CON1bits.SSPEN = 0;
}

void I2C2_Open() 
{
    I2C2_SlaveOpen();
    I2C2_SlaveSetSlaveAddr(I2C2_SLAVE_ADDRESS << 1);
    I2C2_SlaveSetSlaveMask(I2C2_SLAVE_MASK);
    I2C2_SlaveSetIsrHandler(I2C2_Isr);
    I2C2_SlaveSetBusColIntHandler(I2C2_SlaveDefBusColInterruptHandler);
    I2C2_SlaveSetWriteIntHandler(I2C2_SlaveDefWrInterruptHandler);
    I2C2_SlaveSetReadIntHandler(I2C2_SlaveDefRdInterruptHandler);
    I2C2_SlaveSetAddrIntHandler(I2C2_SlaveDefAddrInterruptHandler);
    I2C2_SlaveSetWrColIntHandler(I2C2_SlaveDefWrColInterruptHandler);
    I2C2_SlaveEnableIrq();    
}

void I2C2_Close() 
{
    I2C2_SlaveClose();
}

uint8_t I2C2_Read()
{
   return I2C2_SlaveGetRxData();
}

void I2C2_Write(uint8_t data)
{
    I2C2_SlaveSendTxData(data);
}

void I2C2_Enable()
{
    I2C2_Initialize();
}

void I2C2_SendAck()
{
    I2C2_SlaveSendAck();
}

void I2C2_SendNack()
{
    I2C2_SlaveSendNack();
}

static void I2C2_Isr() 
{ 
    I2C2_SlaveClearIrq();

    // read SSPBUF to clear BF
    i2c2RdData = I2C2_SlaveGetRxData();

    if(I2C2_SlaveIsRead())
    {
        i2c2State = I2C2_TX;
    }
    else
    {
        i2c2State = I2C2_RX;
    }
    
    switch(i2c2State)
    {
        case I2C2_TX:
            if(!I2C2_SlaveIsWriteCollision())
            {
                I2C2_SlaveWrCallBack();
            }
            else
            {
                I2C2_SlaveWrColCallBack();
                I2C2_SlaveRestart();
            }
            i2c2NextState = I2C2_ADDR;
            break;
           
        case I2C2_RX:
            if (I2C2_SlaveIsData()) 
            {
                if(I2C2_SlaveIsRxBufFull())
                { 
                    I2C2_SlaveRdCallBack();
                }
            }
            else
            {
                I2C2_SlaveAddrCallBack();
                i2c2NextState = I2C2_ADDR;
            }
            break;
        default:          
            break;
    }
    i2c2State = i2c2NextState;
    I2C2_SlaveReleaseClock();
}

// Common Event Interrupt Handlers
void I2C2_SlaveSetIsrHandler(interruptHandler handler)
{
    MSSP2_InterruptHandler = handler;
}

// Read Event Interrupt Handlers
void I2C2_SlaveSetReadIntHandler(interruptHandler handler) {
    I2C2_SlaveRdInterruptHandler = handler;
}

static void I2C2_SlaveRdCallBack() {
    // Add your custom callback code here
    if (I2C2_SlaveRdInterruptHandler) 
    {
        I2C2_SlaveRdInterruptHandler();
    }
}

static void I2C2_SlaveDefRdInterruptHandler() {
    i2c2RdData = I2C2_SlaveGetRxData();
}

// Write Event Interrupt Handlers
void I2C2_SlaveSetWriteIntHandler(interruptHandler handler) {
    I2C2_SlaveWrInterruptHandler = handler;
}

static void I2C2_SlaveWrCallBack() {
    // Add your custom callback code here
    if (I2C2_SlaveWrInterruptHandler) 
    {
        I2C2_SlaveWrInterruptHandler();
    }
}

static void I2C2_SlaveDefWrInterruptHandler() {
    I2C2_SlaveSendTxData(i2c2WrData);
}

// ADDRESS Event Interrupt Handlers
void I2C2_SlaveSetAddrIntHandler(interruptHandler handler){
    I2C2_SlaveAddrInterruptHandler = handler;
}

static void I2C2_SlaveAddrCallBack() {
    // Add your custom callback code here
    if (I2C2_SlaveAddrInterruptHandler) {
        I2C2_SlaveAddrInterruptHandler();
    }
}

static void I2C2_SlaveDefAddrInterruptHandler() {
    i2c2SlaveAddr = I2C2_SlaveGetAddr();
}

// Write Collision Event Interrupt Handlers
void I2C2_SlaveSetWrColIntHandler(interruptHandler handler){
    I2C2_SlaveWrColInterruptHandler = handler;
}

static void  I2C2_SlaveWrColCallBack() {
    // Add your custom callback code here
    if ( I2C2_SlaveWrColInterruptHandler) 
    {
         I2C2_SlaveWrColInterruptHandler();
    }
}

static void I2C2_SlaveDefWrColInterruptHandler() {
}

// Bus Collision Event Interrupt Handlers
void I2C2_SlaveSetBusColIntHandler(interruptHandler handler){
    I2C2_SlaveBusColInterruptHandler = handler;
}

static void  I2C2_SlaveBusColCallBack() {
    // Add your custom callback code here
    if ( I2C2_SlaveBusColInterruptHandler) 
    {
         I2C2_SlaveBusColInterruptHandler();
    }
}

static void I2C2_SlaveDefBusColInterruptHandler() {
}

static inline bool I2C2_SlaveOpen()
{
    if(!SSP2CON1bits.SSPEN)
    {      
        SSP2STAT  = 0x40;
        SSP2CON1 |= 0x06;
        SSP2CON2  = 0x10;
        SSP2CON1bits.SSPEN = 1;
        return true;
    }
    return false;
}

static inline void I2C2_SlaveClose()
{
    SSP2STAT  = 0x40;
    SSP2CON1 |= 0x06;
    SSP2CON2  = 0x10;
    SSP2CON1bits.SSPEN = 0;
}

static inline void I2C2_SlaveSetSlaveAddr(uint8_t slaveAddr)
{
    SSP2ADD = slaveAddr;
}

static inline void I2C2_SlaveSetSlaveMask(uint8_t maskAddr)
{
    SSP2MSK = maskAddr;
}

static inline void I2C2_SlaveEnableIrq()
{
    PIE3bits.SSP2IE = 1;
}

static inline bool I2C2_SlaveIsAddr()
{
    return !(SSP2STATbits.D_nA);
}

static inline bool I2C2_SlaveIsRead()
{
    return (SSP2STATbits.R_nW);
}

static inline void I2C2_SlaveClearIrq()
{
    PIR3bits.SSP2IF = 0;
}

static inline void I2C2_SlaveReleaseClock()
{
    SSP2CON1bits.CKP = 1;
}

static inline bool I2C2_SlaveIsWriteCollision()
{
    return SSP2CON1bits.WCOL;
}

static inline bool I2C2_SlaveIsData()
{
    return SSP2STATbits.D_nA;
}

static inline void I2C2_SlaveRestart(void)
{
    SSP2CON2bits.RSEN = 1;
}

static inline bool I2C2_SlaveIsTxBufEmpty()
{
    return !SSP2STATbits.BF;
}

static inline bool I2C2_SlaveIsRxBufFull()
{
    return SSP2STATbits.BF;
}

static inline void I2C2_SlaveSendTxData(uint8_t data)
{
    SSP2BUF = data;
}

static inline uint8_t I2C2_SlaveGetRxData()
{
    return SSP2BUF;
}

static inline uint8_t I2C2_SlaveGetAddr()
{
    return SSP2ADD;
}

static inline void I2C2_SlaveSendAck()
{
    SSP2CON2bits.ACKDT = 0;
    SSP2CON2bits.ACKEN = 1;
}

static inline void I2C2_SlaveSendNack()
{
    SSP2CON2bits.ACKDT = 1;
    SSP2CON2bits.ACKEN = 1;
}

头文件:

/**
  I2C2 Generated Driver API Header File

  @Company
    Microchip Technology Inc.

  @File Name
    i2c2_slave.h

  @Summary
    This is the generated header file for the I2C2 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  @Description
    This header file provides APIs for driver for I2C2.
    Generation Information :
        Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.78.1
        Device            :  PIC18F45Q10
        Driver Version    :  1.0.0
    The generated drivers are tested against the following:
        Compiler          :  XC8 2.10 and above or later
        MPLAB             :  MPLAB X 5.30
*/

/*
    (c) 2018 Microchip Technology Inc. and its subsidiaries. 
    
    Subject to your compliance with these terms,THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS 
    SOFTWARE.
*/

#ifndef I2C2_SLAVE_H
#define I2C2_SLAVE_H

#include <stdbool.h>
#include <stdint.h>

typedef void (*interruptHandler)(void);
/**
 * \brief Initialize I2C2 interface
 * If module is configured to disabled state,the clock to the I2C2 is disabled
 * if this is supported by the device's clock system.
 *
 * \return None
 */
void I2C2_Initialize(void);

/**
 * \brief Open the I2C2 for communication. Enables the module if disabled.
 *
 * \return Nothing
 */
void I2C2_Open(void);

/**
 * \brief Close the I2C2 for communication. Disables the module if enabled.
 * Disables address recognition.
 *
 * \return Nothing
 */
void I2C2_Close(void);

/**
 * \brief Read data from I2C2 communication. 
 *
 * \return Read Data
 */
uint8_t I2C2_Read(void);

/**
 * \brief Write data over the communication. 
 *
 * \return None
 */
void I2C2_Write(uint8_t data);

/**
 * \brief Enable the communication by initialization of hardware 
 *
 * \return None
 */
void I2C2_Enable(void);

/**
 * \brief Send the Ack Signal to Master 
 *
 * \return None
 */
void I2C2_SendAck(void);

/**
 * \brief Send the Nack Signal to Master 
 *
 * \return None
 */
void I2C2_SendNack(void);

/**
 * \brief The function called by the I2C2 Irq handler.
 * Can be called in a polling loop in a polled driver.
 *
 * \return Nothing
 */
void I2C2_SlaveSetIsrHandler(interruptHandler handler);
void I2C2_SlaveSetAddrIntHandler(interruptHandler handler);
void I2C2_SlaveSetReadIntHandler(interruptHandler handler);
void I2C2_SlaveSetWriteIntHandler(interruptHandler handler);
void I2C2_SlaveSetBusColIntHandler(interruptHandler handler);
void I2C2_SlaveSetWrColIntHandler(interruptHandler handler);

void (*MSSP2_InterruptHandler)(void);
void (*I2C2_SlaveRdInterruptHandler)(void);
void (*I2C2_SlaveWrInterruptHandler)(void);
void (*I2C2_SlaveAddrInterruptHandler)(void);
void (*I2C2_SlaveBusColInterruptHandler)(void);
void (*I2C2_SlaveWrColInterruptHandler)(void); 

#endif /* I2C2_SLAVE_H */

解决方法

你不应该在“I2C2_Isr()”中做这行

  i2c2RdData = I2C2_SlaveGetRxData(); //   <- but there is my first ! 
                                        (it reads hardware register)

它将从硬件寄存器复制数据,然后该寄存器将为空。 所以这就是为什么你的“I2C2_SlaveRdCallBack();”永远不会被调用。

此默认句柄将自动调用。

static void I2C2_SlaveDefRdInterruptHandler() {
i2c2RdData = I2C2_SlaveGetRxData();
} 

所以如果你想获取数据然后复制到你的变量,你应该在这里做

static void I2C2_SlaveRdCallBack() {
// Add your custom callback code here
if (I2C2_SlaveRdInterruptHandler) 
{
    I2C2_SlaveRdInterruptHandler();
}

// Copy i2c data to your variable here
}

抱歉我的英语不好

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-