蓝桥杯单片机设计与开发(2) 数码管的显示与闪烁
今天我们介绍一下蓝桥杯开发板数码管模块的操作。
我们先来介绍一下数码管的动态扫秒原理:
数码管分为有两种,共阳数码管和共阴数码管。一个数码管上有段选和位选,位选是送入高低电平使得数码管显示,段选送入需要显示的数据。蓝桥杯比赛采用的是共阳数码管。
这是开发板的数码管原理图。Y7C控制数码管的段选,Y6C控制数码管的位选,有74HC138控制,当Y7C为高电平时可以送入数据,为低电平时处于索存状态。
void enable138(uchar x)
{
P2&=0X1f; //先将138 A B C 置位0 0 0输出Y0为低,其他为高
P2|=(x<<5); //X左移5位后通过或非门对对应的74HC573送入数据
_nop_();
_nop_();
P2&=0X1f;//在此将P2置位
}
这是上文中的HC138代码。
我们先建立好工程。
上代码了:
smg.c
# include "smg.h"
uchar code smgDU[34]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,//0 ~F
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0E,//0.~F.
0xff,0xbf}; //灭 -
uchar smgWE[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar displaydat[8]={1,2,3,4,5,6,7,8};//数码管一定会立刻显示的内容
uchar flashset=0x00;
uint flashT=400;//数码管闪烁周期为400ms,1ms进入一次定时器0中断
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;//开启总中断
ET0=1;//开启定时器0中断
}
void smgdisplay()//数码管子扫描函数,放入中断
{
static uchar WhichWE=0;
P0=0XFF;
enable138(DU);
P0=smgWE[WhichWE];
enable138(WE);
P0=smgDU[displaydat[WhichWE]];
enable138(DU);
WhichWE++;
if(WhichWE==8)
{
WhichWE=0;
}
}
void smg_set(uchar dat1,uchar dat2,uchar dat3,uchar dat4,uchar dat5,uchar dat6,uchar dat7,uchar dat8)//数据传送函数,放入main函数
{
displaydat[0]=dat1;
displaydat[1]=dat2;
displaydat[2]=dat3;
displaydat[3]=dat4;
displaydat[4]=dat5;
displaydat[5]=dat6;
displaydat[6]=dat7;
displaydat[7]=dat8;
}
void flash_service()
{
uchar i;
static uint flashcount=0;
flashcount++;
if(flashcount<flashT/2)//前半个周期给需要闪烁的无效位选
{
for(i=0;i<8;i++)
{
if(flashset&(0x80>>i))//如果是需要闪烁的给无效位选,
{
smgWE[i]=0x00;
}
else //如果不是需要闪烁的给有效位选
{
smgWE[i]=0x01<<i;
}
}
}
else if(flashcount<flashT)//后半个周期给有效位选
{
for(i=0;i<8;i++)
{
smgWE[i]=0x01<<i;
}
}
else
{
flashcount=0;
}
}
void Timer0() interrupt 1
{
smgdisplay();
flash_service();
}
smg.h
#ifndef _SMG_H_
#define _SMG_H_
# include "include.h"
extern uchar flashset;
void Timer0Init(void);
void flash_service();
void smgdisplay();
void smg_set(uchar dat1,uchar dat2,uchar dat3,uchar dat4,uchar dat5,uchar dat6,uchar dat7,uchar dat8);
#endif
main函数
# include"include.h"
void suoyouwaishe_Init()
{
P0=0xff;
enable138(LED);
P0=0x00;
enable138(ULN2003);
P0=0x00;
enable138(WE);
P0=0xff;
enable138(DU);
}
void main()
{
suoyouwaishe_Init();
Timer0Init();
flashset=0xc0;
while(1)
{
smg_set(15,14,13,12,11,10,9,8);
}
}
include.h
#ifndef _INCLUDE_H_
#define _INCLUDE_H_
#define uchar unsigned char
#define uint unsigned int
#include "STC15F2K60S2.h"
#include "intrins.h"
# include "enable138.h"
# include "smg.h"
#endif
如果想实现闪烁位置的改变,只需要修改flashset的值就可以。
拓展:
关于传参函数,还有一种通过指针的方式进行传递:
void smg_set(uchar *smgdatastore)
{
uchar i;
for(i=0;i<8;i++)
{
displaydat[i]=*(smgdatastore+i);
}
}
main函数
# include"include.h"
uchar smgdatastore[8]={1,2,3,4,5,6,7,8};
void suoyouwaishe_Init()
{
P0=0xff;
enable138(LED);
P0=0x00;
enable138(ULN2003);
P0=0x00;
enable138(WE);
P0=0xff;
enable138(DU);
}
void main()
{
suoyouwaishe_Init();
Timer0Init();
flashset=0xc0;
while(1)
{
smg_set(smgdatastore);
}
}
若果是不需要计算的情况下可以这样写,其他的情况下可以修改为(例如):
void main()
{
uchar smgdatastore[8]={0};
uchar keyvalue=244;
suoyouwaishe_Init();
Timer0Init();
flashset=0xc0;
while(1)
{
smgdatastore[5]=keyvalue/100%10;
smgdatastore[6]=keyvalue/10%10;
smgdatastore[7]=keyvalue%10;
smg_set(smgdatastore);
}
}
代码下载链接 https://download.csdn.net/download/weixin_44874337/12156480