硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1510|回复: 2
收起左侧

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

[复制链接]

2

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2022-8-5 14:52:54 | 显示全部楼层 |阅读模式
RP2040 I2C slave 从机一进入中断就不会退出,程序一直在中断里面不出来。
参考了github的 https://github.com/vmilea/pico_i2c_slave

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

Snipaste_2022-08-05_14-50-50.bmp
1.bmp

[C] 纯文本查看 复制代码
#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[256];
uint8_t  tx_buff[2]={0x01,0xaa};
uint8_t  i2c_buff[8]={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[0]=%x\n\r",ram[0]);
        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[0],i2c_buff[1]);
        if((i2c_buff[0]==0x00)&&(i2c_buff[1]==0x99))
        {
            i2c_write_raw_blocking(I2C0_PORT,tx_buff,2);
            i++;
        }
        */
    }

}

void  init_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);

}


void  I2C0_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[ram_addr] = (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[ram_addr];

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

        // Increment the address
        ram_addr++;

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

}


int I2C_BUSCAN(void)
{

    printf("\nI2C Bus Scan\n");
    printf("   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\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;
}











回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106738
QQ
发表于 2022-8-5 16:51:26 | 显示全部楼层
帮顶。
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2022-8-5 17:47:50 | 显示全部楼层
本帖最后由 xiaoqi976633690 于 2022-8-5 17:50 编辑

看了datasheet 不能用i2c中断,得开一个定时器中断然后再定时器中断函数中实现。 2040.bmp
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 02:22 , Processed in 0.162199 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表