stm32 - I2C 在内存读取时返回忙或错误

标签 stm32 ada gnat

我启动了以下代码来处理 Bosch BME280 sensor带有 Nucleo-F446ZE 和 Nucleo-F411RE 板。

with STM32.Device; use STM32.Device;
with STM32.GPIO; use STM32.GPIO;
with STM32; use STM32;
with STM32.I2C;

with HAL.I2C; use HAL.I2C;
use HAL;

procedure Simple_I2C_Demo is

   --  I2C Bus selected
   Selected_I2C_Port      : constant access STM32.I2C.I2C_Port := I2C_1'Access;
   Selected_I2C_Port_AF   : constant GPIO_Alternate_Function := GPIO_AF_I2C1_4;
   Selected_I2C_Clock_Pin : GPIO_Point renames PB8;
   Selected_I2C_Data_Pin  : GPIO_Point renames PB9;

   Port : constant HAL.I2C.Any_I2C_Port := Selected_I2C_Port;

   --  Shift one because of 7-bit addressing
   I2C_Address : constant HAL.I2C.I2C_Address := 16#76# * 2;


   procedure SetupHardware is
      GPIO_Conf_AF : GPIO_Port_Configuration (Mode_AF);
      Selected_Clock_Speed : constant := 10_000;
   begin
      Enable_Clock (Selected_I2C_Clock_Pin);
      Enable_Clock (Selected_I2C_Data_Pin);

      Enable_Clock (Selected_I2C_Port.all);

      STM32.Device.Reset (Selected_I2C_Port.all);

      Configure_Alternate_Function (Selected_I2C_Clock_Pin, Selected_I2C_Port_AF);
      Configure_Alternate_Function (Selected_I2C_Data_Pin, Selected_I2C_Port_AF);

      GPIO_Conf_AF.AF_Speed       := Speed_100MHz;
      GPIO_Conf_AF.AF_Output_Type := Open_Drain;
      GPIO_Conf_AF.Resistors   := Pull_Up;
      Configure_IO (Selected_I2C_Clock_Pin, GPIO_Conf_AF);
      Configure_IO (Selected_I2C_Data_Pin, GPIO_Conf_AF);

      STM32.I2C.Configure
        (Selected_I2C_Port.all,
         (Clock_Speed          => Selected_Clock_Speed,
          Addressing_Mode      => STM32.I2C.Addressing_Mode_7bit,
          Own_Address          => 16#00#, others => <>));

      STM32.I2C.Set_State (Selected_I2C_Port.all, Enabled => True);
   end SetupHardware;

   ID : HAL.I2C.I2C_Data (1 .. 1);
   Status : HAL.I2C.I2C_Status;

begin

   SetupHardware;

   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);

   if Status /= Ok then
      raise Program_Error with "I2C read error:" & Status'Img;
   end if;
end Simple_I2C_Demo;

在这个简单的例子中,我总是在阅读结束时得到一个错误状态。在更完整的代码的上下文中,我总是在等待 15 秒后得到忙碌状态。

我真的看不出发生了什么,因为我的代码很大程度上是从 the code I found on Github 中得到启发的。对于 I2C 传感器。

也许我忘记了 I2C init 的特定代码,但由于我不是专家,我更愿意向专家请教 :)

最佳答案

终于找到问题所在了。在使用STM HAL用C测试并调查Ada配置代码后,我发现缺少一行:

      GPIO_Conf_AF.AF_Speed       := Speed_100MHz;
      GPIO_Conf_AF.AF_Output_Type := Open_Drain;
      GPIO_Conf_AF.Resistors   := Pull_Up;

      -- Missing configuration part of the record
      GPIO_Conf_AF.AF := Selected_I2C_Port_AF;
      -- That should be present even though there was a call to configure
      -- each pin few lines above

      Configure_IO (Selected_I2C_Clock_Pin, GPIO_Conf_AF);
      Configure_IO (Selected_I2C_Data_Pin, GPIO_Conf_AF);

Configure_Alternate_Function 之后使用 Configure_IO 会破坏配置,并且由于有一部分记录未初始化,因此 GPIO 配置不正确。

更准确地说,在查看 GPIO 处理内部的代码后,Configure_IO 使用 AF 部分调用 Configure_Alternate_Function>GPIO_Port_Configuration 记录。就我而言,它正在重置它。

由于缺少行,代码现在可以使用 Mem_ReadMaster_Transmit/Master_Receive 正确运行。

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

关于stm32 - I2C 在内存读取时返回忙或错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59599362/

相关文章:

c - 在 STM32 上使用调试器时如何使用延迟?

c - 在Ada中实现变量数据耦合到函数中(类似于C中函数中的静态变量)

file-io - 在 Ada 中打开、写入和追加的过程

ada - Ada 编程语言的 GUI

linker - GPRbuild:编译器开关被传递给链接器

c - 从闪存 STM32F779II 运行软件

c - 如何初始化 DT028ATFT 显示屏

c - STM32L476 flash 页删除无效

ada - Ada 是否有与 Pascal 集合等价的类型?

gcc - Ada 版本的命令行?