UART自动同步电子钟

成品的电路图什么时候画好还不知道呐,不能再这么拖下去了,先发个帖子整理一下吧。


1、功能说明

使用MAC的电脑将时间数据按指定格式发至单片机,顺便把时间信息显示到屏幕上。


2、模块介绍

ArduinoMini、DS3231时钟模块、IIC显示转换模块、2004LCD外加杜邦线一小堆。


3、成品的样子


4.单片机代码:

Notice:原DS3231函数库有BUG,不要直接套用。

//头文件定义
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <DS3231.h>
//end头文件定义


//宏定义
#define inputStringLength 50
//end宏定义

//变量定义&初始化
DS3231 Clock; // DS3231模块初始化
LiquidCrystal_I2C lcd(0x27, 20, 4); // 显示模块初始化

// 保存时钟数据
byte second, minute, hour;
byte date, month, year;
byte DoW;
float temperature;
bool h12, PM;
bool Century;

byte secondBuffer, minuteBuffer, hourBuffer;
byte dateBuffer, monthBuffer, yearBuffer;
byte DoWBuffer;
float temperatureBuffer;


//串口输入缓存
char inputKeyBuffer[inputStringLength] = "0";
char checkDataBffer[] = "AT99123124606006=#"; // 数据检查样本

// 自定义字符
unsigned char dot[8] = {0x7, 0x5, 0x7}; // 摄氏温标
unsigned char heart[8] = {0x0, 0xa, 0x1f, 0x1f, 0xe, 0x4, 0x0}; // 心
/end变量定义&初始化


//
void setup() {
  h12 = false;
  Wire.begin(); // IIC接口启动
  Serial.begin(9600); // UART接口启动
  lcd.init(); // 显示模块启动
  lcd.backlight(); // 开背光

  // 创建自定义字符
  lcd.createChar(0, dot);
  lcd.createChar(1, heart);
}

void loop() {
  dispClock(); // 显示时间
  setClock4UART(); // 读串口数据,可重入
}



//显示时间函数
void dispClock() {
  readClock();
  lcd.setCursor(0, 0);
  dispWeek();
  lcd.setCursor(5, 1);
  dispDate();
  lcd.setCursor(6, 2);
  dispTime();
  lcd.setCursor(7, 3);
  dispTemp();
}
/end显示时间函数


//读时间函数
void readClock() {
  Clock.getTime(year, month, date, DoW, hour, minute, second, h12, PM);
  temperature = Clock.getTemperature();
}
///end显示时间函数


// 获取时间日期温度函数
void dispTime() { // 获取时间
  if (hour < 10) {
    lcd.print('0');
  }
  lcd.print(hour);

  lcd.print(':');

  if (minute < 10) {
    lcd.print('0');
  }
  lcd.print(minute);

  lcd.print(':');

  if (second < 10) {
    lcd.print('0');
  }
  lcd.print(second);
}

void dispDate() { // 获取日期
  lcd.print("20");
  if (year < 10) {
    lcd.print('0');
  }
  lcd.print(year);

  lcd.print('-');

  if (month < 10) {
    lcd.print('0');
  }
  lcd.print(month);

  lcd.print('-');

  if (date < 10) {
    lcd.print('0');
  }
  lcd.print(date);
}

void dispWeek() { // 获取星期
  switch (DoW) {
    case 0: {
        lcd.print("      ");
        lcd.write(1);
        lcd.print("Monday");
        lcd.write(1);
        lcd.print("      ");
        break;
      }
    case 1: {
        lcd.print("      ");
        lcd.write(1);
        lcd.print("Tuesday");
        lcd.write(1);
        lcd.print("     ");
        break;
      }
    case 2: {
        lcd.print("     ");
        lcd.write(1);
        lcd.print("Wednesday");
        lcd.write(1);
        lcd.print("    ");
        break;
      }
    case 3: {
        lcd.print("     ");
        lcd.write(1);
        lcd.print("Thursday");
        lcd.write(1);
        lcd.print("     ");
        break;
      }
    case 4: {
        lcd.print("      ");
        lcd.write(1);
        lcd.print("Friday");
        lcd.write(1);
        lcd.print("      ");
        break;
      }
    case 5: {
        lcd.print("     ");
        lcd.write(1);
        lcd.print("Saturday");
        lcd.write(1);
        lcd.print("     ");
        break;
      }
    case 6: {
        lcd.print("      ");
        lcd.write(1);
        lcd.print("Sunday");
        lcd.write(1);
        lcd.print("      ");
        break;
      }
  }
}

void dispTemp() { // 获取温度
  lcd.print(temperature);
  lcd.write(0);
  lcd.print('C');
}

///end获取各种时间函数

// 读串口数据
void setClock4UART() {
  if (Serial.available() > 0) {
    transtr();
    if (!checkData()) {
      str2timedata();
      setTime();
      clearBuffer();
    }
  }
}
//end读串口数据




//
//
// 获取串口数据处理并保存

// AT年月日时分秒星期#
// AT14030318431201=#
// 012345678901234567 //16

/*
//串口输入缓存
char inputKeyBuffer[inputStringLength] = "0";
char checkDataBffer[] = "AT99123124606006="; // 数据检查样本
*/
void transtr() { // 存数据至缓冲区
  Serial.readBytesUntil('#', inputKeyBuffer, 23);
  Serial.end();
  Serial.begin(9600);
}
bool checkData() { // 判断输入数据是否合法。 true = 合法
  if (
    ((checkDataBffer[0] == inputKeyBuffer[0]) && (checkDataBffer[1] == inputKeyBuffer[1])) &&
    (checkDataBffer[16] == inputKeyBuffer[16])
  ) {
    return (true);
  } else {
    return (false);
  }
}

void str2timedata() { // 读串口传来数据至缓存
  yearBuffer = str2byte(inputKeyBuffer[2], inputKeyBuffer[3]);
  monthBuffer = str2byte(inputKeyBuffer[4], inputKeyBuffer[5]);
  dateBuffer = str2byte(inputKeyBuffer[6], inputKeyBuffer[7]);
  hourBuffer = str2byte(inputKeyBuffer[8], inputKeyBuffer[9]);
  minuteBuffer = str2byte(inputKeyBuffer[10], inputKeyBuffer[11]);
  secondBuffer = str2byte(inputKeyBuffer[12], inputKeyBuffer[13]);
  DoWBuffer = str2byte(inputKeyBuffer[14], inputKeyBuffer[15]);
}

void setTime() { // 设置时钟模块寄存器
  Clock.setSecond(secondBuffer);
  Clock.setMinute(minuteBuffer);
  Clock.setHour(hourBuffer);
  Clock.setDate(dateBuffer);
  Clock.setMonth(monthBuffer);
  Clock.setYear(yearBuffer);
  Clock.setDoW(DoWBuffer);
  Serial.println("setOK");
}

byte str2byte(char L, char R) { // 字符转数字
  byte temp = (byte)((L - '0') * 10 + (R - '0'));
  return temp;
}

void clearBuffer() { // 清缓冲区
  int i = 0;
  for (int i = 0; i < inputStringLength ; i++)
    inputKeyBuffer[i] = (char)0;

}


//end获取串口数据处理并保存





5.MACOS端代码:

戳我戳我 

clone我clone我

6、使用说明:

把组装好的,通电的单片机连接MAC,同时运行时间同步程序。


7、存在的问题:

咱家完全不会协议栈编程,因此仅仅勉强写了个看起来没问题,实际上BUG泛滥的玩意。以前找的帮我画电路图的人挖洞逃跑了,没办法只好自己画了。因此大家不要期待电路图有完成的一天。我不想也不会把精力放在这方面,因为还有成堆的软件问题等着我去学呢。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值