极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12449|回复: 0

USB 控制七段数码管

[复制链接]
发表于 2014-10-17 10:05:37 | 显示全部楼层 |阅读模式
这次的目标是要实现用 USB 口来控制七段数码管。

硬件上面选用《圈圈教你玩USB》配套的实验板。上面的单片机为STC89S52。实验板上P0接口用来和D12通讯,P1接口连接到一组开关按钮上,P2接口上有一组LED,LED另外一端通过10K电阻上拉。下面用色块对这些端口的用途做了简单标记:



最开始的设想是数码管(用的还是上次出场过的那一款数码管,共阳极,【参考1】)阳极连接到P1(可以理解为SEG选择 Pin接正极),阴极连接到P2(数码段 Pin接负极)。实验发现数码管根本不亮,检查很多次后尝试去掉六个数码段的连接终于能够点亮一段数字。这才恍然大悟,因为共阳极上还有板载的LED所以会使得电压很奇怪,不足以推动全部。同时显示,所以需要更改方案。

做到这里,我忽然明白极客工坊大神弘毅提到的:“驱动数码管限流电阻肯定是必不可少的,限流电阻有两种接法,一种是在d1-d4阳极接,总共接4颗。这种接法好处是需求电阻比较少,但是会产生每一位上显示不同数字亮度会不一样,1最亮,8最暗。另外一种接法就是在其他8个引脚上接,这种接法亮度显示均匀,但是用电阻较多。” 因为电压相同,数字1只需要点亮两根LED,8需要点亮七根。

修改之后,阳极连接到P2,阴极连接到P1上。实验发现即使4个数字同时显示仍然是可以清晰辨认的。连接如下图所示:



继续尝试在上位机程序中自动扫描点亮每个LED,前面一篇Arduino就是使用类似的方法点亮的。实做之后发现这样做会导致每个数码管亮灭之间的间隔太长,这样在人类看起来是逐个亮灭的而不是同时亮。猜测这是程序本身发送和USB传输Delay太长导致的。初步估计每个数字显示间隔至少在200ms以上。如果想做一个类似跑马灯的程序用这样的方案没问题,但是如果想持续稳定的显示数字这个方案不可行。

最后上位机程序直接发送显示的数值,由Firmware本身解析,同时利用单片机上的定时器(15ms一次),不断刷新每个显示位。开始时,Firmware中定时器产生中断后,ISR中将四位数值轮流显示一次,但是实验结果肉眼只能看到最后一个点亮的数值。估计这个可能是因为ISR中每个数码位显示过快,而他们点亮的时间远远小于不在ISR中的时间。

经过无数次的调试后,终于完成了。



对应的Firmware关键点在于中断服务函数

void Timer0Isr(void) interrupt 1
{
//LabzDebug_Start
   static i=0;
//LabzDebug_End

//定时器0重装,定时间隔为5ms,加15是为了修正重装所花费时间
//这个值可以通过软件仿真来确定,在这里设置断点,调整使两次运行
//时间差刚好为5ms即可。
TH0=(65536-Fclk/1000/12*5+15)/256;         
TL0=(65536-Fclk/1000/12*5+15)%256;   //

//LabZDebug_Start
        P2=1 << i;
        P1=zBuf;
        i++;
        if (i==4) {i=0;}
//LabZDebug_End  

}

PC端上位机主要代码

int n=0;       
         while (kbhit()==0)
        {
        WriteReportBuffer[1]=Seven_Dig[n / 1000 % 10];
        WriteReportBuffer[2]=Seven_Dig[n / 100 % 10];
        WriteReportBuffer[3]=Seven_Dig[n / 10 % 10];
        WriteReportBuffer[4]=Seven_Dig[n %10];

        printf("%d \n",n);

        //调用WriteFile函数发送数据
        Result=WriteFile(hUsb,
                                        WriteReportBuffer,
                                    9,
                                    &lpNumberOfBytesWritten,
                                       NULL);
        //如果函数返回失败,则可能是真的失败,也可能是IO挂起
        if(Result==FALSE)
                        {
                                //获取最后错误代码
                                        LastError=GetLastError();
                                //看是否是真的IO挂               
                                        if((LastError==ERROR_IO_PENDING)||(LastError==ERROR_SUCCESS))
                                                { return TRUE;        }
                                        //否则,是函数调用时发生错误,显示错误代码
                                        else       
                                                {
                                                        printf("Sending error:%d \n",LastError);
                                                        //如果最后错误为1,说明该设备不支持该函数。
                                                        if(LastError==1)
                                                        {printf("This device doesn't support WriteFile function \n");}
                                                }
                        }

                n=(n++)%10000;

        }//while (kbhit()==0)

Firmware和PC程序下载








参考:

1. http://www.lab-z.com/4digitial/ Arduino 四位数码管实验
2. http://www.geek-workshop.com/for ... =%CA%FD%C2%EB%B9%DC arduino学习笔记13 - 4位数码管实验

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-29 19:34 , Processed in 0.038826 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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