2017-09-22 10 views
1

J'essaie de configurer une connexion simple sur SPI, mais lorsque j'essaie d'obtenir un SpiDevice, la méthode SpiDevice.FromIdAsync ne se termine jamais. Cela arrive presque toujours, avec quelques rares exceptions qui semblent aléatoires.Méthode asynchrone SpiDevice.FromIdAsync ne se termine pas

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

Le code utilisé pour configurer la connexion provient de https://docs.microsoft.com/en-us/windows/iot-core/learn-about-hardware/pinmappings/pinmappingsrpi#spi-bus.

Dans cet exemple, je génère un octet unique vers un pilote de DEL fonctionnant comme un registre à décalage. J'utilise un Raspberry Pi 3 comme périphérique cible et Visual Studio Community 2017 comme 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> 

Répondre

1

Vous connaissent une impasse en raison du mélange des appels de blocage .Wait() et les appels asynchrones. Je suggère de déplacer cette logique vers un gestionnaire d'événements. J'aime 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

Merci pour votre réponse. Cela fonctionne maintenant. Je n'ai jamais vraiment entendu parler d'interblocages. J'ai trouvé cet article http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html et cela m'a aidé à comprendre le problème. – branbu28