请选择 进入手机版 | 继续访问电脑版

 找回密码
 立即注册
楼主: 电子D***

触摸电子琴从无到有心得分享——基于STC8H4K64TL的电子琴

[复制链接]

该用户从未签到

546

主题

9072

回帖

1万

积分

管理员

积分
14002
发表于 2023-3-16 13:19:56 | 显示全部楼层
在烧录程序时选择

1.png
2.png
3.png
4.png
5.png
6.png

该用户从未签到

546

主题

9072

回帖

1万

积分

管理员

积分
14002
发表于 2023-3-16 13:22:52 | 显示全部楼层
1.png

2.png
3.png
  • TA的每日心情
    开心
    昨天 08:55
  • 签到天数: 81 天

    [LV.6]常住居民II

    37

    主题

    947

    回帖

    6642

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    6642
    QQ
     楼主| 发表于 2023-3-16 13:25:41 | 显示全部楼层
    六、数码管调试

    紧接着上一篇,我们已经把下载部分都测试完成了,那么今天我们开始下一个部分的测试,首先我们先把硬件电路焊起来(由于一点点小失误,数码管只买了个共阳的,共阴的还在购物车里躺着,很尴尬,已经加急买下去了),最后数码管焊完之后成品如下(新焊接的部分如图红圈部分所示,包含原理图上的限流电阻和数码管部分,都是手册推荐的规格):
    1.png
    硬件部分焊完了,然后找个驱动代码测试一下,看看能不能点亮先。既然之前直接down的官网的原理图,那就再去把官网的那个配套的程序也下下来用着:
    2.png
    因为考虑到我们的板子和官方的板子引脚也用的差不多,那直接历程下载进去应该就能直接用,话不多说,直接冲,反正下载程序下错了既不会死机,也不会炸机,下就完了,下载完之后,数码管显示了这:


    看到上面的视频,虽然显示有一点乱码,但是至少点亮了,另外相机拍摄会有一定频闪,这个原因简单的给大家说明下,这就是手机录制的帧率和数码管刷新的帧率不一致,这个问题百度很多 答案,实物上看得出前两位数码管一直在变,后两位一直稳如泰山的乱码,但是至少亮了,说明电路设计的和焊的应该不是问题。那我们开始打开程序分析。
    1. void main(void)
    2. {
    3.         u8        i;
    4.         u16        j;
    5.         P_SW2 |= 0x80;        //允许访问XSFR(扩展特殊功能寄存器)
    6. //        XOSCCR = 0xc0;           //启动外部晶振
    7. //        while (!(XOSCCR & 1));   //等待时钟稳定
    8. //        CLKDIV = 0x00;           //时钟不分频
    9. //        CKSEL = 0x01;            //选择外部晶振
    10.         P0M0 = 0x00;
    11.         P0M1 = 0x00;
    12.         P2n_push_pull(0xff);        //COM0~COM7线设置为推挽输出
    13.         P4n_push_pull(0xff);        //SEG0~SEG7(P4.0~P4.7)线设置为推挽输出
    14.         P3n_push_pull(0xf0);        //SEG12~SEG15(P3.4~P3.7)线设置为推挽输出
    15.         P2DR = 0x00;        //COM0~COM7线设置为强电流驱动
    16.         P4DR = 0x00;        //SEG0~SEG7线设置为强电流驱动
    17.         P3DR = 0x0f;        //SEG12~SEG15线设置为强电流驱动
    18.         COMEN  = 0xff;        //允许8个COM
    19.         SEGENL = 0xff;        //允许8个SEG 低字节
    20.         SEGENH = 0xf0;        //允许8个SEG 高字节
    21.         LEDCTRL = 0x80 + (2<<4) + 0;        //B7=1: ON,  B5 B4: 0共阴, 1共阳, 2共阴共阳, 3保留, B2 B1 B0: 0占空比100%, 1~7占空比7/8~1/8
    22.         LEDCKS = 8;                //数码管COM扫描显示的主频时钟数 = 160*9*LEDCKS, 每个COM显示时间=1440*LEDCKS/fosc(MHz) us, COM扫描频率=fosc/(1440*LEDCKS *COM数).
    23.                                         //例如 fosc = 11.0592MHz, 8个COM, LEDCKS = 8, 则每个COM显示时间=1440*8/11.0592 = 1042 us, COM扫描频率=11059200/(1440*8*8)=120Hz.
    24.                                         //已知扫描时间t(us)计算 LEDCKS = t*fosc(MHz)/1440, 比如fosc = 24MHz, 要求1个COM扫描1ms, 则 LEDCKS = 1000*24/1440 = 16.7, 取整数17.
    25.         for(i=0; i<8; i++)
    26.         {
    27.                 LoadLED_A(i,i);                //共阳,显示01234567
    28.                 LoadLED_B(i,i+8);        //共阳,显示89ABCDEF
    29.         }
    30.         COM4_DAH_tmp = 0;
    31.         COM5_DAH_tmp = 0;
    32.         COM6_DAH_tmp = 0;
    33.         COM7_DAH_tmp = 0;</font>
    34.         P1n_pure_input(0xff);        //Touch Key设置为高阻
    35.         P5n_pure_input(0x0f);
    36.         P0n_pure_input(0x0f);
    37. //        TSCHEN = 0xffff;        //TK0~TK15
    38.         TSCHEN1 = 0xff;                //TK0~TK7
    39.         TSCHEN2 = 0xff;                //TK8~TK15
    40.         TSCFG1  = (7<<4) + 6;        //开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+1)), 放电时间(系统时钟周期数) 0(125) 1(250) 2(500) 3(1000) 4(2000) 5(2500) 6(5000) 7(7500) 最小3
    41.         TSCFG2  = 1;                //配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4)  1(1/2)  2(5/8)  3(3/4)
    42. //        TSCTRL = (1<<7) + (1<<6) +3;        //开始扫描, B7: TSGO,  B6: SINGLE,  B5: TSWAIT, B4: TSWUCS, B3: TSDCEN, B2: TSWUEN, B1 B0: TSSAMP
    43. //        TSRT = 0x00;                //没有LED分时扫描
    44.         IE2 |= 0x80;                //允许触摸按键中断
    45.         EA = 1;
    46.         delay_ms(50);
    47. //        B_TK_Lowpass = 0;        //禁止低通滤波
    48.         B_TK_Lowpass = 1;        //允许低通滤波
    49.         for(read_cnt=0; read_cnt<40; read_cnt++)                //读40次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键
    50.         {
    51.         //        TSCTRL = (1<<7) + (1<<6) +3;        //开始扫描, 4次平均, 读数大约为无平均的一半
    52.                 TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
    53.         //        TSCTRL = (1<<7) + (1<<6);                //开始扫描, 只转换1次, 无平均
    54.                 B_ReadKeyOk = 0;
    55.                 for(i=0; i<100; i++)
    56.                 {
    57.                         if(B_ReadKeyOk)        break;
    58.                         delay_ms(1);
    59.                 }
    60.         }
    61.         for(i=0; i<16; i++)                TK_zero[i] = TK_cnt[i];        //保存0点
    62.         
    63.         B_TK_Lowpass = 1;        //允许低通
    64.         KeyState = 0;
    65.         read_cnt = 0;</font>
    66.         
    67.         B_ReadKeyOk = 0;
    68.         KeyValue = 10;
    69.         KeyCode = 0;
    70.         ShowKey();</font>
    71.         
    72.         while (1)
    73.         {
    74.                 delay_ms(1);
    75.                
    76.                 if(++TrigLimit >= 100)        //触发转换
    77.                 {
    78.                         TrigLimit = 0;
    79.                 //        TSCTRL = (1<<7) + (1<<6) +3;        //开始扫描, 4次平均, 读数大约为无平均的一半
    80.                         TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
    81.                 //        TSCTRL = (1<<7) + (1<<6);                //开始扫描, 只转换1次, 无平均
    82.                 }
    83.                
    84.                 if(B_ReadKeyOk)                        // 16个键都转换完毕
    85.                 {
    86.                         B_ReadKeyOk = 0;
    87.                         TrigLimit = 100;
    88.                         ShowValue(KeyValue);        //显示读数
    89.                         j = KeyState;                //读入上一次键状态
    90.                         for(i=0; i<16; i++)
    91.                         {
    92.                                 if(TK_zero[i] > TK_cnt[i])        //计算与0点的差值
    93.                                 {
    94.                                         TK_zero[i]--;        //缓慢0点跟随
    95.                                                  if((TK_zero[i] - TK_cnt[i]) >= T_KeyPress[i]/2)        KeyState |=  T_KeyState[i];        // 大于按键读数变量的1/2就是按下
    96.                                         else if((TK_zero[i] - TK_cnt[i]) <= T_KeyPress[i]/3)        KeyState &= ~T_KeyState[i];        // 小于按键读数变量的1/3就是释放
    97.                                 }
    98.                                 else
    99.                                 {
    100.                                         KeyState &= ~T_KeyState[i];
    101.                                         if((TK_cnt[i] - TK_zero[i]) > 100)        TK_zero[i] += 50;        //差别很大, 则快速回0点
    102.                                         else                                                                TK_zero[i] += 10;        //差别不大, 则慢速回0点
    103.                                 }
    104.                         }
    105.                         j = (j ^ KeyState) & KeyState;        //检测键是否按下
    106.                         if(j != 0)
    107.                         {
    108.                                 KeyCode = CheckKey(j);        //计算键码 1~16
    109.                                 i = (u8)j;
    110.                                 COM4_DAH_tmp ^= (i << 4);
    111.                                 COM5_DAH_tmp ^= (i & 0xf0);
    112.                                 i = (u8)(j >> 8);
    113.                                 COM6_DAH_tmp ^= (i << 4);
    114.                                 COM7_DAH_tmp ^= (i & 0xf0);
    115.                                 
    116.                                 COM4_DAH = COM4_DAH_tmp;
    117.                                 COM5_DAH = COM5_DAH_tmp;
    118.                                 COM6_DAH = COM6_DAH_tmp;
    119.                                 COM7_DAH = COM7_DAH_tmp;
    120.                                 
    121.                                 ShowKey();
    122.                                 if(KeyCode == 15)
    123.                                 {
    124.                                         KeyValue--;                        //显示数值的键号-1
    125.                                         KeyValue &= 0x0f;
    126.                                         ShowValue(KeyValue);        //显示读数
    127.                                 }
    128.                                 if(KeyCode == 16)
    129.                                 {
    130.                                         KeyValue++;                        //显示数值的键号+1
    131.                                         KeyValue &= 0x0f;
    132.                                         ShowValue(KeyValue);        //显示读数
    133.                                 }
    134.                         }
    135.                 }
    136.         }
    137. }
    复制代码
    可以看到我们的程序部分如上,既然工程名称叫“16个触摸按键16个灯-8个共阴-8个共阳数码管显示”,那么推测程序就是一半灯驱动,一半触摸驱动,秉承着这个思路,我们开始分析程序,就看main开始的部分。

    我们通过注释和函数的名称,变量名称等,我们把程序分为如上三块,红色的部分就是数码管(LED)驱动,绿色的部分就是触摸的驱动,最后while里面那个紫不紫,粉不粉(暂且叫他粉紫色,或者有谁知道这个具体叫啥的下边留言告诉我下)的就是数码管和触摸的组合的用户功能,那我们现在只测数码管,先把上面绿色和粉紫色的代码屏蔽掉,在下载进去看下效果如下:

    3.png

    这时候可以看到数码管显示贼稳了,说明这个代码基本可以用,给官方点个赞:handshake剩下的小细节我们就可以慢慢的通过测试对比然后修改了。

    这时候打开STC8H的手册,找到LED的章节,刚开始是LED的描述,之前截图过了,这里就不赘述了,然后是LED驱动的结构图,

    4.png

    好吧,暂时还看不懂,那就先跳过(很多人会有一个误区,看手册喜欢精读每一句话,每一个字,直到看懂才接着往下看,个人觉得这个是有问题的.这就和英文考阅读理解一样,某个单词某个句子不理解,对我们理解全文来说影响不是特别大,我们完全可以不懂得先跳过,第一遍先看完全文,掌握大概,再回过头来精读句子来理解,看这个图也是一样,先把LED驱动的整个章节读完了,再来看这个图就会豁然开朗,原来是这个样子啊)。

    然后下面就是接着寄存器描述,反正不多,我们一个一个的看:

    5.png

    1.         COMEN  = 0xff;        //允许8个COM
    2.         SEGENL = 0xff;        //允许8个SEG 低字节
    3.         SEGENH = 0xf0;        //允许8个SEG 高字节
    复制代码
    首先是手册的代码,然后是我们的例程里关于这个寄存器配置的代码,看到手册COMEN的寄存器里使能COM几就打开几通道,写1是打开,那我们的原理图里COM对应的8个IO都用上了,那这里和他一样就好,直接写FF。其次是SEGEN,这里我们原理图如下:实际上我们没有用完全部的SEG,只用了其中的八个,那这八个对应的是哪个通道呢,我们看一下手册,这部分寄存器描述这里没有详细展开,那我们去看引脚图(看下面第二张图,是不是一目了然了);

    6.png

    7.png

    所以这里结合我们使用的通道,我们的初始化代码就可以改写为这样:

    1. COMEN = 0xff; //允许8个COM
    2. SEGENL = 0xf4; //允许P47-P44,P42作为SEG
    3. SEGENH = 0xE0; //允许P37-P35作为SEG
    复制代码


    好,再看下一个寄存器:

    8.png

    这个什么共阴共阳啊,打开LED驱动器,还有占空比(亮度)这些,我们是不是一模一样的,都不用去动他,那就接着下一个寄存器;

    9.png

    可以看到这个图片最后一行甚至都已经帮我们算好了这个建议值,我们这例程里写的是8,其实当然我们肉眼现在看起来不闪烁,那我也就不去动他了,实际上要按照推荐的这个75hz的刷新率的话,应该是 11059200/160/8/2/LEDCKS≥75HZ,因为我们用的共阴共阳模式,所以Ncom应该是16来计算,参考上图的蓝色小字。


    然后接着下一个寄存器:

    10.png


    当然这个数据是直接显示的寄存器,也就是说共阴的数码管数据写入COM_DC就能直接显示了,那岂不是爽飞了,都不需要我们自己去刷新数码管,然后看了下后面的描述,为了方便大家看,我这里整理了一个表格,结合了我的板子去测试:

    11.png

    首先最上面一行DA_H和DA_L就是板子上的16个SEG引脚。坐标上的COM0-COM7就是COM引脚,因为com可以作为共阴和共阳所以,这边com分成了两组,但是引脚都是一样的,然后我的板子上P37接了数码管的d,也就是DA_H的最高位bit7接了d的引脚,所以我板子上焊的那个数码管我想点亮她显示一个1,就是数码管的b和c这两段要点亮,还是共阳的数码管。

    12.png

    综上所述,就是选择共阳的COM0的那一行,然后b和c的那一列,在他们交会的地方写1,最后下图所示

    13.png

    是不是就一目了然了,换成代码就是这么两行,就可以在数码管上显示1了;
    1. COM0_DAH = 0X40;
    2. COM0_DAL = 0X04;
    复制代码

    当然其实仔细分析一下我们的代码,其实在代码里还有如下几行,
    1.         P2n_push_pull(0xff);        //COM0~COM7线设置为推挽输出
    2.         P4n_push_pull(0xff);        //SEG0~SEG7(P4.0~P4.7)线设置为推挽输出
    3.         P3n_push_pull(0xf0);        //SEG12~SEG15(P3.4~P3.7)线设置为推挽输出
    4.         P2DR = 0x00;        //COM0~COM7线设置为强电流驱动
    5.         P4DR = 0x00;        //SEG0~SEG7线设置为强电流驱动
    6.         P3DR = 0x0f;        //SEG12~SEG15线设置为强电流驱动
    复制代码
    那么第一个 P2n_push_pull的函数跳转过去之后我们就可以看到他的源码:
    1. #define P2n_push_pull(bitn)                        P2M1 &= ~(bitn),        P2M0 |=  (bitn)
    复制代码
    其实就是用了一个宏定义去将他设置为推挽输出的模式,用来增强驱动能力,说白了就是我们驱动数码管用到哪几个引脚,我们就把哪几个设置为推挽输出,像我这里就可以写成
    1.         P2n_push_pull(0xff);        //COM0~COM7线设置为推挽输出
    2.         P4n_push_pull(0xf4);        //SEG0~SEG7(P4.4~P4.7,P4.2)线设置为推挽输出
    3.         P3n_push_pull(0xE0);        //SEG12~SEG15(P3.5~P3.7)线设置为推挽输出
    复制代码
    最后的PxDR是为了增强电流驱动,可以看到下图我们需要大电流的端口写0就好。所以这里我们可以这么写
    1.         P2DR = 0x00;        //COM0~COM7线设置为强电流驱动
    2.         P4DR = 0x0B;        //SEG4~SEG7,SEG2线设置为强电流驱动
    3.         P3DR = 0x1f;        //SEG13~SEG15线设置为强电流驱动
    复制代码
    14.png
    当然上面的PxDR 也好,P2n_push_pull也好,都是为了设置模式的,要是大家模式不会设置,直接用ISP软件在线配置也可以,办法参考如下,实在不会用的也可以问问自己的销售经理,或者下面留个言:
    15.png

    好了,那么上面的步骤全部结合起来,最终的代码就是这样:
    1. void main(void)
    2. {
    3.         u8        i;
    4.         u16        j;
    5.         P_SW2 |= 0x80;        //允许访问XSFR(扩展特殊功能寄存器)
    6. //        XOSCCR = 0xc0;           //启动外部晶振
    7. //        while (!(XOSCCR & 1));   //等待时钟稳定
    8. //        CLKDIV = 0x00;           //时钟不分频
    9. //        CKSEL = 0x01;            //选择外部晶振
    10.         P0M0 = 0x00;
    11.         P0M1 = 0x00;
    12.     P2n_push_pull(0xff); //COM0~COM7线设置为推挽输出
    13.     P4n_push_pull(0xf4); //SEG0~SEG7(P4.4~P4.7,P4.2)线设置为推挽输出
    14.     P3n_push_pull(0xE0); //SEG12~SEG15(P3.5~P3.7)线设置为推挽输出
    15.     P2DR = 0x00; //COM0~COM7线设置为强电流驱动
    16.     P4DR = 0x0B; //SEG4~SEG7,SEG2线设置为强电流驱动
    17.     P3DR = 0x1f; //SEG13~SEG15线设置为强电流驱动
    18.    
    19.     COMEN = 0xff; //允许8个COM
    20.     SEGENL = 0xf4; //允许P47-P44,P42作为SEG
    21.     SEGENH = 0xE0; //允许P37-P35作为SEG
    22.         LEDCTRL = 0x80 + (2<<4) + 0;        //B7=1: ON,  B5 B4: 0共阴, 1共阳, 2共阴共阳, 3保留, B2 B1 B0: 0占空比100%, 1~7占空比7/8~1/8
    23.         LEDCKS = 8;                //数码管COM扫描显示的主频时钟数 = 160*9*LEDCKS, 每个COM显示时间=1440*LEDCKS/fosc(MHz) us, COM扫描频率=fosc/(1440*LEDCKS *COM数).
    24.                                         //例如 fosc = 11.0592MHz, 8个COM, LEDCKS = 8, 则每个COM显示时间=1440*8/11.0592 = 1042 us, COM扫描频率=11059200/(1440*8*8)=120Hz.
    25.                                         //已知扫描时间t(us)计算 LEDCKS = t*fosc(MHz)/1440, 比如fosc = 24MHz, 要求1个COM扫描1ms, 则 LEDCKS = 1000*24/1440 = 16.7, 取整数17.
    26.    
    27.     COM0_DAH = 0X40;
    28.     COM0_DAL = 0X04;
    29. //        P1n_pure_input(0xff);        //Touch Key设置为高阻
    30. //        P5n_pure_input(0x0f);
    31. //        P0n_pure_input(0x0f);
    32. ////        TSCHEN = 0xffff;        //TK0~TK15
    33. //        TSCHEN1 = 0xff;                //TK0~TK7
    34. //        TSCHEN2 = 0xff;                //TK8~TK15
    35. //        TSCFG1  = (7<<4) + 6;        //开关电容工作频率 = fosc/(2*(TSCFG1[6:4]+1)), 放电时间(系统时钟周期数) 0(125) 1(250) 2(500) 3(1000) 4(2000) 5(2500) 6(5000) 7(7500) 最小3
    36. //        TSCFG2  = 1;                //配置触摸按键控制器的内部参考电压(AVCC的分压比), 0(1/4)  1(1/2)  2(5/8)  3(3/4)
    37. ////        TSCTRL = (1<<7) + (1<<6) +3;        //开始扫描, B7: TSGO,  B6: SINGLE,  B5: TSWAIT, B4: TSWUCS, B3: TSDCEN, B2: TSWUEN, B1 B0: TSSAMP
    38. ////        TSRT = 0x00;                //没有LED分时扫描
    39. //        IE2 |= 0x80;                //允许触摸按键中断
    40. //        EA = 1;
    41. //        delay_ms(50);
    42. ////        B_TK_Lowpass = 0;        //禁止低通滤波
    43. //        B_TK_Lowpass = 1;        //允许低通滤波
    44. //        for(read_cnt=0; read_cnt<40; read_cnt++)                //读40次键, 将此值作为未触摸时的0点, 要求上电时不要触摸按键
    45. //        {
    46. //        //        TSCTRL = (1<<7) + (1<<6) +3;        //开始扫描, 4次平均, 读数大约为无平均的一半
    47. //                TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
    48. //        //        TSCTRL = (1<<7) + (1<<6);                //开始扫描, 只转换1次, 无平均
    49. //                B_ReadKeyOk = 0;
    50. //                for(i=0; i<100; i++)
    51. //                {
    52. //                        if(B_ReadKeyOk)        break;
    53. //                        delay_ms(1);
    54. //                }
    55. //        }
    56. //        for(i=0; i<16; i++)                TK_zero[i] = TK_cnt[i];        //保存0点
    57. //        
    58. //        B_TK_Lowpass = 1;        //允许低通
    59. //        KeyState = 0;
    60. //        read_cnt = 0;
    61. //        
    62. //        B_ReadKeyOk = 0;
    63. //        KeyValue = 10;
    64. //        KeyCode = 0;
    65. //        ShowKey();
    66.         
    67.         while (1)
    68.         {
    69. //                delay_ms(1);
    70. //               
    71. //                if(++TrigLimit >= 100)        //触发转换
    72. //                {
    73. //                        TrigLimit = 0;
    74. //                //        TSCTRL = (1<<7) + (1<<6) +3;        //开始扫描, 4次平均, 读数大约为无平均的一半
    75. //                        TSCTRL = (1<<7) + (1<<6) +1;        //开始扫描, 2次平均, 读数大约为无平均的一半
    76. //                //        TSCTRL = (1<<7) + (1<<6);                //开始扫描, 只转换1次, 无平均
    77. //                }
    78. //               
    79. //                if(B_ReadKeyOk)                        // 16个键都转换完毕
    80. //                {
    81. //                        B_ReadKeyOk = 0;
    82. //                        TrigLimit = 100;
    83. //                        ShowValue(KeyValue);        //显示读数
    84. //                        j = KeyState;                //读入上一次键状态
    85. //                        for(i=0; i<16; i++)
    86. //                        {
    87. //                                if(TK_zero[i] > TK_cnt[i])        //计算与0点的差值
    88. //                                {
    89. //                                        TK_zero[i]--;        //缓慢0点跟随
    90. //                                                 if((TK_zero[i] - TK_cnt[i]) >= T_KeyPress[i]/2)        KeyState |=  T_KeyState[i];        // 大于按键读数变量的1/2就是按下
    91. //                                        else if((TK_zero[i] - TK_cnt[i]) <= T_KeyPress[i]/3)        KeyState &= ~T_KeyState[i];        // 小于按键读数变量的1/3就是释放
    92. //                                }
    93. //                                else
    94. //                                {
    95. //                                        KeyState &= ~T_KeyState[i];
    96. //                                        if((TK_cnt[i] - TK_zero[i]) > 100)        TK_zero[i] += 50;        //差别很大, 则快速回0点
    97. //                                        else                                                                TK_zero[i] += 10;        //差别不大, 则慢速回0点
    98. //                                }
    99. //                        }
    100. //                        j = (j ^ KeyState) & KeyState;        //检测键是否按下
    101. //                        if(j != 0)
    102. //                        {
    103. //                                KeyCode = CheckKey(j);        //计算键码 1~16
    104. //                                i = (u8)j;
    105. //                                COM4_DAH_tmp ^= (i << 4);
    106. //                                COM5_DAH_tmp ^= (i & 0xf0);
    107. //                                i = (u8)(j >> 8);
    108. //                                COM6_DAH_tmp ^= (i << 4);
    109. //                                COM7_DAH_tmp ^= (i & 0xf0);
    110. //                                
    111. //                                COM4_DAH = COM4_DAH_tmp;
    112. //                                COM5_DAH = COM5_DAH_tmp;
    113. //                                COM6_DAH = COM6_DAH_tmp;
    114. //                                COM7_DAH = COM7_DAH_tmp;
    115. //                                
    116. //                                ShowKey();
    117. //                                if(KeyCode == 15)
    118. //                                {
    119. //                                        KeyValue--;                        //显示数值的键号-1
    120. //                                        KeyValue &= 0x0f;
    121. //                                        ShowValue(KeyValue);        //显示读数
    122. //                                }
    123. //                                if(KeyCode == 16)
    124. //                                {
    125. //                                        KeyValue++;                        //显示数值的键号+1
    126. //                                        KeyValue &= 0x0f;
    127. //                                        ShowValue(KeyValue);        //显示读数
    128. //                                }
    129. //                        }
    130. //                }
    131.         }
    132. }
    复制代码
    上面,没用的都屏蔽掉了,然后按照上面分析留下我有用的,最终的实物效果如下:

    16.png

    这样数码管驱动也调通了哈哈~很有成就感!!!
  • TA的每日心情
    开心
    昨天 08:55
  • 签到天数: 81 天

    [LV.6]常住居民II

    37

    主题

    947

    回帖

    6642

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    6642
    QQ
     楼主| 发表于 2023-3-16 13:41:05 | 显示全部楼层
    先占个楼插一嘴,这个项目最终的原理图,PCB, 原代码将全部开源,由于现在还在调试,原理图pcb什么的都还不完美,我就暂时不放源文件了,等到全部结束的时候我给大家把文件一起打包发上来,浅浅的期待一下吧,最后,我也会随机的从回帖列表里抽一个小伙伴送一个成品(摇骰子决定几号楼),qq群里也抽一个小伙伴送一个成品(抢红包手气王~),等成品吧~
  • TA的每日心情
    开心
    昨天 08:55
  • 签到天数: 81 天

    [LV.6]常住居民II

    37

    主题

    947

    回帖

    6642

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    6642
    QQ
     楼主| 发表于 2023-3-16 14:50:43 | 显示全部楼层
    本帖最后由 电子DIY小家 于 2023-3-16 14:52 编辑

    七、数码管的显示调试

    1. u8 code T_LED_CODE[]={                                                //标准字库
    2. //代码            0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
    3. //显示字符   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    4.             0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
    5. //代码            0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F
    6. //显示字符   0.   1.   2.   3.   4.   5.   6.   7.   8.   9.   空   -
    7.             0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x00,0x40};
    复制代码
    可以看到原来的代码里有这么一串代码,明显就是一个调用数组可以再数码管上显示一些字符的码表,但是我们的引脚SEG排列和他不一样,那么我们得重新设置我们的排列的码表,这里我们沿用上一个的表格,直接在线生成:
    1.png

    利用EXCEL我们很方便你的就弄好了这个码表,然后我们把它复制到程序里,并最终整合整和为了这个数组来代替远来的:

    1. u16 code T_LED_CODE[]=          //标准字库
    2. {
    3.   
    4. //代码            0x00    0x01    0x02    0x03    0x04    0x05    0x06    0x07    0x08    0x09    0x0A    0x0B    0x0C    0x0D    0x0E    0x0F
    5. //显示字符   0       1       2       3       4       5       6       7       8       9       A       B       C       D       E       F         
    6.             0xE034, 0x4004,0xE050,  0xE044, 0x4064, 0xA064, 0xA074, 0x6004, 0xE074, 0xE064, 0x6074, 0x8074, 0x8050, 0xC054, 0xA070, 0x2070
    7.             
    8. //代码            0x10    0x11    0x12    0x13    0x14    0x15    0x16    0x17    0x18    0x19    0x1A    0x1B
    9. //显示字符   0.      1.      2.      3.      4.      5.      6.      7.      8.      9.      空       -         
    10.             0xE0B4, 0x4084, 0xE0D0, 0xE0C4, 0x40E4, 0xA0E4, 0xA0F4, 0x6084, 0xE0F4, 0xE0E4, 0x0000, 0x0040
    11. }
    复制代码
    顺便把这个数组放到工程前面去,我喜欢把数组放前面,方便查看和修改。最后变成了这样

    2.png

    这个数组一共有26个元素,那为了验证一下准确性,我们在while里编写一个简单的测试,让这个26个字符循环显示一下看看,直接在while函数编写如下代码:

    1. COM0_DAH = T_LED_CODE[i]>>8;
    2.         COM0_DAL = T_LED_CODE[i];        
    3.         delay_ms(250);delay_ms(250);delay_ms(250);delay_ms(250);
    4.         i++;
    5.         if(i>25)
    6.             i=0;
    复制代码
    上面的代码非常的简单,第一行先把高八位的数据DA_H传送到COM0_DAH 这个寄存器里,第二行先把低八位的数据DA_L传送到COM0_DAL这个寄存器里,第三行简单的4个delay_ms(250);总共延时一秒钟,第5-7行就是让他这个变量从0-25循环自加。是不是非常的简单~(当然如果对这个数码管的显示取模不太懂的话,可以去看官方的STC32教学视频第九集,里面讲了怎么取模,方法一致的哈~)最后我们来看一下实物的演示效果:


    这样是不是就很nice了,后面想显示啥就显示啥,很nice~附件就是我们用到的计算数码管码表的表格,内含公式等待,有兴趣可以下载下来看看

    显示.xls

    64 KB, 下载次数: 75

    回复 支持 1 反对 0 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-1-16 15:48
  • 签到天数: 1 天

    [LV.1]初来乍到

    6

    主题

    25

    回帖

    156

    积分

    注册会员

    积分
    156
    发表于 2023-3-16 15:49:23 | 显示全部楼层
    感觉很厉害的样子,先马克一下

    点评

    嘿嘿  发表于 2023-3-16 16:09

    该用户从未签到

    45

    主题

    2829

    回帖

    6358

    积分

    超级版主

    积分
    6358
    发表于 2023-3-16 16:53:44 | 显示全部楼层
    支持!很赞!我也喜欢做电子琴。
    如果使用单个波表播放,STC8H4K64TL跑45MHz,波表24K采样,用6通道没有问题,估计可以上到8通道。由于ROM容量不大,所以只能使用简单波表,比如八音盒音色的波表。
  • TA的每日心情
    开心
    昨天 08:55
  • 签到天数: 81 天

    [LV.6]常住居民II

    37

    主题

    947

    回帖

    6642

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    6642
    QQ
     楼主| 发表于 2023-3-16 17:02:50 | 显示全部楼层
    梁工 发表于 2023-3-16 16:53
    支持!很赞!我也喜欢做电子琴。
    如果使用单个波表播放,STC8H4K64TL跑45MHz,波表24K采样,用6通道没有问 ...

    感谢梁工提点:handshake
  • TA的每日心情

    昨天 08:48
  • 签到天数: 135 天

    [LV.7]常住居民III

    121

    主题

    173

    回帖

    1481

    积分

    金牌会员

    积分
    1481
    发表于 2023-3-16 20:29:21 | 显示全部楼层
    触摸按键必须使用弹簧吗?板载按键不行吗
  • TA的每日心情
    开心
    昨天 08:55
  • 签到天数: 81 天

    [LV.6]常住居民II

    37

    主题

    947

    回帖

    6642

    积分

    荣誉版主

    冲哥视频教程和各种开源资料QQ交流群884047237,可群

    积分
    6642
    QQ
     楼主| 发表于 2023-3-16 20:40:16 | 显示全部楼层
    QQ624353765 发表于 2023-3-16 20:29
    触摸按键必须使用弹簧吗?板载按键不行吗

    可以,计划上面加一层亚克力的外壳所以要加个弹簧增高
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-4-17 05:28 , Processed in 0.088696 second(s), 70 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表