单片机教学打铃控制器C语言

本设计介绍了一款基于AT89S52单片机的智能教学楼打铃控制系统,通过按键进行时间及闹铃设置,利用AT24C02存储设置的数据,并实现了动态扫描显示当前时间和已设定的闹铃时间。该系统还具备闹铃增加、删除等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
            湖南师范大学工学院课程设计    单片机教学打铃控制器
    芯      片:AT89S52
    晶      振:频率12MHz
    按键说明:
              BellSet   P1^0//时间设置
              TimeSet   P1^1//闹铃设置
              LeftMove  P1^2//向左移动
              Add          P1^3//数据增加
              Sub        P1^4//数据减小
              RightMove P1^5//向右移动
              ESC        P1^6//取消
              Enter      P1^7//确定

*/
#include "AT89X52.H"
#include "intrins.h"


#define A24C02W 0xa0//24C02的写地址
#define A24C02R  0xa1//24C02的读地址

unsigned char TimeData[]={0,0,0};//时钟数据
unsigned char BellDataH[40];//40个闹铃点(时)
unsigned char BellDataL[40];//40个闹铃点(分)
unsigned char BellCount=0;//闹铃总数
unsigned char counter=0;
unsigned char I2cStartB=0xaa;//I2c开始标志字
unsigned char I2cEndB=0x55;//I2c结束标志字
unsigned char RayFlag1=0;//秒闪标志1
sbit RayFlag=P3^1;//秒闪
sbit RayFlag2=P3^0;//秒闪标志2
sbit AlarmSingal=P3^4;//闹铃信号
sbit SDA=P3^2;//I2C BUS数据
sbit SCL=P3^3;//I2C BUS时钟

/*
void Timer1(void)interrupt 3 using 1
unsigned char BCD_to_Text(unsigned char Data)
unsigned char GetClockBit(unsigned char ShowBit)
void Delay(unsigned char count)
void D_Scan(unsigned char *ShowAddress,unsigned char FlagBit)
unsigned char GetKey()
void I2cWait()
void I2cStart()
void I2cStop()
void I2cSend(unsigned char ByteData)
unsigned char I2cReceive()
void I2cWrite24C02(unsigned char I2c24C02Addr,unsigned char I2c24C02Data)
unsigned char I2cRead24C02(unsigned char I2c24C02Addr)
void Init24C02(void)
void Order(void)
void BellSet(void)
void TimeSet()

*/
//--------------------------定义I2C接口子程序-------------------------
/*
I2C特殊字节定义
*/
void I2cWait()//等待
{
    _nop_();
    _nop_();
}
   
void I2cStart()//开始
{   
    SDA=1;
    SCL=1;
    I2cWait();
    SDA=0;
    I2cWait();
    SCL=0;
}

void I2cStop()//停止
{
    SDA=0;
    I2cWait();
    SCL=1;
    I2cWait();
    SDA=1;
}
void I2cSend(unsigned char ByteData)//发送
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        if(ByteData&0x80)
            SDA=1;
        else
            SDA=0;
        ByteData<<=1;
        I2cWait();
        SCL=1;
        I2cWait();
        SCL=0;
        I2cWait();
    }
    SDA=1;
    I2cWait();
    SCL=1;
    I2cWait();
    SCL=0;
    I2cWait();
}

unsigned char I2cReceive()//接收
{
    unsigned char i;
    unsigned char ByteData=0;
    for(i=0;i<8;i++)
    {
        SCL=1;
        I2cWait();
        ByteData<<=1;
        if(SDA)ByteData++;
        SCL=0;
        I2cWait();
    }
    SDA=1;
    I2cWait();
    SCL=1;
    I2cWait();
    SCL=0;
    I2cWait();
    return ByteData;
}
//--------------------------声明AT24C02的读写子程序-------------------
void I2cWrite24C02(unsigned char I2c24C02Addr,unsigned char I2c24C02Data)//写
{
    I2cStart();
    I2cSend(A24C02W);
    I2cSend(I2c24C02Addr);
    I2cSend(I2c24C02Data);
    I2cStop();
}

unsigned char I2cRead24C02(unsigned char I2c24C02Addr)//读
{
    unsigned char Data;
    I2cStart();
    I2cSend(A24C02W);
    I2cSend(I2c24C02Addr);
    I2cStart();
    I2cSend(A24C02R);
    Data=I2cReceive();
    I2cStop();
    return Data;
}
//-------------------------初始化24C02-----------------------------
void Init24C02(void)
{
    unsigned char i,j;
    unsigned char StartByte=I2cRead24C02(0);
    j=1;
    if(StartByte==I2cStartB)
        for(i=0;i<40;i++)
        {
            if(I2cRead24C02(j)==I2cEndB)break;
            BellDataH[i]=I2cRead24C02(j++);
            BellDataL[i]=I2cRead24C02(j++);
            BellCount++;
        }
    else
        {
            I2cWrite24C02(0,I2cStartB);
            I2cWrite24C02(1,I2cEndB);
        }
}




//---------------------T1中断,产生时钟-------------------------------
void Timer1(void)interrupt 3 using 1
{
    TH1=0x3c;
    TL1=0xb0;
    if(counter%10==0)
    {
        RayFlag2=~RayFlag2;
        if(RayFlag1)RayFlag=0;
        else RayFlag=~RayFlag;
    }
    if(counter==20)
    {
        counter=1;
        if(TimeData[0]==59)
        {
            TimeData[0]=0;
            if(TimeData[1]==59)
            {
                TimeData[1]=0;
                if(TimeData[2]==23)
                {
                    TimeData[2]=0;
                }
                else TimeData[2]++;//时
            }
            else TimeData[1]++;//分
        }
        else TimeData[0]++;//秒
    }
    else counter++;   
}
//------------------BCD码转换成字形码的程序-----------------------------
unsigned char BCD_to_Text(unsigned char Data)
{
    switch(Data)
    {
        case 0:return 0x3f;
        case 1:return 0x06;
        case 2:return 0x5b;
        case 3:return 0x4f;
        case 4:return 0xe6;
        case 5:return 0xed;
        case 6:return 0xfd;
        case 7:return 0x07;
        case 8:return 0xff;
        case 9:return 0xef;
    }
}

//-----------------------------得到位地址的程序-------------------------
unsigned char GetClockBit(unsigned char ShowBit)
{
    switch(ShowBit)
    {
        case 0:return 0xdf;
        case 1:return 0xef;
        case 2:return 0xf7;
        case 3:return 0xfb;
        case 4:return 0xfd;
        case 5:return 0xfe;
    }
}
//---------------------延时count个ms的程序-------------------------
void Delay(unsigned char count)
{
    unsigned char i;
    while(count--)
    {
        for(i=0;i<123;i++)
        ;
    }
}
//-----------------------动态扫描的程序-------------------------------
void D_Scan(unsigned char *ShowAddress,unsigned char FlagBit)
{
    unsigned char ShowBit;
    unsigned char Show;
    for(ShowBit=0;ShowBit<6;ShowBit++)
    {
        if(FlagBit!=5)
        {
            switch(ShowBit)
            {
                case 0:Show=BCD_to_Text((*ShowAddress)%10);break;
                case 1:Show=BCD_to_Text((*ShowAddress)/10);break;
                case 2:Show=BCD_to_Text((*(ShowAddress+1))%10);break;
                case 3:Show=BCD_to_Text((*(ShowAddress+1))/10);break;
                case 4:Show=BCD_to_Text((*(ShowAddress+2))%10);break;
                case 5:Show=BCD_to_Text((*(ShowAddress+2))/10);break;
            }
        }
        P2=0xff;
        switch(FlagBit)
        {
            case 0:P0=Show;break;
            case 1://设秒闪动
                    if(RayFlag2 && (ShowBit==0||ShowBit==1))P0=0x40;
                    else P0=Show;
                    break;
            case 2://设分闪动
                    if(RayFlag2 && (ShowBit==2||ShowBit==3))P0=0x40;
                    else P0=Show;
                    break;
            case 3://设时闪动
                    if(RayFlag2 && (ShowBit==4||ShowBit==5))P0=0x40;
                    else P0=Show;
                    break;
            case 4://调闹铃时的闪动
                    if(RayFlag2)P0=0x40;
                    else P0=Show;
                    break;
            case 5://调闹铃时的显示
                    P0=*(ShowAddress+ShowBit);
                    break;
        }   
        P2=GetClockBit(ShowBit);
        Delay(1);
    }
}

//----------------得到键盘值的程序----------------------------------
unsigned char GetKey()
{
    switch(P1)
    {
        case 0xff:return 0;
        case 0xfe:return 1;
        case 0xfd:return 2;
        case 0xfb:return 3;
        case 0xf7:return 4;
        case 0xef:return 5;
        case 0xdf:return 6;
        case 0xbf:return 7;
        case 0x7f:return 8;
    }
}



//-------------------排序的程序------------------------------------
void Order(void)
{
    unsigned char i,j,t;
    for(i=0;i<BellCount;i++)
        for(j=0;j<BellCount-i-1;j++)
            {
                if(BellDataH[j]>BellDataH[j+1])
                    {
                        t=BellDataH[j];
                        BellDataH[j]=BellDataH[j+1];
                        BellDataH[j+1]=t;
                        t=BellDataL[j];
                        BellDataL[j]=BellDataL[j+1];
                        BellDataL[j+1]=t;
                    }
                else if(BellDataH[j]==BellDataH[j+1])
                        if(BellDataL[j]>BellDataL[j+1])
                            {
                                t=BellDataL[j];
                                BellDataL[j]=BellDataL[j+1];
                                BellDataL[j+1]=t;
                            }
            }   
}

//---------------------------闹铃设置--------------------------------
void BellSet(void)
{
    unsigned char Null[]={0x00,0x38,0x38,0x3e,0x37,0x00};//"Null"的字形码
    unsigned char ShowRing[3];
    unsigned char NowKey;
    unsigned char i,j=1;
    unsigned char BeforKey=0xff;
    unsigned char KeyCount=0;
    unsigned char FlagBit=3;
    unsigned char ShowBellCount=0;
    unsigned char count1=0x40;//无操作时的时间控制
    unsigned char count2=0xff;//无操作时的时间控制
    RayFlag1=1;
    ShowRing[0]=BellDataL[ShowBellCount];
    ShowRing[1]=BellDataH[ShowBellCount];
    ShowRing[2]=ShowBellCount;
    while(1)
    {
        if(BellCount==0)
            D_Scan(Null,5);
        else
            D_Scan(ShowRing,FlagBit);
        if(KeyCount==2)
        {
            KeyCount=0;
            NowKey=GetKey();
            if(NowKey!=BeforKey)
            {
                count1=0x40;
                count2=0xff;
                switch(NowKey)
                {
                    case 1://增加一个闹铃
                            if(BellCount!=40 && FlagBit==4)
                            {
                                BellDataH[BellCount]=BellDataL[BellCount]=0;   
                                ShowBellCount=BellCount++;
                            }
                            if(BellCount==0)
                            {
                                BellDataH[0]=BellDataL[0]=0;
                                BellCount++;
                            }
                            ShowRing[0]=BellDataL[ShowBellCount];
                            ShowRing[1]=BellDataH[ShowBellCount];
                            ShowRing[2]=ShowBellCount;
                            break;
                    case 2://删除一个闹铃
                            if(BellCount!=0 && FlagBit==4)
                            {
                                if(BellCount==1)
                                {
                                    BellDataH[0]=BellDataL[0]=0;
                                }
                                else
                                    {
                                        for(i=ShowBellCount;i<BellCount;i++)
                                        {
                                            BellDataH[i]=BellDataH[i+1];
                                            BellDataL[i]=BellDataL[i+1];
                                        }
                                        BellDataH[i]=BellDataL[i]=0;
                                    }
                                BellCount--;   
                                if(BellCount==ShowBellCount)
                                    ShowBellCount--;
                                ShowRing[0]=BellDataL[ShowBellCount];
                                ShowRing[1]=BellDataH[ShowBellCount];
                                ShowRing[2]=ShowBellCount;
                            }
                            break;

                    case 3://左移
                            if(BellCount!=0)
                            {
                                if(FlagBit==4)FlagBit=1;
                                else FlagBit++;
                            }
                            break;
                    case 4://闹铃时间增
                            switch(FlagBit)
                            {
                                case 1:
                                        if(ShowRing[0]==59)
                                            ShowRing[0]=0;
                                        else
                                            ShowRing[0]++;
                                        BellDataL[ShowBellCount]=ShowRing[0];
                                        break;
                                case 2:
                                        if(ShowRing[1]==23)
                                            ShowRing[1]=0;
                                        else
                                            ShowRing[1]++;
                                        BellDataH[ShowBellCount]=ShowRing[1];
                                        break;
                                case 3:
                                        if(ShowBellCount==BellCount-1)
                                            ShowBellCount=0;
                                        else
                                            ShowBellCount++;
                                        ShowRing[0]=BellDataL[ShowBellCount];
                                        ShowRing[1]=BellDataH[ShowBellCount];
                                        ShowRing[2]=ShowBellCount;
                                        break;
                            }
                            break;
                    case 5://闹铃时间减
                            switch(FlagBit)
                            {
                                case 1:
                                        if(ShowRing[0]==0)
                                            ShowRing[0]=59;
                                        else
                                            ShowRing[0]--;
                                        break;
                                case 2:
                                        if(ShowRing[1]==0)
                                            ShowRing[1]=23;
                                        else
                                            ShowRing[1]--;
                                        break;
                                case 3:
                                        if(ShowBellCount==0)
                                            ShowBellCount=BellCount-1;
                                        else
                                            ShowBellCount--;
                                        ShowRing[0]=BellDataL[ShowBellCount];
                                        ShowRing[1]=BellDataH[ShowBellCount];
                                        ShowRing[2]=ShowBellCount;
                                        break;
                            }
                            break;
                    case 6://右移
                            if(BellCount!=0)
                            {
                                if(FlagBit==1)FlagBit=4;
                                else FlagBit--;
                            }
                            break;
                    case 7://取消
L3:                            j=1;
                            BellCount=0;
                            EA=0;
                            for(i=0;i<40;i++)
                            {
                                if(I2cRead24C02(j)==I2cEndB)break;
                                BellDataH[i]=I2cRead24C02(j++);
                                BellDataL[i]=I2cRead24C02(j++);
                                BellCount++;
                            }
                            EA=1;
                            goto L2;
                    case 8://确定
                            j=1;
                            BellDataL[ShowBellCount]=ShowRing[0];
                            BellDataH[ShowBellCount]=ShowRing[1];
                            Order();//排序
                            for(i=0;i<BellCount;i++)
                            {
                                EA=0;
                                I2cWrite24C02(j++,BellDataH[i]);
                                EA=1;
                                D_Scan(ShowRing,FlagBit);
                                EA=0;
                                I2cWrite24C02(j++,BellDataL[i]);
                                EA=1;
                                D_Scan(ShowRing,FlagBit);
                            }
                            EA=0;
                            I2cWrite24C02(j,I2cEndB);
                            EA=1;
                            if(BellCount==0)
                                D_Scan(Null,5);
                            else
                                D_Scan(ShowRing,FlagBit);
                            goto L2;
                               
                } 
            }
            BeforKey=NowKey;
            count2--;
            if(count2==0)
            {
                count2=0x40;
                count1--;
                if(count1==0)
                    goto L3;
            }
        }
        else KeyCount++;
    }
L2:RayFlag1=0;
}

//-------------时间设置的程序--------------------------------------------
void TimeSet()
{
    unsigned char S_Flag=1;
    unsigned char M_Flag=1;
    unsigned char H_Flag=1;
    unsigned char count1=0x40;//无操作时的时间控制
    unsigned char count2=0xff;//无操作时的时间控制
    unsigned char NowKey=0xff;
    unsigned char BeforKey=0xff;
    unsigned char KeyCount=0;
    unsigned char FlagBit=1;
    unsigned char LS_TimeData[3];
    LS_TimeData[2]=TimeData[2];
    LS_TimeData[1]=TimeData[1];
    LS_TimeData[0]=TimeData[0];
    while(1)
    {
        if(S_Flag)LS_TimeData[0]=TimeData[0];
        if(M_Flag)LS_TimeData[1]=TimeData[1];
        if(H_Flag)LS_TimeData[2]=TimeData[2];
        D_Scan(LS_TimeData,FlagBit);//动态扫描显示
        if(KeyCount==2)
        {
       
            KeyCount=0;
            NowKey=GetKey();
            if(NowKey!=BeforKey)
            {
                count1=0x40;
                count2=0xff;
                switch(GetKey())
                {
                    case 3://向左移动
                            if(FlagBit==3)FlagBit=1;
                            else FlagBit++;
                            break;
                    case 4://增加
                            switch(FlagBit)
                            {
                                case 1://秒增加
                                        if(LS_TimeData[0]==59)
                                            LS_TimeData[0]=0;
                                        else LS_TimeData[0]++;   
                                        S_Flag=0;
                                        break;
                                case 2://分增加
                                        if(LS_TimeData[1]==59)
                                            LS_TimeData[1]=0;
                                        else LS_TimeData[1]++;
                                        M_Flag=0;
                                        break;
                                case 3://时增加
                                        if(LS_TimeData[2]==23)
                                            LS_TimeData[2]=0;
                                        else LS_TimeData[2]++;
                                        H_Flag=0;
                                        break;
                            }
                            break;
                    case 5://减小
                            switch(FlagBit)
                            {
                                case 1://秒减小
                                        if(LS_TimeData[0]==0)
                                            LS_TimeData[0]=59;
                                        else LS_TimeData[0]--;
                                        S_Flag=0;
                                        break;
                                case 2://分减小
                                        if(LS_TimeData[1]==0)
                                            LS_TimeData[1]=59;
                                        else LS_TimeData[1]--;
                                        M_Flag=0;
                                        break;
                                case 3://时减小
                                        if(LS_TimeData[2]==0)
                                            LS_TimeData[2]=23;
                                        else LS_TimeData[2]--;
                                        H_Flag=0;
                                        break;
                            }
                            break;
                    case 6://向右移动
                            if(FlagBit==1)FlagBit=3;
                            else FlagBit--;
                            break;
                    case 7://取消
                            goto L1;
                    case 8://确定
                            TimeData[2]=LS_TimeData[2];
                            TimeData[1]=LS_TimeData[1];
                            TimeData[0]=LS_TimeData[0];
                            goto L1;
                }
            }
            BeforKey=NowKey;
            count2--;
            if(count2==0)
            {
                count2=0x40;
                count1--;
                if(count1==0)
                    goto L1;
            }
        }
        else KeyCount++;
    }
L1:;
}




//----------------------主程序-----------------------------------------------
void main()
{
    unsigned char NowKey;
    unsigned char BeforKey=0xff;
    unsigned char KeyCount=0;
    unsigned char i=1;
    AlarmSingal=0;
    RayFlag=1;
    RayFlag2=1;
    Init24C02();//读24C02
    TMOD=0x10;//设置T1
    EA=1;
    ET1=1;
    PT1=1;
    TH1=0x3c;
    TL1=0xb0;
    TR1=1;
    while(1)
    {   
        D_Scan(TimeData,0);//动态扫描
        //闹铃监视
        for(i=0;i<BellCount;i++)
        {
            if((BellDataH[i]==TimeData[2]) && (BellDataL[i]==TimeData[1]))
            {
                AlarmSingal=1;
                break;
            }
            else AlarmSingal=0;
        }
        //按键控制
        if(KeyCount==2)
        {
       
            KeyCount=0;
            NowKey=GetKey();
            if(NowKey!=BeforKey)
            {
                switch (NowKey)
                {
                    case 1:
                            TimeSet();
                            break;
                    case 2:
                            AlarmSingal=0;
                            BellSet();   
                            break;
                    default:
                            break;
                }
            }
            BeforKey=NowKey;
        }
        else KeyCount++;
    }
}

 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值