之前使用数码管做一些东西,由于外设比较少就直接用单片机的IO口控制数码管了。我用的3641BS四位共阳数码管,一共12个引脚,全部使用单片机IO。数码管引脚图如下:

写程序的思路是位选置1,段选为0的地方点亮显示。一般动态显示需要用到延时用于视觉暂留,以前用delay函数空等待,这样只能放在main函数的while循环里面,如果while函数中有程序占用时间过长会产生闪烁的感觉。放在定时器中断里面也会出问题。于是就取消delay函数,把动态扫描程序放在定时器中断中,利用定时器来切换数码管显示位置,方便很多。

1、先在CubeMX配置引脚 全部是输出口

2、原理图

SMG_A SMG_B SMG_C SMG_D SMG_E SMG_F SMG_G SMG_H DIG1 DIG2 DIG3 DIG4 DIG5 DIG6 DIG7 DIG8
A4 A5 A6 A7 A8 A9 A10 A11 B11 B12 B13 A0 A1 C13 C14 C15
main.h
/* USER CODE BEGIN Private defines */

#define SMG_A(a) (a?HAL_GPIO_WritePin(SMG_A_GPIO_Port,SMG_A_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_A_GPIO_Port,SMG_A_Pin,GPIO_PIN_RESET))
#define SMG_B(a) (a?HAL_GPIO_WritePin(SMG_B_GPIO_Port,SMG_B_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_B_GPIO_Port,SMG_B_Pin,GPIO_PIN_RESET))
#define SMG_C(a) (a?HAL_GPIO_WritePin(SMG_C_GPIO_Port,SMG_C_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_C_GPIO_Port,SMG_C_Pin,GPIO_PIN_RESET))
#define SMG_D(a) (a?HAL_GPIO_WritePin(SMG_D_GPIO_Port,SMG_D_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_D_GPIO_Port,SMG_D_Pin,GPIO_PIN_RESET))
#define SMG_E(a) (a?HAL_GPIO_WritePin(SMG_E_GPIO_Port,SMG_E_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_E_GPIO_Port,SMG_E_Pin,GPIO_PIN_RESET))
#define SMG_F(a) (a?HAL_GPIO_WritePin(SMG_F_GPIO_Port,SMG_F_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_F_GPIO_Port,SMG_F_Pin,GPIO_PIN_RESET))
#define SMG_G(a) (a?HAL_GPIO_WritePin(SMG_G_GPIO_Port,SMG_G_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_G_GPIO_Port,SMG_G_Pin,GPIO_PIN_RESET))
#define SMG_H(a) (a?HAL_GPIO_WritePin(SMG_H_GPIO_Port,SMG_H_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(SMG_H_GPIO_Port,SMG_H_Pin,GPIO_PIN_RESET))

#define DIG1(a) (a?HAL_GPIO_WritePin(DIG1_GPIO_Port,DIG1_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG1_GPIO_Port,DIG1_Pin,GPIO_PIN_RESET))
#define DIG2(a) (a?HAL_GPIO_WritePin(DIG2_GPIO_Port,DIG2_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG2_GPIO_Port,DIG2_Pin,GPIO_PIN_RESET))
#define DIG3(a) (a?HAL_GPIO_WritePin(DIG3_GPIO_Port,DIG3_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG3_GPIO_Port,DIG3_Pin,GPIO_PIN_RESET))
#define DIG4(a) (a?HAL_GPIO_WritePin(DIG4_GPIO_Port,DIG4_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG4_GPIO_Port,DIG4_Pin,GPIO_PIN_RESET))
#define DIG5(a) (a?HAL_GPIO_WritePin(DIG5_GPIO_Port,DIG5_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG5_GPIO_Port,DIG5_Pin,GPIO_PIN_RESET))
#define DIG6(a) (a?HAL_GPIO_WritePin(DIG6_GPIO_Port,DIG6_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG6_GPIO_Port,DIG6_Pin,GPIO_PIN_RESET))
#define DIG7(a) (a?HAL_GPIO_WritePin(DIG7_GPIO_Port,DIG7_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG7_GPIO_Port,DIG7_Pin,GPIO_PIN_RESET))
#define DIG8(a) (a?HAL_GPIO_WritePin(DIG8_GPIO_Port,DIG8_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(DIG8_GPIO_Port,DIG8_Pin,GPIO_PIN_RESET))
main.c
/* USER CODE BEGIN PD */

#define DIS_NUM 7

/* USER CODE END PD */


//                          0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F    全灭  .
uint8_t smg_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x7f};

//数码管位选表,最后一位表示全部不选择
uint8_t numb[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

uint8_t dis_pos=0;   //数码管显示位置


/*******************************************************************************
* Function Name  : Write_data
* Description    : 数码管写段选
* Input          : data :要发送的段选数据
* Output         : None
* Return         : None
*******************************************************************************/
void  Write_data(uint8_t data)
{
        if((data & 0x80) >> 7)    SMG_H(1);
        else  SMG_H(0);     
            if((data & 0x40) >> 6)  SMG_G(1);
        else  SMG_G(0);     
            if((data & 0x20) >> 5)  SMG_F(1);
        else  SMG_F(0);     
            if((data & 0x10) >> 4)  SMG_E(1);
        else  SMG_E(0);     
            if((data & 0x08) >> 3)  SMG_D(1);
        else  SMG_D(0);     
            if((data & 0x04) >> 2)  SMG_C(1);
        else  SMG_C(0);     
            if((data & 0x02) >> 1)  SMG_B(1);
        else  SMG_B(0);     
            if((data & 0x01) )      SMG_A(1);
        else  SMG_A(0);     
}


/*******************************************************************************
* Function Name  : dis_bit
* Description    : 数码管显示位置,用于选择某个要显示的数码管
* Input          : pos : 数码管位置
* Output         : None
* Return         : None
*******************************************************************************/
void  dis_bit(uint8_t pos)
{
    switch(pos)
    {
        case 0x01:
            DIG1(0); DIG2(1); DIG3(1); DIG4(1);    DIG5(1); DIG6(1); DIG7(1); DIG8(1);    
        break;
        case 0x02:
            DIG1(1); DIG2(0); DIG3(1); DIG4(1);    DIG5(1); DIG6(1); DIG7(1); DIG8(1);    
        break;
        case 0x04:
            DIG1(1); DIG2(1); DIG3(0); DIG4(1);    DIG5(1); DIG6(1); DIG7(1); DIG8(1);    
        break;
        case 0x08:
            DIG1(1); DIG2(1); DIG3(1); DIG4(0);    DIG5(1); DIG6(1); DIG7(1); DIG8(1);    
        break;
        case 0x10:
            DIG1(1); DIG2(1); DIG3(1); DIG4(1);    DIG5(0); DIG6(1); DIG7(1); DIG8(1);    
        break;
        case 0x20:
            DIG1(1); DIG2(1); DIG3(1); DIG4(1);    DIG5(1); DIG6(0); DIG7(1); DIG8(1);    
        break;
        case 0x40:
            DIG1(1); DIG2(1); DIG3(1); DIG4(1);    DIG5(1); DIG6(1); DIG7(0); DIG8(1);    
        break;
        case 0x80:
            DIG1(1); DIG2(1); DIG3(1); DIG4(1);    DIG5(1); DIG6(1); DIG7(1); DIG8(0);    
        break;

    }
}


/*******************************************************************************
* Function Name  : dis_num
* Description    : 数码管显示数据
* Input          : num:要显示的数据
* Output         : None
* Return         : None
*******************************************************************************/
void  dis_num(uint16_t num1,uint16_t num2)
{
    uint8_t tab[8];    //定义一个数组,用于存放各个数码管显示的数据
    tab[7]=smg_code[num1%10000/1000]& smg_code[17];
    tab[6]=smg_code[num1%1000/100];
    tab[5]=smg_code[num1%100/10] ;
    tab[4]=smg_code[num1%10];       //分离数据
    
    tab[3]=smg_code[num2%10000/1000];
    tab[2]=smg_code[num2%1000/100];
    tab[1]=smg_code[num2%100/10] & smg_code[17];
    tab[0]=smg_code[num2%10];       //分离数据
 
    Write_data(smg_code[16]);   //段选全不亮,消影
  Write_data(tab[dis_pos]);   //送段选
    dis_bit(numb[dis_pos]);     //送位选
}



显示的内容要在定时器里写
dis_num(1200,time);    //显示数据
        dis_pos++;        //数码管位置变化1位
        if(dis_pos>DIS_NUM)    dis_pos=0;  //限定数码管显示位数,可改小DIS_NUM得到想要的位数    

 

发表回复

后才能评论