打印
[APM32F4]

【APM32F411V Tiny Board测评】硬件I2C读取传感器测试

[复制链接]
114|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本次研究了一下APM32F411的I2C接口功能。看了一下官方例子是使用的中断模式,感觉不太方便。这里我就不使用中断模式操作I2C接口。
首先初始化I2C接口IO和外设:使用PB8和PB9的I2C1外设。
void drv_i2c_gpio_init( void )
{
    GPIO_Config_T   gpioConfigStruct;

    /* Enable I2C related Clock */
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
   
#ifdef I2C_USE_GPIO

#else
    I2C_Config_T    i2cConfigStruct;
   
    gpioConfigStruct.mode = GPIO_MODE_AF;
    gpioConfigStruct.speed = GPIO_SPEED_50MHz;
    gpioConfigStruct.pin = GPIO_PIN_8 | GPIO_PIN_9;
    gpioConfigStruct.otype = GPIO_OTYPE_OD;
    gpioConfigStruct.pupd = GPIO_PUPD_UP;
    GPIO_Config(GPIOB, &gpioConfigStruct);
   
    /* Free I2C_SCL and I2C_SDA */
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_8, GPIO_AF_I2C1);
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_9, GPIO_AF_I2C1);
   
    /*  Config I2C1 */
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);
    I2C_Reset(I2C1);
    i2cConfigStruct.mode = I2C_MODE_I2C;
    i2cConfigStruct.dutyCycle = I2C_DUTYCYCLE_2;
    i2cConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT;
    i2cConfigStruct.ownAddress1 = 0XA0;
    i2cConfigStruct.ack = I2C_ACK_DISABLE;
    i2cConfigStruct.clockSpeed = 100000;
    I2C_Config(I2C1, &i2cConfigStruct);
   
    I2C_DisableDualAddress(I2C1);
    /* Enable I2Cx */
    I2C_Enable(I2C1);

#endif
}


下面就是我的I2C读写接口:
static int __CheckErrFlag(I2C_T* i2c)
{
    int bflag;
    bflag = 0;
    if(I2C_ReadStatusFlag(i2c, I2C_FLAG_BERR))    //
    {
        bflag =1;
        I2C_ClearStatusFlag(i2c, I2C_FLAG_BERR);    //
    }
    if(I2C_ReadStatusFlag(i2c, I2C_FLAG_AL))    //
    {
        bflag =2;
        I2C_ClearStatusFlag(i2c, I2C_FLAG_AL);    //
    }
    if(I2C_ReadStatusFlag(i2c, I2C_FLAG_AE))    //
    {
        bflag =3;
        I2C_ClearStatusFlag(i2c, I2C_FLAG_AE);    //
    }
    if(I2C_ReadStatusFlag(i2c, I2C_FLAG_OVRUR))    //
    {
        bflag =4;
        I2C_ClearStatusFlag(i2c, I2C_FLAG_OVRUR);    //
    }
    if(I2C_ReadStatusFlag(i2c, I2C_FLAG_PECE))    //
    {
        bflag =5;
        I2C_ClearStatusFlag(i2c, I2C_FLAG_PECE);    //
    }
    if(I2C_ReadStatusFlag(i2c, I2C_FLAG_TTE))    //
    {
        bflag =6;
        I2C_ClearStatusFlag(i2c, I2C_FLAG_TTE);    //
    }
    if(I2C_ReadStatusFlag(i2c, I2C_FLAG_SMBALT))    //
    {
        bflag =7;
        I2C_ClearStatusFlag(i2c, I2C_FLAG_SMBALT);    //
    }
    return bflag;
}

static int __WaitEvtTimeout(I2C_T* i2c, I2C_EVENT_T evt)
{
    volatile uint32_t timeout;
    timeout = 10000;
    while (!I2C_ReadEventStatus(i2c, evt))
    {
        timeout--;
        if(timeout == 0)
        {
            return -1;
        }
        if(__CheckErrFlag(i2c))
        {
            return 1;
        }
    }
    return 0;
}

uint8_t I2C_WriteByte(uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t Byte)
{
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
    {
        I2C_EnableGenerateStop(I2C1);
        delay_us(15);
        break;
    }
    /* Send START condition */
    I2C_EnableGenerateStart(I2C1);
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
    /* Send address for write */
    I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
    /* Send the current byte */
    I2C_TxData(I2C1,addr &0xff);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
    /* Send the current byte */
    I2C_TxData(I2C1,Byte);
   __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
    I2C_EnableGenerateStop(I2C1);
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
   
    return 0;
}

uint8_t I2C_ReadByte (uint8_t index,uint32_t dev_addr, uint32_t addr)
{
    uint8_t buff;
   
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
    {
        I2C_EnableGenerateStop(I2C1);
        delay_us(15);
        break;
    }
    /* Send START condition */
    I2C_EnableGenerateStart(I2C1);
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
    /* Send address for write */
    I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
    /* Send the current byte */
    I2C_TxData(I2C1,addr &0xff);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
   
    /* Send START condition */
    I2C_EnableGenerateStart(I2C1);
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
    /* Send address for write */
    I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_RX);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);   //wait flag
   
    I2C_DisableAcknowledge(I2C1);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
    /* Recv the current byte */
    buff = I2C_RxData(I2C1);
   
    I2C_EnableGenerateStop(I2C1);
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
   
    return buff;
}


uint8_t I2C_PageWrite(uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t *str,uint32_t num)
{
    uint32_t i;
   
    if((num == 0)||(str==NULL)) return 1;
   
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
    {
        I2C_EnableGenerateStop(I2C1);
        delay_us(15);
        break;
    }
    /* Send START condition */
    I2C_EnableGenerateStart(I2C1);
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
    /* Send address for write */
    I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
    /* Send the current byte */
    I2C_TxData(I2C1,addr &0xff);
    for(i=num;i>0;i--)
    {
        __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
        /* Send the current byte */
        I2C_TxData(I2C1,*str++);
    }
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
    I2C_EnableGenerateStop(I2C1);
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
   
    return 0;
}

uint8_t I2C_PageRead (uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t *str,uint32_t num)
{
    uint32_t i;
   
    if((num == 0)||(str==NULL)) return 1;
   
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
    {
        I2C_EnableGenerateStop(I2C1);
        delay_us(15);
        break;
    }
    /* Send START condition */
    I2C_EnableGenerateStart(I2C1);
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
    /* Send address for write */
    I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //wait flag
    /* Send the current byte */
    I2C_TxData(I2C1,addr &0xff);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
   
    /* Send START condition */
    I2C_EnableGenerateStart(I2C1);
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
    /* Send address for write */
    I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_RX);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);   //wait flag
   
    for(i=num-1;i>0;i--)
    {
        I2C_EnableAcknowledge(I2C1);
        __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
        /* Recv the current byte */
        *str++ = I2C_RxData(I2C1);
    }
   
    I2C_DisableAcknowledge(I2C1);
    __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
    /* Recv the current byte */
    *str++ = I2C_RxData(I2C1);
   
    I2C_EnableGenerateStop(I2C1);
    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
    return 0;
}


调试这个I2C花了不少时间,主要是这个时序状态。我这里是用逻辑分析仪一步步慢慢调试出来的。
下面是一个检测I2C设备地址的函数,检测总线上设备。通过shell来检查地址状态。
static int __AddrDetect(uint8_t addr)
{
    uint32_t bflag;

    while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)    //bus busy
    {
        I2C_EnableGenerateStop(I2C1);
        delay_us(15);
        break;
    }
    /* Send START condition */
    I2C_EnableGenerateStart(I2C1);
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT));   //wait flag
    /* Send address for write */
    I2C_Tx7BitAddress(I2C1, addr << 1, I2C_DIRECTION_TX);
    bflag = 0;
    while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
        delay_us(25);
        bflag = __CheckErrFlag(I2C1);
        if(bflag)    break;
    }
    delay_us(10);
    I2C_EnableGenerateStop(I2C1);
   
    return bflag;
}

#if UART_SHELL == 2
#include "nr_micro_shell.h"

void I2C_AddrDetect(char argc, char *argv)
{
    int i,j;
   
    printf("Detect I2C addr:\r\n");
   
    for(i=0;i<8;i++)
    {
        for(j=0;j<16;j++)
        {
            if(__AddrDetect(j + i*16) == 0) printf("%02X ",j + i*16);
            else  printf("-- ");
            delay_ms(1);
        }
        printf("\r\n");
    }
    printf("\r\nDetect I2C addr over.\r\n");
}

NR_SHELL_CMD_EXPORT(i2c_detect,   I2C_AddrDetect,     "I2C detect device address");

#endif



这里我板子上接了4个I2C设备。分别是光照的RPR0521RS,3轴加速度BM1422,气压BM1383,和温湿度SHTC3。
接下来我们看看设备检测效果:

可以看到检测了4个地址设备了。

设备驱动都写好了测试成功,也可以通过shell读取数据了:



使用特权

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

本版积分规则

119

主题

4469

帖子

26

粉丝