2017-09-22 7 views
1

SPI를 통한 간단한 연결을 설정하려고하지만 SpiDevice를 가져올 때 SpiDevice.FromIdAsync 메서드가 끝나지 않습니다. 이것은 거의 예외없이 예외없이 거의 항상 발생합니다.비동기 메서드 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 드라이버에 단일 바이트를 출력합니다. 나는 라즈베리 파이 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> 

답변

1

당신 때문에 차단 통화 .Wait() 및 비동기 호출의 혼합의 교착 상태를 경험하고 있습니다. 그 논리를 이벤트 핸들러로 옮기는 것이 좋습니다. Like 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) { 

     } 
    }; 
} 
+0

답장을 보내 주셔서 감사합니다. 이제 작동합니다. 나는 교착 상태에 대해 정말로 들어 본 적이 없다. 이 기사는 http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html에서 발견되었으며 문제를 이해하는 데 도움이되었습니다. – branbu28