[技术问答]

I2C读写:keil代码与arduino代码,帮看看有什么问题

[复制链接]
1184|16
手机看帖
扫描二维码
随时随地手机跟帖
kylongmu|  楼主 | 2022-2-20 20:03 | 显示全部楼层 |阅读模式
int chdrv_read_byte(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data) {

        return (chbsp_i2c_mem_read(dev_ptr, mem_addr, data, 1));
}
int chbsp_i2c_mem_read(ch_dev_t *dev_ptr, uint16_t u16_mem_addr, uint8_t *pu8_data, uint16_t u16_num_bytes)
{
    int i32_error = 1;      // default is error return
    uint8_t u8_i2c_addr = ch_get_i2c_address(dev_ptr);

    i32_error = i2c_master_read_register(u8_i2c_addr, u16_mem_addr, u16_num_bytes, pu8_data);
    return i32_error;
}
uint64_t i2c_master_read_register(uint8_t u8_Address, uint8_t u8_RegisterAddr, uint16_t u16_RegisterLen, uint8_t *pu8_RegisterValue)
{
    return !(u16_RegisterLen == I2C_ReadMultiBytesOneReg(I2C0, u8_Address, u8_RegisterAddr, pu8_RegisterValue, u16_RegisterLen));
}
uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t au8Rdata[], uint32_t u32rLen)
{
    uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
    uint32_t u32rxLen = 0u;

    I2C_START(i2c);                                                /* Send START */

    while (u8Xfering && (u8Err == 0u))
    {
        I2C_WAIT_READY(i2c) {}

        switch (I2C_GET_STATUS(i2c))
        {
            case 0x08u:
                I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));      /* Write SLA+W to Register I2CDAT */
                u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
                break;

            case 0x18u:                                             /* Slave Address ACK */
                I2C_SET_DATA(i2c, u8DataAddr);                     /* Write Lo byte address of register */
                break;

            case 0x20u:                                             /* Slave Address NACK */
            case 0x30u:                                             /* Master transmit data NACK */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Err = 1u;
                break;

            case 0x28u:
                u8Ctrl = I2C_CTL_STA_SI;                         /* Send repeat START */
                break;

            case 0x10u:
                I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u));    /* Write SLA+R to Register I2CDAT */
                u8Ctrl = I2C_CTL_SI;                             /* Clear SI */
                break;

            case 0x40u:                                             /* Slave Address ACK */
                u8Ctrl = I2C_CTL_SI_AA;                          /* Clear SI and set ACK */
                break;

            case 0x48u:                                             /* Slave Address NACK */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Err = 1u;
                break;

            case 0x50u:
                au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */

                if (u32rxLen < (u32rLen - 1u))
                {
                    u8Ctrl = I2C_CTL_SI_AA;                      /* Clear SI and set ACK */
                }
                else
                {
                    u8Ctrl = I2C_CTL_SI;                         /* Clear SI */
                }

                break;

            case 0x58u:
                au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c);   /* Receive Data */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Xfering = 0u;
                break;

            case 0x38u:                                             /* Arbitration Lost */
            default:                                               /* Unknow status */
                u8Ctrl = I2C_CTL_STO_SI;                         /* Clear SI and send STOP */
                u8Err = 1u;
                break;
        }

        I2C_SET_CONTROL_REG(i2c, u8Ctrl);                          /* Write controlbit to I2C_CTL register */
    }

    return u32rxLen;                                               /* Return bytes length that have been received */
}

以上代码来自于新唐m263的例子,功能是从I2C设备读取内部寄存器一个字节。
                ret_val = chdrv_write_byte(dev_ptr, 0x07, 2);
int chdrv_write_byte(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t data_value) {
        uint8_t message[] = { sizeof(data_value), data_value };                // insert byte count (1) at start of data

        int ch_err = chbsp_i2c_mem_write(dev_ptr, mem_addr, message, sizeof(message));

        return ch_err;
}
int chbsp_i2c_mem_write(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *pu8_data, uint16_t u16_num_bytes)
{
    int i32_error = 0;

    i32_error = i2c_master_write_register(dev_ptr->i2c_address, mem_addr, u16_num_bytes, pu8_data);

    return i32_error;
}
uint64_t i2c_master_write_register(uint8_t u8_Address, uint8_t u8_RegisterAddr, uint16_t u16_RegisterLen, uint8_t *pu8_RegisterValue)
{
    return !(u16_RegisterLen == I2C_WriteMultiBytesOneReg(I2C0, u8_Address, u8_RegisterAddr, pu8_RegisterValue, u16_RegisterLen));
}
uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t au8Data[], uint32_t u32wLen)
{
    uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
    uint32_t u32txLen = 0u;

    I2C_START(i2c);                                              /* Send START */

    while (u8Xfering && (u8Err == 0u))
    {
        I2C_WAIT_READY(i2c) {}

        switch (I2C_GET_STATUS(i2c))
        {
            case 0x08u:
                I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u));    /* Write SLA+W to Register I2CDAT */
                u8Ctrl = I2C_CTL_SI;
                break;

            case 0x18u:                                           /* Slave Address ACK */
                I2C_SET_DATA(i2c, u8DataAddr);                   /* Write Lo byte address of register */
                break;

            case 0x20u:                                           /* Slave Address NACK */
            case 0x30u:                                           /* Master transmit data NACK */
                u8Ctrl = I2C_CTL_STO_SI;                       /* Clear SI and send STOP */
                u8Err = 1u;
                break;

            case 0x28u:
                if (u32txLen < u32wLen)
                {
                    I2C_SET_DATA(i2c, au8Data[u32txLen++]);
                }
                else
                {
                    u8Ctrl = I2C_CTL_STO_SI;                   /* Clear SI and send STOP */
                    u8Xfering = 0u;
                }

                break;

            case 0x38u:                                           /* Arbitration Lost */
            default:                                             /* Unknow status */
                u8Ctrl = I2C_CTL_STO_SI;                       /* Clear SI and send STOP */
                u8Err = 1u;
                break;
        }

        I2C_SET_CONTROL_REG(i2c, u8Ctrl);                        /* Write controlbit to I2C_CTL register */
    }

    return u32txLen;                                             /* Return bytes length that have been transmitted */
}

以上代码来自于新唐m263的例子,功能是从I2C设备写入内部寄存器2个字节。感觉好绕,最后底层的I2C代码我已看不出时序,现在用arduino来取代,代码如下:
int chbsp_i2c_mem_write(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data, uint16_t num_bytes){
    TwoWire* pWire;
    pWire=chbsp_i2c_get_device(dev_ptr);
        if (pWire != NULL) {

                pWire->beginTransmission(dev_ptr->i2c_address);
                pWire->write(lowByte(mem_addr)); // LSB
                pWire->write(data,num_bytes);
                info = pWire->endTransmission();
        }
}
int chbsp_i2c_mem_read(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data, uint16_t num_bytes){

    TwoWire* pWire = NULL;
        int retval = 0;
    pWire=chbsp_i2c_get_device(dev_ptr);

        if (pWire != NULL) {
                pWire->beginTransmission(dev_ptr->i2c_address);
            pWire->write(lowByte(mem_addr));
            pWire->endTransmission();
                int receivedBytes = pWire->requestFrom((int)dev_ptr->i2c_address,(int)num_bytes,1);
            if(receivedBytes != num_bytes)
            {
                Serial.printf("did not receive enough bytes %dmem %dnum %drec %d\n.",mem_addr,num_bytes,receivedBytes,dev_ptr->i2c_address);
                retval = 1;  
            }else{
                    for(int i = 0; i < num_bytes; i++)   
                    {
                        data[i] = pWire->read();    // receive a byte as character
                    }
            }
        }else{
                retval = 1;
        }

    return retval;
}

但是我的arduino代码执行不正确,写入收到NACK,读出返回0字节,新唐的底层I2C实在看不懂,有大侠帮看看问题出在哪里,谢谢!

使用特权

评论回复
kiwis66| | 2022-2-21 09:39 | 显示全部楼层
arduino也是开发环境?

使用特权

评论回复
kylongmu|  楼主 | 2022-2-21 14:55 | 显示全部楼层
kiwis66 发表于 2022-2-21 09:39
arduino也是开发环境?

是的,一个跨平台的,可以找到大量三方库的环境。

使用特权

评论回复
jasontu| | 2022-2-22 08:20 | 显示全部楼层
nak表示address错误,看下规格书上面的i2c devices是不是正碉的。
可以的话拿个la录下波形

使用特权

评论回复
kylongmu|  楼主 | 2022-2-22 12:00 | 显示全部楼层
jasontu 发表于 2022-2-22 08:20
nak表示address错误,看下规格书上面的i2c devices是不是正碉的。
可以的话拿个la录下波形
...

器件是TDK的CH101,有两个地址区,有一个prog脚来区分:原手册描述
The CH101 contains two separate I2C interfaces, running on two separate slave addresses. The first is for loading firmware into the
on-chip program memory, and the second is for in-application communication with the CH101. The 7-bit programming address is
0x45, and the 7-bit application address default is 0x29. The application address can be reprogrammed to any valid 7-bit I2C address.
m263的官网例子里也是这两个地址。我的arduino程序做了个测试,prog脚高选中读0x45能返回正确值。然后prog脚低电平,把0~127号地址都读了一遍,没有一个能返回的。
la手上没有,先定了一块例子用同款m263开发板,拿来跑一遍看看现象。
TDK的这颗芯片实在难受,手册内容少的可怜,同时这颗芯片I2C操作之复杂,是我目前遇到过最难的,分地址区,传固件,然后是一堆命令来回,而这些东西都是手册上没有的。
以下链接可以看到这个例子原工程:
https://www.nuvoton.com.cn/products/microcontrollers/arm-cortex-m23-mcus/m261-m262-m263-series/m263kiaae/?group=Software&tab=2

使用特权

评论回复
kylongmu|  楼主 | 2022-2-22 14:58 | 显示全部楼层
刚刚考虑了一下,估计是第一步下载I2C固件有问题,固件没有工作,所以后面与固件通信的操作没有响应。还是只有等m263的开发板来跑一遍看看。

使用特权

评论回复
tpgf| | 2022-3-3 19:03 | 显示全部楼层
这俩是不同的软件吗

使用特权

评论回复
labasi| | 2022-3-3 19:10 | 显示全部楼层
应该是地址有错误

使用特权

评论回复
paotangsan| | 2022-3-3 19:16 | 显示全部楼层
还是参考官网例程吧

使用特权

评论回复
renzheshengui| | 2022-3-3 19:30 | 显示全部楼层
严格检查时序

使用特权

评论回复
wakayi| | 2022-3-3 19:37 | 显示全部楼层
这么看着实看不出问题来

使用特权

评论回复
wowu| | 2022-3-3 19:43 | 显示全部楼层
更改了哪一部分呢

使用特权

评论回复
豌豆爹| | 2022-3-4 10:47 | 显示全部楼层
多多参考下官方例程总是没错的

使用特权

评论回复
kylongmu|  楼主 | 2022-3-6 21:57 | 显示全部楼层
测试了官方263例子,读写都正确,arduino那边代码对比检查,实在找不出毛病,先放弃了。
改为移植到stm32l433上,一次成功。
因为263与stm32l433都是1.8V电平直接连接ch101,而arduino那边是用TXS0108EPWR做了个电平转换,目前感觉是这里有可能出问题,也怀疑arduino在连续传固件的时候会中断。先把arduino放一边吧。

使用特权

评论回复
kylongmu|  楼主 | 2022-3-6 22:03 | 显示全部楼层
目前测试ch101返回的测量数值乱跳,在263上与stm32l4上都是,看了263的例子里用的ch101库还是早期的,很长时间没有更新了,又到TDK那边下了最新的库来自己升级替换,结果测试值还是乱跳,网上搜了一遍没有看到谁用过这颗超声TOF,看来我踩深坑里了

使用特权

评论回复
kylongmu|  楼主 | 2022-3-6 22:07 | 显示全部楼层
我为啥要反向移植到stm32呢?因为cubemx实在是太方便了,我可以省去很多学习成本。而263这边就费劲多了。当然要是能用arduino来开发,二者皆可抛

使用特权

评论回复
kiwis66| | 2022-3-11 16:49 | 显示全部楼层
再学习一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

18

帖子

0

粉丝