找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3739|回复: 2
收起左侧

基于51单片机和Proteus仿真的自动打铃器

[复制链接]
ID:517871 发表于 2019-5-9 17:29 | 显示全部楼层 |阅读模式
#include <AT89X52.h>
#include <stdio.h>     
bit bclassFlg = 0;
sbit FMQ = P3 ^ 7;

unsigned char stringtemp[10]="";

struct time
{
        unsigned char        second;
        unsigned char        minute;
        unsigned char        hour;
        unsigned char        day;
        unsigned char        weekday;
        unsigned char        month;
        unsigned int        year;
} time;

sbit tim_sda=P2^6;
sbit tim_scl=P2^7;

sbit        lcd16rs        =        P2^0;
sbit        lcd16rw        =        P2^1;
sbit        lcd16en        =        P2^2;

unsigned char        lcd16_1[16];
unsigned char        lcd16_2[16] = {"welcome"};


bit         tim_ack;                // i2c slave ack.
bit         tim_err;
unsigned char tim_rd_buffer[16];
unsigned char tim_wr_buffer[16];

/*****************11us延时函数*************************/
void delay11us(unsigned char t)
{
  for (;t>0;t--);
}



void delay(unsigned int x)
{
        unsigned int a,b;
        for(a=x;a>5;a--);
                for(b=10;b>0;b--);
}



//写指令
void write_com(unsigned char com)
{
        P1=com;// 将指令值写到数据线上
        lcd16rs=0;//写指令
        lcd16en=0;//给一个LCD 使能脉冲
        delay(10);
        lcd16en=1;
        delay(10);
        lcd16en=0;
       
}

//写数据
void write_date(unsigned char date)
{
        P1=date;    //将数据写到数据线上
        lcd16rs=1;    //写数据
        lcd16en=0;    //给一个LCD 使能脉冲
        delay(10);
        lcd16en=1;
        delay(10);
        lcd16en=0;
       
}


//初始化LCD
void lcd_init()
{
        lcd16rw = 0;
        write_com(0x38);//显示模式设置
        delay(20);
        write_com(0x0f);//开显示,显示光标、光标闪烁
        delay(20);
        write_com(0x06);//光标和显示指针加一,屏幕不移动
        delay(20);
        write_com(0x01);//清显示屏
        delay(20);       
}


//在第N行显示第M个字
void lcd16_n_line_n_byte(unsigned char n_line,unsigned char n_byte)
{
        unsigned char j;
        unsigned char com;
        unsigned char *dat1;
        unsigned char *dat2;

        dat1 = lcd16_1;
        dat2 = lcd16_2;

        if(n_line==0)                                   //显示第一行。
        {
                for(j=0;j<n_byte;j++)
                {
                        com = 0x80+j;
                        write_com(com);
                        write_date(*dat1);
                        dat1++;
                }       
        }
        if(n_line==1)                           //显示第二行。
        {
                for(j=0;j<n_byte;j++)
                {
                        com = 0xc0+j;
                        write_com(com);
                        write_date(*dat2);
                        dat2++;
                }       
        }
}

// i2c start.
void PCF8563_start()        //start flag is when tim_scl 1, tim_sdafrom 1 to 0.
{
        tim_sda = 1;
        delay11us(1);
        tim_scl = 1;
        delay11us(1);
        tim_sda = 0;
        delay11us(1);
}

// i2c stop.
void PCF8563_stop()                         //start flag is when tim_scl 1, tim_sdafrom 0 to 1.
{
        tim_sda = 0;
        delay11us(1);
        tim_scl = 1;
        delay11us(1);
        tim_sda = 0;
}

//i2c slave respons.
void PCF8563_respons()
{
        unsigned char i;
        tim_scl = 1;
        delay11us(1);
        while((tim_sda)&&(i<250))  i++;
        if(!tim_sda)
                tim_ack = 1;
        else
                tim_ack = 0;
        tim_scl = 0;
        delay11us(1);
}

// i2c master respons.
void PCF8563_master_respons(bit master_ack)
{
        tim_scl = 0;
        delay11us(1);
        tim_sda = ~master_ack;
        delay11us(1);
        tim_scl = 1;
        delay11us(1);
        tim_scl = 0;
        delay11us(1);
}

//i2c init.
void PCF8563_init()
{
        tim_sda = 1;
        delay11us(1);
        tim_scl = 1;
        delay11us(1);
}

// i2c write n byte.
void PCF8563_wr_byte(unsigned char dat)
{
        unsigned char i , temp;
        temp = dat;
        for(i=0;i<8;i++)
        {
                tim_scl = 0;
                delay11us(1);

               
                if(temp&0x80)
                        tim_sda = 1;
                else
                        tim_sda = 0;
                temp = temp<<1;
               
                delay11us(1);
                tim_scl = 1;
                delay11us(1);

        }
        tim_scl = 0;
        delay11us(1);
        tim_sda = 1;                       
        delay11us(1);
}

unsigned char PCF8563_rd_byte()
{
        unsigned char i,k;
        tim_scl = 0;
        delay11us(1);
        tim_sda = 1;
        delay11us(1);
        for(i=0;i<8;i++)
        {
                tim_scl = 1;
                delay11us(1);
                k = (k<<1)|tim_sda;
                tim_scl = 0;
                delay11us(1);
        }
        return k;
}

void PCF8563_write_n_byte(unsigned char add,unsigned char com,unsigned char *dat,unsigned char n_byte)   //
{
        unsigned char i = 0;
        unsigned char temp;

        temp = *dat;                                  // send to begin address to 'temp'.

        add = add<<1;
        add = 0xa0+add+0x00;                       

        PCF8563_start();
        PCF8563_wr_byte(add);                 //send EEPROM address, bit 0 = 0 is write.
        PCF8563_respons();
        if(!tim_ack)                                //if i2c respons.
        {
                tim_err = 1;
                return;
        }
       
        PCF8563_wr_byte(com);                        //send EEPROM beginning address.
        PCF8563_respons();
        if(!tim_ack)                                //if i2c respons.
        {
                tim_err = 1;
                return;
        }
       
        while(n_byte)                           //write n byte.
        {
                PCF8563_wr_byte(temp);
                PCF8563_respons();
                if(!tim_ack)                               
                {
                        tim_err = 1;
                        PCF8563_stop();       
                        return;
                }
                temp++;
                n_byte--;
        }
       
        PCF8563_stop();       
}

void PCF8563_read_n_byte(unsigned char add,unsigned char com,unsigned char n_byte)
{
        unsigned char *temp;

        temp = tim_rd_buffer;

        add = add<<1;
        add = 0xa0+add+0x00;                       

        PCF8563_start();

        PCF8563_wr_byte(add);                                 //send address + wr.
        PCF8563_respons();

        PCF8563_wr_byte(com);                                // first byte address.
        PCF8563_respons();

        add = add+0x01;                       

        PCF8563_start();
        PCF8563_wr_byte(add);                           //send address + rd.
        PCF8563_respons();

        while(n_byte)                                   // rd n byte .
        {
                *temp = PCF8563_rd_byte();
                if(n_byte != 1)                                //if i2c respons.
                {
                        PCF8563_master_respons(1);        //if the number is not the last one, master send a ack bit.
                }
                temp++;
                n_byte--;
        }
        PCF8563_stop();
}

void PCF8563_wr_time()
{
        tim_wr_buffer[0] = 0x00;        //second
        tim_wr_buffer[1] = 0x11;        //minute
        tim_wr_buffer[2] = 0x22;        //hour

        tim_wr_buffer[3] = 0x15;        //day
        tim_wr_buffer[4] = 0x03;        //weekday
        tim_wr_buffer[5] = 0x06;        //month
        tim_wr_buffer[6] = 0x10;        //year

       
        PCF8563_write_n_byte(1,2,tim_wr_buffer,8);
}

//延时眼熟
void DelayFM(unsigned int x)  
{
        unsigned char t;
        while(x--)
        {
                 for(t=0;t<120;t++);
        }
}
//蜂鸣器驱动函数,参数为发声声调
void FM(unsigned char x)
{
        unsigned char i;
        for(i=0;i<100;i++)
        {
                 FMQ = ~FMQ;
                DelayFM(x);
        }
        FMQ = 0;
}

void PCF8563_rd_time()
{
        unsigned char        temp;


        PCF8563_read_n_byte(1,2,9);

        time.second = ((tim_rd_buffer[1]&0x70)>>4)*10 + (tim_rd_buffer[1]&0x0f);        //second                        

        time.minute = ((tim_rd_buffer[2]&0x70)>>4)*10 + (tim_rd_buffer[2]&0x0f);        //minute

        time.hour = ((tim_rd_buffer[3]&0x30)>>4)*10 + (tim_rd_buffer[3]&0x0f);                //hour
        time.day = ((tim_rd_buffer[4]&0x30)>>4)*10 + (tim_rd_buffer[4]&0x0f);                //day
        time.weekday = tim_rd_buffer[5]&0x07;                                                                                //weekday
        time.month = ((tim_rd_buffer[6]&0x10)>>4)*10 + (tim_rd_buffer[6]&0x0f);                //month

  if(time.second == 0)
  {
    if(bclassFlg == 0 )
    {
      sprintf(stringtemp,"%x%x",time.hour,time.minute);
//      printf("%s\n",stringtemp);
      printf("it's time to have class\n"); //上课
      bclassFlg = 1;
      FM(3);
    }
  }
  else if(time.second == 45) //如果到了45分钟,开始下课铃
  {
    if(bclassFlg == 1)
    {
      sprintf(stringtemp,"%x%x",time.hour,time.minute);
//      printf("%s\n",stringtemp);
      printf("it's time to finish class\n");
      bclassFlg = 0;
      FM(7);
    }
  }
  else
  {
  }

        temp = (tim_rd_buffer[4]&0x80)>>7;
        time.year = (temp+20)*100+((tim_rd_buffer[7]&0x70)>>4)*10 + (tim_rd_buffer[7]&0x0f);           //year
                lcd16_1[0] = time.hour/10+0x30;          //hour
                lcd16_1[1] = time.hour%10+0x30;
                lcd16_1[2] = '-';
                lcd16_1[3] = time.minute/10+0x30;          //minute
                lcd16_1[4] = time.minute%10+0x30;
                lcd16_1[5] = '-';
                lcd16_1[6] = time.second/10+0x30;          //second
                lcd16_1[7] = time.second%10+0x30;

                lcd16_2[0] = time.year/1000+0x30;          //year
                lcd16_2[1] = (time.year%1000)/100+0x30;
                lcd16_2[2] = (time.year%100)/10+0x30;
                lcd16_2[3] = time.year%10+0x30;
                lcd16_2[4] = '-';
                lcd16_2[5] = time.month/10+0x30;  //mon
                lcd16_2[6] = time.month%10+0x30;
                lcd16_2[7] = '-';
                lcd16_2[8] = time.day/10+0x30;          //day
                lcd16_2[9] = time.day%10+0x30;

                lcd16_2[10] = 'w';
                lcd16_2[11] = 'e';
                lcd16_2[12] = 'e';
                lcd16_2[13] = 'k';
                lcd16_2[14] = ':';
                lcd16_2[15] = time.weekday+0x30;

                lcd16_n_line_n_byte(0,16);
                lcd16_n_line_n_byte(1,16);
}




void DelayMS(unsigned int ms)
{
        unsigned char i;
        while(ms--)
        {
                 for(i=0;i<120;i++);
        }
}

void InitUart(void)
{
        SCON = 0x50;                                  //工作方式1
        TMOD = 0x21;
        PCON = 0x00;
        TH1 = 0xfd;                                   //使用T1作为波特率发生器
        TL1 = 0xfd;
        TI = 1;
        TR1 = 1;                                      //启动T1                                                                  //启动T1  
}

void main()
{
  PCF8563_init();
//        PCF8563_wr_time();
        lcd_init();
  InitUart();
        while(1)
        {
                PCF8563_rd_time();
    DelayMS(250);
        }
}

打铃.png

基于51单片机和Proteus仿真的自动打铃器.zip

75.87 KB, 下载次数: 79, 下载积分: 黑币 -5

回复

使用道具 举报

ID:91165 发表于 2020-3-20 08:19 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:856413 发表于 2020-12-13 16:22 来自手机 | 显示全部楼层
楼主,有方案说明和原理图吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表