异步方法 SpiDevice.FromIdAsync 没有完成

Asynchronous method SpiDevice.FromIdAsync does not finish

我正在尝试通过 SPI 建立一个简单的连接,但是在尝试获取 SpiDevice 时,SpiDevice.FromIdAsync 方法永远不会完成。这种情况几乎总是会发生,除了一些看似随机的罕见例外。

spi = await SpiDevice.FromIdAsync(dis[0].Id, settings);

用于设置连接的代码来自https://docs.microsoft.com/en-us/windows/iot-core/learn-about-hardware/pinmappings/pinmappingsrpi#spi-bus

在示例中,我将单个字节输出到用作移位寄存器的 LED 驱动器。我使用 Raspberry Pi 3 作为目标设备,Visual Studio Community 2017 作为我的 IDE.

MainPage.xaml.cs

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Gpio;
using Windows.Devices.Spi;
using Windows.Devices.Enumeration;
using System.Threading.Tasks;

namespace SPI_Test
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            try
            {
                InitGPIO();
                InitSpi().Wait();

                timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromMilliseconds(500);
                timer.Tick += Timer_Tick;
            }
            catch (Exception)
            {

            }
        }

        GpioPin enablePin;
        SpiDevice spi;

        private void InitGPIO()
        {
            var gpio = GpioController.GetDefault();

            //create pin to control the output of the LED driver
            //the outputs are active when the pin is low
            enablePin = gpio.OpenPin(12);
            enablePin.Write(GpioPinValue.High); //disable outputs at first
            enablePin.SetDriveMode(GpioPinDriveMode.Output);
        }

        private async Task InitSpi()
        {
            try
            {
                // Use chip select line CS0
                var settings = new SpiConnectionSettings(0);
                // Set clock to 10MHz 
                settings.ClockFrequency = 10000000;

                // Get a selector string that will return our wanted SPI controller
                string aqs = SpiDevice.GetDeviceSelector("SPI0");

                // Find the SPI bus controller devices with our selector string
                var dis = await DeviceInformation.FindAllAsync(aqs);

                spi = await SpiDevice.FromIdAsync(dis[0].Id, settings);  /* Create an SpiDevice with our bus controller and SPI settings */

            }
            /* If initialization fails, display the exception and stop running */
            catch (Exception ex)
            {
                throw new Exception("SPI Initialization Failed", ex);
            }
        }

        private DispatcherTimer timer;
        private byte value = 0;
        private void Timer_Tick(object sender, object e)
        {
            enablePin.Write(GpioPinValue.High); //disable outputs
            spi.Write(new byte[] { value++ }); //send the current value to the LEDs and increase by 1
            enablePin.Write(GpioPinValue.Low); //re-enable outputs
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            timer.Start();
        }
    }
}

MainPage.xaml

<Page
    x:Class="SPI_Test.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SPI_Test"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button Click="Button_Click" Content="Start" Margin="15" />
        </StackPanel>
    </Grid>
</Page>

由于混合了阻塞调用 .Wait() 和异步调用,您遇到了死锁。我建议将该逻辑移至事件处理程序。喜欢Loaded

public MainPage() {
    this.InitializeComponent();
    this.Loaded += async (sender, e) => {
        try {
            InitGPIO();
            await InitSpi();

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(500);
            timer.Tick += Timer_Tick;
        } catch (Exception) {

        }
    };
}