问题描述
我打算用navigationview
编写一个UWP,在其中我使用rs485
与某些设备进行通信。
我有一个DS3231 RTC
,我之前已经在较早的应用程序中使它正常工作。
我的SettingPage
是我配置时间的地方,当我设置时间时,我遇到了错误。 system.nullreferenceexception: 'object reference not set to an instance of an object.'
我的startClock()
,readDS3231
和setDS3231
例程位于MainPage.xaml.cs
中。
我的datepicker
和timepicker
例程位于SettingsPage
中。
请帮助让我知道我在哪里做错了以及如何纠正它。
实际上,我对page
很困惑。我不明白。
SettingsPage.xaml.cs
private void DatePicker_DateChanged(object sender,DatePickerValueChangedEventArgs e)
{
DateTimeSettings.SetSystemDateTime(e.NewDate.UtcDateTime);
mainPage.SetTime_DS3231(e.NewDate.UtcDateTime);
}
private void TimePicker_TimeChanged(object sender,TimePickerValueChangedEventArgs e)
{
var currentDate = DateTime.Now.ToUniversalTime();
var newDateTime = new DateTime(currentDate.Year,currentDate.Month,currentDate.Day,e.NewTime.Hours,e.NewTime.Minutes,e.NewTime.Seconds);
DateTimeSettings.SetSystemDateTime(newDateTime);
mainPage.SetTime_DS3231(newDateTime);
}
private void TimeZoneComboBox_SelectionChanged(object sender,SelectionChangedEventArgs e)
{
TimeZoneInfo selectedTimeZone = (TimeZoneInfo)this.TimeZoneComboBox.SelectedItem;
Zone.Text = selectedTimeZone.ToString();
TimeZoneInfo.ConvertTime(DateTime.Now,selectedTimeZone);
}
private void UpdateRTC_Click(object sender,RoutedEventArgs e)
{
mainPage.SetTime_DS3231(DateTime.Now);
}
private void ReadRTC_Click(object sender,RoutedEventArgs e)
{
mainPage.GetTime_DS3231();
ReadSec.Text = mainPage.readSec;
ReadMin.Text = mainPage.readMin;
ReadHour.Text = mainPage.readHour;
ReadDay.Text = mainPage.readDay;
ReadDate.Text = mainPage.readDate;
ReadMth.Text = mainPage.readMth;
ReadYear.Text = mainPage.readYear;
}
MainPage.xaml.cs
public async void GetTime_DS3231()
{
/* DS3231 I2C SLAVE address */
int SlaveAddress = 0x68;
try
{
// Initialize I2C
var Settings = new I2cConnectionSettings(SlaveAddress);
Settings.Busspeed = I2cBusspeed.StandardMode;
if (AQS == null || dis == null)
{
AQS = I2cDevice.GetDeviceSelector("I2C1");
dis = await Deviceinformation.FindAllAsync(AQS);
}
//rtcError = false;
using (I2cDevice Device = await I2cDevice.FromIdAsync(dis[0].Id,Settings))
{
byte[] writeBuf = { 0x00 };
Device.Write(writeBuf);
byte[] readBuf = new byte[7];
Device.Read(readBuf);
byte second = bcdToDec((byte)(readBuf[0] & 0x7f));
byte minute = bcdToDec(readBuf[1]);
byte hour = bcdToDec((byte)(readBuf[2] & 0x3f));
byte dayOfWeek = bcdToDec(readBuf[3]);
byte dayOfMonth = bcdToDec(readBuf[4]);
byte month = bcdToDec(readBuf[5]);
byte year = bcdToDec(readBuf[6]);
readSec = second.ToString();
readMin = minute.ToString();
readHour = hour.ToString();
readDay = dayOfWeek.ToString();
readDate = dayOfMonth.ToString();
readMth = month.ToString();
readYear = year.ToString();
var currentDate = DateTime.Now.ToUniversalTime();
var newDateTime = new DateTime(currentDate.Year,month,dayOfMonth,hour,minute,second);
DateTimeSettings.SetSystemDateTime(newDateTime);
}
}
catch (Exception ex)
{
MainStatusdisplay.Text = ex.Message;
//System.Diagnostics.Debug.Write(ex.Message);
}
}
public async void SetTime_DS3231(DateTime dt)
{
int SlaveAddress = 0x68;
try
{
// Initialize I2C
var Settings = new I2cConnectionSettings(SlaveAddress);
Settings.Busspeed = I2cBusspeed.StandardMode;
if (AQS == null || dis == null)
{
AQS = I2cDevice.GetDeviceSelector("I2C1");
dis = await Windows.Devices.Enumeration.Deviceinformation.FindAllAsync(AQS);
}
//rtcError = false;
using (I2cDevice Device = await I2cDevice.FromIdAsync(dis[0].Id,Settings))
{
byte write_seconds = decToBcd((byte)dt.Second);
byte write_minutes = decToBcd((byte)dt.Minute);
byte write_hours = decToBcd((byte)dt.Hour);
byte write_dayofweek = decToBcd((byte)dt.DayOfWeek);
byte write_day = decToBcd((byte)dt.Day);
byte write_month = decToBcd((byte)dt.Month);
//byte write_year = decToBcd((byte)dt.Year);
byte write_year = IntToBcd(dt.Year % 100);
byte[] write_time = { 0x00,write_seconds,write_minutes,write_hours,write_dayofweek,write_day,write_month,write_year };
Device.Write(write_time);
}
}
catch (Exception ex)
{
//rtcError = true;
MainStatusdisplay.Text = ex.Message;
//System.Diagnostics.Debug.Write(ex.Message);
}
}
解决方法
必须使用SettingsPage.mainPage
当前活动的页面实例初始化成员MainPage
。如果不使用MVVM,事情将变得复杂而丑陋。因此,我建议引入一个在两个视图之间共享的视图模型。
还请注意,异步方法必须返回Task
,否则您将遇到奇怪的行为,尤其是当等待方法引发异常时。您还忘记了await
异步方法。考虑遵循最佳做法的命名约定,并将“ Async”后缀添加到异步方法,例如GetTime_DS3231Async
:
MainViewModel.cs
class MainViewModel : INotifyPropertyChanged
{
public async Task GetTimeDs3231Async()
{
/* DS3231 I2C SLAVE address */
int SlaveAddress = 0x68;
try
{
// Initialize I2C
var Settings = new I2cConnectionSettings(SlaveAddress);
Settings.BusSpeed = I2cBusSpeed.StandardMode;
if (AQS == null || DIS == null)
{
AQS = I2cDevice.GetDeviceSelector("I2C1");
DIS = await DeviceInformation.FindAllAsync(AQS);
}
//rtcError = false;
using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id,Settings))
{
byte[] writeBuf = { 0x00 };
Device.Write(writeBuf);
byte[] readBuf = new byte[7];
Device.Read(readBuf);
byte second = bcdToDec((byte)(readBuf[0] & 0x7f));
byte minute = bcdToDec(readBuf[1]);
byte hour = bcdToDec((byte)(readBuf[2] & 0x3f));
byte dayOfWeek = bcdToDec(readBuf[3]);
byte dayOfMonth = bcdToDec(readBuf[4]);
byte month = bcdToDec(readBuf[5]);
byte year = bcdToDec(readBuf[6]);
readSec = second.ToString();
readMin = minute.ToString();
readHour = hour.ToString();
readDay = dayOfWeek.ToString();
readDate = dayOfMonth.ToString();
readMth = month.ToString();
readYear = year.ToString();
var currentDate = DateTime.Now.ToUniversalTime();
var newDateTime = new DateTime(currentDate.Year,month,dayOfMonth,hour,minute,second);
DateTimeSettings.SetSystemDateTime(newDateTime);
}
}
catch (Exception ex)
{
MainStatusDisplay.Text = ex.Message;
//System.Diagnostics.Debug.Write(ex.Message);
}
}
public async Task SetTimeDs3231Async(DateTime dt)
{
int SlaveAddress = 0x68;
try
{
// Initialize I2C
var Settings = new I2cConnectionSettings(SlaveAddress);
Settings.BusSpeed = I2cBusSpeed.StandardMode;
if (AQS == null || DIS == null)
{
AQS = I2cDevice.GetDeviceSelector("I2C1");
DIS = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(AQS);
}
//rtcError = false;
using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id,Settings))
{
byte write_seconds = decToBcd((byte)dt.Second);
byte write_minutes = decToBcd((byte)dt.Minute);
byte write_hours = decToBcd((byte)dt.Hour);
byte write_dayofweek = decToBcd((byte)dt.DayOfWeek);
byte write_day = decToBcd((byte)dt.Day);
byte write_month = decToBcd((byte)dt.Month);
//byte write_year = decToBcd((byte)dt.Year);
byte write_year = IntToBcd(dt.Year % 100);
byte[] write_time = { 0x00,write_seconds,write_minutes,write_hours,write_dayofweek,write_day,write_month,write_year };
Device.Write(write_time);
}
}
catch (Exception ex)
{
//rtcError = true;
MainStatusDisplay.Text = ex.Message;
//System.Diagnostics.Debug.Write(ex.Message);
}
}
}
App.xaml
<Application>
<Application.Resources>
<MainViewModel x:Key="MainViewModel"/>
</Application.Resources>
</Application>
MainPage.xam
<Page DataContext="{StaticResource MainViewModel}">
</Page>
SettingsPage.xam
<Page DataContext="{StaticResource MainViewModel}">
</Page>
SettingsPage.xaml.cs
private async void DatePicker_DateChanged(object sender,DatePickerValueChangedEventArgs e)
{
DateTimeSettings.SetSystemDateTime(e.NewDate.UtcDateTime);
var viewModel = this.DataContext as MainViewModel;
// Await the asynchronous method
await viewModel.SetTimeDs3231Async(e.NewDate.UtcDateTime);
}
,
在您使用mainPage.SetTime_DS3231(newDateTime)
时,变量mainPage
的值为null。确保已正确初始化。
在此之前它已经初始化了吗?然后可能会在代码执行过程中的某个时候将其删除,例如在切换页面时。
您可以尝试将其放在mainPage.SetTime_DS3231(newDateTime)
之前:
if(mainPage == null)
mainPage = new MainPage();