/*---------------------------------------------------------------------*/ /* --- STC MCU Limited ------------------------------------------------*/ /* --- STC 1T Series MCU Demo Programme -------------------------------*/ /* --- Mobile: (86)13922805190 ----------------------------------------*/ /* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/ /* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/ /* --- Web: www.STCMCU.com --------------------------------------------*/ /* --- Web: www.STCMCUDATA.com ---------------------------------------*/ /* --- QQ: 800003751 -------------------------------------------------*/ /* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */ /*---------------------------------------------------------------------*/ #include "APP.h" #include "STC8A_GPIO.h" #include "STC8A_I2C.h" #include "STC8A_NVIC.h" #include "STC8A_Switch.h" /************* 功能说明 ************** 读写RTC, IC为PCF8563. 用STC的MCU的IO方式驱动8位数码管。 使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms. 8位数码管显示时间(小时-分钟-秒). 行列扫描按键键码为17~32. 按键只支持单键按下, 不支持多键同时按下, 那样将会有不可预知的结果. 键按下超过1秒后,将以10键/秒的速度提供重键输出. 用户只需要检测KeyCode是否非0来判断键是否按下. 调整时间键: 键码17: 小时+. 键码18: 小时-. 键码19: 分钟+. 键码20: 分钟-. 下载时, 选择时钟 24MHz (可以在配置文件"config.h"中修改). ******************************************/ //======================================================================== // 本地常量声明 //======================================================================== //======================================================================== // 本地变量声明 //======================================================================== //======================================================================== // 本地函数声明 //======================================================================== void IO_KeyScan(void); //50ms call void DisplayRTC(void); void ReadRTC(void); void WriteRTC(void); //======================================================================== // 外部函数和变量声明 //======================================================================== //======================================================================== // 函数: RTC_init // 描述: 用户初始化程序. // 参数: None. // 返回: None. // 版本: V1.0, 2020-09-25 //======================================================================== void RTC_init(void) { u8 i; I2C_InitTypeDef I2C_InitStructure; I2C_InitStructure.I2C_Mode = I2C_Mode_Master; //主从选择 I2C_Mode_Master, I2C_Mode_Slave I2C_InitStructure.I2C_Enable = ENABLE; //I2C功能使能, ENABLE, DISABLE I2C_InitStructure.I2C_MS_WDTA = DISABLE; //主机使能自动发送, ENABLE, DISABLE I2C_InitStructure.I2C_Speed = 16; //总线速度=Fosc/2/(Speed*2+4), 0~63 I2C_Init(&I2C_InitStructure); NVIC_I2C_Init(I2C_Mode_Master,DISABLE,Priority_0); //主从模式, I2C_Mode_Master, I2C_Mode_Slave; 中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3 P0_MODE_IO_PU(GPIO_Pin_All); //P0 设置为准双向口 P1_MODE_IO_PU(GPIO_Pin_4 | GPIO_Pin_5); //P1.4,P1.5 设置为准双向口 P6_MODE_IO_PU(GPIO_Pin_All); //P6 设置为准双向口 P7_MODE_IO_PU(GPIO_Pin_All); //P7 设置为准双向口 I2C_SW(I2C_P14_P15); //I2C_P14_P15,I2C_P24_P25,I2C_P33_P32 display_index = 0; for(i=0; i<8; i++) LED8[i] = 0x10; //上电消隐 ReadRTC(); F0 = 0; if(second >= 60) F0 = 1; //错误 if(minute >= 60) F0 = 1; //错误 if(hour >= 24) F0 = 1; //错误 if(F0) //有错误, 默认12:00:00 { second = 0; minute = 0; hour = 12; WriteRTC(); } DisplayRTC(); LED8[2] = DIS_; LED8[5] = DIS_; KeyHoldCnt = 0; //键按下计时 KeyCode = 0; //给用户使用的键码 IO_KeyState = 0; IO_KeyState1 = 0; IO_KeyHoldCnt = 0; cnt50ms = 0; } //======================================================================== // 函数: Sample_RTC // 描述: 用户应用程序. // 参数: None. // 返回: None. // 版本: V1.0, 2020-09-25 //======================================================================== void Sample_RTC(void) { DisplayScan(); if(++msecond >= 1000) //1秒到 { msecond = 0; ReadRTC(); DisplayRTC(); } if(++cnt50ms >= 50) //50ms扫描一次行列键盘 { cnt50ms = 0; IO_KeyScan(); } if(KeyCode != 0) //有键按下 { if(KeyCode == 17) //hour +1 { if(++hour >= 24) hour = 0; WriteRTC(); DisplayRTC(); } if(KeyCode == 18) //hour -1 { if(--hour >= 24) hour = 23; WriteRTC(); DisplayRTC(); } if(KeyCode == 19) //minute +1 { second = 0; if(++minute >= 60) minute = 0; WriteRTC(); DisplayRTC(); } if(KeyCode == 20) //minute -1 { second = 0; if(--minute >= 60) minute = 59; WriteRTC(); DisplayRTC(); } KeyCode = 0; } } //======================================================================== // 函数: DisplayRTC // 描述: 显示时钟函数. // 参数: None. // 返回: None. // 版本: V1.0, 2020-09-25 //======================================================================== void DisplayRTC(void) { if(hour >= 10) LED8[0] = hour / 10; else LED8[0] = DIS_BLACK; LED8[1] = hour % 10; LED8[2] = DIS_; LED8[3] = minute / 10; LED8[4] = minute % 10; LED8[6] = second / 10; LED8[7] = second % 10; } //======================================================================== // 函数: ReadRTC // 描述: 读RTC函数. // 参数: None. // 返回: None. // 版本: V1.0, 2020-09-25 //======================================================================== void ReadRTC(void) { u8 tmp[3]; I2C_ReadNbyte(2, tmp, 3); second = ((tmp[0] >> 4) & 0x07) * 10 + (tmp[0] & 0x0f); minute = ((tmp[1] >> 4) & 0x07) * 10 + (tmp[1] & 0x0f); hour = ((tmp[2] >> 4) & 0x03) * 10 + (tmp[2] & 0x0f); } //======================================================================== // 函数: WriteRTC // 描述: 写RTC函数. // 参数: None. // 返回: None. // 版本: V1.0, 2020-09-25 //======================================================================== void WriteRTC(void) { u8 tmp[3]; tmp[0] = ((second / 10) << 4) + (second % 10); tmp[1] = ((minute / 10) << 4) + (minute % 10); tmp[2] = ((hour / 10) << 4) + (hour % 10); I2C_WriteNbyte(2, tmp, 3); } /***************************************************** 行列键扫描程序 使用XY查找4x4键的方法,只能单键,速度快 Y P04 P05 P06 P07 | | | | X | | | | P00 ---- K00 ---- K01 ---- K02 ---- K03 ---- | | | | P01 ---- K04 ---- K05 ---- K06 ---- K07 ---- | | | | P02 ---- K08 ---- K09 ---- K10 ---- K11 ---- | | | | P03 ---- K12 ---- K13 ---- K14 ---- K15 ---- | | | | ******************************************************/ //======================================================================== // 函数: IO_KeyDelay // 描述: 按键扫描延迟程序. // 参数: None. // 返回: None. // 版本: V1.0, 2020-09-25 //======================================================================== void IO_KeyDelay(void) { u8 i; i = 60; while(--i) ; } //======================================================================== // 函数: IO_KeyScan // 描述: 按键扫描程序. // 参数: None. // 返回: None. // 版本: V1.0, 2020-09-25 //======================================================================== void IO_KeyScan(void) //50ms call { u8 j; j = IO_KeyState1; //保存上一次状态 P0 = 0xf0; //X低,读Y IO_KeyDelay(); IO_KeyState1 = P0 & 0xf0; P0 = 0x0f; //Y低,读X IO_KeyDelay(); IO_KeyState1 |= (P0 & 0x0f); IO_KeyState1 ^= 0xff; //取反 if(j == IO_KeyState1) //连续两次读相等 { j = IO_KeyState; IO_KeyState = IO_KeyState1; if(IO_KeyState != 0) //有键按下 { F0 = 0; if(j == 0) F0 = 1; //第一次按下 else if(j == IO_KeyState) { if(++IO_KeyHoldCnt >= 20) //1秒后重键 { IO_KeyHoldCnt = 18; F0 = 1; } } if(F0) { j = T_KeyTable[IO_KeyState >> 4]; if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0)) KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16; //计算键码,17~32 } } else IO_KeyHoldCnt = 0; } P0 = 0xff; }