程序设计目标及程序运行效果说明
(1)用STC ISP默认设置,打开工程中的HEX并下载
(2)下载后观察现象为:8个数码管从00-00-00开始计数,最右边二极管被点亮(默认为最高扫描频率所以秒部分变化很快)
(3)辅助操作:长按下key1数码管扫描频率减半,从右起第二个二极管点亮、第一个灭,上方数码管显示的内容有轻微的闪动;再长按下key1,扫描频率继续减半,从右起第三个二极管点亮、第二个灭,数码管闪动明显;继续按下key1键,跳动现象更加明显…接下来观察单个LED数码管2次被点亮的时间间隔:当key1控制到左起第三个二极管点亮时,左起第5个LED数码管两次点亮的时间间隔为1;当key1控制到左起第二个二极管点亮时,点亮左起第5个LED数码管的间隔为2,从此以后可以看到一次只有一个LED数码管点亮;当key1控制到最左边二极管点亮时,点亮左起第5个LED数码管的间隔为4,此时扫描频率最低;再按key1,最右边二极管点亮,重新以最快速度扫描,如此重复操作。

程序相关电路及工作原理说明

1.LED数码管电路

python 二极管 计时器 二极管时钟_python 二极管 计时器


2.按键电路

python 二极管 计时器 二极管时钟_单片机_02


3.工作原理

本实验中同时用发光二极管和LED数码管,由于其功用P0口,所以采用分时复用的形式。

代码如下:

#include "STC15F2K60S2.h"
#include "intrins.h"
#define uint unsigned int
#define uchar unsigned char
#define i1 interrupt 1
sbit ledSel=P2^3; // led or digital tube
sbit key1=P3^2; //控制数码管扫描频率
uchar baseSevenSegment[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//段选
unsigned char const line=0x40;//横杠的七段码
char timeAddOneFlag=0;    //标记为1,此时需要秒+1
char key1ActionFlag=0;    //值为1时表示按键操作需要执行
unsigned int ledOnFlag=0; //led亮
char tubeOnFlag=0;        //数码管亮
int ledValue=1;           //led显示数值
int myDisplay[8]={0};     //数码管显示内容
unsigned int timeCount=1; //时间计时器
unsigned int currHour=0;
unsigned int currMinute=0;
unsigned int currSecond=0;
unsigned int interruptCount=0;
unsigned int keyDownTime=0;
unsigned int scanTime=1;  //扫描时间
unsigned int currBit=0;   //当前显示的位
void Delay5us()       //@11.0592MHz
{
    unsigned char i;
    _nop_();
    i = 11;
    while(--i);
}
//设置ledSel,转为数码管显示
void switchToTube()
{
    ledSel=0;
}
//设置ledSel,转为led设置
void switchToLed()
{
    P0=0;
    ledSel=1;
}
/**
 * 改变其中一位的内容
 *
 * @param bitNum 位数(第几位)(例如最左那位,则调用1)
 * @param value 改变后的数字,确保大于0小于10
 */
void change1Bit(int bitNum,int value)
{
    myDisplay[bitNum-1]=baseSevenSegment[value];
}
/**
 * 改变其中一位的内容(设置七段码)
 *
 * @param bitNum 位数(第几位)(例如最左那位,则调用1)
 * @param sevenSegCode 目标七段码
 */
void change1Bit_seven(int bitNum,int sevenSegCode)
{
    myDisplay[bitNum-1]=sevenSegCode;
}
/**
 * 数码管设置为显示指定的长度
 *
 * @param num 数字
 */
void changeAll(long num)
{
    int i;
    for(i=7;i>=0;--i)
	{
        int foo=num%10;
        myDisplay[i]=baseSevenSegment[foo];
        num/=10;
    }
}
//led亮
void displayLed()
{
    if(ledOnFlag)
	{
        switchToLed();
        P0=ledValue;
    }
}
//显示数码管
void showTube()
{
    if(tubeOnFlag)
	{
        switchToTube();
        P0=0;
        P2=currBit;
        P0=myDisplay[currBit];
        Delay5us();
    }
}
//初始化定时器
void timer0Initialize()        //0.1毫秒@12MHz
{

    AUXR|=0x80;        //定时器时钟1T模式
    TMOD&=0xF0;        //设置定时器模式
    TL0=0xAE;        //设置定时器初值
    TH0=0xFB;        //设置定时器初值
    TF0=0;        //清除TF0标志
    TR0=1;        //定时器0开始计时
    EA=1; //打开总中断
    ET0=1; //打开定时器0中断
}
//初始化
void initialize()
{
    P0M0=0xFF;
    P0M1=0x00;
    P2M0=0x0f; //设置P2.0-3为推挽模式
    P2M1=0x00;
    ledSel=0;
    timer0Initialize();
    changeAll(0);
		//第三位和第六位设置为'-'
    change1Bit_seven(3,line);
    change1Bit_seven(6,line);
}
//时间自增1s
void addTime()
{
    ++currSecond;
    if(currSecond==60)
	{
        ++currMinute;
        currSecond=0;
        if(currMinute==60)
		{
            ++currHour;
            currMinute=0;
            if(currHour==24)
                currHour=0;
            change1Bit(2,currHour%10);
            change1Bit(1,currHour/10);
        }
        change1Bit(5,currMinute%10);
        change1Bit(4,currMinute/10);
    }
    change1Bit(8,currSecond%10);
    change1Bit(7,currSecond/10);
}
//按下key1要做的事
void key1Action()
{
    if(key1ActionFlag)
	{
        if(ledValue==0x80)
            ledValue=0x01;
        else
            ledValue<<=1;
        if(ledValue==1)
            scanTime=1;
        else if(ledValue==2)
            scanTime=50;
        else if(ledValue==4)
            scanTime=100;
        else if(ledValue==8)
            scanTime=200;
        else if(ledValue==16)
            scanTime=500;
        else if(ledValue==32)
            scanTime=1000;
        else if(ledValue==64)
            scanTime=2000;
        else if(ledValue==128)
            scanTime=5000;
        key1ActionFlag=0;
    }
}
//收到中断的信号(是时候自增时间了)
void timeSignalHandler()
{
    if(timeAddOneFlag)
	{
        addTime();
        timeAddOneFlag=0;
    }
}
//每0.1ms进入一次定时器中断
void interruptFunction()i1
{
    static const int KEY_TIME_THRESHOLD=500;
    interruptCount=(interruptCount+1)%20000;
    //led显示的频率应该低些才有好的显示效果
    if(interruptCount%12>10)
	{
        ledOnFlag=1;
        tubeOnFlag=0;
    }
	else
	{
        tubeOnFlag=1;
        ledOnFlag=0;
    }
    //数码管的扫描
    if(interruptCount%scanTime==0)
        currBit=(currBit+1)%8;
    //读秒
    if(interruptCount%10000==0)
        timeAddOneFlag=1;
    //按键功能设置
    if(key1==0)
	{
        if(keyDownTime<KEY_TIME_THRESHOLD)
            ++keyDownTime;
    }
	else
	{
        if(keyDownTime>=KEY_TIME_THRESHOLD)
            key1ActionFlag=1;
        keyDownTime=0;
    }
}
int main()
{
    initialize();
    while(1)
	{
        timeSignalHandler();
        displayLed();
        showTube();
        key1Action();
    }
    return 0;
}