今天玩了一下最近很火的Caht GPT
要求寫一個 “1602屏 PCF8563ic 三個按鍵 的51單片機萬年歷的C語言代碼”
然后就給了我一段下面的代碼,各位看官看看,純屬娛樂!蠻有意思的。
#include <reg51.h>
#include <intrins.h>
sbit LCD_RS = P2^0; // LCD_RS引腳
sbit LCD_RW = P2^1; // LCD_RW引腳
sbit LCD_E = P2^2; // LCD_E引腳
sbit SDA = P1^1; // I2C數據線
sbit SCL = P1^0; // I2C時鐘線
sbit KEY_UP = P3^2; // 上鍵
sbit KEY_DOWN = P3^3; // 下鍵
sbit KEY_SET = P3^4; // 設置鍵
typedef unsigned char uint8_t; // 無符號8位整型數據類型
typedef unsigned int uint16_t; // 無符號16位整型數據類型
void Delay(uint16_t i); // 延時函數
void WriteCmd(uint8_t cmd); // 寫指令到LCD函數
void WriteData(uint8_t dat); // 寫數據到LCD函數
void LCD_Init(); // LCD初始化函數
void LCD_ShowString(uint8_t x, uint8_t y, uint8_t* str); // LCD顯示字符串函數
void LCD_ShowTime(); // LCD顯示時間函數
void LCD_ShowDate(); // LCD顯示日期函數
void PCF8563_Write(uint8_t addr, uint8_t dat); // 寫PCF8563芯片寄存器函數
uint8_t PCF8563_Read(uint8_t addr); // 讀PCF8563芯片寄存器函數
void ReadTime(); // 讀取當前時間函數
void SetTime(); // 設置時間函數
uint8_t Key_Scan(); // 按鍵掃描函數
void AdjustTime(); // 調整時間函數
uint8_t sec, min, hour, day, week, month, year; // 時間變量定義
void main()
{
LCD_Init(); // LCD初始化
while(1){
ReadTime(); // 讀取當前時間
LCD_ShowTime(); // 顯示時間
LCD_ShowDate(); // 顯示日期
Delay(1000); // 延時1s
}
}
void Delay(uint16_t i) // 延時函數
{
while(i--);
}
void WriteCmd(uint8_t cmd) // 寫指令到LCD函數
{
LCD_RS = 0; // 設置LCD_RS引腳為0,表示傳輸的是指令
LCD_RW = 0; // 設置LCD_RW引腳為0,表示寫操作
P0 = cmd; // 設置P0口輸出值為指令
LCD_E = 1; // 設置LCD_E引腳為1,表示開始傳輸數據
_nop_(); // 等待一段時間
_nop_();
LCD_E = 0; // 設置LCD_E引腳為0,表示數據傳輸結束
}
void WriteData(uint8_t dat) // 寫數據到LCD函數
{
LCD_RS = 1; // 設置LCD_RS引腳為1,表示傳輸的是數據
LCD_RW = 0; // 設置LCD_RW引腳為0,表示寫操作
P0 = dat; // 設置P0口輸出值為數據
LCD_E = 1; // 設置LCD_E引腳為1,表示開始傳輸數據
_nop_(); // 等待一段時間
_nop_();
LCD_E = 0; // 設置LCD_E引腳為0,表示數據傳輸結束
}
void LCD_Init() // LCD初始化函數
{
Delay(1000); // 延時等待LCD初始化完成
WriteCmd(0x38); // 初始化LCD顯示模式
WriteCmd(0x0c); // 開啟LCD顯示,并設置光標不可見
WriteCmd(0x06); // 光標右移,字符不動
WriteCmd(0x01); // 清屏
}
void LCD_ShowString(uint8_t x, uint8_t y, uint8_t* str) // LCD顯示字符串函數
{
uint8_t i;
if(y == 0) WriteCmd(0x80 + x); // 如果y為0,則設置光標在第一行的第x個位置
else WriteCmd(0xc0 + x); // 如果y為1,則設置光標在第二行的第x個位置
for(i=0; str[i]!='\0'; i++){ // 逐個字符顯示到LCD上
WriteData(str[i]);
}
}
void LCD_ShowTime() // LCD顯示時間函數
{
LCD_ShowString(0, 0, "Time: "); // 在第一行第一個字符顯示"Time: "
WriteData(hour/10+'0'); // 顯示小時十位數
WriteData(hour%10+'0'); // 顯示小時個位數
WriteData(':'); // 顯示冒號
WriteData(min/10+'0'); // 顯示分鐘十位數
WriteData(min%10+'0'); // 顯示分鐘個位數
WriteData(':'); // 顯示冒號
WriteData(sec/10+'0'); // 顯示秒鐘十位數
WriteData(sec%10+'0'); // 顯示秒鐘個位數
}
void LCD_ShowDate() // LCD顯示日期函數
{
uint8_t buf[16];
sprintf(buf, "%04d-%02d-%02d", year+2000, month, day); // 將年、月、日格式化為字符串
LCD_ShowString(0, 1, buf); // 在第二行顯示日期
}
void PCF8563_Write(uint8_t addr, uint8_t dat) // 寫PCF8563芯片寄存器函數
{
Start_I2C(); // 啟動I2C總線
Write_I2C(0xa2); // 發送寫地址
Write_I2C(addr); // 發送寄存器地址
Write_I2C(dat); // 發送數據
Stop_I2C(); // 停止I2C總線
}
uint8_t PCF8563_Read(uint8_t addr) // 讀PCF8563芯片寄存器函數
{
uint8_t dat;
Start_I2C(); // 啟動I2C總線
Write_I2C(0xa2); // 發送寫地址
Write_I2C(addr); // 發送寄存器地址
Start_I2C(); // 啟動I2C總線
Write_I2C(0xa3); // 發送讀地址
dat = Read_I2C(); // 讀取數據
NoAck_I2C(); // 發送非應答信號
Stop_I2C(); // 停止I2C總線
return dat; // 返回讀到的數據
}
void ReadTime() // 讀取當前時間函數
{
sec = bcd2hex(PCF8563_Read(0x02) & 0x7f); // 讀取秒,并將轉換后的十進制數賦值給sec變量
min = bcd2hex(PCF8563_Read(0x03) & 0x7f); // 讀取分,并將轉換后的十進制數賦值給min變量
hour = bcd2hex(PCF8563_Read(0x04) & 0x3f); // 讀取小時,并將轉換后的十進制數賦值給hour變量
day = bcd2hex(PCF8563_Read(0x05) & 0x3f); // 讀取日,并將轉換后的十進制數賦值給day變量
week = bcd2hex(PCF8563_Read(0x06) & 0x07); // 讀取周,并將轉換后的十進制數賦值給week變量
month = bcd2hex(PCF8563_Read(0x07) & 0x1f); // 讀取月,并將轉換后的十進制數賦值給month變量
year = bcd2hex(PCF8563_Read(0x08)); // 讀取年,并將轉換后的十進制數賦值給year變量
}
void SetTime() // 設置時間函數
{
PCF8563_Write(0x02, hex2bcd(sec)); // 寫入秒
PCF8563_Write(0x03, hex2bcd(min)); // 寫入分
PCF8563_Write(0x04, hex2bcd(hour)); // 寫入小時
PCF8563_Write(0x05, hex2bcd(day)); // 寫入日
PCF8563_Write(0x06, hex2bcd(week)); // 寫入周
PCF8563_Write(0x07, hex2bcd(month)); // 寫入月
PCF8563_Write(0x08, hex2bcd(year)); // 寫入年
}
uint8_t Key_Scan() // 按鍵掃描函數
{
uint8_t key = 0xff; // 初始化按鍵值為無效值
if(KEY_UP == 0){ // 如果檢測到上鍵按下
Delay(10); // 延時一段時間
if(KEY_UP == 0) key = KEY_UP; // 如果還是檢測到上鍵按下,則將按鍵值設置為KEY_UP
}
if(KEY_DOWN == 0){ // 如果檢測到下鍵按下
Delay(10); // 延時一段時間
if(KEY_DOWN == 0) key = KEY_DOWN; // 如果還是檢測到下鍵按下,則將按鍵值設置為KEY_DOWN
}
if(KEY_SET == 0){ // 如果檢測到設置鍵
|