 |
【单片机程序】 #include <reg52.h> #include <intrins.h>
#define BCD(n) (((n) / 10 << 4) + (n) % 10) #define DEBCD(n) ((((n) & 0xf0) >> 4) * 10 + ((n) & 0x0f))
sbit SCLK = P1^0; sbit DATA = P1^1; sbit RST = P1^2;
sbit RS = P2^0; sbit RW = P2^1; sbit E = P2^2; sbit BF = P0^7;
sbit K5 = P1^4; // 写入数据的按键 sbit K6 = P1^5; // 清除数据的按键 sbit K7 = P1^6; // AM/PM切换键 sbit K8 = P1^7; // 小时调整键
bit load_flag = 0; char comm_buf[32]; int comm_i = -1; unsigned char comm_cmd = 0;
void delay(unsigned int n) { unsigned char i; while (n--) for (i = 0; i < 115; i++); }
void Write1302(unsigned char dat) { unsigned char i; for (i = 0; i < 8; i++) { DATA = dat & 1; dat >>= 1; SCLK = 1; _nop_(); _nop_(); SCLK = 0; } }
void WriteSet1302(unsigned char addr, unsigned char dat) { RST = 0; SCLK = 0; RST = 1; Write1302(addr & 0xfe); Write1302(dat); RST = 0; }
unsigned char Read1302(void) { unsigned char dat = 0; unsigned char i; DATA = 1; for (i = 0; i < 8; i++) { _nop_(); _nop_(); dat >>= 1; if (DATA) dat |= 0x80; SCLK = 1; _nop_(); _nop_(); SCLK = 0; } return dat; }
unsigned char ReadSet1302(unsigned char addr) { unsigned char dat; RST = 0; // 开机时RST默认为1,所以必须先置0防止第一次读的时候出错 SCLK = 0; RST = 1; Write1302(addr | 1); dat = Read1302(); RST = 0; return dat; }
void LCDBusyTest(void) { RS = 0; RW = 1; E = 1; _nop_(); _nop_(); BF = 1; while (BF); E = 0; _nop_(); }
void LCDWriteCmd(unsigned char cmd) { LCDBusyTest(); RS = 0; RW = 0; E = 1; P0 = cmd; _nop_(); E = 0; _nop_(); }
void LCDWriteData(unsigned char dat) { LCDBusyTest(); RS = 1; RW = 0; P0 = dat; E = 1; _nop_(); _nop_(); E = 0; _nop_(); }
void LCDWriteString(char *s) { while (*s) LCDWriteData(*s++); }
/*void LCDWriteNumber(unsigned char num) { char str[4]; str[0] = num / 100 + '0'; str[1] = num % 100 / 10 + '0'; str[2] = num % 10 + '0'; str[3] = '\0'; if (str[0] == '0') { if (str[1] == '0') LCDWriteString(str + 2); else LCDWriteString(str + 1); } else LCDWriteString(str); }*/
void LCDInit(void) { delay(40); LCDWriteCmd(0x30); delay(10); LCDWriteCmd(0x30); delay(10); LCDWriteCmd(0x0c); delay(1); LCDWriteCmd(0x01); }
void SaveData(void) { char str[] = "Keyword:abcd45efThat's a string"; char i; WriteSet1302(0x8e, 0); for (i = 0; str[i] != '\0'; i++) WriteSet1302(0xc0 + i * 2, str[i]); WriteSet1302(0x8e, 0x80); }
void ClearData(void) { char i; WriteSet1302(0x8e, 0); for (i = 0; i < 31; i++) WriteSet1302(0xc0 + i * 2, '*'); WriteSet1302(0x8e, 0x80); }
void LoadData(void) { unsigned char i, dat; bit end = 0; LCDWriteCmd(0x80); for (i = 0; i < 31; i++) { if (i == 16) LCDWriteCmd(0x90); if (!end) { dat = ReadSet1302(0xc1 + i * 2); if (dat == '\0') { end = 1; dat = ' '; } } LCDWriteData(dat); } LCDWriteData(' '); }
void DisplayNum(unsigned char num) { num = DEBCD(num); LCDWriteData('0' + num % 100 / 10); LCDWriteData('0' + num % 10); }
void DisplayTime(void) { char list[] = {0xc8, 0xd5, 0xd2, 0xbb, 0xb6, 0xfe, 0xc8, 0xfd, 0xcb, 0xc4, 0xce, 0xe5, 0xc1, 0xf9, 0x00}; unsigned char tmp = ReadSet1302(0x81); char pm = 2; unsigned char hour = ReadSet1302(0x85); static unsigned char last_sec = -1; static unsigned char last_hour = -1; if (tmp == last_sec && hour == last_hour) return; last_sec = tmp; last_hour = hour; LCDWriteCmd(0x88); LCDWriteString("20"); DisplayNum(ReadSet1302(0x8d)); LCDWriteString("年"); DisplayNum(ReadSet1302(0x89)); LCDWriteString("月"); DisplayNum(ReadSet1302(0x87)); LCDWriteString("日"); LCDWriteCmd(0x98); if (hour & 0x80) { if (hour & 0x20) pm = 1; else pm = 0; hour &= 0x1f; } DisplayNum(hour); LCDWriteData(':'); DisplayNum(ReadSet1302(0x83)); LCDWriteData(':'); DisplayNum(tmp); if (pm == 0) LCDWriteString("AM"); else if (pm == 1) LCDWriteString("PM"); else LCDWriteString(" "); LCDWriteString("星期"); tmp = (ReadSet1302(0x8b) & 0x07); if (tmp == 7) tmp = 0; LCDWriteData(list[2 * tmp]); LCDWriteData(list[2 * tmp + 1]); }
void ChangeHour(void) { unsigned char dat = ReadSet1302(0x85); unsigned char hour; if (dat & 0x80) { // 12 -> 24 hour = dat & 0x1f; hour = DEBCD(hour); if (dat & 0x20) { if (hour != 12) hour += 12; } else { if (hour == 12) hour = 0; // 12 AM } dat = BCD(hour); } else { // 24 -> 12 hour = DEBCD(dat); dat = 0x80; if (hour > 12) { hour -= 12; dat |= 0x20 | BCD(hour); } else if (hour == 0) dat |= BCD(12); // 12 AM else { dat |= BCD(hour); if (hour == 12) dat |= 0x20; // 12 PM } } WriteSet1302(0x8e, 0); WriteSet1302(0x84, dat); WriteSet1302(0x8e, 0x80); }
void IncrementHour(void) { unsigned char dat = ReadSet1302(0x85); unsigned char hour; if (dat & 0x80) { hour = dat & 0x1f; hour = DEBCD(hour); dat &= 0xe0; if (hour == 12) // 12 AM/PM -> 1 AM/PM hour = 1; else { hour++; if (hour == 12) dat ^= 0x20; // 11 AM/PM -> 12 PM/AM } dat |= BCD(hour); } else { hour = DEBCD(dat); if (hour == 23) hour = 0; else hour++; dat = BCD(hour); } WriteSet1302(0x8e, 0); WriteSet1302(0x84, dat); WriteSet1302(0x8e, 0x80); }
int main(void) { LCDInit(); LoadData(); if (ReadSet1302(0x81) & 0x80) { WriteSet1302(0x8e, 0); WriteSet1302(0x8c, BCD(16)); WriteSet1302(0x8a, BCD(1)); WriteSet1302(0x88, BCD(7)); WriteSet1302(0x86, BCD(11)); WriteSet1302(0x84, BCD(23)); WriteSet1302(0x82, BCD(8)); WriteSet1302(0x80, BCD(40)); WriteSet1302(0x8e, 0x80); } SCON = 0x50; TMOD = 0x20; TH1 = TL1 = 0xfd; TR1 = 1; ES = 1; EA = 1; while (1) { DisplayTime(); if (load_flag) { load_flag = 0; LoadData(); } if (!K5) { delay(10); if (!K5) { SaveData(); LoadData(); while (!K5); } } if (!K6) { delay(10); if (!K6) { ClearData(); LoadData(); while (!K6); } } if (!K7) { delay(10); if (!K7) { ChangeHour(); while (!K7); } } if (!K8) { delay(10); if (!K8) { IncrementHour(); while (!K8); } } } }
void send(unsigned char dat) { SBUF = dat; while (!TI); TI = 0; }
void send1302data(void) { char i; for (i = 0; i < 31; i++) send(ReadSet1302(0xc1 + i * 2)); }
void sendtime(void) { unsigned char i; for (i = 0x81; i <= 0x8f; i += 2) send(ReadSet1302(i)); }
void es(void) interrupt 4 { unsigned char i, dat; if (RI) { dat = SBUF; if (comm_i >= 0 && comm_i < sizeof(comm_buf)) { comm_buf[comm_i] = dat; if (comm_cmd == 0x02 && dat == '\0') { comm_i = -1; WriteSet1302(0x8e, 0); for (i = 0; i < 31; i++) { WriteSet1302(0xc0 + i * 2, comm_buf[i]); if (comm_buf[i] == '\0') break; } WriteSet1302(0x8e, 0x80); load_flag = 1; send(0x80 | i); // 应答信号: 最高位始终为1,其他位表示收到的字符串长度 } else if (comm_cmd == 0x04 && comm_i >= 7) { comm_i = -1; WriteSet1302(0x8e, 0); WriteSet1302(0x80, 0x80); // 停止走时 WriteSet1302(0x80, comm_buf[0]); WriteSet1302(0x82, comm_buf[1]); if (ReadSet1302(0x85) & 0x80) WriteSet1302(0x84, comm_buf[3]); else WriteSet1302(0x84, comm_buf[2]); WriteSet1302(0x86, comm_buf[4]); WriteSet1302(0x88, comm_buf[5]); WriteSet1302(0x8a, comm_buf[6]); WriteSet1302(0x8c, comm_buf[7]); WriteSet1302(0x8e, 0x80); send(0x80); } else comm_i++; } else { comm_cmd = dat; switch (dat) { case 0x01: ChangeHour(); i = ReadSet1302(0x85); if (i & 0x80) send(0x81); else send(0x80); break; case 0x02: case 0x04: comm_i = 0; break; case 0x03: send(0x20); send1302data(); break; case 0x05: send(0x20); sendtime(); break; default: send(0xff); } } RI = 0; } }
|
 |
【电脑端程序(使用C语言编写)】 #include <tchar.h> #include <time.h> #include <Windows.h> #include <CommCtrl.h> #include <strsafe.h> #include "resource.h"
#define BCD(n) (((n) / 10 << 4) + (n) % 10) #define DEBCD(n) ((((n) & 0xf0) >> 4) * 10 + ((n) & 0x0f))
#pragma comment(lib, "comctl32.lib") #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' language='*' publicKeyToken='6595b64144ccf1df'\"")
HANDLE hCommPort; HWND hwndMain; HWND hwndEdit1, hwndEdit2;
void OpenPort(void) { COMMTIMEOUTS tout; DCB dcb; hCommPort = CreateFile(TEXT("\\\\.\\COM10"), GENERIC_READ | GENERIC_WRITE, (DWORD)NULL, NULL, OPEN_EXISTING, (DWORD)NULL, NULL); if (hCommPort == INVALID_HANDLE_VALUE) { MessageBox(hwndMain, TEXT("打开串口失败"), TEXT("错误"), MB_ICONERROR); EndDialog(hwndMain, 0); }
// 指定波特率 ZeroMemory(&dcb, sizeof(dcb)); dcb.DCBlength = sizeof(DCB); GetCommState(hCommPort, &dcb); dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; SetCommState(hCommPort, &dcb);
// 指定超时时间 ZeroMemory(&tout, sizeof(tout)); tout.ReadTotalTimeoutConstant = 1000; SetCommTimeouts(hCommPort, &tout); }
void DisplayTime(LPSTR buf) { int hour, wday; TCHAR h[4]; LPTSTR list = TEXT("日一二三四五六"); TCHAR str[100]; if (buf[3] & 0x80) { if (buf[3] & 0x20) h[0] = 'P'; else h[0] = 'A'; h[1] = 'M'; h[2] = ' '; h[3] = '\0';
hour = buf[3] & 0x1f; hour = DEBCD(hour); } else { h[0] = '\0'; hour = DEBCD(buf[3]); }
wday = buf[6] & 0x07; if (wday == 7) wday = 0;
StringCbPrintf(str, sizeof(str), TEXT("20%02d年%02d月%02d日\r\n%02d:%02d:%02d %s星期%c"), DEBCD(buf[7]), DEBCD(buf[5]), DEBCD(buf[4]), hour, DEBCD(buf[2]), DEBCD(buf[1]), h, list[wday]); SetWindowText(hwndEdit1, str); }
void SendTime(void) { BYTE buf[9]; DWORD dwSize; time_t t = time(NULL); struct tm info; localtime_s(&info, &t); buf[0] = 0x04; buf[1] = BCD(info.tm_sec); buf[2] = BCD(info.tm_min); buf[3] = BCD(info.tm_hour); buf[5] = BCD(info.tm_mday); buf[6] = BCD(info.tm_mon + 1); if (info.tm_wday == 0) buf[7] = 7; else buf[7] = info.tm_wday; buf[8] = BCD(info.tm_year - 100);
buf[4] = 0x80; if (info.tm_hour > 12) buf[4] |= 0x20 | BCD(info.tm_hour - 12); else if (info.tm_hour == 0) buf[4] |= BCD(12); else { buf[4] |= buf[3]; if (info.tm_hour == 12) buf[4] |= 0x20; }
WriteFile(hCommPort, buf, sizeof(buf), &dwSize, NULL); ReadFile(hCommPort, buf, 1, &dwSize, NULL); if (buf[0] & 0x80) SetWindowText(hwndEdit1, TEXT("更新时间成功")); else SetWindowText(hwndEdit1, TEXT("更新时间失败")); }
INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { char buf[101]; DWORD dwSize; int i; int wmId; WCHAR str[100];
switch (uMsg) { case WM_INITDIALOG: hwndMain = hWnd; hwndEdit1 = GetDlgItem(hWnd, IDC_EDIT1); hwndEdit2 = GetDlgItem(hWnd, IDC_EDIT2); SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(NULL, IDI_APPLICATION)); OpenPort(); break; case WM_COMMAND: wmId = LOWORD(wParam); switch (wmId) { case IDOK: GetWindowTextW(hwndEdit2, str, _countof(str)); // 获取用户输入的内容(UTF-16) ZeroMemory(buf, sizeof(buf)); WideCharToMultiByte(20936, (DWORD)NULL, str, wcslen(str), buf + 1, sizeof(buf) - 1, NULL, NULL); // 将UTF-16编码转换为液晶使用的GB2312编码(第一个参数指定) buf[0] = 0x02; // 要发送的第一个字节为控制指令
// 计算要发送的数据量 dwSize = strlen(buf); if (dwSize < 32) dwSize++; // 发送小于32字节的内容时, 必须以\0结束 else if (dwSize > 32) { MessageBox(hwndMain, TEXT("您输入的内容太长, 无法保存"), TEXT("提示"), MB_ICONWARNING); break; }
// 检查输入的字符串能否在液晶上成功显示,例如"a中"就不能正常显示 for (i = 1; i < (int)dwSize; i += 2) { if (!(buf[i] & 0x80) && (buf[i + 1] & 0x80)) { MessageBox(hwndMain, TEXT("您输入的内容无法在液晶上正确显示\n请重新输入!"), TEXT("提示"), MB_ICONWARNING); return FALSE; } }
WriteFile(hCommPort, buf, strlen(buf) + 1, &dwSize, NULL); ReadFile(hCommPort, buf, 1, &dwSize, NULL); if (buf[0] & 0x80) { StringCbPrintf(str, sizeof(str), TEXT("成功写入%d个字符"), buf[0] & 0x7f); MessageBox(hwndMain, str, TEXT("提示"), MB_ICONINFORMATION); } else MessageBox(hwndMain, TEXT("写入数据失败"), TEXT("提示"), MB_ICONWARNING); // 若收到的数据最高位不是1, 则表明写入失败 break; case IDCANCEL: CloseHandle(hCommPort); EndDialog(hWnd, wmId); break; case IDC_BUTTON1: buf[0] = 0x03; WriteFile(hCommPort, buf, 1, &dwSize, NULL); ReadFile(hCommPort, buf, _countof(buf), &dwSize, NULL); if (buf[0] != 0x20) { MessageBox(hwndMain, TEXT("读取数据失败"), TEXT("提示"), MB_ICONWARNING); break; } buf[dwSize] = '\0'; for (i = 1; i < (int)dwSize; i++) { if (buf[i] == '\0') buf[i] = ' '; } ZeroMemory(str, sizeof(str)); MultiByteToWideChar(20936, (DWORD)NULL, buf + 1, strlen(buf + 1), str, _countof(str)); SetWindowTextW(hwndEdit1, str); break; case IDC_BUTTON2: buf[0] = 0x05; WriteFile(hCommPort, buf, 1, &dwSize, NULL); ReadFile(hCommPort, buf, _countof(buf), &dwSize, NULL); if (buf[0] != 0x20) { SetWindowText(hwndEdit1, TEXT("读取时间失败")); break; } DisplayTime(buf); break; case IDC_BUTTON3: SendTime(); break; case IDC_BUTTON4: buf[0] = 0x01; WriteFile(hCommPort, buf, 1, &dwSize, NULL); ReadFile(hCommPort, buf, _countof(buf), &dwSize, NULL); if (buf[0] & 0x80) { if (buf[0] & 1) SetWindowText(hwndEdit1, TEXT("成功切换为12小时制")); else SetWindowText(hwndEdit1, TEXT("成功切换为24小时制")); } else SetWindowText(hwndEdit1, TEXT("切换失败")); break; } break; } return FALSE; }
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { InitCommonControls(); DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc); return 0; }
|