一.数码管原理:
见上图,上图是一个数码管的内部示意图,它们的发光原理和普通发光二极管是一样的,所以可将数码管的亮段当成几个发光二极管。根据内部发光二极管的共连接端不同,可以分为共阳极接法和共阴极接法,共阳极接法就是七个发光二极管的正极共同接电源VCC,通过控制每个发光二极管的负极是否接地来显示数字。共阴极接法就是车个发光二极管的负极共同接地GND,通过控制每个发光二极管的正极是否接电源来显示数字。图中A~G管脚分别控制着每个发光二极管的亮暗,所以,如果要显示1的话,只需要点亮B,C两段即可;如果要显示数字5,则只需要点亮a,f,g,c,d段即可组成数字5的显示。
在实际电路中,如果要显示0~9这10个数字时,就会发现显示的数字和对应的亮暗组合之间关联性不强,不利于实现电路的控制,并且有点浪费单片机I/O口,所以我们通常不直接控制内部的亮段,而是使用一个译码器的东西对数码管进行驱动,如上图,这样只需向译码器中输入BCD码就可以得到相应的数字显示。
二.代码:
共阳数码管:
#include "stm32f10x.h"
u8 table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80};//共阳数码管0 1 2 3 4 5 6 7 8的编码
void delayms(u16 time)//延时函数 延时1ms
{
u16i=0;
while(time--)
{
i=12000;
while(i--);
}
}
void Init()
{
GPIO_InitTypeDef GPIO_InitStructure; //定义一个管脚初始化的结构体
//开启PA口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//配置PAO的模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
int main(void)
{
Init();
while(1)
{
inti;
for(i=0;i<9;i++)
{
GPIO_Write(GPIOA,table[i]);
delayms(200);
}
}
}
共阴数码管:
#include"stm32f10x.h"
u8 table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f};//0 1 2 3 4 5 6 7 8 9
void delayms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000;
while(i--);
}
}
void InitStm32()
{
GPIO_InitTypeDef GPIO_InitStructure; //定义一个管脚初始化的结构体
//开启PA口时钟
GPIO_InitTypeDef DuanAndWeiMa;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
//配置PAO的模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;
DuanAndWeiMa.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
DuanAndWeiMa.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
DuanAndWeiMa.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_Init(GPIOB,&DuanAndWeiMa);
}
intmain(void)
{
InitStm32();
while(1)
{
GPIO_SetBits(GPIOB,GPIO_Pin_1);
GPIO_Write(GPIOA,0xfe);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
GPIO_Write(GPIOA,table[0]);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
delayms(2);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
GPIO_Write(GPIOA,0xfd);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
GPIO_Write(GPIOA,table[1]);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
delayms(2);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
GPIO_Write(GPIOA,0xfb);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
GPIO_Write(GPIOA,table[2]);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
delayms(2);
GPIO_SetBits(GPIOB,GPIO_Pin_1);
GPIO_Write(GPIOA,0xf7);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
GPIO_Write(GPIOA,table[2]);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
delayms(2);
}
}
三.总结:
学长让我们做数码管,主要是为了锻炼和考察我们对寄存器的应用。所有做完库函数版本后,我又理解了一下寄存器版本。同时学姐也提供了一种新的思路,通过io口直接分段控制led来使数码管显示不同的数字。这三种方法,寄存器版本最底层,对初学者更有帮助。库函数主要是锻炼一下对库函数的使用。io口直接控制则更考验代码功底。