3735|1

940

帖子

0

TA的资源

纯净的硅(高级)

楼主
 

【R7F0C809】加入蜂鸣器和AD按键,通过OLED显示按键值 [复制链接]

本帖最后由 wgsxsm 于 2015-10-28 23:44 编辑

离交作业的日子越来越近,最近刚好也空闲了一些,赶紧补一下,要不然真的要烂尾了。当时申请板子的理由是做一个简易的门禁系统,按部就班,功能要一点点加入进来了。
这两天加入了如下的AD按键模块和用来提醒解锁成功的蜂鸣器模块。
接下来可能要加入EEPROM用来存储密码,时间充足或者加入无线(蓝牙)和RTC时钟等等。
~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.硬件部分
最近花了半天的时间做了下面的这个硬件,按键码与下图的编码一一对应:

实物图与硬件电路如下,AD测量使用的前面帖子里提到的P07/ANI0,但是要割断板子上的S4跳线处

加之之前焊接的无源蜂鸣器模块,实物图以及电路图如下,蜂鸣器引脚为P40,因为该引脚刚好有蜂鸣器输出控制功能。
顺便提一下,具有蜂鸣器输出控制功能的还有一个P10口(被OLED占用了)。


2.软件部分
AD按键部分主要还是移植应用笔记中的:R01AN2007CC0110-A/D 按键输入配合 4 位 8 段数码管显示部分代码。
  1. const uint16_t  AD_Key_Data[13] = {
  2.     983,        /* 13/13*1023=1023 */
  3.     904,        /* 12/13*1023=944 */
  4.     825,        /* 11/13*1023=865 */
  5.     747,        /* 10/13*1023=786 */
  6.     668,        /* 9/13*1023=708 */
  7.     589,        /* 8/13*1023=629 */
  8.     511,        /* 7/13*1023=550 */
  9.     432,        /* 6/13*1023=472 */
  10.     353,        /* 5/13*1023=393 */
  11.     275,        /* 4/13*1023=314 */
  12.     196,        /* 3/13*1023=236 */
  13.     117,         /* 2/13*1023=157 */
  14.     39          /* 1/13*1023=78 */
  15. };
复制代码

static        void AD_Init(void)
{
    ADCEN = 1;              /* SFR used by A/D converter can be read/written */
        
    ADM0 = 0x00U;   /* disable AD conversion and clear ADM0 register */
    ADMK = 1U;      /* disable INTAD interrupt */
    ADIF = 0U;      /* clear INTAD interrupt flag */
    /* Set INTAD low priority */
    ADPR1 = 1U;
    ADPR0 = 1U;        
        
    ADM0 = 0;               /* Select Mode, fCLK/8 */
    ADM2 = 0;               /* 10-bit resolution */
    ADS = 0;                /* ANI0 */
}

void ADKey_Init(void)
{
        ADKey_IO_Init();
        AD_Init();
}


static        void AD_In(void)
{
    uint16_t i, ADValue;
    static uint16_t s_ADCnt=0;          /* A/D conversion counter */
    static uint16_t s_AD_Sum;           /* Summation of A/D conversion results */
    static uint16_t s_AD_Max;           /* Maximum value of A/D conversion result */
    static uint16_t s_AD_Min;           /* Minimum value of A/D conversion result */

    ADCE = 1;
    for(i = 0; i < 10; i++);            /* 0.1us waiting is needed */
    ADCS = 1;
    for(i = 0; i < 3; i++);

    /* Waiting A/D conversion */
    while(ADCS != 0);                   /* A/D conversion completed? */
    ADValue = (((uint16_t)(ADCRL >> 6)) | ((uint16_t)ADCRH << 2));

    /* Refresh a max and min ad value */
    if (s_ADCnt == 0)                   /* If it is the first conversion */
    {
        s_AD_Max = ADValue;             /* Saves the maximum value */
        s_AD_Min = ADValue;             /* Saves the minimum value */
    }
    else
    {
        if (ADValue > s_AD_Max)
            s_AD_Max = ADValue;         /* Renews the maximum value */
        if (ADValue < s_AD_Min)
            s_AD_Min = ADValue;         /* Renews the minimum value */
    }

    /* Up a count of ad sampling count */
    s_ADCnt += 1;                       /* Conversion counter +1 */
    s_AD_Sum += ADValue;                /* Adds A/D conversion result */

    /* Set a fixed  ad value */
    if (s_ADCnt == 6)                   /* If converted counter is 6 */
    {
        s_ADCnt = 0;                    /* Clears A/D conversion counter */
        s_AD_Sum -= s_AD_Max;           /* Omits the maximum value */
        s_AD_Sum -= s_AD_Min;           /* Omits the minimum value */
        g_AD_Fix = s_AD_Sum >> 2;       /* A/D value fixed */
        s_AD_Sum = 0;                   /* Clears summation data */
        g_Flag_AD_Fix = 1;              /* Sets A/D value fixed flag */
    }
}


static        void AD_Key_In(void)
{
    uint8_t i;
    static uint8_t  s_Last_AD_Key;      /* Fixed key code last time */

    /* Check a fix of ad data */
    if (g_Flag_AD_Fix == 1)             /* A/D value fixed ? */
    {
        g_Flag_AD_Fix = 0;              /* A/D value fixed flag off */
        /* Decode ad-value to ad-keycode */
        for(i = 0;i < 13 ;i++)
        {
            if (g_AD_Fix >= AD_Key_Data)
                break;
        }
        /* Check the last key data */
        if (s_Last_AD_Key == i)         /* Is it the same key as the last one ? */
            g_AD_Key_Code = i;          /* g_AD_Key_Code fixed */
        else
            s_Last_AD_Key = i;          /* Save the key code as the last one */
    }
}


static        void Key_Process(void)
{
    if(g_Last_AD_Key_Code != g_AD_Key_Code)     /* Current key update? */
    {
        switch(g_AD_Key_Code)
        {
            case 1:
                                OLED_DrawChar1608(0,4,'1');
                break;
            case 2:
                                OLED_DrawChar1608(0,4,'2');
                break;
            case 3:
                                OLED_DrawChar1608(0,4,'3');
                break;
            case 4:
                                OLED_DrawChar1608(0,4,'4');
                break;
            case 5:
                                OLED_DrawChar1608(0,4,'5');
                break;
            case 6:
                                OLED_DrawChar1608(0,4,'6');
                break;
            case 7:
                                OLED_DrawChar1608(0,4,'7');
                break;
            case 8:
                                OLED_DrawChar1608(0,4,'8');
                break;
            case 9:
                                OLED_DrawChar1608(0,4,'9');
                break;
            case 10:
                                OLED_DrawChar1608(0,4,'*');
                break;
            case 11:
                                OLED_DrawChar1608(0,4,'0');
                break;
            case 12:
                                OLED_DrawChar1608(0,4,'#');
                break;
            default:
                break;
        }
        g_Last_AD_Key_Code = g_AD_Key_Code;
    }
}


void Key_Handle(void)
{        
    AD_In();                /* Gets A/D fixed value */
    AD_Key_In();            /* Confirms A/D key code */
    Key_Process();          /* Inputted key function handle */
}


蜂鸣器部分主要是根据用户手册:第8章--时钟输出 / 蜂鸣器输出控制电路进行一步步设置
但是值得说明的是,仿真时,用到了P40口,所以为了使蜂鸣器发声不受影响的话还是需要拔掉仿真器的.
蜂鸣器的频率曲线如下,因此为了使发声更大,要选择在4KHz附近值。
而P40作为 蜂鸣器输出控制功能时,其输出时钟最接近于4KHz的值为4.88KHz:

  1. void BUZ_Init(void)
  2. {
  3.     P4 &= 0xfe;         /* P40 bit set 0*/   
  4.     PM4 &= 0xfe;        /* Output mode */        
  5.         PIOR |= 0x01;                /* PCLBUZ0 Sel P4.0  */

  6. //        PMC1 &= 0xfe;
  7. //  P1 &= 0xfe;         /* P10 bit set 0*/   
  8. //  PM1 &= 0xfe;        /* Output mode */
  9. //        PIOR &= 0xfe;                /* PCLBUZ0 Sel P1.0  */
  10.         
  11.         CKS0=0x06;                        /* f=4.88kHz */        
  12. }

  13. void BUZ_Off(void)
  14. {
  15.     CKS0 &= 0x7f;
  16. }

  17. void BUZ_On(void)
  18. {
  19.     CKS0 |= 0x80;
  20. }
复制代码

3.操作演示
蜂鸣器的发声就先不做了,以后有机会上视频时才有声音。












最新回复

不错的样子。。。。  详情 回复 发表于 2015-10-29 08:18
点赞 关注

回复
举报

1891

帖子

2

TA的资源

纯净的硅(中级)

沙发
 
不错的样子。。。。
 
个人签名
分享铸就美好未来。。。




 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表