端口直接驅動4位數碼管

分類: 打印機驅動使用 发布时间:2019-01-14 05:00

1位數碼管,需要8根線與單片機連接,如果是4數碼管個也用同樣的方式連接,則需要32個端口,很顯然UNO主板沒有這麽多端口,那麽最終有什麽方法節省端口呢?答案是“動態掃描顯示”,只有一個數碼管的時候,需要顯示某個數據,只要賦值對應數值,然後端口的狀態就不會改變了,直到下一次需要改變顯示信息。多個數碼管的方法會有所不同。先參考一些電路原理圖:

從電路圖上可以看出,8個數碼管的數據端(a-dp)是連接在一起的,每個數碼管都有一個公共端,用一個IO口控制通斷。這種硬件方式決定軟件形式,用上一節的程序是不能實現的,這裏存在端口共用,也就帶出了2個關鍵字,段碼和位碼。

什麽是段碼?

對照電路圖,首先對段碼、位碼關鍵字講解一下。一般的數碼管成爲7段數碼管或者8段數碼管,7段的不帶小數點,當然還有米字數碼管。以8段數碼管爲例講解。通過給數據端(a-dp)不同的數據組合,可以實現不同的字符顯示,這個數據是控制字形的,稱之爲段碼。

什麽是位碼?

8個三極管控制8個數碼管的公共端,通過組合數據使能其中之一或者多個數碼管,只有在對應的數碼管使能的情況下,對應的段碼數據才能有效的顯示。這個數據用于控制某一位數碼管的通斷,稱之爲位碼。

它的工作原理是什麽呢?

下面分析一下它的工作原理,如果這個基本原理理解以後,後面的多種驅動形式無非就是使用了不同類型的芯片,基本原理是不變的。

假設第一個數碼管的位碼控制端賦值0,其他的都賦值1,此時PNP三極管Q1導通,其他的7個三極管截止,三極管導通相當于一個開關(理論分析忽略壓降),第一個數碼管的公共端(COM)直接連接到VCC,其他的7個三極管截止,理論上沒有電流可以通過,此時只有第一個數碼管有效,這就等同于上一節學習到的單個共陽數碼管,只要在數據端(段碼)賦值特定的數據,就能顯示對應的字符。雖然段碼值也同時賦值給另外7個數碼管,但是由于7個數碼管的公共端(COM)是出于關斷狀態,沒有電流流過,所以它們不會顯示任何字形。

同樣的方法,只選通第二個數碼管,並賦值對應的數據,第二個數碼管也能顯示指定的字符,依此類推,一直到第八個數碼管,用圖示樣例來描述一下之前分析的狀態。

從圖中可以看出,任何一個時刻只能顯示一位數碼管,如果同時選通2位數碼管,就是導致2個數碼管顯示同樣的數據,這並不是實驗目的,最終需要的顯示效果如下圖:

显示完第八位數碼管后再从头显示第一位數碼管,第一位數碼管仍然显示原有数值 0,依此类推重复显示,虽然是断断续续的显示,但是任何一个數碼管显示的数值是一样的,然后通过加快循环显示的频率,利用人眼的视觉暂留效应,就可以看到连续的显示效果,如上图,看上去是静态显示,实际上是分时扫描,称之为动态扫描显示。现在的大部分數碼管应用都是动态扫描显示。

8位數碼管的工作原理,是用2个4位數碼管拼接在一起的。上 图 使 用 了 驱动三極管,因为一些单片机拉电流很小,不足以驱动數碼管,在 arduino 里面,这个三極管可以 省略,甚至电阻也可以省略。

其電路圖如下所示。

实物连接图,引脚顺序与芯片相同,左下角是 1 脚,逆时针增加。

端口直接驱动 4 位數碼管的程序如下所示。

int ledCount=8;

int segCount=4;

long previousMillis = 0;

const unsigned chardofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

//unsigned char const dofly_WeiMa[]={0,1,2,3};

int ledPins[] = {

12,8,5, 3, 2, 11, 6, 4,};   // 11,7,4,2,1,10,5,3 注释是數碼管实际引脚数,和芯片一样,逆时针数

int segPins[] = {

unsigned char displayTemp[4];//显示缓冲区

void setup() {

// 循环设置,把对应的端口都设置成输出

for (int thisLed = 0; thisLed< ledCount; thisLed++) {

pinMode(ledPins[thisLed],OUTPUT); }

for (int thisSeg = 0;thisSeg < segCount; thisSeg++) {

pinMode(segPins[thisSeg],OUTPUT);

// 数据处理,把需要处理的byte数据写到对应的引脚端口。

void deal(unsigned char value){

for(int i=0;i<8;i++)

digitalWrite(ledPins[i],bitRead(value,i));//使用了bitWrite函數,非常簡單

// !bitRead(value,i),这里前面加!(非运算符号),取决于使用的是共阴还是共阳數碼管。

// 主循环

void loop() {

static unsigned int num;//定义一个数据

static unsigned  long lastTime=0;

if (millis() - lastTime>= 1000) {

lastTime = millis();

//serialOutput();

//displayTemp[0]=dofly_DuanMa[num/1000];       //动态显示

//displayTemp[1]=dofly_DuanMa[(num%1000)/100];

//displayTemp[2]=dofly_DuanMa[((num%1000)%100)/10];

//displayTemp[3]=dofly_DuanMa[((num%1000)%100)%10];

displayTemp[0]=dofly_DuanMa[1]; //静态显示

displayTemp[1]=dofly_DuanMa[2];

displayTemp[2]=dofly_DuanMa[3];

displayTemp[3]=dofly_DuanMa[4];

static int i;

unsigned long currentMillis= millis();

if(currentMillis -previousMillis > 0) {

previousMillis =currentMillis;

deal(0);// 清除“鬼影”

for(int a=0;a<4;a++)//循环写位码,任何时刻只有1位數碼管选通,之前全部关闭,然后再选通需要的那位數碼管

digitalWrite(segPins[a],1);//

digitalWrite(segPins[i],0);//

deal(displayTemp[i]);//讀取對應的段碼值

if(i==4) //4位结束后重新循环

端口直接驱动 4 位數碼管

實驗結果如圖所示。

程序解讀:本程序4個數碼管顯示固定數字,是不變化的,但是它的掃描方式仍然是動態掃描,而不是靜態顯示。4個數碼管需要設置4個字節的緩沖區,緩沖區可以理解爲中轉站,比如飛機不是直達,而是中轉、經停,這個過程中機上的人有下的也有上的,是變化的,但是整個路程是沒有變化的。緩沖區的意義也可以這樣理解,每個數碼管對應的緩沖區是唯一的、固定的,但是緩沖區裏面的內容是可以任意變化的。緩沖區的變化會直接通過對應的數碼管反映出來,只需要改變緩沖區的內容就能改變數碼管的最終顯示信息。