I am intending to write a UWP with navigationview
where I use rs485
to communicate to some devices.
I have a DS3231 RTC
, which I have made it work previously in earlier app.
My SettingPage
is where I configure the time, when I set the time, i ran into error. system.nullreferenceexception: 'object reference not set to an instance of an object.'
My startClock()
, readDS3231
and setDS3231
routines are in MainPage.xaml.cs
. My datepicker
and timepicker
routines are in SettingsPage
.
Please help to let me know where did I do wrong and how do I correct it. Actually I am quite confused with the page
thing. I can't understand it.
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);
}
}
You must initialize the member SettingsPage.mainPage
with the currently active page instance of MainPage
. If you don't use MVVM things become complicated and ugly. For this reason I recommend to introduce a view model which is shared between both views.
Also note that an async method must return Task
otherrwise you will experience strange behavior especially when exceptions are thrown by the awaitable method. You also forget to await
the asynchronous methods. Consider to follow best practice naming conventions and ad the "Async" suffix to asynchronous methods eg 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);
}
At the time you use mainPage.SetTime_DS3231(newDateTime)
the variable mainPage
has the Value null. Make sure it is correctly initialized. Was it already initialized before that? Then it is probably deleted at some point during your code, maybe when switching pages.
You could try putting this before the mainPage.SetTime_DS3231(newDateTime)
:
if(mainPage == null)
mainPage = new MainPage();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.