【发布时间】:2017-12-07 04:14:09
【问题描述】:
我正在玩运行 Windows IoT 的 Raspberry Pi 3。我已经连接了一个 DS18B20 传感器,我可以通过 UWP 应用程序与之通信。
我现在想把这个应用程序变成一个 BackgroundTask 应用程序。 我正在将此代码用于 OneWire coms
class WireSearchResult
{
public byte[] id = new byte[8];
public int lastForkPoint = 0;
}
public class OneWire
{
private SerialDevice serialPort = null;
DataWriter dataWriteObject = null;
DataReader dataReaderObject = null;
public async Task<string> GetFirstSerialPort()
{
try
{
string aqs = SerialDevice.GetDeviceSelector("UART0");
var dis = await DeviceInformation.FindAllAsync(aqs);
if (dis.Count > 0)
{
var deviceInfo = dis.First();
return deviceInfo.Id;
}
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get serial device: " + ex.Message);
}
return null;
}
public void shutdown()
{
if (serialPort != null)
{
serialPort.Dispose();
serialPort = null;
}
}
async Task<bool> onewireReset(string deviceId)
{
try
{
if (serialPort != null)
serialPort.Dispose();
serialPort = await SerialDevice.FromIdAsync(deviceId);
// Configure serial settings
serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.BaudRate = 9600;
serialPort.Parity = SerialParity.None;
serialPort.StopBits = SerialStopBitCount.One;
serialPort.DataBits = 8;
serialPort.Handshake = SerialHandshake.None;
dataWriteObject = new DataWriter(serialPort.OutputStream);
dataWriteObject.WriteByte(0xF0);
await dataWriteObject.StoreAsync();
dataReaderObject = new DataReader(serialPort.InputStream);
await dataReaderObject.LoadAsync(1);
byte resp = dataReaderObject.ReadByte();
if (resp == 0xFF)
{
System.Diagnostics.Debug.WriteLine("Nothing connected to UART");
return false;
}
else if (resp == 0xF0)
{
System.Diagnostics.Debug.WriteLine("No 1-wire devices are present");
return false;
}
else
{
//System.Diagnostics.Debug.WriteLine("Response: " + resp);
serialPort.Dispose();
serialPort = await SerialDevice.FromIdAsync(deviceId);
// Configure serial settings
serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.BaudRate = 115200;
serialPort.Parity = SerialParity.None;
serialPort.StopBits = SerialStopBitCount.One;
serialPort.DataBits = 8;
serialPort.Handshake = SerialHandshake.None;
dataWriteObject = new DataWriter(serialPort.OutputStream);
dataReaderObject = new DataReader(serialPort.InputStream);
return true;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception: " + ex.Message);
return false;
}
}
public async Task onewireWriteByte(byte b)
{
for (byte i = 0; i < 8; i++, b = (byte)(b >> 1))
{
// Run through the bits in the byte, extracting the
// LSB (bit 0) and sending it to the bus
await onewireBit((byte)(b & 0x01));
}
}
async Task<byte> onewireBit(byte b)
{
var bit = b > 0 ? 0xFF : 0x00;
dataWriteObject.WriteByte((byte)bit);
await dataWriteObject.StoreAsync();
await dataReaderObject.LoadAsync(1);
var data = dataReaderObject.ReadByte();
return (byte)(data & 0xFF);
}
async Task<byte> onewireReadByte()
{
byte b = 0;
for (byte i = 0; i < 8; i++)
{
// Build up byte bit by bit, LSB first
b = (byte)((b >> 1) + 0x80 * await onewireBit(1));
}
// System.Diagnostics.Debug.WriteLine("onewireReadByte result: " + b);
return b;
}
public async Task<double> getTemperature(string deviceId)
{
double tempCelsius = -200;
if (await onewireReset(deviceId))
{
await onewireWriteByte(0xCC); //1-Wire SKIP ROM command (ignore device id)
await onewireWriteByte(0x44); //DS18B20 convert T command
// (initiate single temperature conversion)
// thermal data is stored in 2-byte temperature
// register in scratchpad memory
// Wait for at least 750ms for data to be collated
await Task.Delay(750);
// Get the data
await onewireReset(deviceId);
await onewireWriteByte(0xCC); //1-Wire Skip ROM command (ignore device id)
await onewireWriteByte(0xBE); //DS18B20 read scratchpad command
// DS18B20 will transmit 9 bytes to master (us)
// starting with the LSB
byte tempLSB = await onewireReadByte(); //read lsb
byte tempMSB = await onewireReadByte(); //read msb
// Reset bus to stop sensor sending unwanted data
await onewireReset(deviceId);
// Log the Celsius temperature
tempCelsius = ((tempMSB * 256) + tempLSB) / 16.0;
var temp2 = ((tempMSB << 8) + tempLSB) * 0.0625; //just another way of calculating it
System.Diagnostics.Debug.WriteLine("Temperature: " + tempCelsius + " degrees C " + temp2);
}
return tempCelsius;
}
}
最后是 StartupTask
public sealed class StartupTask : IBackgroundTask
{
private BackgroundTaskDeferral deferral;
private OneWire onewire;
private string deviceId = string.Empty;
private bool inprog = false;
private Timer timer;
public void Run(IBackgroundTaskInstance taskInstance)
{
deferral = taskInstance.GetDeferral();
onewire = new OneWire();
deviceId = await onewire.GetFirstSerialPort();
if(deviceId != null)
await onewire.getTemperature(deviceId));
BackgroundTaskDeferral.Complete();
}
}
我遇到的问题是,当我运行此代码时,它会挂在处理 OneWire 类中的 SerialDevice 的行之一上。
我在一些地方读到它与 BackgroundTask 和使用 Async/Await 相关
【问题讨论】:
-
您是否真的阅读了代码示例中显示的链接中的文档? IE。 aka.ms/backgroundtaskdeferral。在我看来,它似乎提供了一个非常清晰、易于理解的解释,以准确说明如何处理您所询问的问题。
-
确保在每个
serialPort.Dispose();之后设置serialPort = null;并再次测试。 -
@PeterDuniho 请详细说明。我已阅读文档,但没有看到对我的问题的明确解释。我获得了一个延迟,我执行了代码,唯一缺少的是在代码完成后设置 Defferral.Complete()。我的问题是代码没有完成,它挂起,所以我永远无法设置 Defferral.Complete()。
-
@RitaHan-MSFT 我尝试将串口设置为空,但没有成功。
-
"唯一缺少的部分是设置 Deferral.Complete()" -- 是的,缺少那部分。为什么不从尽可能正确的代码开始,而不是从已知不正确的代码开始。您声称代码挂在对
Dispose()的调用上,但是a)您的非minimal reproducible example 显示没有对Dispose()的调用,并且b)处置完全有可能没有完成,因为您从不调用@ 987654331@方法。
标签: c# asynchronous windows-10-iot-core