Windows IoT 和 DS3231 RTC 时钟
Windows IoT and DS3231 RTC clock
对于我的项目,我需要当前时间和日期。不幸的是,RP2 在关闭时会丢失所有内容。接下来的事情是,我将没有互联网连接来使用 NTP。
为此,我需要实现一个 DS3231 RTC 模块。
所有设备的通信都通过 I2C(Raspberry <-> Arduino <-> DS3231)运行。
目前,我的 Arduino 与模块通信并将日期和时间存储在字符数组中。 RP2 与 Arduino 通信以获得 date/time。这实际上工作得很好。但我想直接与模块通信以节省 Arduino 上的资源(它只是一个 Nano)。
因此,我想知道是否有人对模块和 Windows 物联网有经验。
下面是我当前的解决方案:
Arduino:
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
#define MyAddress 0x40 /* Define the i2c address */
char time_char[10];
char date_char[10];
byte ReceivedData;
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}
void setup()
{
Wire.begin(MyAddress);
Serial.begin(9600);
Wire.onReceive(I2CReceived);
Wire.onRequest(I2CRequest);
}
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
// request seven bytes of data from DS3231 starting from register 00h
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void displayTime()
{
String hour_str, minute_str, second_str, day_str, month_str, year_str, hour_str_orig, minute_str_orig, second_str_orig, time_str, date_str;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// retrieve data from DS3231
readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,&year);
if (hour<10)
{
hour_str_orig = (hour);
hour_str = ("0" + hour_str_orig);
}
else
{
hour_str = (hour);
}
if (minute<10)
{
minute_str_orig = (minute);
minute_str = ("0" + minute_str_orig);
}
else
{
minute_str = (minute);
}
if (second<10)
{
second_str_orig = (second);
second_str = ("0" + second_str_orig);
}
else
{
second_str = (second);
}
day_str = (dayOfMonth);
month_str = (month);
year_str = (year);
time_str = (hour_str + ":" + minute_str + ":" + second_str);
date_str = (day_str + "." + month_str + "." + "20" +year_str);
time_str.toCharArray(time_char, 10);
date_str.toCharArray(date_char, 10);
}
void loop()
{
displayTime(); // send the real-time clock data to IoT
delay(1000); // every second
}
void I2CReceived(int NumberOfBytes)
{
/* WinIoT have sent data byte; read it */
ReceivedData = Wire.read();
}
void I2CRequest()
{
if (ReceivedData == 50)
{
Wire.write(time_char);
}
if (ReceivedData == 51)
{
Wire.write(date_char);
}
}
物联网:
public async void TestFunction()
{
for (int i = 0; i < 50; i++)
{
for (byte DataToBeSend = 50; DataToBeSend < 52; DataToBeSend++)
{
if (DataToBeSend == 50)
{
byte ReceivedData;
ReceivedData = await Time.WriteRead_OneByte(DataToBeSend);
await Task.Delay(10);
}
if (DataToBeSend == 51)
{
byte ReceivedData;
ReceivedData = await Time.WriteRead_OneByte(DataToBeSend);
await Task.Delay(10);
}
}
await Task.Delay(1000);
}
}
Class:
public class Time
{
private static string AQS;
private static DeviceInformationCollection DIS;
public static float result_fl;
public static async System.Threading.Tasks.Task<byte> WriteRead_OneByte(byte ByteToBeSend)
{
byte[] ReceivedData = new byte[10];
/* Gateway's I2C SLAVE address */
int SlaveAddress = 64; // 0x40
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);
}
using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
{
/* Send byte to Arduino Nano */
Device.Write(new byte[] { ByteToBeSend });
/* Read byte from Arduino Nano */
Device.Read(ReceivedData);
/* Rewrite Array to avoid empty space in source array */
var i = ReceivedData.Length - 1;
while (ReceivedData[i] == 255)
{
--i;
}
var date_time_arr = new byte[i + 1];
Array.Copy(ReceivedData, date_time_arr, i + 1);
/* Show date or time */
string result = System.Text.Encoding.UTF8.GetString(date_time_arr);
Debug.WriteLine(result);
}
}
catch (Exception)
{
}
return ReceivedData[0];
}
}
如果您需要更多信息,请告诉我。
谢谢!
抱歉回复晚了!
到目前为止我的解决方案:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.I2c;
using System.Diagnostics;
namespace _015_Test15_I2C_Clock_RTC3231
{
public class I2C_Time
{
private static string AQS;
private static DeviceInformationCollection DIS;
public static async Task GetTimeFromDS3231()
{
/* 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);
}
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]);
}
}
catch (Exception)
{
Debug.WriteLine("Error in I2C_Time Class");
}
}
private static byte bcdToDec(byte val)
{
return (byte)(((int)val / 16 * 10) + ((int)val % 16));
}
}
}
设置时钟:
using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
{
byte write_seconds = decToBcd(set_Time_now_seconds);
byte write_minutes = decToBcd(set_Time_now_minutes);
byte write_hours = decToBcd(set_Time_now_hours);
byte write_dayofweek = decToBcd(set_Date_now_dayofweek);
byte write_day = decToBcd(set_Date_now_day);
byte write_month = decToBcd(set_Date_now_month);
byte write_year = decToBcd(set_Date_now_year);
byte[] write_time = {0x00, write_seconds, write_minutes, write_hours, write_dayofweek, write_day, write_month, write_year };
Device.Write(write_time);
}
// Convert normal decimal numbers to binary coded decimal
private static byte decToBcd(byte val)
{
return (byte)(((int)val / 10 * 16) + ((int)val % 10));
}
对于我的项目,我需要当前时间和日期。不幸的是,RP2 在关闭时会丢失所有内容。接下来的事情是,我将没有互联网连接来使用 NTP。 为此,我需要实现一个 DS3231 RTC 模块。 所有设备的通信都通过 I2C(Raspberry <-> Arduino <-> DS3231)运行。 目前,我的 Arduino 与模块通信并将日期和时间存储在字符数组中。 RP2 与 Arduino 通信以获得 date/time。这实际上工作得很好。但我想直接与模块通信以节省 Arduino 上的资源(它只是一个 Nano)。 因此,我想知道是否有人对模块和 Windows 物联网有经验。
下面是我当前的解决方案:
Arduino:
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
#define MyAddress 0x40 /* Define the i2c address */
char time_char[10];
char date_char[10];
byte ReceivedData;
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}
void setup()
{
Wire.begin(MyAddress);
Serial.begin(9600);
Wire.onReceive(I2CReceived);
Wire.onRequest(I2CRequest);
}
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
// request seven bytes of data from DS3231 starting from register 00h
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void displayTime()
{
String hour_str, minute_str, second_str, day_str, month_str, year_str, hour_str_orig, minute_str_orig, second_str_orig, time_str, date_str;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// retrieve data from DS3231
readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,&year);
if (hour<10)
{
hour_str_orig = (hour);
hour_str = ("0" + hour_str_orig);
}
else
{
hour_str = (hour);
}
if (minute<10)
{
minute_str_orig = (minute);
minute_str = ("0" + minute_str_orig);
}
else
{
minute_str = (minute);
}
if (second<10)
{
second_str_orig = (second);
second_str = ("0" + second_str_orig);
}
else
{
second_str = (second);
}
day_str = (dayOfMonth);
month_str = (month);
year_str = (year);
time_str = (hour_str + ":" + minute_str + ":" + second_str);
date_str = (day_str + "." + month_str + "." + "20" +year_str);
time_str.toCharArray(time_char, 10);
date_str.toCharArray(date_char, 10);
}
void loop()
{
displayTime(); // send the real-time clock data to IoT
delay(1000); // every second
}
void I2CReceived(int NumberOfBytes)
{
/* WinIoT have sent data byte; read it */
ReceivedData = Wire.read();
}
void I2CRequest()
{
if (ReceivedData == 50)
{
Wire.write(time_char);
}
if (ReceivedData == 51)
{
Wire.write(date_char);
}
}
物联网:
public async void TestFunction()
{
for (int i = 0; i < 50; i++)
{
for (byte DataToBeSend = 50; DataToBeSend < 52; DataToBeSend++)
{
if (DataToBeSend == 50)
{
byte ReceivedData;
ReceivedData = await Time.WriteRead_OneByte(DataToBeSend);
await Task.Delay(10);
}
if (DataToBeSend == 51)
{
byte ReceivedData;
ReceivedData = await Time.WriteRead_OneByte(DataToBeSend);
await Task.Delay(10);
}
}
await Task.Delay(1000);
}
}
Class:
public class Time
{
private static string AQS;
private static DeviceInformationCollection DIS;
public static float result_fl;
public static async System.Threading.Tasks.Task<byte> WriteRead_OneByte(byte ByteToBeSend)
{
byte[] ReceivedData = new byte[10];
/* Gateway's I2C SLAVE address */
int SlaveAddress = 64; // 0x40
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);
}
using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
{
/* Send byte to Arduino Nano */
Device.Write(new byte[] { ByteToBeSend });
/* Read byte from Arduino Nano */
Device.Read(ReceivedData);
/* Rewrite Array to avoid empty space in source array */
var i = ReceivedData.Length - 1;
while (ReceivedData[i] == 255)
{
--i;
}
var date_time_arr = new byte[i + 1];
Array.Copy(ReceivedData, date_time_arr, i + 1);
/* Show date or time */
string result = System.Text.Encoding.UTF8.GetString(date_time_arr);
Debug.WriteLine(result);
}
}
catch (Exception)
{
}
return ReceivedData[0];
}
}
如果您需要更多信息,请告诉我。 谢谢!
抱歉回复晚了! 到目前为止我的解决方案:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.I2c;
using System.Diagnostics;
namespace _015_Test15_I2C_Clock_RTC3231
{
public class I2C_Time
{
private static string AQS;
private static DeviceInformationCollection DIS;
public static async Task GetTimeFromDS3231()
{
/* 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);
}
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]);
}
}
catch (Exception)
{
Debug.WriteLine("Error in I2C_Time Class");
}
}
private static byte bcdToDec(byte val)
{
return (byte)(((int)val / 16 * 10) + ((int)val % 16));
}
}
}
设置时钟:
using (I2cDevice Device = await I2cDevice.FromIdAsync(DIS[0].Id, Settings))
{
byte write_seconds = decToBcd(set_Time_now_seconds);
byte write_minutes = decToBcd(set_Time_now_minutes);
byte write_hours = decToBcd(set_Time_now_hours);
byte write_dayofweek = decToBcd(set_Date_now_dayofweek);
byte write_day = decToBcd(set_Date_now_day);
byte write_month = decToBcd(set_Date_now_month);
byte write_year = decToBcd(set_Date_now_year);
byte[] write_time = {0x00, write_seconds, write_minutes, write_hours, write_dayofweek, write_day, write_month, write_year };
Device.Write(write_time);
}
// Convert normal decimal numbers to binary coded decimal
private static byte decToBcd(byte val)
{
return (byte)(((int)val / 10 * 16) + ((int)val % 10));
}