异步方法 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) {
}
};
}
我正在尝试通过 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) {
}
};
}