[原创] 【R7F0C809】简易电子锁密码校验与时间显示功能已实现

wgsxsm   2015-11-15 22:28 楼主
接上贴:https://bbs.eeworld.com.cn/thread-476175-1-1.html在添加完AD按键和OLED显示功能的情况下,现在加入了RTC时钟显示和EEPROM存储电子锁密码的功能。 通过模拟IIC来实现,在一组IIC线上外挂一个PCF8563和一个AT24C02,通过设定PCF8563每秒一次的中断来更新时间; 通过对AT24C02进行数据的读取与存储来进行密码的管理。 ~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1.硬件部分 IIC_SCL--P02 IIC_SDA--P03 PCF_INT--P00 R7F0C809.jpg AT24C02.jpg AT24C02_PCB.jpg PCF8563.jpg PCF8563_PCB.jpg R7F0C809主控板通过杜邦线与各模块相连。 需要说明的是:PCF8563通过配置寄存器0E和0F来产生每秒钟进行INT pin一次中断, 由于模块电路忘记对该PIN进行加上拉电阻,软件里不得不配置该PIN脚P00为上拉输入。 P00.jpg 2.软件部分 贴上来部分代码并给予说明
  1. static void IIC_SW_IO_Config(void)
  2. {
  3. PMC0 &= 0xf3; /* P0.2&P0.3:Digital I/O */
  4. POM0 &= 0xf3; /* P0.2&P0.3:Normal output mode.*/
  5. P0 |= 0x0c; /* P0.2&P0.3:set 1*/
  6. PM0 &= 0xf3; /* P0.2&P0.3:Output mode */
  7. }
  8. void IIC_Init(void)
  9. {
  10. IIC_SW_IO_Config();
  11. }
更新INTC_Create函数,因为PCF_INF采用了外部中断方式.
  1. void INTC_Create(void)
  2. {
  3. PMK0 = 1U; /* disable INTP0 operation */
  4. PIF0 = 0U; /* clear INTP0 interrupt flag */
  5. PMK1 = 1U; /* disable INTP1 operation */
  6. PIF1 = 0U; /* clear INTP1 interrupt flag */
  7. PMK2 = 1U; /* disable INTP2 operation */
  8. PIF2 = 0U; /* clear INTP2 interrupt flag */
  9. PMK3 = 1U; /* disable INTP3 operation */
  10. PIF3 = 0U; /* clear INTP3 interrupt flag */
  11. PMK4 = 1U; /* disable INTP4 operation */
  12. PIF4 = 0U; /* clear INTP4 interrupt flag */
  13. PMK5 = 1U; /* disable INTP5 operation */
  14. PIF5 = 0U; /* clear INTP5 interrupt flag */
  15. /* Set INTP1/5 priority */
  16. PPR11 = 0U; //priority-->0
  17. PPR01 = 0U;
  18. PPR15 = 0U; //priority-->1
  19. PPR05 = 1U;
  20. EGN0 = 0x22U; //INTP1/5--Falling edge.
  21. EGP0 = 0x02U; //INTP1--Rising edge.
  22. }
另外说明的是,K1按键也即是P11-INTP1脚采用的是双边沿检测, 其功能是按下后,蜂鸣器叫,一直到松开按键后,蜂鸣器停止发声。 这样按键K1也即是起到了门铃作用。
  1. __interrupt void INTC1_Interrupt(void)
  2. {
  3. /* Waiting about 10ms for rejection */
  4. while (!TMIF00)
  5. {
  6. HALT(); /* Waiting of TM00 interrupt request */
  7. }
  8. TMIF00 = 0U; /* INTTM00 interrupt request clear */
  9. LED_Toggle();
  10. /* After 10ms or more from when the SW is turned ON */
  11. /* check the status of the SW again */
  12. if (P1.1==0) /* Is SW really ON ? */
  13. {
  14. BUZ_On();
  15. }
  16. else if (P1.1==1)
  17. {
  18. BUZ_Off();
  19. }
  20. PIF0 = 0U; /* INTP0 interrupt request clear */
  21. /* End user code. Do not edit comment generated here */
  22. }
PCF_INT PIN每秒产生一次中断,通过该中断告知设置的定时器到了,将更新时间标志位置位。
  1. __interrupt void INTC5_Interrupt(void)
  2. {
  3. if (P0.0==0)
  4. {
  5. time_Refresh=1;
  6. PCF8563_WriteAdress(CTRL_BUF2,0x01); //TF-->0,w to clear:timer flag is cleared
  7. }
  8. PIF5 = 0U; /* INTP5 interrupt request clear */
  9. }
为了得到更好的体验,将MCU的TAU0_Channel0配置为间隔时间为4ms的定时器,这样对模拟输入引脚的电压进行 6 次 A/D 采集,去掉最大、最小值并求平均。重复上述操作,如果两次获得的平均值相同,即确认当前按键。因此按键按下的确认时间为 4×6×2=48ms.此时的AD按键输入性能才能达到最佳。
  1. void TAU0_Create(void)
  2. {
  3. TAU0EN = 1U; /* supplies input clock */
  4. TPS0 |= 0x04U; /* 1.25MHz */
  5. /* Stop all channels */
  6. TT0 |= 0x0FU;
  7. /* Mask channel 0 interrupt */
  8. TMMK00 = 1U; /* disable INTTM00 interrupt */
  9. TMIF00 = 0U; /* clear INTTM00 interrupt flag */
  10. /* Set INTTM00 low priority */
  11. TMPR100 = 1U;
  12. TMPR000 = 1U;
  13. /* Channel 0 used as interval timer */
  14. TMR00H = 0x00U;
  15. TMR00L = 0x00U;
  16. /* 4ms interval compare value */
  17. TDR00H = 0x13U; //1250*4-1=4999
  18. TDR00L = 0x87U;
  19. TO0 &= 0x0EU;
  20. TOE0 &= 0x0EU;
  21. }
EEPROM操作部分在上电时会进行检测,是否为新的AT24C02,如果是,将对该新器件进行写入密码初始值(151122--作品最晚提交日期),并将给密码进行打包,包头为0x55,包尾为0xAA,以进行下次开机时读取判定。
  1. void EEReadPassword(void)
  2. {
  3. uint8_t i;
  4. for(i=0;i<8;i++)
  5. {
  6. EEBuffer[i]= AT24CXX_ReadOneByte(i);
  7. }
  8. /*The flag of valid password*/
  9. if(EEBuffer[0]==0x55 && EEBuffer[7]==0xAA)
  10. {
  11. NewDevice_Sign=0;
  12. for(i=0;i<8;i++)
  13. {
  14. PassWords[i]= EEBuffer[i];
  15. }
  16. }
  17. else
  18. {
  19. NewDevice_Sign=1;
  20. }
  21. }
  22. void EEWritePassword(void)
  23. {
  24. uint8_t i;
  25. for(i=0;i<8;i++)
  26. {
  27. AT24CXX_WriteOneByte( i, PassWords[i]);
  28. }
  29. }
AD按键操作处,处于实时进行检测,密码输入完毕后,以#为结尾进行通知进行校验,检测到第七位为#则进行比对密码,其余则认为密码无效,即便输入了正确密码;密码比对成功,则提示“密码正确”;否则,则表示密码错误。
  1. if(g_Last_AD_Key_Code != g_Live_AD_Key_Code) /* Current key update? */
  2. {
  3. g_Last_AD_Key_Code = g_Live_AD_Key_Code;
  4. if(g_Live_AD_Key_Code!=13) /*valid key*/
  5. {
  6. if(NoticeTimeDelay!=0) return;
  7. if(KeyWordShowPosition==6)
  8. {
  9. if(g_Live_AD_Key_Code==12)
  10. {
  11. /*compare*/
  12. if( KeyWords[0]==PassWords[1] && KeyWords[1]== PassWords[2]
  13. &&KeyWords[2]==PassWords[3] && KeyWords[3]==PassWords[4]
  14. &&KeyWords[4]==PassWords[5] && KeyWords[5]==PassWords[6] ) /* correct key */
  15. {
  16. NoticeKeywordStatus(STATUS_OK);
  17. /*
  18. OPEN THE DOOR!
  19. */
  20. BUZ_Call_Long(1500); /*1.5s*/
  21. }
  22. else /* error key */
  23. {
  24. NoticeKeywordStatus(STATUS_ERROR);
  25. BUZ_Call(2); /*call 2 times*/
  26. }
  27. NoticeTimeDelay=500;
  28. }
  29. else
  30. {
  31. /* invalid key */
  32. NoticeKeywordStatus(STATUS_INVALID);
  33. NoticeTimeDelay=300;
  34. BUZ_Call(2); /*call 2 times*/
  35. }
  36. KeyWordShowPosition=0;
  37. }
  38. else
  39. {
  40. KeyWords[KeyWordShowPosition]=g_Live_AD_Key_Code;
  41. KeyValue_Display(40+KeyWordShowPosition*8,2,g_Live_AD_Key_Code);
  42. KeyWordShowPosition++;
  43. }
  44. }
  45. }
由于硬件上AD按键没有给出各按键的标识“123456789*0#”,因此在OLED上显示出按键值来进行录像,否则无法观看处效果。 3.操作演示 本帖最后由 wgsxsm 于 2015-11-15 22:47 编辑

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复