用户工具

站点工具


icore4trtt_6
银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-02-29 zh. 初次建立

iCore4T_RTT_6_添加I2C设备驱动挂载AXP152

  • iCore4T ARM+FPGA双核心板I2C总线挂有三个设备,分别为AXP152电源管理芯片,LM75A温度传感器,EEPROM存储器,今天给大家分享I2C总线驱动的添加过程及AXP152的挂载过程。

一、修改Kconfig文件

  • 这里我们采用的是RT-Thread的模拟I2C,使用普通IO就可以了,不再需要通过CubeMx配置I2C引脚。在kconfig文件中增加menuconfig菜单配置中I2C的选项及I2C IO的 选项。这里需要特别说明的是23,24怎么来的。我在DAY2里制作的最简BSP中已经添加了PIN设备,所以这里就可以直接使用GPIO了,从原理图可以看到I2C的两个引脚SDA、SCL分别为PB7、PB8,RT-Thread中对GPIO驱动进行了再封装,对编号也进行了重编。我们知道一组IO是16个,所以RTT把PA0作为引脚0,以此累加进行编号。因此23即PB7,24即PB8。

二、使用scons命令生成MDK5工程,编译,烧录。

  • 启动之后,我们查看设备,可以发现i2c1已经做为一个BUS设备添加成功了。

         

三、挂载AXP152

  • axp152是一款I2C总线接口的电源管理芯片,可输出8路电源,分别为4路DCDC,4路LDO,添加AXP152驱动,然后在menuconfig中添加配置AXP152的选项及各路输出电源的参数,这样就可以直接通过menuconfig方便地管理各路电源的输出电压了。
  • 3.1 修改kconfig文件,在menuconfig中添加配置AXP152的选项及各路输出电源的参数。

  • 3.2 添加axp152的驱动程序,并将该文件放在../bsp/stm32/libraries/HAL_Drivers,我把源码帖在下面。
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-02-17     zh.          first version
 */
 
#include <board.h>
#include <drv_qspi.h>
#include <rtdevice.h>
#include <rthw.h>
#include <finsh.h>

#ifdef BSP_USING_I2C_AXP152

#define	AXP152_CHIP_VERSION                        0x03
#define	AXP152_DCDC1_VOLTAGE                    0x26
#define	AXP152_DCDC2_VOLTAGE                    0x23
#define	AXP152_DCDC3_VOLTAGE                    0x27
#define	AXP152_DCDC4_VOLTAGE                    0x2B
#define	AXP152_DLDO1_VOLTAGE                    0x29
#define	AXP152_DLDO2_VOLTAGE                    0x2A
#define	AXP152_ALDO1_ALD02_VOLTAGE         0x28
#define	AXP152_SHUTDOWN                            0x32

#define AXP152_POWEROFF                         (1 << 7)

/* For axp_gpio.c */
char AXP152_ADDR = (0x60 >> 1);
#define AXP152_ADDR_0                    (0x60 >> 1)
#define AXP152_ADDR_1                    (0x62 >> 1)
#define AXP152_ADDR_2                    (0x64 >> 1)
#define AXP152_ADDR_3                    (0x66 >> 1)
#define AXP_GPIO0_CTRL                          0x90
#define AXP_GPIO1_CTRL                          0x91
#define AXP_GPIO2_CTRL                          0x92
#define AXP_GPIO3_CTRL                          0x93
#define AXP_GPIO_CTRL_OUTPUT_LOW                0x00 /* Drive pin low */
#define AXP_GPIO_CTRL_OUTPUT_HIGH               0x01 /* Drive pin high */
#define AXP_GPIO_CTRL_INPUT                            0x02 /* Input */
#define AXP_GPIO_STATE                                      0x97
#define AXP_GPIO_STATE_OFFSET                         0x00

/* For axp152 i2c bus*/
#define AXP152_I2CBUS_NAME     "i2c1"

static struct rt_i2c_bus_device *axp152_i2c_bus = RT_NULL;

static rt_err_t i2c_write_nbyte(rt_uint8_t slave_addr, rt_uint8_t cmd, rt_uint8_t *value, rt_uint32_t len)
{
    rt_uint32_t i;
    rt_uint8_t *buffer;
    rt_size_t result;
	
    buffer = rt_malloc(len + 1);
    buffer[0] = cmd;
	for(i  = 0;i < len;i ++)
	{
		buffer[i+1] = value[i];
	}	
    result = rt_i2c_master_send(axp152_i2c_bus, slave_addr, RT_I2C_WR, buffer, len+1);
	rt_free(buffer);
	
    if (result == (len+1))
    {
        return RT_EOK;       
    }
    else
    {
        return -RT_ERROR;       
    }
}

static rt_err_t i2c_read_nbyte(rt_uint8_t slave_addr, rt_uint8_t cmd, rt_uint8_t *buf, rt_uint32_t len)
{
    rt_i2c_master_send(axp152_i2c_bus, slave_addr, RT_I2C_WR, &cmd, 1);
    
    rt_i2c_master_recv(axp152_i2c_bus, slave_addr, RT_I2C_RD, buf, len);
    
    return RT_EOK;
}

static rt_uint8_t axp152_mvolt_to_target(rt_uint32_t mvolt, rt_uint32_t min, rt_uint32_t max, rt_uint32_t div)
{
    if(mvolt < min)		mvolt = min;
    else if (mvolt > max)		mvolt = max;

    return (mvolt - min) / div;
}

rt_err_t axp152_set_dcdc1(rt_uint32_t mvolt)
{
    rt_uint8_t target = axp152_mvolt_to_target(mvolt, 1700, 3500, 100);
	
    if(mvolt >= 2400 || mvolt <= 2800)target = target - 2;
    if(mvolt >= 3000 || mvolt <= 3500)target = target - 3;

    return i2c_write_nbyte(AXP152_ADDR,AXP152_DCDC1_VOLTAGE,&target,1);
}

rt_err_t axp152_set_dcdc2(rt_uint32_t mvolt)
{
    rt_uint8_t target = axp152_mvolt_to_target(mvolt, 700, 2275, 25);

    return i2c_write_nbyte(AXP152_ADDR,AXP152_DCDC2_VOLTAGE,&target,1);
}

rt_err_t axp152_set_dcdc3(rt_uint32_t mvolt)
{
     rt_uint8_t target = axp152_mvolt_to_target(mvolt, 700, 3500, 50);

     return i2c_write_nbyte(AXP152_ADDR,AXP152_DCDC3_VOLTAGE,&target,1);
}

rt_err_t axp152_set_dcdc4(rt_uint32_t mvolt)
{
    rt_uint8_t target = axp152_mvolt_to_target(mvolt, 700, 3500, 25);

    return i2c_write_nbyte(AXP152_ADDR,AXP152_DCDC4_VOLTAGE,&target,1);
}

rt_err_t axp152_set_dldo1(rt_uint32_t mvolt)
{
    rt_uint8_t target = axp152_mvolt_to_target(mvolt, 700, 3500, 100);

    return i2c_write_nbyte(AXP152_ADDR,AXP152_DLDO1_VOLTAGE,&target,1);	
}

rt_err_t axp152_set_dldo2(rt_uint32_t mvolt)
{
    rt_uint8_t target = axp152_mvolt_to_target(mvolt, 700, 3500, 100);

    return i2c_write_nbyte(AXP152_ADDR,AXP152_DLDO2_VOLTAGE,&target,1);
}

rt_err_t axp152_set_aldo1(rt_uint32_t mvolt)
{
    rt_uint8_t data;
    rt_uint8_t target;

    if(mvolt >= 1200 && mvolt <= 2000)
    {
        target = axp152_mvolt_to_target(mvolt, 1200, 2000, 100);
    }
    else if(mvolt == 2500) 
    {
        target = 0x09;
    }
    else if(mvolt == 2700)
    {
        target = 0x0A;
    }
    else if(mvolt == 2800)
    {
        target = 0x0B;
    }
    else if(mvolt >= 3000 || mvolt <= 3300)
    {
        target = axp152_mvolt_to_target(mvolt, 3000, 3300, 100);
        target += 0x0C;
    }

    i2c_read_nbyte(AXP152_ADDR,AXP152_ALDO1_ALD02_VOLTAGE,&data,1);

    data &= 0x0F;
    target = target << 4;
    target &= 0xF0;
    target = data | target;

    return i2c_write_nbyte(AXP152_ADDR,AXP152_ALDO1_ALD02_VOLTAGE,&target,1);
}

rt_err_t axp152_set_aldo2(rt_uint32_t mvolt)
{
    rt_uint8_t data;
    rt_uint8_t target;

    if(mvolt >= 1200 && mvolt <= 2000)
    {
        target = axp152_mvolt_to_target(mvolt, 1200, 2000, 100);
    }
    else if(mvolt == 2500)
    {
        target = 0x09;
    }
    else if(mvolt == 2700)
    {
        target = 0x0A;
    }
    else if(mvolt == 2800)
    {
        target = 0x0B;
    }
    else if(mvolt >= 3000 || mvolt <= 3300)
    {
        target = axp152_mvolt_to_target(mvolt, 3000, 3300, 100);
        target += 0x0C;
    }

    i2c_read_nbyte(AXP152_ADDR,AXP152_ALDO1_ALD02_VOLTAGE,&data,1);
    data &= 0xF0;
    target = target & 0x0F;
    target = data | target;
    return i2c_write_nbyte(AXP152_ADDR,AXP152_ALDO1_ALD02_VOLTAGE,&target,1);
}

int axp152_init(void)
{
    rt_uint8_t ver;

    axp152_i2c_bus = rt_i2c_bus_device_find(AXP152_I2CBUS_NAME);

    if(axp152_i2c_bus == RT_NULL)
    {
        rt_kprintf("i2c_bus %s for axp152 not found!\n", axp152_i2c_bus);
        return -RT_ERROR;			
    }
    /* detect axp152 */
    i2c_read_nbyte(AXP152_ADDR_0, AXP152_CHIP_VERSION, &ver, 1);
		if(ver != 0x05){
			rt_thread_mdelay(10);
			i2c_read_nbyte(AXP152_ADDR_1,AXP152_CHIP_VERSION,&ver,1);
			if(ver != 0x05){
				rt_thread_mdelay(10);
				i2c_read_nbyte(AXP152_ADDR_2,AXP152_CHIP_VERSION,&ver,1);
				if(ver != 0x05){
					rt_thread_mdelay(10);
					i2c_read_nbyte(AXP152_ADDR_3,AXP152_CHIP_VERSION,&ver,1);
					if(ver != 0x05){
						rt_kprintf("[AXP152] probe fail!\n");
						return -RT_ERROR;
					}else{
						AXP152_ADDR = AXP152_ADDR_3;
						rt_kprintf("[AXP152] i2c addr is 0x66\n");
						rt_kprintf("[AXP152] 3 probe ok! Version is 0x%02X\n",ver);
					}
				}else{
					AXP152_ADDR = AXP152_ADDR_2;
					rt_kprintf("[AXP152] i2c addr is 0x64\n");
					rt_kprintf("[AXP152] 2 probe ok! Version is 0x%02X\n",ver);
				}
			}else{
				AXP152_ADDR = AXP152_ADDR_1;
				rt_kprintf("[AXP152] i2c addr is 0x62\n");
				rt_kprintf("[AXP152] 1 probe ok! Version is 0x%02X\n",ver);
			}
		}else{
			AXP152_ADDR = AXP152_ADDR_0;
			rt_kprintf("[AXP152] i2c addr is 0x60\n");
			rt_kprintf("[AXP152] probe ok! Version is 0x%02X\n",ver);
		}
    /* config axp152 */
    axp152_set_dcdc1(AXP_DCDC1_VOLT);
    axp152_set_dcdc2(AXP_DCDC2_VOLT);
    axp152_set_dcdc3(AXP_DCDC3_VOLT);
    axp152_set_dcdc4(AXP_DCDC4_VOLT);
    axp152_set_dldo1(AXP_DLDO1_VOLT);
    axp152_set_dldo2(AXP_DLDO2_VOLT);
    axp152_set_aldo1(AXP_ALDO1_VOLT);
    axp152_set_aldo2(AXP_ALDO2_VOLT);
		
    return RT_EOK;
}
INIT_DEVICE_EXPORT(axp152_init);

#endif /* BSP_USING_I2C_AXP152 */
  • 3.3 添加文件路径,这样生成工程的时候可以自动将该文件加入MDK工程。

  • 3.4 打开menuconfig,配置AXP152,这里直接用默认的配置参数即可,当然如果有其他的需求也可以进行修改。

  • 3.5 再次使用scons命令生成MDK5工程,编译、烧录,我们可以看到已经探测到了AXP152,并对其各路电压进行了配置。

  • 至此,我们成功的添加了I2C总线驱动,添加了AXP152设备。

四、源代码

源代码可以移步这里下载:

链接:https://pan.baidu.com/s/1fcLU4WaRDlgr0mNYwZj1Yg 提取码:zstq

icore4trtt_6.txt · 最后更改: 2022/04/01 11:10 由 sean