| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**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。 {{ :icore4t:iCore4T_RTT_6_1.png?direct |}} {{ :icore4t:iCore4T_RTT_6_2.png?direct |}} ==== 二、使用scons命令生成MDK5工程,编译,烧录。 ==== * 启动之后,我们查看设备,可以发现i2c1已经做为一个BUS设备添加成功了。 {{ :icore4t:iCore4T_RTT_6_3.png?direct |}}          ==== 三、挂载AXP152 ==== * axp152是一款I2C总线接口的电源管理芯片,可输出8路电源,分别为4路DCDC,4路LDO,添加AXP152驱动,然后在menuconfig中添加配置AXP152的选项及各路输出电源的参数,这样就可以直接通过menuconfig方便地管理各路电源的输出电压了。 * 3.1 修改kconfig文件,在menuconfig中添加配置AXP152的选项及各路输出电源的参数。 {{ :icore4t:iCore4T_RTT_6_4.png?direct |}} * 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 #include #include #include #include #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工程。 {{ :icore4t:iCore4T_RTT_6_5.png?direct |}} * 3.4 打开menuconfig,配置AXP152,这里直接用默认的配置参数即可,当然如果有其他的需求也可以进行修改。 {{ :icore4t:iCore4T_RTT_6_6.png?direct |}} * 3.5 再次使用scons命令生成MDK5工程,编译、烧录,我们可以看到已经探测到了AXP152,并对其各路电压进行了配置。 {{ :icore4t:iCore4T_RTT_6_7.png?direct |}} * 至此,我们成功的添加了I2C总线驱动,添加了AXP152设备。 ==== 四、源代码 ==== 源代码可以移步这里下载: 链接:https://pan.baidu.com/s/1fcLU4WaRDlgr0mNYwZj1Yg 提取码:zstq