用户工具

站点工具


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

STM32CubeMX教程七——I2C实验

1. 在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR 2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。 3. 配置RCC,使用外部时钟源 4. 时基源选择SysTick 5. 将PA10,PB7,PB8设置为GPIO_Output 6. 引脚模式配置 7. 时钟源设置,选择外部高速时钟源,配置为最大主频 8. 工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK V5.27 9. 点击Code Generator,进行进一步配置

  • Copy all used libraries into the project folder
  • 将HAL库的所有.C和.H都复制到所建工程中
    • 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便
    • 缺点:体积大,编译时间很长 * Copy only the necessary library files
  • 只复制所需要的.C和.H(推荐)
    • 优点:体积相对小,编译时间短,并且工程可复制拷贝
    • 缺点:新增外设时需要重新用STM32CubeMX导入
  • Add necessary library files as reference in the toolchain project configuration file
  • 不复制文件,直接从软件包存放位置导入.C和.H
    • 优点:体积小,比较节约硬盘空间
    • 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径
  • 自行选择方式即可

10. 然后点击GENERATE CODE 创建工程 创建成功,打开工程。


实验七:I2C通信实验——驱动电源管理AXP152

一、 实验目的与意义

  1. 了解STM32 I2C结构
  2. 了解STM32 I2C特征
  3. 掌握I2C的使用方法
  4. 掌握STM32 HAL库中I2C属性的配置方法
  5. 掌握KEILMDK 集成开发环境使用方法

二、 实验设备及平台

  1. iCore4T 双核心板。点击购买
  2. JLINK(或相同功能)仿真器。点击购买
  3. Micro USB线缆。
  4. Keil MDK 开发平台。
  5. STM32CubeMX开发平台。
  6. 装有WIN XP(及更高版本)系统的计算机。

三、 实验原理

1、 I2C简介

  • I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。是微电子通信控制领域广泛采用的一种总线标准。

2、 I2C工作方式

I2C设备之间常用的连接方式如下图。

  • 可以看到上图中有两根总线,一根是主控时序 SCL, 另一根是主控数据SDA。“总线”指多个设备公用的信号线, 在一个 I2C 通信总线中,可连接多个 I2C设备通信,支持多个通信主机及多个通信从机。
  • 为了区分设备,每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。 当有多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
  • I2C 支持不同的通信速度,标准速度高达100kHz, 快速速度高达 400kHz。

3、 I2C通信流程

  • 通信开始:主设备发送起始条件(启动数据传输并生成时钟信号);主设备发送要寻址的从设备的地址以及通信方向。
  • 通信过程中:主设备发送数据,从设备发送应答;从设备发送数据,主设备发送应答。
  • 通信结束:主设备发送停止条件。

  • 空闲状态:SDA和SCL两条信号线同时处于高电平。
  • 起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号, 而不是一个电平信号。
  • 停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

  • 应答信号ACK:
  • 发送器每发送一个字节, 就在时钟脉冲9期间释放数据线, 由接收器反馈一个应答信号。
  • 应答信号为低电平时, 为有效应答位(ACK) , 表示接收成功。
  • 应答信号为高电平时, 为非应答位(NACK) , 表示接收没有成功。
  • 对于反馈有效应答位ACK的要求是, 接收器在第9个时钟脉冲之前的。
  • 低电平期间将SDA线拉低, 并且确保在该时钟的高电平期间为稳定的低电平。

  • 数据有效性:
  • I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

  • 我们I2C通过SDA和SCL即可实现通信,那么我们在STM32上直接通过控制两个 GPIO口的电平,即可利用这个来产生通信的时序,这种方法称为“软件I2C”。还有一种是“硬件 I2C”,是STM32的I2C片上外设专门负责实现 I2C 通信协议,配置好该外设,它就会自动地根据协议要求产生通信信号,收发数据并缓存,CPU只要检测该外设的状态和访问相应寄存器,即可实现数据的接发。

4、 AXP152简介

  • AXP152是一款高度集成的电源管理芯片,包含 4 路高效 DCDC、7 路 LDO,输出电压可灵活配置。AXP152用于需要多路电源转换的应用场景,并可与本公司其它 PMU 配合构成完整的单芯或多芯锂电池(锂离子或锂聚合物)应用场景电源解决方案,充分满足目前日益复杂的应用处理器系统对于电源多输出、大电流、高精度的要求。
  • AXP152 内部集成了过压欠压保护(OVP/UVP)、过温保护(OTP)等保护功能,可充分保障供电的安全稳定。
  • AXP152 提供了一个两线串行通信接口:Two Wire Serial Interface (TWSI),应用处理器可以通过这个接口设置各路输出的电压,打开/关闭某些电源输出,以及配置中断和睡眠唤醒系统。
  • 原理图如下所示:

四、 实验程序

1. 主函数

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  i2c.initialize();
  axp152.initialize();
  axp152.set_dcdc1(3500);//[ARM & FPGA BK1/2/6 &OTHER]
  axp152.set_dcdc2(1200);//[FPGA INT & PLL D]
  axp152.set_aldo1(2500);//[FPGA PLL A]
  axp152.set_dcdc4(3300);//[POWER_OUTPUT]
  axp152.set_dcdc3(3300);//[FPGA BK4][Adjustable]
  axp152.set_aldo2(3300);//[FPGA BK3][Adjustable]
  axp152.set_dldo1(3300);//[FPGA BK7][Adjustable]
  axp152.set_dldo2(3300);//[FPGA BK5][Adjustable]
  MX_GPIO_Init();
  while (1)
  {
  }
}

2. I2C配置函数

static int initialize(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
 
    SDA_OUTPUT;
    SCL_OUTPUT;
 
    SDA_ON;
    SCL_ON;
 
    return 0;
}
//起始信号
static
int start(void)
{
    SDA_ON;
    delay();
 
    SCL_ON;
    delay();
 
    SDA_OFF;
    delay();
 
    SCL_OFF;
    delay();
    SDA_OFF;
    delay();
 
    SCL_OFF;
    delay();
 
    return 0;
}
//终止信号
static
int stop(void)
{
//  SDA_OUTPUT;
 
    SDA_OFF;
    delay();
 
    SCL_ON;
    delay();
 
    SDA_ON;
    delay();
 
    return 0;
}
//应答
static int
ack(char a)
{
//  SDA_OUTPUT;
 
    if (a) {
        SDA_OFF;
    }else {
        SDA_ON;
    }
    delay();
    SCL_ON;
    delay();
    SCL_OFF;
 
    delay();
 
    return 0;
};
//发送
static int
write(unsigned char data)
{
    unsigned char i = 8;
//  SDA_OUTPUT;
 
    for (i = 0; i < 8; i++) { /*要传送的数据长度为8 位*/
        if ((data << i) & 0x80) SDA_ON;  /*判断发送位*/
        else SDA_OFF;
        delay();
        SCL_ON;
        delay();
        SCL_OFF;
    }
    SDA_INPUT;
    delay();
 
    delay();
    SCL_ON;
 
    delay();
    if (SDA_DATA) i2c.ack_flag = 0;
    else i2c.ack_flag = 1;  /*判断是否接收到应答信号*/
    SCL_OFF;
    SDA_OUTPUT;
    delay();
 
    return 0;
}
//接收
static unsigned char read(void)
{
    unsigned char retc;
    unsigned char BitCnt;
 
    retc = 0;
 
    SDA_ON; /*置数据线为输入方式*/
    SDA_INPUT;
 
    for (BitCnt = 0; BitCnt < 8; BitCnt++) {
        delay();
        SCL_OFF; /*置时钟线为低,准备接收数据位*/
        delay();
        SCL_ON; /*置时钟线为高使数据线上数据有效*/
        delay();
        retc = retc << 1;
        if ((SDA_DATA) == 1) retc = retc + 1;  /*读数据位,接收的数据位放入retc 中 */
        delay();
    }
    SCL_OFF;
    delay();
 
    SDA_OUTPUT;
 
    return(retc);
}
//接受数据
static int
read_nbyte(unsigned char sla, unsigned char suba, unsigned char *s, unsigned char no)
{
    unsigned char i;
 
    i2c.start(); /*启动总线*/
    i2c.write(sla); /*发送器件地址*/
//  if(i2c.ack_flag==0)return(0);
    i2c.write(suba); /*发送器件子地址*/
//  if(i2c.ack_flag==0)return(0);
    i2c.start();
    i2c.write(sla + 1);
//  if(i2c.ack_flag==0)return(0);
    for (i = 0; i < no - 1; i++) {
        *s = i2c.read(); /*发送数据*/
        i2c.ack(1); /*发送就答位*/
        s++;
    }
    *s = i2c.read();
    i2c.ack(0);
    i2c.stop();
 
    return(1);
}
//发送数据
static int
write_nbyte(unsigned char sla, unsigned char suba, unsigned char *s, unsigned char no)
{
    unsigned char i;
 
    i2c.start();
    i2c.write(sla);
    if (i2c.ack_flag == 0) return(0);
    i2c.write(suba);
    if (i2c.ack_flag == 0) return(0);
 
    for (i = 0; i < no; i++) {
        i2c.write(*s);
        if (i2c.ack_flag == 0) return(0);
        s++;
    }
    i2c.stop();
 
    return(1);
}

3. AXP初始化函数

int initialize(void)
{
    unsigned char ver;
    int rc;
    rc = i2c.read_nbyte(AXP152_I2C_ADDR,AXP152_CHIP_VERSION,&ver,1);
    if (rc){
        return rc;
    }
    if (ver != 0x05){
        return -1;
    }
    return 0;
}

4. 电压参数调整函数

static unsigned char axp152_mvolt_to_target(int mvolt, int min, int max, int div)
{
    if (mvolt < min)
        mvolt = min;
    else if (mvolt > max)
        mvolt = max;
return (mvolt - min) / div;
}
 
int set_dcdc2(unsigned int mvolt)
{
    unsigned char target = axp152_mvolt_to_target(mvolt, 700, 2275, 25);
    return i2c.write_nbyte(AXP152_I2C_ADDR,AXP152_DCDC2_VOLTAGE,&target,1);

五、 实验步骤

  1. 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连);
  2. 把iCore4T通过Micro USB线与计算机相连,为iCore4T供电;
  3. 打开Keil MDK 开发环境,并打开本实验工程;
  4. 烧写程序到iCore4T上;
  5. 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。

六、 实验现象

用万用表测量各测试点电压与程序设定电压一致。

icore4t_7.txt · 最后更改: 2022/03/22 10:39 由 sean