丄帝De咗臂 发表于 2015-8-31 10:49:03

遥控数码管显示数字

【简介】本项目中我们使用红外遥控器,通过Arduino程序控制数码管显示不同的数字。最后完成图如下


【器材】Arduino Nano,一位数码管,蜂鸣器,红外遥控器,红外接收头,电阻,面包板,导线若干。
【原理】电路原理图如下


【接线】接线示意图如下


【程序】代码程序如下
/*
YOCO 红外遥控数字显示器
功能:用红外遥控模块控制数码管显示0-9十个数字;每按动一次,数码管闪灭一次,同时蜂鸣器叫一声
红外接受头输出端接到Arduino的数字口D8。
遙控器功能键的键值:
紅色电源开关 0xba45
MODE 0xb946
静音 0xb847
←← 0xbb44
→→ 0xbf40
‖   0xbc43
VOL- 0xf807
VOL+ 0xba15
EQ 0xf609
100+ e609
return 0xf200
*/
/********************************设置变量********************************/
#define IR_IN8//红外接收:D8
int Pulse_Width=0;//存储脉宽
int ir_code=0x00;//命令值,十六进制值

//设置控制各段的数字I/O脚
int a=16;//模拟口的A2,以下同
int b=17;
int c=4;
int d=3;
int e=2;
int f=15;
int g=14;
int dp=5;

//以下用数组给数码管管脚、0-9十个数字赋值,简洁
byte segs = { a, b, c, d, e, f, g };//除了小数点的7笔划段
byte seven_seg_digits = { { 1,1,1,1,1,1,0 },// = 0
                                 { 0,1,1,0,0,0,0 },// = 1
                                 { 1,1,0,1,1,0,1 },// = 2
                                 { 1,1,1,1,0,0,1 },// = 3
                                 { 0,1,1,0,0,1,1 },// = 4
                                 { 1,0,1,1,0,1,1 },// = 5
                                 { 1,0,1,1,1,1,1 },// = 6
                                 { 1,1,1,0,0,0,0 },// = 7
                                 { 1,1,1,1,1,1,1 },// = 8
                                 { 1,1,1,1,0,1,1 }   // = 9
                           };
/***************************定时器初始化函数*****************************/
void timer1_init(void)
{
TCCR1A = 0X00;
TCCR1B = 0X05;//给定时器时钟源
TCCR1C = 0X00;
TCNT1 = 0X00;
TIMSK1 = 0X00;//禁止定时器溢出中断
}
/**************************译码输出子函数******************************/
//执行译码结果函数,输出用灯光、数码管显示,必要可以加蜂鸣器
void remote_deal(void)
{
switch(ir_code)
{
    case 0xba45: //左上角的电源开关按键
    init_wire();//数码管熄灭
    buzzer_led();//蜂鸣器鸣叫
    break;
//以下显示所按的数字
   case 0xE916://显示0
   lightSegments(0);
   break;
   case 0xF30C://1
    lightSegments(1);
   break;
   case 0xE718://2
    lightSegments(2);
   break;
   case 0xA15E://3
    lightSegments(3);
   break;
   case 0xF708://4
    lightSegments(4);
   break;
   case 0xE31C://5
    lightSegments(5);
   break;
   case 0xA55A://6
    lightSegments(6);
   break;
   case 0xBD42://7
    lightSegments(7);
   break;
   case 0xAD52://8
    lightSegments(8);
   break;
   case 0xB54A://显示9
    lightSegments(9);
   break;
}
}
/************************逻辑值“0”和“1”子函数****************************/
char logic_value()
{
while(!(digitalRead(8))); //低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=5&&Pulse_Width<=11)//低电平560us——放宽了原来的条件:6-10
{
   while(digitalRead(8));//红外接收管输出的是负脉冲,无信号保持高,高就等待
   Pulse_Width=TCNT1;
   TCNT1=0;
   if(Pulse_Width>=5&&Pulse_Width<=11)//如果Pulse_Width满足该条件,则脉冲持续高电平560us
    return 0;
    else if(Pulse_Width>=19&&Pulse_Width<=30) //如果Pulse_Width满足该条件,则脉冲持续高电平1.7ms
    return 1;
}
    return -1;
}
/*********************接收地址码和命令码脉冲子函数***********************/
void pulse_deal()
{
int i;
//执行8个0
for(i=0; i<8; i++)
{
    if(logic_value() != 0) //不是0
    return;
}
   for(i=0; i<8; i++)
{
    if(logic_value() != 1) //不是1
    return;
}

//解析遥控器编码中的command指令
ir_code=0x00;//清零
for(i=0; i<16;i++ )
{
    if(logic_value() == 1)
    {
      ir_code |=(1<<i);//从i的值写出键码值,十六进制
    }
}
}
/***************************译码子函数******************************/
void remote_decode(void)
{
TCNT1=0X00;      
while(digitalRead(8))//是高就等待
{
   if(TCNT1>=1563)//当高电平持续时间超过100ms,表明此时没有按键按下
    {
      ir_code = 0xff00;
      return;
   }
}
//如果高电平持续时间不超过100ms
TCNT1=0X00;
while(!(digitalRead(8))); //低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=130&&Pulse_Width<=150)//9ms——修改了原来的条件:140-141
{
    while(digitalRead(8));//是高电平就等待
    Pulse_Width=TCNT1;
    TCNT1=0;
    if(Pulse_Width>=60&&Pulse_Width<=79)//4.5ms——放宽了原来的条件
    {
      pulse_deal();
      return;
   }
    else if(Pulse_Width>=28&&Pulse_Width<=40)//2.25ms
    {
      while(!(digitalRead(8)));//低电平等待
      Pulse_Width=TCNT1;
      TCNT1=0;
      if(Pulse_Width>=5&&Pulse_Width<=12)//560us
      {
      return;
       }
   }
   }
}
/***************************初始化设置函数******************************/
void setup()
{
   unsigned char i;
   for(i=2;i<=19;i++)
{
    pinMode(i,OUTPUT);//设置2~19引脚为输出模式
   }
//pinMode(LED_RED,OUTPUT);//设置与红灯连接的引脚为输出模式
pinMode(IR_IN,INPUT);//设置红外接收引脚为输入
digitalWrite(9,LOW);//为红外接收头的接地端,节省连接的导线
digitalWrite(10,HIGH);//为红外接收头的+端,节省连接的导线
digitalWrite(18,HIGH);//A4,为蜂鸣器-
digitalWrite(19,HIGH);//A5,为蜂鸣器-,蜂鸣器可接在A4、A5中的任何一个
Serial.begin(9600);//在计算机的串口窗口里面观察键码值,需要打开串口窗口
}
/***************************主函数(循环)******************************/
void loop()
{
timer1_init();//定时器初始化
while(1)
   {
    remote_decode();//译码
    remote_deal();   //执行译码结果
//以下是观察键码值的程序:
Serial.println("ir_code");
Serial.println(ir_code, DEC);//显示十进制
}
}
/***********************熄灭数码管全部笔画子函数************************/
void init_wire()
{
for (int i=0;i<7;i++)
{
    digitalWrite(segs, HIGH);
    }
digitalWrite(dp,HIGH);
}
/************************点亮对应数字的数码管0-9*************************/
void lightSegments(int x)
{
for (int i=0;i<7;i++)
{
digitalWrite(segs, 1-seven_seg_digits);
   }
buzzer_led();//蜂鸣器函数,数码管眨眼
for (int i=0;i<7;i++)
{
    digitalWrite(segs, 1-seven_seg_digits);
}
}
/********************蜂鸣器函数,同时数码管眨眼**********************/
void buzzer_led()
{
delay(20);//数码管亮
init_wire();//数码管熄灭
digitalWrite(18,LOW);//蜂鸣器响
digitalWrite(19,LOW);//蜂鸣器响
delay(80);//响持续时间
digitalWrite(18,HIGH);//蜂鸣器停
digitalWrite(19,HIGH);
}
【效果】最终效果图如下







hnyzcj 发表于 2015-8-31 16:05:36

张禄挺喜欢NANO板子的,我看你写的帖子都是用NANO。

丄帝De咗臂 发表于 2015-8-31 16:21:37

hnyzcj 发表于 2015-8-31 16:05
张禄挺喜欢NANO板子的,我看你写的帖子都是用NANO。

个头小,买着便宜,因为俺没钱:'(

hnyzcj 发表于 2015-8-31 16:26:02

丄帝De咗臂 发表于 2015-8-31 16:21
个头小,买着便宜,因为俺没钱:'(

装,接着装,无锡一中的老师。

hnyzcj 发表于 2015-8-31 16:26:48

丄帝De咗臂 发表于 2015-8-31 16:21
个头小,买着便宜,因为俺没钱:'(

刘正云就是别你带坏的。哈哈

丄帝De咗臂 发表于 2015-8-31 16:27:46

hnyzcj 发表于 2015-8-31 16:26
刘正云就是别你带坏的。哈哈

真没钱啊,刘正云跟我没有半毛钱关系

hnyzcj 发表于 2015-8-31 17:23:41

丄帝De咗臂 发表于 2015-8-31 16:27
真没钱啊,刘正云跟我没有半毛钱关系

房子解决了吗

大连林海 发表于 2015-8-31 18:13:31

hnyzcj 发表于 2015-8-31 17:23
房子解决了吗

他是和nano好上了 本期都是数码管

1973742214 发表于 2017-5-6 20:12:43

呵呵,我只是笑笑不说话

20060606 发表于 2020-8-13 06:30:56

好创意,赞一个
页: [1]
查看完整版本: 遥控数码管显示数字