应广单片机应用之--数码管驱动

       在单片机应用中,数码管是经常用的是器件之一.如果把一个简单的单片机系统看成是一台电脑,那么数码管就相当于一台电脑的显示器.现用一个2位半的数码管做个范例,循环显示0-199,稍作改造就可以做成一个计算器.使用8pin数码管,采用扫描方式驱动,4*4,正好16段.单片机使用pms152,不多说上代码.

                             

实际显示效果

#include "extern.h"

BIT        COM1             :PB.0;/*Pin8*/
BIT        COM2             :PB.1;/*Pin1*/
BIT        COM3            :PB.2;/*Pin6*/
BIT        COM4            :PB.3;/*Pin3*/

BIT        SEG1             :PB.4;/*Pin7*/
BIT        SEG2             :PB.5;/*Pin5*/
BIT        SEG3            :PB.6;/*Pin4*/
BIT        SEG4            :PB.7;/*Pin2*/

/*显示变量区域*/
byte ucLcdComVoltSw;

byte ucHun;
byte ucTen;
byte ucOne;

bit  SB2:ucHun.1;
bit  SC2:ucHun.2;

bit  SA0:ucTen.0;
bit  SB0:ucTen.1;
bit  SC0:ucTen.2;
bit  SD0:ucTen.3;
bit  SE0:ucTen.4;
bit  SF0:ucTen.5;
bit  SG0:ucTen.6;
bit  SH0:ucTen.7;


bit  SA1:ucOne.0;
bit  SB1:ucOne.1;
bit  SC1:ucOne.2;
bit  SD1:ucOne.3;
bit  SE1:ucOne.4;
bit  SF1:ucOne.5;
bit  SG1:ucOne.6;
bit  SH1:ucOne.7;


/*系统时钟变量*/
bit     FLAG_NMS;/*定时时间是否到了cinit*/
word    usSystick;
BYTE    count;/*     count区*/
word    T16COUNTER;/*定时器初始化cinit*/
word    usMsTmr;


BYTE     ucVoltChgTmr; 
BYTE     ucVoltPerc;

/*系统变量*/
word    point;

/*算法变量*/
BYTE    div_src, div_val, div_res;

void    Byte_Div_Byte (void)
{    //    div_src[B] / div_val[B]    =    div_src[B] * div_val[B] + div_res[B]
    BYTE    div_cnt;
    div_cnt    =    0;
    div_res    =    0;
    A        =    -div_val;
    div_src    <<=    1;
    do
    {
        slc        div_res;
        div_cnt++;

        div_res    +=    A;
        if (!CF)    div_res    -=    A;

        div_src    <<<=    1;
    } while (! div_cnt.3);
}


/* 共阳led表,共阴取反即可*/
void ReadLedTab ( void )
{    
    _pcadd
    {
        ret       0x3f;/*0*/
        ret    0x06;/*1*/
        ret    0x5b;/*2*/
         ret    0x4f;/*3*/
        ret    0x66;/*4*/
        ret    0x6d;/*5*/
        ret    0x7d;/*6*/
        ret    0x07;/*7*/
        ret    0x7f;/*8*/
        ret    0x6f;/*9*/
    }
}
/***************************************/
void    TIME16_Init(void)
{
    /*计数值清零*/
    T16COUNTER    =488;
    /*ms标记reset*/
    FLAG_NMS    =0;
    
    /*使能定时器*/
    INTEN.T16=1;
    /*关中断*/
    INTRQ        =    0;
    
    STT16 T16COUNTER;
    
    /*计算方法16M/*/
    $    T16M    IHRC,/1,BIT11;     
}

/*显示百分比*/
void DispVoltPerc(void)
{
    byte ucTemp;
    if(ucVoltPerc>99&&ucVoltPerc<200)
    {
       /*表示显示1*/
       ucHun=0x00;
    }
    else
    {
        ucHun=0xff;
    }

    /*把电压值变成0-99之间的值*/  
    div_src=ucVoltPerc;
    div_val=100;
    Byte_Div_Byte();
   
  
    div_src=div_res;
    div_val=10;
    Byte_Div_Byte();
    /*10 位*/
    A=(div_src+1);
    ReadLedTab();
    /*保存当前值*/
    ucTemp=A;
    /*输出为0*/
    if(ucTemp==0x3f)
    {
       /*最高位为1*/
       if(!ucHun)
       {
             /*显示十位*/
             ucTen=~ucTemp;
       }
       /*十位为0,且最高位为0*/
       else
       {
             /*十位不显示*/
             ucTen=0xff;
       }
    }
    else
    {
        ucTen=~ucTemp;
    }
    
    /*个位*/
    A=div_res+1;
    ReadLedTab();
    ucOne=~A;
    
}

void AppInit(void)
{
    ucVoltChgTmr=0;
    ucVoltPerc=0;
}

void    FPPA0 ( void )
{
    /*    SYSCLK=2MHz, one cycles =0.5 us */
    .ADJUST_IC    SYSCLK=IHRC/8, IHRC=16MHz, VDD=3.9v;
    WORD usTmp;

    TIME16_Init();

    /*全亮2s,查看数码管是否连接OK*/
    $ COM1   out,high;             
    $ COM2   out,high;             
    $ COM3   out,high;           
    $ COM4   out,high;          
    
    $ SEG1      out,low;         
    $ SEG2      out,low;          
    $ SEG3   out,low;           
    $ SEG4   out,low; 

    usTmp=200;
    while(usTmp--)
    {
          .delay 20000;
         wdreset;    //复位看门狗定时器
    }
    /*关闭显示*/
    COM1=0;        
    COM2=0;             
    COM3=0;           
    COM4=0;          
    
    SEG1=0;           
    SEG2=0;             
    SEG3=0;            
    SEG4=0;
    AppInit();
    ucVoltPerc=0;
    engint;
    while ( 1 )
    {    
        if(FLAG_NMS)
        {
            usMsTmr++;
            /*300ms更新一次*/
            if(usMsTmr>300)
            {   
                /*数字范围0-199*/
                ucVoltPerc++;
                if(ucVoltPerc>199)
                {
                    ucVoltPerc=0;
                }
                usMsTmr=0;
            }
            FLAG_NMS=0;
        }
        /*数码管显示*/
        DispVoltPerc();
        
    }
}

void IntFlashLed(void)
{
       
   ucLcdComVoltSw++;
   if(ucLcdComVoltSw>3)
   {
       ucLcdComVoltSw=0;
   }


   switch(ucLcdComVoltSw)
   {
       case 0:
       SEG1=1;
       SEG2=1;
       SEG3=1;
       SEG4=1;

       #if 1
       COM1=1;
       COM2=0;
       COM3=0;
       COM4=0;
       #endif
          if(SA0)
          {
              SEG1=1;
          }
       else
       {
              SEG1=0;
       }
       
       
       if(SB0)
          {
              SEG2=1;
          }
       else
       {
              SEG2=0;
       }
       
       
       if(SC0)
          {
              SEG3=1;
          }
       else
       {
              SEG3=0;
       }
       

       if(SD0)
          {
              SEG4=1;
          }
       else
       {
              SEG4=0;
       }
       
       
       
       break;
       
   case 1:
          SEG1=1;
       SEG2=1;
       SEG3=1;
       SEG4=1;
          #if 0
          COM1=1;
       COM2=0;
       COM3=1;
       COM4=1;
       #endif

       #if 1
       COM1=0;
       COM2=1;
       COM3=0;
       COM4=0;

       #endif
          if(SF0)
          {
              SEG1=1;
          }
       else
       {
              SEG1=0;
       }
       
       
       if(SG0)
          {
              SEG2=1;
          }
       else
       {
              SEG2=0;
       }
       
       
       if(SE0)
          {
              SEG3=1;
          }
       else
       {
              SEG3=0;
       }
       

       if(SB2)
          {
              SEG4=1;
          }
       else
       {
              SEG4=0;
       }
      
       
      
       break;

   case 2:
          SEG1=1;
       SEG2=1;
       SEG3=1;
       SEG4=1;
          #if 0
          COM1=1;
       COM2=1;
       COM3=0;
       COM4=1;
       #endif
       #if 1
          COM1=0;
       COM2=0;
       COM3=1;
       COM4=0;
       #endif
         if(SA1)
          {
              SEG1=1;
          }
       else
       {
              SEG1=0;
       }
       
       if(SB1)
          {
              SEG2=1;
          }
       else
       {
              SEG2=0;
       }
       
       if(SC1)
          {
              SEG3=1;
          }
       else
       {
              SEG3=0;
       }

       if(SD1)
          {
              SEG4=1;
          }
       else
       {
              SEG4=0;
       }
       
       
       
       
       break;
       
   case 3:
          SEG1=1;
       SEG2=1;
       SEG3=1;
       SEG4=1;
          #if 0
          COM1=1;
       COM2=1;
       COM3=1;
       COM4=0;
       #endif

       #if 1
          COM1=0;
       COM2=0;
       COM3=0;
       COM4=1;
       #endif
           if(SF1)
          {
              SEG1=1;
          }
       else
       {
              SEG1=0;
       }
       
       if(SG1)
          {
              SEG2=1;
          }
       else
       {
              SEG2=0;
       }
       
       if(SE1)
          {
              SEG3=1;
          }
       else
       {
              SEG3=0;
       }


       

       if(SC2)
          {
              SEG4=1;
          }
       else
       {
              SEG4=0;
       }
       
       break;
       
       default:
           break;
   
   }
}

void    Interrupt ( void )
{
    pushaf;
    
    
    if ( Intrq.T16 )  
    {

        Intrq.T16    =    0;

        STT16 T16COUNTER;
        IntFlashLed();
        if ( count>0 )
        {
            count--;
        }
        else
        {
            count   =   9;
            /*1ms*/
            FLAG_NMS=   1;  
        }
        
    }
    popaf;
}

 

 

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个基于ARM单片机的静态驱动数码管的接口电路及显示程序: 1. 数码管选型 选择常见的共阴极数码管,这种数码管的所有阴极都连接在一起,而每个阳极都需要单独控制。 2. 数码管数量 确定需要驱动数码管数量,这将决定所需的IO口数量。假设需要驱动4个数码管。 3. IO口数量 由于共阴极数码管需要控制每个阳极,因此需要4个IO口来控制4个数码管的阳极。此外,还需要一个IO口来控制4个数码管中的每个数码管的DP点,因此总共需要5个IO口。 4. 转换电路 由于单片机的IO口输出电压为3.3V或5V,而数码管的工作电压为1.8V至2.2V,因此需要使用转换电路将IO口的电压转换为数码管所需的电压。这可以通过使用PNP型晶体管和电阻来实现。 5. 程序设计 下面是一个基于Keil C编写的静态驱动数码管的显示程序示例: ```c #include "stm32f10x.h" // 定义数码管各段管的控制IO口 #define SEG_A GPIO_Pin_0 #define SEG_B GPIO_Pin_1 #define SEG_C GPIO_Pin_2 #define SEG_D GPIO_Pin_3 #define SEG_E GPIO_Pin_4 #define SEG_F GPIO_Pin_5 #define SEG_G GPIO_Pin_6 #define SEG_DP GPIO_Pin_7 #define SEG_GPIO GPIOB // 定义数码管阳极控制IO口 #define DIGIT_1 GPIO_Pin_0 #define DIGIT_2 GPIO_Pin_1 #define DIGIT_3 GPIO_Pin_2 #define DIGIT_4 GPIO_Pin_3 #define DIGIT_GPIO GPIOA void GPIO_Configuration(void); void delay(unsigned int count); int main() { unsigned char digit[4] = {0, 0, 0, 0}; // 定义数组存储4位数码管显示的数字 unsigned char i = 0; GPIO_Configuration(); // 配置IO口 // 循环显示 while(1) { // 数码管1 DIGIT_GPIO->BSRR = DIGIT_1; // 选择数码管1 SEG_GPIO->BSRR = (SEG_A<<16)|(SEG_B<<16)|(SEG_C<<16)|(SEG_D<<16)|(SEG_E<<16)|(SEG_F<<16)|SEG_G; // 显示数字0 delay(1); // 延时1ms DIGIT_GPIO->BRR = DIGIT_1; // 关闭数码管1 // 数码管2 DIGIT_GPIO->BSRR = DIGIT_2; // 选择数码管2 SEG_GPIO->BSRR = SEG_B|SEG_C; // 显示数字1 delay(1); // 延时1ms DIGIT_GPIO->BRR = DIGIT_2; // 关闭数码管2 // 数码管3 DIGIT_GPIO->BSRR = DIGIT_3; // 选择数码管3 SEG_GPIO->BSRR = (SEG_A<<16)|(SEG_B<<16)|(SEG_G<<16)|(SEG_E<<16)|(SEG_D<<16); // 显示数字2 delay(1); // 延时1ms DIGIT_GPIO->BRR = DIGIT_3; // 关闭数码管3 // 数码管4 DIGIT_GPIO->BSRR = DIGIT_4; // 选择数码管4 SEG_GPIO->BSRR = (SEG_A<<16)|(SEG_B<<16)|(SEG_C<<16)|(SEG_D<<16)|SEG_G; // 显示数字3 delay(1); // 延时1ms DIGIT_GPIO->BRR = DIGIT_4; // 关闭数码管4 } } // 配置IO口 void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOA和GPIOB的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); // 配置数码管各段管的控制IO口 GPIO_InitStructure.GPIO_Pin = SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G|SEG_DP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SEG_GPIO, &GPIO_InitStructure); // 配置数码管阳极控制IO口 GPIO_InitStructure.GPIO_Pin = DIGIT_1|DIGIT_2|DIGIT_3|DIGIT_4; GPIO_Init(DIGIT_GPIO, &GPIO_InitStructure); } // 延时函数 void delay(unsigned int count) { unsigned int i, j; for(i = 0; i < count; i++) for(j = 0; j < 115; j++); } ``` 以上是一个基于ARM单片机的静态驱动数码管的接口电路及显示程序示例,希望对你有所帮助。需要注意的是,以上程序只是一个简单的示例,实际应用中需要根据具体需求进行完善和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值