stm32f3的i2c使用小结
来源:互联网 发布:常用dhcp服务器软件 编辑:程序博客网 时间:2024/05/22 03:50
<span style="font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;">这几天拿到了stm32f3discovery,拿到手的第一件事就是测试了硬件i2c,使用stm32cube生成库,测试对象为AD5934与ADG715。经过两天的调试,完美调通。中间也碰到了些问题。</span><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;">1、一开始用的I2C1,一仿真就会出现死机的情况。</div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;"><span apple-tab-span="" style="word-wrap: break-word; word-break: break-all;"> </span>由于I2C1与swd接口重合,所以调用HAL_I2C_Init()函数后就死机,改成I2C2后问题解决。</div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;">2、无法访问指定地址的设备</div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;"><span apple-tab-span="" style="word-wrap: break-word; word-break: break-all;"> </span>库函数中的入口地址并不是7bit地址,需要输入8bit。我的设备地址为13,始终无法访问设备,改为26后解决。</div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;">3、可以读写单个地址的数据,但是不能多字节读写。</div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;"><span apple-tab-span="" style="word-wrap: break-word; word-break: break-all;"> (1)、对于多字节写, </span>库函数中的</div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;"> HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)</div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;"><span line-height:="" 1="" 8em="" style="word-wrap: break-word; word-break: break-all;"> 其中</span><span line-height:="" 25="" 2000007629395px="" style="word-wrap: break-word; word-break: break-all;">MemAddSize表示地址的位数,0表示7bit地址,1表示10bit地址。我误认为这个写的字节数,所以导致在写多字节的时候出错。</span></div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;"><span line-height:="" 25="" 2000007629395px="" style="word-wrap: break-word; word-break: break-all;"> (2)、对于多字节读,由于AD5934的读操作与库函数的读操作有些出入,所以导致一直读错误。在库函数中写完读的内存地址就开始读,而AD5934中写完block read后接着还要再写一个number bytes read然后才开始读。所以需要对库函数进行修改,新增一个函数,以适合AD5934的block read.</span></div><div style="word-wrap: break-word; word-break: break-all; font-family: Tahoma, 'Microsoft Yahei', Simsun; font-size: 14px; line-height: 25.2000007629395px;"><p style="word-wrap: break-word; word-break: break-all; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><a target=_blank href="http://bbs.21ic.com/data/attachment/album/201504/26/203136h658z8f7k7f072k6.png" target="_blank" style="word-wrap: break-word; word-break: break-all; color: rgb(0, 102, 153); text-decoration: none;"><img src="http://bbs.21ic.com/data/attachment/album/201504/26/203136h658z8f7k7f072k6.png" style="word-wrap: break-word; word-break: break-all; border: none; max-width: 620px;" alt="" /></a></p><p style="word-wrap: break-word; word-break: break-all; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span line-height:="" 1="" 8em="" style="word-wrap: break-word; word-break: break-all;"><span apple-tab-span="" style="word-wrap: break-word; word-break: break-all;"> </span>stm32f3的i2c有三种模式:Reload、AutoEnd、SoftEnd模式。</span></p><p style="word-wrap: break-word; word-break: break-all; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span line-height:="" 1="" 8em="" style="word-wrap: break-word; word-break: break-all;"> i2c每发送完一个字节,就会产生TXIS标志,当发送完最后一个字节时:</span></p><p style="word-wrap: break-word; word-break: break-all; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span apple-tab-span="" style="word-wrap: break-word; word-break: break-all;"> </span>对于Reload模式,当字节大于255字节时,必须使用此模式,此模式下发送结束后,会产生tcr标志。</p><p style="word-wrap: break-word; word-break: break-all; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"> 对于AutoEnd模式,发送后最后一个字节时,会自动产生STOP。</p><p style="word-wrap: break-word; word-break: break-all; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"> 对于<span line-height:="" 25="" 2000007629395px="" style="word-wrap: break-word; word-break: break-all;">SoftEnd模式,发送完最后一个字节时,会产生</span>tc标志,对于发送过程中需要Restart的需要使用此模式。</p><p style="word-wrap: break-word; word-break: break-all; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"> 对于AD5934的读操作,可以事先工作在SoftEnd模式,发送完<span line-height:="" 25="" 2000007629395px="" style="word-wrap: break-word; word-break: break-all;">block read与number bytes read字节后,再转入AutoEnd模式进行Restart,读取完指定的字节后自动产生STOP。操作流程如下:</span></p></div>
HAL_StatusTypeDef HAL_I2C_Mem_Read_AD5934_Block(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout){ uint32_t Sizetmp = 0; /* Check the parameters */ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); if(hi2c->State == HAL_I2C_STATE_READY) { if((pData == NULL) || (Size == 0)) { return HAL_ERROR; } if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) { return HAL_BUSY; } /* Process Locked */ __HAL_LOCK(hi2c); hi2c->State = HAL_I2C_STATE_MEM_BUSY_RX; hi2c->ErrorCode = HAL_I2C_ERROR_NONE; /* //Send Slave Address and Memory Address if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { // Process Unlocked __HAL_UNLOCK(hi2c); return HAL_ERROR; } else { // Process Unlocked __HAL_UNLOCK(hi2c); return HAL_TIMEOUT; } }*/ I2C_TransferConfig(hi2c,DevAddress,MemAddSize+1, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); /* Wait until TXIS flag is set */ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* If Memory address size is 8Bit */ if(MemAddSize == I2C_MEMADD_SIZE_8BIT) { /* Send Memory Address */ hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_LSB(MemAddress); } /* If Mememory address size is 16Bit */ else { /* Send MSB of Memory Address */ hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_MSB(MemAddress); /* Wait until TXIS flag is set */ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Send LSB of Memory Address */ hi2c->Instance->TXDR = __HAL_I2C_MEM_ADD_LSB(MemAddress); } /* Wait until TXIS flag is set */ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } hi2c->Instance->TXDR = Size; /* Wait until TC flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } /* Send Slave Address */ /* Set NBYTES to write and reload if size > 255 and generate RESTART */ /* Size > 255, need to set RELOAD bit */ if(Size > 255) { I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); Sizetmp = 255; } else { I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); Sizetmp = Size; } do { /* Wait until RXNE flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } /* Read data from RXDR */ (*pData++) = hi2c->Instance->RXDR; /* Decrement the Size counter */ Sizetmp--; Size--; if((Sizetmp == 0)&&(Size!=0)) { /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout) != HAL_OK) { return HAL_TIMEOUT; } if(Size > 255) { I2C_TransferConfig(hi2c,DevAddress,255, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); Sizetmp = 255; } else { I2C_TransferConfig(hi2c,DevAddress,Size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); Sizetmp = Size; } } }while(Size > 0); /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is reset */ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, I2C_TIMEOUT_STOPF) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Clear Configuration Register 2 */ __HAL_I2C_RESET_CR2(hi2c); hi2c->State = HAL_I2C_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_OK; } else { return HAL_BUSY; }}
0 0
- stm32f3的i2c使用小结
- stm32f3的i2c使用小结
- STM32F3的ADC使用DMA模式传输转换数据
- STM32F3硬件I2C与LSM303DLHC通信
- 简单介绍STM32F3系列单片机中片内运算放大器的使用——以STM32F303DISCOVERY板为例
- <I2C小结>
- I2C 小结
- I2C 小结
- i2c tool 的使用
- i2c tool 的使用
- I2C的使用
- STM32F3使用USART串口DMA发送数据,使用蓝牙发送
- msp430使用i2c的局限
- 使用可靠的I2C代码
- 使用可靠的I2C代码
- i2c测试工具的使用
- 浅谈I2C的使用吧
- I2C调试小结
- Shell基础-Bash基本功能-历史命令与补全
- 各大型网站架构分析收集
- WebCollector多代理切换机制
- 最小生成树_Prim.c
- [BZOJ 1564][NOI 2009]二叉查找树(DP)
- stm32f3的i2c使用小结
- Android学习笔记(一)
- 安卓面试题系列-1
- 第七周项目——思维框图
- 追MM与23种设计模式
- AndroidのViewFlipper和ViewPager
- 对一个字符数组连续用gets函数出现的问题(缓冲区内容补充)
- 说说大型高并发高负载网站的系统架构(更新)
- Java关键字