Stm32 I2C在内存读取时返回忙碌或错误

Stm32 I2C在内存读取时返回忙碌或错误,stm32,ada,gnat,Stm32,Ada,Gnat,我开始使用下面的代码来处理一个带有核子-F446ZE和核子-F411RE板的 使用STM32.Device;使用STM32.0设备; 使用STM32.GPIO;使用STM32.GPIO; STM32;使用STM32; STM32.I2C; 与HAL.I2C;使用HAL.I2C; 使用HAL; 简单的I2C演示程序是 --选择I2C总线 选择的_I2C_端口:常量访问STM32.I2C.I2C_端口:=I2C_1'访问; 所选的_I2C_端口_AF:恒定GPIO_备用函数:=GPIO_AF_I2C

我开始使用下面的代码来处理一个带有核子-F446ZE和核子-F411RE板的

使用STM32.Device;使用STM32.0设备;
使用STM32.GPIO;使用STM32.GPIO;
STM32;使用STM32;
STM32.I2C;
与HAL.I2C;使用HAL.I2C;
使用HAL;
简单的I2C演示程序是
--选择I2C总线
选择的_I2C_端口:常量访问STM32.I2C.I2C_端口:=I2C_1'访问;
所选的_I2C_端口_AF:恒定GPIO_备用函数:=GPIO_AF_I2C1_4;
选定的_I2C_时钟_引脚:GPIO_点重命名PB8;
选定的_I2C_数据_引脚:GPIO_点重命名PB9;
端口:常量HAL.I2C。任意_I2C_端口:=所选的_I2C_端口;
--由于采用7位寻址,因此移位1
I2C#U地址:常数HAL.I2C.I2C#U地址:=16#76#*2;
程序设置硬件是
GPIO\ U配置\ U AF:GPIO\ U端口\ U配置(模式\ U AF);
所选时钟速度:常数:=10\u 000;
开始
启用时钟(选定的I2C时钟引脚);
启用时钟(选定的I2C数据引脚);
启用时钟(所选的I2C端口全部);
STM32.Device.Reset(所选的I2C端口全部);
配置_备用_功能(选择的_I2C_时钟_引脚、选择的_I2C_端口_AF);
配置备用功能(所选I2C数据引脚、所选I2C端口AF);
GPIO_Conf_AF.AF_速度:=速度100MHz;
GPIO_Conf_AF.AF_输出_类型:=开路_漏极;
GPIO_Conf_AF.Resistors:=上拉;
配置IO(所选的I2C时钟引脚、GPIO配置AF);
配置IO(所选的I2C数据引脚、GPIO配置AF);
STM32.I2C.Configure
(选定的I2C端口全部,
(时钟速度=>选定的时钟速度,
寻址模式=>STM32.I2C。寻址模式7bit,
自有地址=>16#00#,其他地址=>);
STM32.I2C.Set_状态(选中的_I2C_Port.all,已启用=>True);
终端硬件;
ID:HAL.I2C.I2C_数据(1..1);
状态:HAL.I2C.I2C_状态;
开始
设置硬件;
HAL.I2C.Mem_读取(This=>Port.all,
地址=>I2C_地址,
Mem#u Addr=>16#D0#,
Mem_Addr_Size=>HAL.I2C.Memory_Size_8b,
数据=>ID,
状态=>状态,
超时=>15000);
如果状态/=正常,则
用“I2C读取错误”引发程序错误:&Status'Img;
如果结束;
结束简单的I2C演示;
在这个简单的例子中,我总是在阅读结束时得到一个错误状态。在更完整的代码环境中,我总是在等待15秒后处于忙碌状态

我真的不知道发生了什么,因为我的代码主要是从I2C传感器的设计中得到启发的


也许我忘记了I2C初始化的特定代码,但由于我不是专家,我更喜欢向专家询问:)

不,在
HAL_I2C_Mem_Read
HAL_I2C_Master_Transmission
等待
HAL_I2C_Master_Receive
过程之间只是一个细微差别。如果您知道要接收的数据大小,可以使用
HAL\u I2C\u Master\u传输
,等待,
HAL\u I2C\u Master\u接收
过程

一个C++ HAL I2C例子在


您试图从寄存器
D0
cf第26页中读取1字节的芯片识别号,最终发现了错误。在使用STM HAL使用C进行测试并调查Ada配置代码后,我发现缺少一行:

GPIO\u Conf\u AF.AF\u速度:=速度100MHz;
GPIO_Conf_AF.AF_输出_类型:=开路_漏极;
GPIO_Conf_AF.Resistors:=上拉;
--缺少记录的配置部分
GPIO_Conf_AF.AF:=所选的_I2C_端口_AF;
--即使调用了configure,也应该存在
--每个针上面有几行
配置IO(所选的I2C时钟引脚、GPIO配置AF);
配置IO(所选的I2C数据引脚、GPIO配置AF);
在Configure_Alternate_函数之后使用Configure_IO会破坏配置,并且由于有一部分记录未初始化,因此GPIO配置不正确

更准确地说,在查看GPIO处理内部的代码之后,使用GPIO_端口_配置记录的AF部分配置_IO调用Configure_Alternate_函数。在我的情况下,它是重置它

由于缺少这一行,代码现在可以通过Mem_Read和Master_Transmit/Master_Receive正确运行


非常感谢您建议我深入研究生成的C代码。

如果您有一台装有linux的PC,您可以使用
i2c工具
测试Bosch传感器及其行为,然后在ada代码中实现这一点。此外,任何传感器都有其特定的命令代码,可以从数据表第31页的i2c cf中访问,我将用它进行测试
i2c工具
遵循此指南:问题是我的电脑上没有任何i2c接口,因此无法使用Linux工具测试行为。我可以说,使用Mc++ C++例子,传感器工作,但是它依赖于一个旧的MaBrand框架,我不能检查整个代码。如果你有一个RaspberryPi,你可以在上面安装代码> i2c工具< /C>,使用它的I2C接口。您必须执行第31页数据表()中的命令(即发送Bosch的总线地址),才能访问传感器的寄存器,如何读取传感器的寄存器见第33页第I2C段。您在代码中使用的传感器地址是否准确?默认地址为
76h
(十六进制)如果SDO连接到GND(数据表第32页),问题是我不知道ada…我的配置中肯定还有另一个问题,即使您使用Master_Transmit和Master_Receive解决方案,我最终用STM32Cube生成的C代码进行了测试,HAL_I2C_Mem_Read的工作非常出色。我需要研究Ada配置部分。代码将
GPIO\U端口\U配置作为聚合传递,这意味着您不能意外遗漏组件(除非
//Trigger Temperature measurement 
buffer[0]=0x00;  
HAL_I2C_Master_Transmit(&hi2c1,0x40<<1,buffer,1,100);  
HAL_Delay(20);  
HAL_I2C_Master_Receive(&hi2c1,0x40<<1,buffer,2,100);  
//buffer[0] : MSB data 
//buffer[1] : LSB data 
rawT = buffer[0]<<8 | buffer[1]; //combine 2 8-bit into 1 16bit  
Temperature = ((float)rawT/65536)*165.0 -40.0;  
//Trigger Humidity measurement buffer[0]=0x01; 
HAL_I2C_Master_Transmit(&hi2c1,0x40<<1,buffer,1,100);  
HAL_Delay(20);  
HAL_I2C_Master_Receive(&hi2c1,0x40<<1,buffer,2,100);  
//buffer[0] : MSB data 
//buffer[1] : LSB data 
rawH = buffer[0]<<8 | buffer[1]; //combine 2 8-bit into 1 16bit  
Humidity = ((float)rawH/65536)*100.0; HAL_Delay(100); }
HAL.I2C.Mem_Read (This          => Port.all,
                 Addr          => I2C_Address,
                 Mem_Addr      => 16#D0#,
                 Mem_Addr_Size => HAL.I2C.Memory_Size_8b,
                 Data          => ID,
                 Status        => Status,
                 Timeout => 15000);