xiaoqi976633690 发表于 2022-8-5 14:52:54

RP2040 I2C slave 从机一进入中断就不会退出,程序一直在中断里面不出来。

RP2040 I2C slave 从机一进入中断就不会退出,程序一直在中断里面不出来。
参考了github的 https://github.com/vmilea/pico_i2c_slave

这读写目前都能正常就是cpu被i2c中断占用,我的while里的循环不会运行




#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/irq.h"

#include "hardware/gpio.h"
// I2C defines
// This example will use I2C0 on GPIO8 (SDA) and GPIO9 (SCL) running at 400KHz.
// Pins can be changed, see the GPIO function select table in the datasheet for information on GPIO assignments
#define I2C_PORT i2c0
#define I2C0_PORT i2c0
#define I2C0_SDA 8
#define I2C0_SCL 9

#define I2C1_PORT i2c1
#define I2C1_SDA 14
#define I2C1_SCL 15

#define MASTER 0
#define SLAVE 1


//函数声明
void init_I2CPort(i2c_inst_t *i2c, uint baudrate,uint I2C_SDA,uint I2C_SCL,bool mood);
void I2C0_callback(void);
int I2C_BUSCAN(void);
bool reserved_addr(uint8_t addr);
//全局变量
uint8_t ram_addr = 0;
uint8_t ram;
uint8_ttx_buff={0x01,0xaa};
uint8_ti2c_buff={0};
uint32_t i=0;
int main()
{
    int ret=0;
    stdio_init_all();
   
    // I2C Initialisation. Using it at 100Khz.
    init_I2CPort(I2C1_PORT,1000*100,I2C1_SDA,I2C1_SCL,MASTER);
    printf("hello i2c1\n");
    init_I2CPort(I2C0_PORT,1000*100,I2C0_SDA,I2C0_SCL,SLAVE);
    printf("hello i2c0\n");
   // I2C0_PORT->hw->intr_mask = (1 << 12) | (1 << 10) | (1 << 9) | (1 << 6) | (1 << 5) | (1 << 2);
    I2C0_PORT->hw->intr_mask = I2C_IC_INTR_MASK_M_RX_FULL_BITS | I2C_IC_INTR_MASK_M_RD_REQ_BITS | I2C_IC_RAW_INTR_STAT_TX_ABRT_BITS | I2C_IC_INTR_MASK_M_STOP_DET_BITS | I2C_IC_INTR_MASK_M_START_DET_BITS;
    irq_set_exclusive_handler(I2C0_IRQ,I2C0_callback);
    irq_set_enabled(I2C0_IRQ,true);
    printf("irq_set_enabled i2c0 irq\n");
    printf("hello i2c0 irq=%d\n",irq_is_enabled(I2C0_IRQ));
    printf("i2c init ok!\n");
    gpio_init(25);
    gpio_set_dir(25,GPIO_OUT);
    while(1)
    {

      printf("ram=%x\n\r",ram);
      sleep_ms(1000);
       /*
      i2c_write_blocking(I2C1_PORT,0X53,tx_buff,2,true);
      i2c_read_raw_blocking(I2C0_PORT,i2c_buff,2);
      // printf("ret=%d\n",ret);
      printf("i2c_buff=0x%x 0x%x\n\r",i2c_buff,i2c_buff);
      if((i2c_buff==0x00)&&(i2c_buff==0x99))
      {
            i2c_write_raw_blocking(I2C0_PORT,tx_buff,2);
            i++;
      }
      */
    }

}

voidinit_I2CPort(i2c_inst_t *i2c, uint baudrate,uint I2C_SDA,uint I2C_SCL,bool mood)
{
   
    i2c_init(i2c,baudrate);
    // Addresses of the form 000 0xxx or 111 1xxx are reserved. No slave should
    if(SLAVE==mood) i2c_set_slave_mode(i2c,true,0X53);

    gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
    gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
    gpio_pull_up(I2C_SDA);
    gpio_pull_up(I2C_SCL);

}


voidI2C0_callback(void)
{
   
    i++;
      // Get interrupt status
    uint32_t status = i2c0->hw->intr_stat;

    // Check to see if we have received data from the I2C controller
    if (status & I2C_IC_INTR_STAT_R_RX_FULL_BITS) {

      // Read the data (this will clear the interrupt)
      uint32_t value = i2c0->hw->data_cmd;

      // Check if this is the 1st byte we have received
      if (value & I2C_IC_DATA_CMD_FIRST_DATA_BYTE_BITS) {

            // If so treat it as the address to use
            ram_addr = (uint8_t)(value & I2C_IC_DATA_CMD_DAT_BITS);

      } else {
            // If not 1st byte then store the data in the RAM
            // and increment the address to point to next byte
            ram = (uint8_t)(value & I2C_IC_DATA_CMD_DAT_BITS);
            ram_addr++;
      }
    }

    // Check to see if the I2C controller is requesting data from the RAM
    if (status & I2C_IC_INTR_STAT_R_RD_REQ_BITS) {

      // Write the data from the current address in RAM
      i2c0->hw->data_cmd = (uint32_t)ram;

      // Clear the interrupt
      i2c0->hw->clr_rd_req;

      // Increment the address
      ram_addr++;

    }
    if(ram==0)
    {
      gpio_put(25, 0);
    }
    else if (ram!=0)
    {
      gpio_put(25, 1);
    }

}


int I2C_BUSCAN(void)
{

    printf("\nI2C Bus Scan\n");
    printf("   0123456789ABCDEF\n");

    for (int addr = 0; addr < (1 << 7); ++addr)
    {
      if (addr % 16 == 0)
      {
            printf("%02x ", addr);
      }

      // Perform a 1-byte dummy read from the probe address. If a slave
      // acknowledges this address, the function returns the number of bytes
      // transferred. If the address byte is ignored, the function returns
      // -1.

      // Skip over any reserved addresses.
      int ret;
      uint8_t rxdata;
      if (reserved_addr(addr))
            ret = PICO_ERROR_GENERIC;
      else
            ret = i2c_read_blocking(I2C1_PORT, addr, &rxdata, 1, false);

      printf(ret < 0 ? "." : "@");
      printf(addr % 16 == 15 ? "\n" : "");
    }
    printf("Done.\n");
    return 0;
}



bool reserved_addr(uint8_t addr)
{
    return (addr & 0x78) == 0 || (addr & 0x78) == 0x78;
}











eric2013 发表于 2022-8-5 16:51:26

帮顶。

xiaoqi976633690 发表于 2022-8-5 17:47:50

本帖最后由 xiaoqi976633690 于 2022-8-5 17:50 编辑

看了datasheet 不能用i2c中断,得开一个定时器中断然后再定时器中断函数中实现。
页: [1]
查看完整版本: RP2040 I2C slave 从机一进入中断就不会退出,程序一直在中断里面不出来。