Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1211038
  • 博文数量: 124
  • 博客积分: 5772
  • 博客等级: 大校
  • 技术积分: 1647
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-27 10:39
文章分类

全部博文(124)

文章存档

2020年(1)

2019年(1)

2018年(5)

2017年(2)

2016年(17)

2015年(3)

2014年(7)

2013年(11)

2012年(13)

2011年(30)

2010年(34)

分类: 嵌入式

2018-05-06 14:17:52

【1.背景介绍】
使用arduino控制4段数码管显示数值,常用方法是在一个循环中不停刷新各数码管的值,使用余晖效应,显示4位数值。但是这种在循环中不停刷新的方式使得主程序很难再做别的事情,一种解决方法是使用定时中断来刷新4段数码管显示的值,这样主程序可以空闲出来处理别的事情。

【2.硬件连接】
这里的4段数码管采用的是共阳数码管,型号:MSQC6412C,采用arduino uno控制板。数码管引脚定义以及和arduino主控帮的链接方式如图1所示。

                      图1
【3.自定义mblock扩展】
这里使用mblock图形环境来编写程序。需要开发相应的扩展模块。此外,本程序中使用MsTimer2时钟产生定时中断,因此需要在arduino IDE中加载MsTimer2标准库。(加载方法:打开mblock自带的arduino IDE,搜搜MsTimer2标准库,然后安装)

自定义的4段数码管扩展只支持arduino模式,不支持Scratch模式,扩展压缩包中包括Seg4_led.s2e文件和src文件夹,src文件夹中包括demo.cpp,demo.h,seg4_led.c,seg4_led.h,相应的文件内容如下:

Seg4_led.s2e:

  1. {    
  2.     "extensionName": "SEG4_LED",
  3.     "description": "SEG4_LED for common anode",
  4.     "version": "1.1",
  5.     "author": "yoyoba(stuyou@126.com)",
  6.     "homepage": "youhaidong.cn",
  7.     "sort":0,
  8.     "javascriptURL":"",
  9.       "firmware":"1.0",
  10.       "extensionPort":0,
  11.     "tags" : "makeblock,seg4_led",
  12.     "blockSpecs": [
  13.         [
  14.             "w",
  15.             "seg4_led_init( %n , %n , %n , %n , %n , %n , %n , %n , %n , %n , %n , %n )",
  16.             "seg4_led_init",
  17.             "2",
  18.             "3",
  19.             "4",
  20.             "5",
  21.             "6",
  22.             "7",
  23.             "8",
  24.             "14",
  25.             "15",
  26.             "16",
  27.             "17",
  28.             "18",
  29.             {
  30.                 "setup":"",
  31.                 "inc":"#include \"demo.h\" \n #include ", //添加<MsTimer2.h>头文件
  32.                 "def":"DemoClass demo; \n",
  33.                 "work":"demo.seg4_led_init({0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11}); \n",
  34.                 "loop":""
  35.             }
  36.         ],
  37.         [
  38.             "w",
  39.             "seg4_led_display( %n )",
  40.             "seg4_led_display",
  41.             "1234",
  42.             {
  43.                 "setup":"",
  44.                 "inc":"#include \"demo.h\"",
  45.                 "def":"DemoClass demo; \n",
  46.                 "work":"demo.seg4_led_display({0}); \n",
  47.                 "loop":""
  48.             }
  49.         ],
  50.     ],
  51.     "translators":{
  52.         "zh_CN":{
  53.                   "seg4_led_init( %n , %n , %n , %n , %n , %n , %n , %n , %n , %n , %n , %n )":"4段共阳数码管初始化( %n , %n , %n , %n , %n , %n , %n , %n , %n , %n , %n , %n )",
  54.                   "seg4_led_display( %n )":"4段共阳数码管显示数值( %n )"
  55.         }
  56.     }
  57. }

demo.h文件内容:

  1. #ifndef demo_h
  2. #define demo_h

  3. #include <Arduino.h>
  4. ///@brief Class for DemoClass
  5. class DemoClass
  6. {
  7.     public:
  8.     
  9.         DemoClass();
  10.         ~DemoClass();

  11.         // 4段LED共阳数码管引脚初始化函数
  12.         // con1~con4为数码管4个共阳引脚使用的arduino数字I/O口;
  13.         // a~dp为数码管a~dp引脚使用的arduino数字I/O口
  14.         void seg4_led_init(int con1,int con2,int con3,int con4,
  15.                             int a,int b,int c,int d,int e,int f,int g,int dp);

  16.         // 4段共阳数码管显示数值num
  17.         void seg4_led_display(int num);
  18.         
  19.     private:
  20. };

  21. #endif

demo.cpp文件内容

  1. #include "demo.h"
  2. #include "seg4_led.h"
  3. #include <MsTimer2.h>
  4. //添加arduino MsTimer2中断头文件
  5. DemoClass::DemoClass(){//构造函数
  6.     pinMode(13,OUTPUT);
  7. }
  8. DemoClass::~DemoClass()//析构函数
  9. {
  10.     MsTimer2::stop();//停止mstime2时钟中断
  11. }

  12. // 4段共阳数码管初始化函数,初始化函数完成如下功能:
  13. // 1.根据硬件连接,确定4段共阳数码管12个引脚使用的arduino I/O口
  14. // 这里con1/con2/con3/con4,分别对应共阳数码管的4个阳极公共端,
  15. // con1对应最右边一个数码管的阳极;con4对应最左边一个数码管的阳极
  16. // 2.启动mstime2 定时中断,为了实现4位数码管同时显示,这里
  17. // 采用定时中断,每15ms 刷新一次4段数码管
  18. void DemoClass::seg4_led_init(int con1, int con2, int con3, int con4, int a, int b, int c, int d, int e, int f, int g, int dp)
  19. {
  20.     SEG4_con1=con1;
  21.     SEG4_con2=con2;
  22.     SEG4_con3=con3;
  23.     SEG4_con4=con4;
  24.     SEG4_a=a;
  25.     SEG4_b=b;
  26.     SEG4_c=c;
  27.     SEG4_d=d;
  28.     SEG4_e=e;
  29.     SEG4_f=f;
  30.     SEG4_g=g;
  31.     SEG4_dp=dp;
  32.     pinMode(SEG4_con1,OUTPUT);
  33.     pinMode(SEG4_con2,OUTPUT);
  34.     pinMode(SEG4_con3,OUTPUT);
  35.     pinMode(SEG4_con4,OUTPUT);
  36.     pinMode(SEG4_a,OUTPUT);
  37.     pinMode(SEG4_b,OUTPUT);
  38.     pinMode(SEG4_c,OUTPUT);
  39.     pinMode(SEG4_d,OUTPUT);
  40.     pinMode(SEG4_e,OUTPUT);
  41.     pinMode(SEG4_f,OUTPUT);
  42.     pinMode(SEG4_g,OUTPUT);
  43.     pinMode(SEG4_dp,OUTPUT);
  44.     // 设置mstime2时钟中断的刷新频率和ISR
  45.     MsTimer2::set(15,isr_led8_4seg);
  46.     // 启动mstime2中断。
  47.     MsTimer2::start();
  48. }

  49. // 数码管显示函数,计算num的千位、百位、十位和个位。
  50. void DemoClass::seg4_led_display(int num)
  51. {
  52.     k_num=num/1000;
  53.     h_num=(num/100)%10;
  54.     d_num=(num/10)%10;
  55.     g_num=(num)%10;
  56. }

seg4_led.h文件内容

  1. #ifndef SEG4_LED__H__
  2. #define SEG4_LED__H__

  3. #ifdef __cplusplus
  4. extern "C"
  5. {
  6. #endif//__cplusplus

  7. // 声明使用的全局变量和数码管显示码表
  8. extern int k_num,h_num,d_num,g_num;
  9. extern int SEG4_con1,SEG4_con2,SEG4_con3,SEG4_con4,
  10.      SEG4_a,SEG4_b,SEG4_c,SEG4_d,SEG4_e,SEG4_f,SEG4_g,SEG4_dp;
  11. extern unsigned char t_table[10][8];
  12.     

  13. void isr_led8_4seg();
  14. void con_display(int con, int num);
  15.     
  16. #ifdef __cplusplus
  17. }
  18. #endif//__cplusplus

  19. #endif

seg4_led.c文件内容

  1. #include <Arduino.h>
  2. #include "seg4_led.h"

  3. #ifdef __cplusplus
  4. extern "C"
  5. {
  6. #endif//__cplusplus
  7. // 全局变量k_num,h_num,d_num,g_num分别存放
  8. // 4段共阳数码管显示的数值的千位、
  9. // 百位、十位、个位
  10. int k_num=0,h_num=0,d_num=0,g_num=0;

  11. // 全局变量SEG4_X用来存放seg4_led_init()函数初始化的
  12. // 4段共阳数码管使用的I/O引脚号。
  13. int SEG4_con1,SEG4_con2,SEG4_con3,SEG4_con4,
  14.      SEG4_a,SEG4_b,SEG4_c,SEG4_d,SEG4_e,SEG4_f,SEG4_g,SEG4_dp;

  15. // 共阴数码管显示码表,使用时需要转换为共阳码表
  16. unsigned char table[10][8]=
  17.             {
  18.                  {0,0,1,1,1,1,1,1},//0
  19.                  {0,0,0,0,0,1,1,0},// 1
  20.                  {0,1,0,1,1,0,1,1},// 2
  21.                  {0,1,0,0,1,1,1,1},// 3
  22.                  {0,1,1,0,0,1,1,0},// 4
  23.                  {0,1,1,0,1,1,0,1},// 5
  24.                  {0,1,1,1,1,1,0,1},// 6
  25.                  {0,0,0,0,0,1,1,1},// 7
  26.                  {0,1,1,1,1,1,1,1},// 8
  27.                  {0,1,1,0,1,1,1,1},// 9
  28.             };    

  29.     
  30. #ifdef __cplusplus
  31. }
  32. #endif//__cplusplus

  33. // mstime2时钟中断服务函数
  34. void isr_led8_4seg()
  35. {
  36.     if(k_num>0){
  37.         con_display(4,k_num);
  38.         delay(3);//延迟3ms
  39.         con_display(3,h_num);
  40.         delay(3);
  41.         con_display(2,d_num);
  42.         delay(3);
  43.         con_display(1,g_num);
  44.         delay(3);
  45.     }
  46.     else if(h_num>0){
  47.         con_display(4,0);
  48.         delay(3);
  49.         con_display(3,h_num);
  50.         delay(3);
  51.         con_display(2,d_num);
  52.         delay(3);
  53.         con_display(1,g_num);
  54.         delay(3);
  55.     }
  56.     else if(d_num>0){
  57.         con_display(4,0);
  58.         delay(3);
  59.         con_display(3,0);
  60.         delay(3);
  61.         con_display(2,d_num);
  62.         delay(3);
  63.         con_display(1,g_num);
  64.         delay(3);
  65.     }
  66.     else    {
  67.         con_display(4,0);
  68.         delay(3);
  69.         con_display(3,0);
  70.         delay(3);
  71.         con_display(2,0);
  72.         delay(3);
  73.         con_display(1,g_num);
  74.         delay(3);
  75.     }
  76. }

  77. // 指定第con个数码管显示num
  78. //con取值1~4,con=1,最右边一个数码管
  79. // con=4,最左边一个数码管
  80. void con_display(int con, int num)
  81. {
  82.     //所有的数码管熄灭,消除"鬼影"
  83.     digitalWrite(SEG4_a,LOW);
  84.     digitalWrite(SEG4_b,LOW);
  85.     digitalWrite(SEG4_c,LOW);
  86.     digitalWrite(SEG4_d,LOW);
  87.     digitalWrite(SEG4_e,LOW);
  88.     digitalWrite(SEG4_f,LOW);
  89.     digitalWrite(SEG4_g,LOW);
  90.     digitalWrite(SEG4_dp,LOW);

  91. //根据con的值,把相应数码管的共阳极置高电平
  92.     switch(con){
  93.         case 1:
  94.             digitalWrite(SEG4_con1,HIGH);
  95.             digitalWrite(SEG4_con2,LOW);
  96.             digitalWrite(SEG4_con3,LOW);
  97.             digitalWrite(SEG4_con4,LOW);
  98.             break;
  99.         case 2:
  100.             digitalWrite(SEG4_con1,LOW);
  101.             digitalWrite(SEG4_con2,HIGH);
  102.             digitalWrite(SEG4_con3,LOW);
  103.             digitalWrite(SEG4_con4,LOW);
  104.             break;
  105.         case 3:
  106.             digitalWrite(SEG4_con1,LOW);
  107.             digitalWrite(SEG4_con2,LOW);
  108.             digitalWrite(SEG4_con3,HIGH);
  109.             digitalWrite(SEG4_con4,LOW);
  110.             break;
  111.         case 4:
  112.             digitalWrite(SEG4_con1,LOW);
  113.             digitalWrite(SEG4_con2,LOW);
  114.             digitalWrite(SEG4_con3,LOW);
  115.             digitalWrite(SEG4_con4,HIGH);
  116.             break;
  117.             
  118.     }

  119. //第con个LED数码管显示num,
  120. //由于table是共阴码值表,这里使用的是共阳数码管;
  121. // 因此这里需要用1减去其值。
  122.     digitalWrite(SEG4_a,1-table[num][7]);
  123.     digitalWrite(SEG4_b,1-table[num][6]);
  124.     digitalWrite(SEG4_c,1-table[num][5]);
  125.     digitalWrite(SEG4_d,1-table[num][4]);
  126.     digitalWrite(SEG4_e,1-table[num][3]);
  127.     digitalWrite(SEG4_f,1-table[num][2]);
  128.     digitalWrite(SEG4_g,1-table[num][1]);
  129.     digitalWrite(SEG4_dp,1-table[num][0]);
  130.     
  131. }

【4.使用扩展】
把该扩展导入mblock中,在mblock扩展菜单中选中"SEG4_LED"扩展,就能在机器人模块中出现SEG4_LED扩展及其相应的语句。这里对4段共阳数码管的操作只实现了两个语句,即“4段共阳数码管初始化”和“4段共阳数码管显示数值”。使用mblock编写测试程序,下载到arduino运行,正常。如图2所示。实际运行如图3所示。


             图2


                      图3

【5.注意事项】
本程序中使用了很多全局变量,这些全局变量都定义在seg4_led.c文件中。

  1. // 全局变量k_num,h_num,d_num,g_num分别存放
  2. // 4段共阳数码管显示的数值的千位、
  3. // 百位、十位、个位
  4. int k_num=0,h_num=0,d_num=0,g_num=0;

  5. // 全局变量SEG4_X用来存放seg4_led_init()函数初始化的
  6. // 4段共阳数码管使用的I/O引脚号。
  7. int SEG4_con1,SEG4_con2,SEG4_con3,SEG4_con4,
  8.      SEG4_a,SEG4_b,SEG4_c,SEG4_d,SEG4_e,SEG4_f,SEG4_g,SEG4_dp;

  9. // 共阴数码管显示码表,使用时需要转换为共阳码表
  10. unsigned char table[10][8]=
  11.             {
  12.                  {0,0,1,1,1,1,1,1},//0
  13.                  {0,0,0,0,0,1,1,0},// 1
  14.                  {0,1,0,1,1,0,1,1},// 2
  15.                  {0,1,0,0,1,1,1,1},// 3
  16.                  {0,1,1,0,0,1,1,0},// 4
  17.                  {0,1,1,0,1,1,0,1},// 5
  18.                  {0,1,1,1,1,1,0,1},// 6
  19.                  {0,0,0,0,0,1,1,1},// 7
  20.                  {0,1,1,1,1,1,1,1},// 8
  21.                  {0,1,1,0,1,1,1,1},// 9
  22.             };

然后在seg4_led.h中使用extern声明这些全局变量,别的cpp文件/c文件如果要使用这些全局变量,直接包含seg4_led.h文件即可。


  1. // 声明使用的全局变量和数码管显示码表
  2. extern int k_num,h_num,d_num,g_num;
  3. extern int SEG4_con1,SEG4_con2,SEG4_con3,SEG4_con4,
  4.      SEG4_a,SEG4_b,SEG4_c,SEG4_d,SEG4_e,SEG4_f,SEG4_g,SEG4_dp;
  5. extern unsigned char t_table[10][8];

如果把这些全局变量直接定义在seg4_led.h头文件中,则链接时容易造成“全局变量重复定义”错误。
使用全局变量的一个原则:全局变量最好在.cpp/.C文件中定义,在.h文件中加上extern申明,因为在.h文件中定义,容易在链接时造成变量重定义。具体请参考:https://blog.csdn.net/xxxxxx91116/article/details/7446455

Seg4_led.zip  seg4_led扩展


























 

阅读(962) | 评论(0) | 转发(0) |
0

上一篇:mblock扩展

下一篇:mblock控制SG90舵机模块

给主人留下些什么吧!~~