DW_apb_i2c 使用介绍2--i2c初始化以及读写eeprom测试
1.DW_apb_i2c寄存器
目前我使用DW_apb_i2c协议是:DW_apb_i2c_2018,即2018版本。这个IP的寄存器共有68个,相对于stm32来说,这个寄存器数量确实有点多,实际使用起来也确实有点繁琐,不过当前的项目需求,有一大部分寄存器是用不到的,所以也还好。另外因为项目原因,一些具体的代码细节不太方便写出来,有疑问可以留言交流。
寄存器是在第5章,截图如下:
具体每个寄存器如何使用就不展开了,直接看寄存器说明即可。
2.DW_apb_i2c初始化流程
在第6章的6.3章节,有一个初始化流程图,如下图:
这是一个结合DMA的使用流程图,现在我只是初始化i2c,所以只关心上图的黄色框部分,做一个简单的初始化总结:
(1)先在i2c_enable寄存器中disable i2c。因为这个IP的有些寄存器必须在i2c处于disable状态下才能配置生效;
(2)在i2c_con寄存器中使能restart_en
(3)在i2c_con寄存器中选择地址模式,一般都是使用7bit模式;
(4)在i2c_con寄存器中配置SCL速率模式,我的用例是配置成standard mode;
(5)在i2c_con寄存器中使能master模式;
(6)在IC_TAR寄存器中设置slave device地址;
(7)配置i2c_ss_scl_hcnt和i2c_ss_scl_lcnt。虽然步骤4配置SCL成standard mode,但是实际SCL的大小是与i2c_ss_scl_hcnt和i2c_ss_scl_lcnt有关的。
(8)配置i2c_intr_mask寄存器,使能相关的中断;
(9)配置i2c_tx_tl和i2c_rx_tl寄存器,这2个寄存器这关系到TX_EMPTY和RX_FULL中断的触发条件;
(10)配置i2c_dma_tdlr和i2c_dma_rdlr寄存器,这里是配置DMA水线;
(11)最后在i2c_enable寄存器中enable i2c。
3.初始化测试代码
以下是个人的初始化代码,仅作参考。这里与上面的流程顺序可能不太一致,我还增加了广播功能、中断函数注册等,这个不影响功能。
(1)用结构体 i2c_reg_s 定义寄存器:
typedef struct{i2c_con_s i2c_con; /* offset: 0x00 i2c control */i2c_tar_s i2c_tar; /* offset: 0x04 i2c target address */i2c_sar_s i2c_sar; /* offset: 0x08 i2c slave address */i2c_hs_maddr_s i2c_hs_maddr; /* offset: 0x0c i2c hs master mode code address */i2c_data_cmd_s i2c_data_cmd; /* offset: 0x10 i2c rx/tx data buffer and command */i2c_ss_scl_hcnt_s i2c_ss_scl_hcnt; /* offset: 0x14 standard speed i2c clock scl high count */i2c_ss_scl_lcnt_s i2c_ss_scl_lcnt; /* offset: 0x18 standard speed i2c clock scl low count */i2c_fs_scl_hcnt_s i2c_fs_scl_hcnt; /* offset: 0x1c fast speed i2c clock scl high count */i2c_fs_scl_lcnt_s i2c_fs_scl_lcnt; /* offset: 0x20 fast speed i2c clock scl low count */i2c_hs_scl_hcnt_s i2c_hs_scl_hcnt; /* offset: 0x24 high speed i2c clock scl high count */i2c_hs_scl_lcnt_s i2c_hs_scl_lcnt; /* offset: 0x28 high speed i2c clock scl low count */i2c_intr_stat_s i2c_intr_stat; /* offset: 0x2c i2c interrupt status */i2c_intr_mask_s i2c_intr_mask; /* offset: 0x30 i2c interrupt mask */i2c_raw_intr_stat_s i2c_raw_intr_stat; /* offset: 0x34 i2c raw interrupt status */i2c_rx_tl_s i2c_rx_tl; /* offset: 0x38 i2c receive fifo threshold */i2c_tx_tl_s i2c_tx_tl; /* offset: 0x3c i2c transmit fifo threshold */i2c_clr_intr_s i2c_clr_intr; /* offset: 0x40 clear combined and individual interrupts */i2c_clr_rx_under_s i2c_clr_rx_under; /* offset: 0x44 i2c clear rx_under interrupt */i2c_clr_rx_over_s i2c_clr_rx_over; /* offset: 0x48 i2c clear rx_over interrupt */i2c_clr_tx_over_s i2c_clr_tx_over; /* offset: 0x4c i2c clear tx_over interrupt */i2c_clr_rd_req_s i2c_clr_rd_req; /* offset: 0x50 i2c clear rd_req interrupt */i2c_clr_tx_abrt_s i2c_clr_tx_abrt; /* offset: 0x54 i2c clear tx_abrt interrupt */i2c_clr_rx_done_s i2c_clr_rx_done; /* offset: 0x58 i2c clear rx_done interrupt */i2c_clr_activity_s i2c_clr_activity; /* offset: 0x5c i2c clear activity interrupt */i2c_clr_stop_det_s i2c_clr_stop_det; /* offset: 0x60 i2c clear stop_det interrupt */i2c_clr_start_det_s i2c_clr_start_det; /* offset: 0x64 i2c clear start_det interrupt */i2c_clr_gen_call_s i2c_clr_gen_call; /* offset: 0x68 i2c clear gen_cal interrupt */i2c_enable_s i2c_enable; /* offset: 0x6c i2c enable */i2c_status_s i2c_status; /* offset: 0x70 i2c status register */i2c_txflr_s i2c_txflr; /* offset: 0x74 tansmit fifo level register */i2c_rxflr_s i2c_rxflr; /* offset: 0x78 receive fifo level register*/i2c_sda_hold_s i2c_sda_hold; /* offset: 0x7c set sda hold time */i2c_tx_abrt_source_s i2c_tx_abrt_source; /* offset: 0x80 i2c transmit abort status register */i2c_slv_data_nack_only_s i2c_slv_data_nack_only; /* offset: 0x84 */i2c_dma_cr_s i2c_dma_cr; /* offset: 0x88 dma control register for transmit and receive handshaking interface */i2c_dma_tdlr_s i2c_dma_tdlr; /* offset: 0x8c dma transmit data level */i2c_dma_rdlr_s i2c_dma_rdlr; /* offset: 0x90 dma receive data level */i2c_sda_setup_s i2c_sda_setup; /* offset: 0x94 */i2c_ack_general_call_s i2c_ack_general_call; /* offset: 0x98 */i2c_enable_status_s i2c_enable_status; /* offset: 0x9c */i2c_fs_spklen_s i2c_fs_spklen; /* offset: 0xa0 */i2c_hs_spklen_s i2c_hs_spklen; /* offset: 0xa4 */i2c_clr_restart_det_s i2c_clr_restart_det; /* offset: 0xa8 */i2c_scl_stuck_at_low_timeout_s i2c_scl_stuck_at_low_timeout; /* offset: 0xac */i2c_sda_stuck_at_low_timeout_s i2c_sda_stuck_at_low_timeout; /* offset: 0xb0 */i2c_clr_scl_stuck_det_s i2c_clr_scl_stuck_det; /* offset: 0xb4 */i2c_device_id_s i2c_device_id; /* offset: 0xb8 */i2c_smbus_clk_low_sext_s i2c_smbus_clk_low_sext; /* offset: 0xbc */i2c_smbus_clk_low_mext_s i2c_smbus_clk_low_mext; /* offset: 0xc0 */i2c_smbus_thigh_max_idle_count_s i2c_smbus_thigh_max_idle_count; /* offset: 0xc4 */i2c_smbus_intr_stat_s i2c_smbus_intr_stat; /* offset: 0xc8 */i2c_smbus_intr_mask_s i2c_smbus_intr_mask; /* offset: 0xcc */i2c_smbus_raw_intr_stat_s i2c_smbus_raw_intr_stat; /* offset: 0xd0 */i2c_clr_smbus_intr_s i2c_clr_smbus_intr; /* offset: 0xd4 */i2c_optional_sar_s i2c_optional_sar; /* offset: 0xd8 */i2c_smbus_udid_lsb_s i2c_smbus_udid_lsb; /* offset: 0xdc *///i2c_smbus_udid_word0_s i2c_smbus_udid_word0; /* offset: 0xdc */i2c_smbus_udid_word1_s i2c_smbus_udid_word1; /* offset: 0xe0 */i2c_smbus_udid_word2_s i2c_smbus_udid_word2; /* offset: 0xe4 */i2c_smbus_udid_word3_s i2c_smbus_udid_word3; /* offset: 0xe8 */unsigned int reserved; /* offset: 0xec reserved */i2c_reg_timeout_rst_s reg_timeout_rst; /* offset: 0xf0 */i2c_comp_param_1_s i2c_comp_param_1; /* offset: 0xf4 */i2c_comp_version_s i2c_comp_version; /* offset: 0xf8 */i2c_comp_type_s i2c_comp_type; /* offset: 0xfc */i2c_sar2_s i2c_sar2; /* offset: 0x100 */i2c_sar3_s i2c_sar3; /* offset: 0x104 */i2c_sar4_s i2c_sar4; /* offset: 0x108 */unsigned int reserved1; /* offset: 0x10c reserved */unsigned int reserved2; /* offset: 0x110 reserved */unsigned int reserved3; /* offset: 0x114 reserved */unsigned int reserved4; /* offset: 0x118 reserved */i2c_clr_wr_req_s i2c_clr_wr_req; /* offset: 0x11c */i2c_clr_slv_addr_tag_s i2c_clr_slv_addr_tag; /* offset: 0x120 */
}volatile i2c_reg_s;
(2)定义 i2c_handle,传递相关配置参数:
typedef struct i2c_handle {i2c_reg_s *instance; /**< i2c base address */unsigned int irq_num; /**< interruption number */i2c_mode_e i2c_mode; /**< i2c work mode: master or slave mode */i2c_speed_mode_e i2c_speed_mode; /**< i2c_speed_mode: standrd,fast or high speed*/i2c_addr_mode_e i2c_addr_mode; /**< i2c_addr_mode: 7bit or 10bit mode */i2c_general_cell_e i2c_general_cell; /**< i2c_general_cell: enable or disable*/i2c_restart_e i2c_restart; /**< i2c_restart: enable or disable restart */i2c_dma_mode_e i2c_dma_mode; /**< dma_mode: enable or disable dma_mode */i2c_notify_type_e i2c_notify_type; /**< indicate the way to send or receive date */
} i2c_handle_s;
(3)i2c初始化函数: 这里省略了i2c的时钟门控、软复位、管脚复用配置,这部分和CPU以及硬件环境有关,参考意义不大,就不展示出来了。
void i2c_init(i2c_handle_s *handle)
{i2c_reg_s *i2c_reg = handle->instance; //get i2c base addr/* 时钟门控使能 */i2c_clk_en(handle);/* 软复位和解复位 */i2c_rst_en(handle);/* 管脚复用 */i2c_io_config(handle);i2c_disable(i2c_reg);i2c_clear_all_irq(i2c_reg);i2c_disable_all_irq(i2c_reg);//work mode settingif (handle->i2c_mode == I2C_MODE_MASTER) {i2c_set_operation_mode(i2c_reg, I2C_MODE_MASTER);} else {i2c_set_operation_mode(i2c_reg, I2C_MODE_SLAVE);i2c_set_own_address(i2c_reg,0x4f);}//speed mode settingi2c_set_speed_mode(i2c_reg, handle->i2c_speed_mode);//address mode settingi2c_set_addr_mode(i2c_reg, handle->i2c_addr_mode);//genereal call settingif (handle->i2c_general_cell == GENERAL_CELL_ENABLE) {i2c_master_set_general_call(i2c_reg, GENERAL_CELL_ENABLE);i2c_slave_set_general_call(i2c_reg, ACK_GENERAL_CALL);} else {i2c_master_set_general_call(i2c_reg, GENERAL_CELL_DISABLE);i2c_slave_set_general_call(i2c_reg, NACK_GENERAL_CALL);}//restart settingif (handle->i2c_restart == RESTART_ENABLE) {i2c_enable_restart(i2c_reg);} else {i2c_disable_restart(i2c_reg);}//DMA settingif (handle->i2c_dma_mode == DMA_ENABLE) {i2c_dma_transmit_enable(i2c_reg);i2c_dma_receive_enable(i2c_reg);} else {i2c_dma_transmit_disable(i2c_reg);i2c_dma_receive_disable(i2c_reg);}//notify type settingif (handle->i2c_notify_type == I2C_NOTIFY_TYPE_INT) {//注册中断号、中断回调函数drv_irq_register(handle->irq_num, i2c_irq_handle_callback, handle); //设置中断优先级 drv_irq_enable(handle->irq_num, IRQ_TYPE_VECTOR_HIGH_LEVEL, IRQ_PRIORITY_2); } else {drv_irq_disable(handle->irq_num);drv_irq_unregister(handle->irq_num);}//intr mask settingi2c_set_intr_mask(i2c_reg);//SDA hold time settingi2c_set_sda_hold_time(i2c_reg, 0x01, 0x01);//SCL/SDA timeout settingi2c_set_scl_stuck_at_low_timeout(i2c_reg, 0xffffffff);i2c_set_sda_stuck_at_low_timeout(i2c_reg, 0xffffffff);//rx_fifo_full_hold_ctrl enable(逻辑默认使能)i2c_set_rx_fifo_full_hold_ctrl(i2c_reg, 1);//i2c_fifo_threshold setting(配置超过fifo深度的时候,这里实际写进去的是fifo深度-1)i2c_set_transmit_fifo_threshold(i2c_reg, 0);i2c_set_receive_fifo_threshold(i2c_reg, 7);i2c_enable(i2c_reg);
}
4.读写eeprom
#define I2C1_ADDR (i2c_reg_s *)I2C1_BASE/*
* i2c1 作为 master,采用轮训方式,写AT24C16
* 验证:100khz速率读写测试
*/
void i2c1_master_test_case_write_read_100khz(void)
{i2c_reg_s *i2c_reg = NULL;static i2c_handle_s i2c1_handle ={0};unsigned char receive_data[3] = {0};i2c1_handle.instance = I2C1_ADDR;i2c1_handle.irq_num = IRQ_NUM_I2C1;i2c1_handle.i2c_mode = I2C_MODE_MASTER;i2c1_handle.i2c_speed_mode = I2C_BUS_SPEED_STANDARD;i2c1_handle.i2c_addr_mode = I2C_ADDRESS_7BIT;i2c1_handle.i2c_general_cell = GENERAL_CELL_DISABLE;i2c1_handle.i2c_restart = RESTART_DISABLE;i2c1_handle.i2c_dma_mode = DMA_DISABLE;i2c1_handle.i2c_notify_type = I2C_NOTIFY_TYPE_INT;i2c_init(&i2c1_handle);dbg_uart_print("i2c1_master_100khz init end!!\r\n");i2c_reg = i2c1_handle.instance;i2c_clear_all_irq(i2c_reg);// 0x57:1010 111 这是器件地址,其中1010是固定地址;111是页地址高3位。// 0x12: 00010002 这是操作地址,其中0001是页地址低,0002是页地址偏移量,即该页第2个地址// 故页地址是111 0001,即0x71,第113页;即往第113页第2个字节地址写入0x45AT24C16_write_byte(i2c_reg, 0x57, 0x12, 0x45); mdelay(5);//即往第113页第3个字节地址写入0x87AT24C16_write_byte(i2c_reg, 0x57, 0x13, 0x87); mdelay(5);receive_data[0] = AT24C16_read_byte(i2c_reg, 0x57, 0x12);dbg_uart_print("read_date, 0x%x\r\n", receive_data[0]);receive_data[1] = AT24C16_read_byte(i2c_reg, 0x57, 0x13);mdelay(5);dbg_uart_print("read_date, 0x%x\r\n", receive_data[1]);if ((receive_data[0] == 0x45) & (receive_data[1] == 0x87)) {dbg_uart_print("100khz_write_read pass!!\r\n");} else {dbg_uart_print("100khz_write_read failed!!\r\n");}
}
用逻辑分析仪抓写数据的波形:
用逻辑分析仪抓读数据的波形:
100KHz速率读写数据都是OK的。
DW_apb_i2c 使用介绍2--i2c初始化以及读写eeprom测试相关推荐
- STM32学习之I2C协议(读写EEPROM)
关于STM32学习分享 第七章 I2C协议(读写EEPROM) 文章目录 关于STM32学习分享 前言 二.代码 1.i2c.c 2.i2c.h 3.main.c 总结 前言 开始!开始!单片机的I2 ...
- STM32学习笔记(9)——(I2C续)读写EEPROM
STM32学习笔记(9)--(I2C续)读写EEPROM 一.概述 1. 背景介绍 2. EEPROM简介 二.AT24C02--常用的EEPROM 1. 电路原理图 2. 写操作 (1)按字节写操作 ...
- STM32CubeMX学习笔记(9)——I2C接口使用(读写EEPROM AT24C02)
一.I2C简介 I2C(Inter-Integrated Circuit ,内部集成电路) 总线是一种由飞利浦 Philip 公司开发的串行总线.是两条串行的总线,它由一根数据线(SDA)和一根 时钟 ...
- STM32 I2C通信(读写eeprom)
I2C通信 双线制:串行时钟线SCL,串行数据线SDA. 通常采用软件模拟i2c通信.
- STM32F10x_硬件I2C读写EEPROM(标准外设库版本)
Ⅰ.写在前面 上一篇文章是"STM32F10x_模拟I2C读写EEPROM",讲述使用IO口模拟I2C总线通信,对EEPROM(AT24Xxx)进行读写操作的过程. 上一篇文章主要 ...
- 再造STM32---第十九部分:I2C—读写 EEPROM
本章参考资料:<STM32F4xx 参考手册>.<STM32F4xx 规格书>.库帮助文档<stm32f4xx_dsp_stdperiph_lib_um.chm>及 ...
- STM32模拟I2C时序读写EEPROM精简版
平台:STM32ZET6(核心板)+ST-LINK/V2+SD卡+USB串口线+外部EEPROM(不需要上拉电阻) 工程介绍:主要文件在USER组中,bsp_i2c_ee.c,bsp_i2c_ee.h ...
- iic获取salve设备地址_Linux下使用IIC总线读写EEPROM(读写i2c从设备通用程序)
Linux 下使用IIC总线 读写 EEPROM by 韩大卫 @吉林师范大学 handawei@jusontech.com 转载请务必表明出处 ******************* ******* ...
- STM32系统学习——I2C (读写EEPROM)
I2C 通讯协议(Inter-Integrated Circuit)引脚少,硬件实现简单,可扩展性强,不需要 USART.CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC) ...
最新文章
- SQL Server 2016 AlwaysOn 安装及配置介绍
- 附pdf下载 | 入门Python和深度学习的经典书
- mvc模式缺点 php,mvc模式有哪些优缺点
- 关于java嵌入式数据库的选择,强烈建议H2 嵌入式数据库
- 从计算机体系结构方面思考深度学习
- java编译时文件是什么,JAVA编译出现 进行语法解释时已抵达文件结尾 是什么意思?...
- java的tcp实时接收json格式报文_tcp - 如何使用带有rsocket Java的TcpClientTransport将自定义数据格式转换为JSON - 堆栈内存溢出...
- NHibernate扩展:FluentNHibernate基础教程
- 一加7T Pro最新渲染图曝光:背部有小改动
- 解析JSON字串的方法有eval,json_parse,JSON.parse
- DEP机制的保护原理
- 区块链 solidity 零知识证明DApp开发实践【身份证明/以太坊】
- ZOJ1002-Fire Net(深度优先搜索)
- LINUX下载编译libssh2
- 【运动学】基于matlab计步【含Matlab源码 524期】
- 中国能源统计年鉴面板数据-分省市主要污染物排放指标(包含ECXEL2020年中国统计年鉴)
- 诺基亚n1平板电脑刷机教程_诺基亚n1平板电脑刷机教程_诺基亚N1 完整包线刷升级或救砖教程(不分台版;国行)......
- 二手车预测part1
- RFC1738——Uniform Resource Locators统一资源定位器 (URL)
- python 拼音读音-Python 中拼音库 PyPinyin 的用法(转)
热门文章
- Redis-Redis 主从架构
- [加密]账号登录密码传输加密
- 携程App无线开发全流程介绍
- 组队学习李宏毅的深度学习-1
- Reconcile failed: Signature mismatch for shared user:
- VK1088B QFN32L超小体积封装4*4 LCD液晶段码驱动IC/LCD液晶驱动IC
- 手机计算机数字显示在桌面上,手机桌面上的应用如何取消显示的数字角标
- 2021FME博客大赛 —— 基于FME的电子地图道路面快速构建方法研究
- Spring框架漏洞总结
- 室外场景注意事项(一)距离场阴影的利弊!