嵌入式实操----基于RT1170 首板硬件之EEPROM AT24C16调试(十五)
本文主要是通过迁移的思维,记录本人初次使用NXP MCUXpresso SDK API进行BSP开发
前面调通了SDRAM Flash GPIO之后,接下来调试EEPROM AT24C16功能,硬件设计如下所示
1. 首先阅读原理图
针对EEPROM的调试一般需要配置i2c总线的时钟源,总线的通讯速率,对i2c总脚的引脚进行初始化,发送i2c 地址命令判断i2c设备工作是否正常,接下来就是通过官方的接口对i2c设备进行操作。
2. 调试过程
2. 1 时钟初始化
void bsp_i2c5_eeprom_clock_init(){/* Configure LPI2C5 using OSC_24M */rootCfg.mux = kCLOCK_LPI2C5_ClockRoot_MuxOsc24MOut;rootCfg.div = 1;CLOCK_SetRootClock(kCLOCK_Root_Lpi2c5, &rootCfg);
}
2. 2 引脚初始化
/*** @brief i2c5 pin mux init** @param [in] None* @param [out] None* * @return * * @history* 1.Date : 2021-5-27 17:13:28* Author : panzidong* Modification : Created function*/
void bsp_i2c5_eeprom_pin_init(){CLOCK_EnableClock(kCLOCK_Iomuxc_Lpsr); /* LPCG on: LPCG is ON. */IOMUXC_SetPinMux(IOMUXC_GPIO_LPSR_04_LPI2C5_SDA, /* GPIO_LPSR_04 is configured as LPI2C5_SDA */1U); /* Software Input On Field: Input Path is determined by functionality */IOMUXC_SetPinMux(IOMUXC_GPIO_LPSR_05_LPI2C5_SCL, /* GPIO_LPSR_05 is configured as LPI2C5_SCL */1U); IOMUXC_SetPinConfig(IOMUXC_GPIO_LPSR_04_LPI2C5_SDA, /* GPIO_LPSR_04 PAD functional properties : */0x10U); /* Slew Rate Field: Slow Slew RateDrive Strength Field: normal driverPull / Keep Select Field: Pull DisablePull Up / Down Config. Field: Weak pull downOpen Drain LPSR Field: Enabled */IOMUXC_SetPinConfig(IOMUXC_GPIO_LPSR_05_LPI2C5_SCL, /* GPIO_LPSR_05 PAD functional properties : */0x10U); /* Slew Rate Field: Slow Slew RateDrive Strength Field: normal driverPull / Keep Select Field: Pull DisablePull Up / Down Config. Field: Weak pull downOpen Drain LPSR Field: Enabled */
}
2.3 总线初始化
/*** @brief i2c5 bus init** @param [in] void * @param [out] None* * @return * * @history* 1.Date : 2021-5-27 17:35:18* Author : panzidong* Modification : Created function*/
void bsp_i2c5_eeprom_init(void)
{lpi2c_master_config_t masterConfig;/** masterConfig.debugEnable = false;* masterConfig.ignoreAck = false;* masterConfig.pinConfig = kLPI2C_2PinOpenDrain;* masterConfig.baudRate_Hz = 100000U;* masterConfig.busIdleTimeout_ns = 0;* masterConfig.pinLowTimeout_ns = 0;* masterConfig.sdaGlitchFilterWidth_ns = 0;* masterConfig.sclGlitchFilterWidth_ns = 0;*/LPI2C_MasterGetDefaultConfig(&masterConfig);/* Change the default baudrate configuration */masterConfig.baudRate_Hz = LPI2C_BAUDRATE;/* Initialize the LPI2C master peripheral */LPI2C_MasterInit(EEPROM_I2C_MASTER, &masterConfig, 24000000UL);//LPI2C5_Bus_Driver_Init();}
2.4 总线设备探测
/*** @brief print i2c devices on i2c bus 5** @param [in] None* @param [out] None* * @return * * @history* 1.Date : 2021-6-7 16:3:18* Author : panzidong* Modification : Created function*/
uint32_t bsp_i2c5_bus_detect()
{lpi2c_master_transfer_t masterXfer = {0};status_t reVal = kStatus_Fail;uint8_t temp_buf[1] = {0};uint8_t i = 0;for(i = 0 ;i < 127; i++){masterXfer.slaveAddress = (i<<1) ;masterXfer.direction = kLPI2C_Read;masterXfer.subaddress = 0;masterXfer.subaddressSize = 0x01;masterXfer.data = temp_buf;masterXfer.dataSize = 1;masterXfer.flags = kLPI2C_TransferDefaultFlag;reVal = LPI2C_MasterTransferBlocking(EEPROM_I2C_MASTER, &masterXfer);if (reVal == kStatus_Success){PRINTF("find i2c device i2caddr = %x \r\n", i);}}return 0;
}
只要对应的i2c设备地址有回答,才能说明外设工作正常。
2.5 EEPROM读写
虽然官方提供了AT24C02的例程,针对AT24C16的操作还是有所区别。主由容量变大,所以8位地址空间无法满足,操作地址的高位在从设备地址当中。再则原来的接口没有返回值可以判断,最后重新写了一份。
/*** @brief lpi2c5 wait for standby state** @param [in] uint8_t ClientAddr * @param [out] None* * @return * * @history* 1.Date : 2021-5-27 17:36:19* Author : panzidong* Modification : Created function*/
uint8_t I2C_EEPROM_WaitStandbyState(uint8_t ClientAddr)
{status_t lpi2c_status;uint32_t delay_count = 10*256; do{LPI2C_MasterClearStatusFlags(EEPROM_I2C_MASTER, kLPI2C_MasterNackDetectFlag);lpi2c_status = LPI2C_MasterStart(EEPROM_I2C_MASTER, (ClientAddr>>1), kLPI2C_Write);SDK_DelayAtLeastUs(40,SystemCoreClock);}while(EEPROM_I2C_MASTER->MSR & kLPI2C_MasterNackDetectFlag && delay_count-- );LPI2C_MasterClearStatusFlags(EEPROM_I2C_MASTER, kLPI2C_MasterNackDetectFlag);lpi2c_status = LPI2C_MasterStop(EEPROM_I2C_MASTER);SDK_DelayAtLeastUs(10,SystemCoreClock);if(delay_count == 0 || lpi2c_status != kStatus_Success){return 1;}return 0;
}/*** @brief at24c16 page innet read/write** @param [in] uint8_t slave_addr * @param [in] uint32_t subaddr * @param [in] uint8_t *p_buf * @param [in] uint32_t len * @param [in] bool is_read * @param [out] None* * @return * * @history* 1.Date : 2021-5-28 9:49:22* Author : panzidong* Modification : Created function*/
int __eeprom_program_data ( uint8_t slave_addr,uint32_t subaddr,uint8_t *p_buf,uint32_t len,bool is_read)
{lpi2c_master_transfer_t masterXfer = {0};status_t reVal = kStatus_Fail;if(len > EEPROM_PAGE_SIZE){PRINTF("len > EEPROM_PAGE_SIZE\r\n");return 1;} /*calculate slave address and register address,some register bits are embeded in slave address*/masterXfer.slaveAddress = (slave_addr>>1) | ((subaddr >> 8) & 0x7);masterXfer.direction = is_read;masterXfer.subaddress = (uint16_t)(subaddr & 0xff);masterXfer.subaddressSize = EEPROM_INER_ADDRESS_SIZE;masterXfer.data = p_buf;masterXfer.dataSize = len;masterXfer.flags = kLPI2C_TransferDefaultFlag;reVal = LPI2C_MasterTransferBlocking(EEPROM_I2C_MASTER, &masterXfer);if (reVal != kStatus_Success){return 1;} /* add one more tick to make sure has enough time to program */if(! is_read){I2C_EEPROM_WaitStandbyState(slave_addr);}return 0;}/*** @brief eeprom write/read func** @param [in] int start * @param [in] uint8_t *p_buf * @param [in] size_t len * @param [in] bool is_read is_read false : eeprom writeis_read true : eeprom read* @param [out] None* * @return 0: success* other: fail* @history* 1.Date : 2021-5-28 9:54:13* Author : panzidong* Modification : Created function*/
int bsp_eeprom_rw ( int start,uint8_t *p_buf,size_t len,bool is_read)
{int ret = 0;/* start address beyond this eeprom's capacity */if (start > EEPROM_MAX_NUM) {return -1;}/* no data will be read or written */if (len == 0) {return 0;}/* adjust len that will not beyond eeprom's capacity */if ((start + len) > EEPROM_MAX_NUM) {len = EEPROM_MAX_NUM - start;}/* write the unaligned data of the start */int len_tmp = (EEPROM_PAGE_SIZE - start%EEPROM_PAGE_SIZE);if (len < len_tmp) {len_tmp = len;}ret = __eeprom_program_data(LPI2C_MASTER_SLAVE_ADDR_8BIT, start, p_buf, len_tmp, is_read);if (ret != 0) {ret = -1;goto exit;}len -= len_tmp;start += len_tmp;p_buf += len_tmp;/* write the rest data */while (len) {len_tmp = len > EEPROM_PAGE_SIZE ? EEPROM_PAGE_SIZE : len;ret = __eeprom_program_data(LPI2C_MASTER_SLAVE_ADDR_8BIT, start, p_buf, len_tmp, is_read);if (ret != 0) {ret = -1;goto exit;}len -= len_tmp;start += len_tmp;p_buf += len_tmp;}exit:return ret;
}uint8_t bsp_eeprom_test(void)
{uint16_t i;int result = 0;PRINTF("Write data:\n");for ( i=0; i<EEPROM_TEST_NUM; i++ ){ EEPROM_Buffer_Write[i] = i % 256;PRINTF("0x%02X ", EEPROM_Buffer_Write[i]);if((i+1)%16 == 0 || i == (EEPROM_TEST_NUM-1)) PRINTF("\r\n"); }result = bsp_eeprom_rw(0x0,EEPROM_Buffer_Write,EEPROM_TEST_NUM,false);if(result != 0){PRINTF("Write Failed \r\n");return 1;}PRINTF("Write SUCCESS \r\n");PRINTF("Read data: \r\n");result = bsp_eeprom_rw(0x0,EEPROM_Buffer_Read,EEPROM_TEST_NUM,true);if(result != 0){PRINTF("Read Failed \r\n");return 1;}PRINTF("Read SUCCESS \r\n");for (i=0; i<EEPROM_TEST_NUM; i++){ if(EEPROM_Buffer_Read[i] != EEPROM_Buffer_Write[i]){PRINTF("0x%02X ", EEPROM_Buffer_Read[i]);PRINTF("data ERROR!\r\n");return 1;}PRINTF("0x%02X ", EEPROM_Buffer_Read[i]);if((i+1)%16 == 0 || i == (EEPROM_TEST_NUM-1)) PRINTF("\r\n");}PRINTF("I2C(AT24C016) SUCCESS!\r\n");return 0;
}
3. 总结
以前从来没有写过裸机代码,eeprom的driver在linux下面是很常见的,但是以前也没有细看,主要是通过配置,驱动起来,通过相关的/sys/路径进行访问,在这次机会下重新深入学习。
嵌入式实操----基于RT1170 首板硬件之EEPROM AT24C16调试(十五)相关推荐
- 嵌入式实操----基于RT1170 使能展频功能(二十七)
本文主要是通过迁移的思维,记录本人初次使用NXP MCUXpresso SDK API进行BSP开发 车载电子设备对EMC的要求比较高,本文主要讲述在RT1170上面,使能spread spectru ...
- 嵌入式Linux下基于FFmpeg的视频硬件编解码
嵌入式Linux下基于FFmpeg的视频硬件编解码[图] http://www.c114.net ( 2012/3/1 15:41 ) 摘要: 对FFmpeg多媒体解决方案中的视频编解码流程进行研究. ...
- 从零实操基于WSL2 Docker部署Asp.Net Core项目
前言 平日在公司里都是基于阿里Teambition中的飞流进行Docker部署Api项目或服务,已经习惯了那一套成熟的操作流程,开发和部署确实快捷方便,但是还没在自己的电脑上进行操作过,特别是Wind ...
- 嵌入式Linux下基于FFmpeg的视频硬件编解码[图]
转自:http://tech.c114.net/167/a674033.html 摘要: 对FFmpeg多媒体解决方案中的视频编解码流程进行研究.结合对S3C6410处理器视频硬件编解码方法的分析,阐 ...
- 嵌入式开发-迅为IMX6开发板硬件详情介绍
迅为-I.MX6开发板 Cortex-A9四核I.MX6Q,主频1G,2G内存,16G存储,支持4G全网通,GPS WIFI蓝牙模块,千兆以太网,摄像头,SATA等接口,多屏异显,双屏同显 2.POW ...
- stm32 读取sd卡图片显示_「正点原子STM32Mini板资料连载」第三十五章 汉字显示实验...
1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第三十五章 汉字显示实验 汉字显示在 ...
- 个推0代码数据可视化实操 | 基于Tableau的中国奥运数据探索
8月8日,东京奥运会正式落下帷幕.经过17天的激烈角逐,中国代表团在本届奥运会上共斩获38金32银18铜,位居奖牌榜第二,追平了在伦敦奥运会取得的境外参赛最好成绩. 奥运会期间,奖牌榜上的每一次变动都 ...
- 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十五)驱动程序基石
文章目录 1.1 休眠与唤醒 1.1.1 适用场景 1.1.2 内核函数 1.1.2.1 休眠函数 1.1.2.2 唤醒函数 19.1.3 驱动框架 1.1.4 编程 1.1.4.1 驱动程序关键代码 ...
- 基于VC709开发板的光纤收发的调试与实现,以及过程中遇到的问题与解决。
VC709是xilinx旗下的一款开发板,搭载了强大的Virtex-7芯片.有着丰富存储资源,时钟资源与高速接口.具体可参考xilinx官网的ug887手册,本次主要是想记录一下自己的学习过程与遇到的 ...
最新文章
- Kappa:比Lambda更好更灵活的实时处理架构
- 基于 Spring Boot 的 Restful 风格实现增删改查
- java中各种流的详细使用
- liferay跳转页面
- [恢]hdu 1019
- subline3插件html,Sublime Text3与html的插件
- 面向对象(OOP)基本概念
- java中的文本框_java里的JTextField文本框怎么设置大小?
- 微服务化之服务拆分与服务发现
- openssl学习笔记--CA及https网站证书配置
- iOS 解决导航栏左右 BarButtonItem偏移位置的问题
- 【原创】Nginx+PHP-FPM优化技巧总结
- 6*6数独,要求输出结果
- 中秋之际献上【中秋快乐】藏头诗
- 大白话讲解,大数据基本术语
- Js、 replace 全部内容替换、替换全部匹配内容、替换第一个
- 美的楼宇科技荆州工厂正式投产;华为加入国际电联P2C数字联盟 | 美通企业日报...
- python pdf解析毕业论文_电影数据读取、分析与展示毕业论文+任务书+Python项目源码...
- 移动互联网安全技术研究
- 微信小程序:扫描身份证读取身份信息
热门文章
- 喜讯!双驰企业正式成为欧盟地平线2020 项目合作伙伴
- 三年的php简历_【完整模板】PHP工程师简历-简洁橙色-1-3年经验-Word简历模板
- Oracle序列相关命令
- 用于大规模视觉定位的直接2D-3D匹配(IROS 2021)
- (附源码)小程序springboot口腔诊所预约系统 毕业设计 201738
- 131-从键盘输入一个字符串,将其中的小写字母全部换成大写字母,然后输出到一个磁盘文件
- 如何使用 vimdiff 来 git diff
- mico3165嵌入式开发板IAR环境搭建以及Demo运行
- Socket和ServerSocket的介绍
- React构造函数中为什么要写 super(props)