| **银杏科技有限公司旗下技术文档发布平台** ||||
|技术支持电话|**0379-69926675-801**|||
|技术支持邮件|Gingko@vip.163.com|||
^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^
| V1.0 | 2019-02-16 | gingko | 初次建立 |
===== STM32CubeMX教程七——I2C实验 =====
1. 在主界面选择File-->New Project 或者直接点击ACCEE TO MCU SELECTOR
{{ :icore4t:icore4t_cube_7_1.png?direct |}}
2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置
在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。
{{ :icore4t:icore4t_cube_7_2.png?direct |}}
3. 配置RCC,使用外部时钟源
{{ :icore4t:icore4t_cube_7_3.png?direct |}}
4. 时基源选择SysTick
{{ :icore4t:icore4t_cube_7_4.png?direct |}}
5. 将PA10,PB7,PB8设置为GPIO_Output
{{ :icore4t:icore4t_cube_7_5.png?direct |}}
6. 引脚模式配置
{{ :icore4t:icore4t_cube_7_6.png?direct |}}
{{ :icore4t:icore4t_cube_7_7.png?direct |}}
7. 时钟源设置,选择外部高速时钟源,配置为最大主频
{{ :icore4t:icore4t_cube_7_8.png?direct |}}
8. 工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK V5.27
{{ :icore4t:icore4t_cube_7_9.png?direct |}}
9. 点击Code Generator,进行进一步配置
{{ :icore4t:icore4t_cube_7_10.png?direct |}}
* **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 创建工程
{{ :icore4t:icore4t_cube_7_11.png?direct |}}
创建成功,打开工程。
\\
\\
\\
===== 实验七:I2C通信实验——驱动电源管理AXP152 =====
==== 一、 实验目的与意义 ====
- 了解STM32 I2C结构
- 了解STM32 I2C特征
- 掌握I2C的使用方法
- 掌握STM32 HAL库中I2C属性的配置方法
- 掌握KEILMDK 集成开发环境使用方法
==== 二、 实验设备及平台 ====
- iCore4T 双核心板。[[https://item.taobao.com/item.htm?spm=a1z10.1-c.w137644-251734891.3.5923532fDrMDOe&id=610595120319|点击购买]]
- JLINK(或相同功能)仿真器。[[https://item.taobao.com/item.htm?id=554869837940|点击购买]]
- Micro USB线缆。
- Keil MDK 开发平台。
- STM32CubeMX开发平台。
- 装有WIN XP(及更高版本)系统的计算机。
==== 三、 实验原理 ====
=== 1、 I2C简介 ===
* I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。是微电子通信控制领域广泛采用的一种总线标准。
=== 2、 I2C工作方式 ===
I2C设备之间常用的连接方式如下图。
{{ :icore4t:icore4t_arm_hal_7_1.png?direct |}}
* 可以看到上图中有两根总线,一根是主控时序 SCL, 另一根是主控数据SDA。“总线”指多个设备公用的信号线, 在一个 I2C 通信总线中,可连接多个 I2C设备通信,支持多个通信主机及多个通信从机。
* 为了区分设备,每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。 当有多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
* I2C 支持不同的通信速度,标准速度高达100kHz, 快速速度高达 400kHz。
=== 3、 I2C通信流程 ===
* 通信开始:主设备发送起始条件(启动数据传输并生成时钟信号);主设备发送要寻址的从设备的地址以及通信方向。
* 通信过程中:主设备发送数据,从设备发送应答;从设备发送数据,主设备发送应答。
* 通信结束:主设备发送停止条件。
{{ :icore4t:icore4t_arm_hal_7_2.png?direct |}}
* 空闲状态:SDA和SCL两条信号线同时处于高电平。
* 起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号, 而不是一个电平信号。
* 停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
{{ :icore4t:icore4t_arm_hal_7_3.png?direct |}}
* **应答信号ACK:**
* 发送器每发送一个字节, 就在时钟脉冲9期间释放数据线, 由接收器反馈一个应答信号。
* 应答信号为低电平时, 为有效应答位(ACK) , 表示接收成功。
* 应答信号为高电平时, 为非应答位(NACK) , 表示接收没有成功。
* 对于反馈有效应答位ACK的要求是, 接收器在第9个时钟脉冲之前的。
* 低电平期间将SDA线拉低, 并且确保在该时钟的高电平期间为稳定的低电平。
{{ :icore4t:icore4t_arm_hal_7_4.png?direct |}}
* **数据有效性:**
* I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
{{ :icore4t:icore4t_arm_hal_7_5.png?direct |}}
* 我们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),应用处理器可以通过这个接口设置各路输出的电压,打开/关闭某些电源输出,以及配置中断和睡眠唤醒系统。
* 原理图如下所示:
{{ :icore4t:icore4t_arm_hal_7_6.png?direct |}}
==== 四、 实验程序 ====
=== 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);
==== 五、 实验步骤 ====
- 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连);
- 把iCore4T通过Micro USB线与计算机相连,为iCore4T供电;
- 打开Keil MDK 开发环境,并打开本实验工程;
- 烧写程序到iCore4T上;
- 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。
==== 六、 实验现象 ====
用万用表测量各测试点电压与程序设定电压一致。