资源描述
基于51单片机控制的语音报时万年历
-----20/11/2013 SDU(WH)
一. 实验要求
运用单片机及相关外设实现以下功能:
1) 万年历及时钟显示
2) 时间日期可调
3) 可对时间进行整点报时和随机报时
二. 方案分析
根据实验要求,选用STC公司的8051系列,STC12C5A16S2增强型51单片机。此单片机功能强大,具有片内EEPROM、1T分频系数、片内ADC转换器等较为实用功能,故选用此款。
实验中,对日期和时间进行显示,显示的字符数较多,故选用12864LCD屏幕。该屏幕操作较为便捷,外围电路相对简单,实用性较强。
为了实现要求中的时间日期可调,故按键是不可缺少的,所以使用了较多的按键。一方面,单片机的I/O口较为充足;另一方面,按键较多,选择的余地较大,方便编程控制。
实验中,并未要求对时间和日期进行保存和掉电续运行,所以并未添加EEPROM和DS12C887-RTC芯片。实际上,对万年历来说,这是较为重要的,但为了方便实现和编程的简单,此处并未添加,而是使用单片机的定时器控制时间,精度有差别。且上电默认时间为2014-01-01 09:00:00 之后需要手动调整为正确时间。
要求中的语音报时功能,这里选用ISD1760芯片的模块来帮助实现。此模块通过软件模拟SPI协议控制。先将所需要的声音片段录入芯片的EEPROM区域,之后读出各段声音的地址段,然后在程序中定义出相应地址予以控制播放哪一声音片段。
三. 电路硬件设计
实际效果图
四. 程序代码部分
Main.h
#ifndef _MAIN_H
#define _MAIN_H
#include "reg52.h"
#include "INTRINS.H"
#include "math.h"
#include "string.h"
#include "key.h"
#include "led.h"
#include "12864.h"
#include "main.h"
#include "isd1700.h"
#include "sound.h"
extern unsigned int count;
extern unsigned int key_time[8];
extern unsigned char key_new;
extern unsigned char key_old;
extern unsigned char stop_flag;
extern unsigned char key_follow[8];
extern unsigned int key_num[8];
sbit BEEP=P3^7;
sbit ISD_SS=P0^7;
sbit ISD_MISO=P0^4;
sbit ISD_MOSI=P0^5;
sbit ISD_SCLK=P0^6;
extern unsigned char date_show[];
extern unsigned char time_show[];
extern unsigned char sec;
extern unsigned char min;
extern unsigned char hour;
extern unsigned char day;
extern unsigned char month;
extern unsigned char year_f;
extern unsigned char year_l;
extern unsigned char leap_year_flag;
extern unsigned char update_flag;
extern unsigned char adjust_flag;
extern unsigned char key;
unsigned char report();
#endif
Main.c
#include "main.h"
unsigned int count=0;
unsigned int key_num[8]=0;
unsigned char key_new=0;
unsigned char key_old=0;
unsigned char stop_flag=0;
unsigned char key_follow[8]=0;
unsigned char sec=1;
unsigned char min=0;
unsigned char hour=9;
unsigned char day=1;
unsigned char month=1;
unsigned char year_f=20;
unsigned char year_l=14;
unsigned char leap_year_flag=0;
unsigned char date_show[]="2014-01-01";
unsigned char time_show[]="09:00:00";
unsigned char update_flag=1;
unsigned char key=0;
unsigned char adjust_flag=0;
unsigned char adjust_pos=0;
unsigned char report_flag=0;
void main()
{
unsigned char i;
P2=0XFF;
BEEP=0;
init();
initinal(); //调用LCD字库初始化程序
TMOD=0x01; //使用定时器T0
TH0=(65536-1000)/256; //定时器高八位赋初值
TL0=(65536-1000)%256; //定时器低八位赋初值 */
EA=1; //开中断总允许
ET0=1; //允许T0中断
TR0=1; //启动定时器T0
while(1)
{
if(update_flag)
{
lcd_pos(1,0);
for(i=0;i<10;i++)
write_dat(date_show[i]);
lcd_pos(2,4);
for(i=0;i<8;i++)
write_dat(time_show[i]);
update_flag=0;
}
if(key!=keyscan_nor())
{
key=keyscan_nor();
if(key==8&&!adjust_flag)
adjust_flag=1;
if(key&&adjust_flag)
{
if(key==1)
{
adjust_pos++;
if(adjust_pos==14)
adjust_pos=0;
}
else if(key==2)
{
if(!adjust_pos)
adjust_pos=13;
else
adjust_pos--;
}
else if(key==6)
{
if(!adjust_pos)
sec++;
else if(adjust_pos==1)
sec=sec+10;
else if(adjust_pos==2)
min++;
else if(adjust_pos==3)
min=min+10;
else if(adjust_pos==4)
hour++;
else if(adjust_pos==5)
hour=hour+10;
else if(adjust_pos==6)
day++;
else if(adjust_pos==7)
day=day+10;
else if(adjust_pos==8)
month++;
else if(adjust_pos==9)
month=month+10;
else if(adjust_pos==10)
year_l++;
else if(adjust_pos==11)
year_l=year_l+10;
else if(adjust_pos==12)
year_f++;
else if(adjust_pos==13)
year_f=year_f+10;
}
else if(key==7)
{
if(!adjust_pos)
sec--;
else if(adjust_pos==1)
sec=sec-10;
else if(adjust_pos==2)
min--;
else if(adjust_pos==3)
min=min-10;
else if(adjust_pos==4)
hour--;
else if(adjust_pos==5)
hour=hour-10;
else if(adjust_pos==6)
day--;
else if(adjust_pos==7)
day=day-10;
else if(adjust_pos==8)
month--;
else if(adjust_pos==9)
month=month-10;
else if(adjust_pos==10)
year_l--;
else if(adjust_pos==11)
year_l=year_l-10;
else if(adjust_pos==12)
year_f--;
else if(adjust_pos==13)
year_f=year_f-10;
}
else if(key==3)
adjust_flag=0;
if(key==6||key==7)
{
if(sec>=80)
sec=0;
if(min>=80)
min=0;
if(hour>=40)
hour=0;
if(month>30)
month=1;
if(day>50)
day=0;
if(year_f>=120)
year_f=0;
if(year_l>=120)
year_l=0;
}
}
}
if(key==3)
report_flag=1;
if(report_flag)
{
clrram();
Dingwei(2,1);
lcd_mesg("REPORTING!!!");
report();
clrram();
}
}
}
void time0() interrupt 1
{
static unsigned char timer=0;
TH0=(65536-50000)/256; //定时器高八位赋初值
TL0=(65536-50000)%256; //定时器低八位赋初值
timer++;
if(timer==20)
{
sec++;
time_show[6]=sec/10+48;
time_show[7]=sec%10+48;
if(sec>=60)
{
sec=0;
min++;
time_show[6]=sec/10+48;
time_show[7]=sec%10+48;
time_show[3]=min/10+48;
time_show[4]=min%10+48;
}
if(min>=60)
{
min=0;
hour++;
time_show[3]=min/10+48;
time_show[4]=min%10+48;
time_show[0]=hour/10+48;
time_show[1]=hour%10+48;
}
if(hour>=24)
{
hour=0;
day++;
time_show[0]=hour/10+48;
time_show[1]=hour%10+48;
date_show[8]=day/10+48;
date_show[9]=day%10+48;
}
if((day>=29&&!leap_year_flag&&month==2)||(day==30&&leap_year_flag&&month==2)||
(day==31&&(month==4||month==6||month==9||month==11))||(month==32))
{
day=1;
month++;
date_show[8]=day/10+48;
date_show[9]=day%10+48;
date_show[5]=month/10+48;
date_show[6]=month%10+48;
}
if(month>=13)
{
month=1;
year_l++;
date_show[5]=month/10+48;
date_show[6]=month%10+48;
date_show[0]=year_f/10+48;
date_show[1]=year_f%10+48;
date_show[2]=year_l/10+48;
date_show[3]=year_l%10+48;
}
if(year_l>=100)
{
year_l=0;
year_f++;
if(((!((year_f*100+year_l)%4))&&((year_f*100+year_l)%100))||(!((year_f*100+year_l)%400)))
leap_year_flag=1;
else
leap_year_flag=0;
date_show[0]=year_f/10+48;
date_show[1]=year_f%10+48;
date_show[2]=year_l/10+48;
date_show[3]=year_l%10+48;
}
timer=0;
update_flag=1;
if(adjust_flag)
{
time_show[7]=sec%10+48;
time_show[6]=sec/10+48;
time_show[4]=min%10+48;
time_show[3]=min/10+48;
time_show[1]=hour%10+48;
time_show[0]=hour/10+48;
date_show[9]=day%10+48;
date_show[8]=day/10+48;
date_show[6]=month%10+48;
date_show[5]=month/10+48;
date_show[3]=year_l%10+48;
date_show[2]=year_l/10+48;
date_show[1]=year_f%10+48;
date_show[0]=year_f/10+48;
}
}
if(adjust_flag&&timer==10)
{
if(!adjust_pos)
time_show[7]=' ';
else if(adjust_pos==1)
time_show[6]=' ';
else if(adjust_pos==2)
time_show[4]=' ';
else if(adjust_pos==3)
time_show[3]=' ';
else if(adjust_pos==4)
time_show[1]=' ';
else if(adjust_pos==5)
time_show[0]=' ';
else if(adjust_pos==6)
date_show[9]=' ';
else if(adjust_pos==7)
date_show[8]=' ';
else if(adjust_pos==8)
date_show[6]=' ';
else if(adjust_pos==9)
date_show[5]=' ';
else if(adjust_pos==10)
date_show[3]=' ';
else if(adjust_pos==11)
date_show[2]=' ';
else if(adjust_pos==12)
date_show[1]=' ';
else if(adjust_pos==13)
date_show[0]=' ';
update_flag=1;
}
if(!min&&!sec&&!adjust_flag)
report_flag=1;
}
unsigned char report()
{
PlaySoundTick(11);
long_delay();
if(!min)
{
if(hour<=10)
{
PlaySoundTick(hour);
short_delay();
PlaySoundTick(12);
short_delay();
PlaySoundTick(14);
short_delay();
}
else if(hour>10&&hour<20)
{
PlaySoundTick(10);
short_delay();
PlaySoundTick(hour-10);
short_delay();
PlaySoundTick(12);
short_delay();
PlaySoundTick(14);
short_delay();
}
else if(hour==20)
{
PlaySoundTick(2);
short_delay();
PlaySoundTick(10);
short_delay();
PlaySoundTick(12);
short_delay();
PlaySoundTick(14);
short_delay();
}
else
{
PlaySoundTick(2);
short_delay();
PlaySoundTick(10);
short_delay();
PlaySoundTick(hour-20);
short_delay();
PlaySoundTick(12);
short_delay();
PlaySoundTick(14);
short_delay();
}
}
else
{
if(hour<=10)
{
PlaySoundTick(hour);
short_delay();
PlaySoundTick(12);
short_delay();
}
else if(hour>10&&hour<20)
{
PlaySoundTick(10);
short_delay();
PlaySoundTick(hour-10);
short_delay();
PlaySoundTick(12);
short_delay();
}
else if(hour==20)
{
PlaySoundTick(2);
short_delay();
PlaySoundTick(10);
short_delay();
PlaySoundTick(12);
short_delay();
}
else
{
PlaySoundTick(2);
short_delay();
PlaySoundTick(10);
short_delay();
PlaySoundTick(hour-20);
short_delay();
PlaySoundTick(12);
short_delay();
}
if(min<=10)
{
PlaySoundTick(min);
short_delay();
PlaySoundTick(13);
short_delay();
}
else if(min>10&&min%10)
{
PlaySoundTick(min/10);
short_delay();
PlaySoundTick(10);
short_delay();
PlaySoundTick(min-10*(min/10));
short_delay();
PlaySoundTick(13);
short_delay();
}
else
{
PlaySoundTick(min/10);
short_delay();
PlaySoundTick(10);
short_delay();
PlaySoundTick(13);
short_delay();
}
}
report_flag=0;
time_show[7]=sec%10+48;
time_show[6]=sec/10+48;
time_show[4]=min%10+48;
time_show[3]=min/10+48;
time_show[1]=hour%10+48;
time_show[0]=hour/10+48;
date_show[9]=day%10+48;
date_show[8]=day/10+48;
date_show[6]=month%10+48;
date_show[5]=month/10+48;
date_show[3]=year_l%10+48;
date_show[2]=year_l/10+48;
date_show[1]=year_f%10+48;
date_show[0]=year_f/10+48;
return 0;
}
Isd1700.h
#ifndef _ISD1760_H
#define _ISD1760_H
#include "main.h"
#define ISD1700_PU 0x01
#define ISD1700_STOP 0X02
#define ISD1700_REST 0x03
#define ISD1700_CLR_INT 0x04
#define ISD1700_RD_STAUS 0x05
#define ISD1700_RD_PLAY_PTR 0x06
#define ISD1700_PD 0x07
#define ISD1700_RD_REC_PTR 0x08
#define ISD1700_DEVID 0x09
#define ISD1700_PLAY 0x40
#define ISD1700_REC 0x41
#define ISD1700_ERASE 0x42
#define ISD1700_G_ERASE 0x43
#define ISD1700_RD_APC 0x44
#define ISD1700_WR_APC1 0x45
#define ISD1700_WR_APC2 0x65
#define ISD1700_WR_NVCFG 0x46
#define ISD1700_LD_NVCFG 0x47
#define ISD1700_FWD 0x48
#define ISD1700_CHK_MEM 0x49
#define ISD1700_EXTCLK 0x4A
#define ISD1700_SET_PLAY 0x80
#define ISD1700_SET_REC 0x81
#define ISD1700_SET_ERASE 0x82
#define NULL 0x00
#define ISD_LED 0x10
extern unsigned char data ISD_COMM_RAM_C[7];
extern void init(void);
extern void delay_isd(int x);
extern void comm_sate(void);
extern void rest_isd_comm_ptr(void);
extern unsigned char T_R_comm_byte(unsigned char comm_data );
extern void isd1700_par2_comm(unsigned char comm_par, unsigned int data_par);
extern void isd1700_Npar_comm(unsigned char comm_par,comm_byte_count);
extern void isd1700_7byte_comm(unsigned char comm_par, unsigned int star_addr, unsigned int end_addr);
extern void spi_pu (void);
extern void spi_stop (void);
extern void spi_Rest ( void );
extern void spi_CLR_INT(void);
extern void spi_RD_STAUS(void);
extern void spi_RD_play_ptr(void);
extern void spi_pd(void);
extern void spi_RD_rec_ptr(void);
extern void spi_devid(void);
extern void spi_play(void);
extern void spi_rec (void);
extern void spi_erase (void);
extern void spi_G_ERASE (void);
extern void spi_rd_apc(void);
extern void spi_wr_apc1 (void);
extern void spi_wr_apc2 (void);
extern void spi_wr_nvcfg (void);
extern void spi_ld_nvcfg (void);
extern void spi_fwd (void);
extern void spi_chk_mem(void);
extern void spi_CurrRowAddr(void);
extern void seril_back_sate(unsigned char byte_number);
extern void spi_set_opt(unsigned char spi_set_comm);
void init(void);
#endif
Isd1700.c
//#pragma src
#include "isd1700.h"
#include "sound.h"
#define uchar unsigned char
#define uint unsigned int
sbit DAC_sync=P2^0;
sbit DAC_sclk=P2^1;
sbit DAC_din =P2^2;
bit re_fig;
uchar data comm_temp;
uchar data ISD_COMM_RAM[7];
uchar data ISD_COMM_RAM_C[7];
uchar data *isd_comm_ptr;
uchar data *back_data_ptr;
void init(void);
void isd_delay(int x);
void comm_sate(void);
void rest_isd_comm_ptr(void);
uchar T_R_comm_byte( uchar comm_data );
void isd1700_par2_comm(uchar comm_par, uint data_par);
void isd1700_Npar_comm(uchar comm_par,comm_byte_count); //no parameter comm
void isd1700_7byte_comm(uchar comm_par, uint star_addr, uint end_addr);
void spi_pu (void);
void spi_stop (void);
void spi_Rest ( void );
void spi_CLR_INT(void);
void spi_RD_STAUS(void);
void spi_RD_play_ptr(void);
void spi_pd(void);
void spi_RD_rec_ptr(void);
void spi_devid(void);
void spi_play(void);
void spi_rec (void);
void spi_erase (void);
void spi_G_ERASE (void);
void spi_rd_apc(void);
void spi_wr_apc1 (void);
void spi_wr_apc2 (void);
void spi_wr_nvcfg (void);
void spi_ld_nvcfg (void);
void spi_fwd (void);
void spi_chk_mem(void);
void spi_CurrRowAddr(void);
void seril_back_sate(uchar byte_number);
void spi_set_opt(uchar spi_set_comm);
void comm_sate(void)
{
uchar sate_temp;
uint apc_temp;
if(RI)
{ sate_temp=SBUF;
if(sate_temp==0x09)
{ spi_devid();}
if(sate_temp==0x44)
{spi_rd_apc();}
if(sate_temp==0x40)
{spi_play();}
if(sate_temp==0x04)
{spi_CLR_INT();}
if(sate_temp==0x05)
{spi_RD_STAUS();}
if(sate_temp==0x43)
{ spi_G_ERASE();}
if(sate_temp==0x01)
{ spi_pu ();}
if(sate_temp==0x02)
{ spi_stop();}
if(sate_temp==0x03)
{ spi_Rest ();}
if(sate_temp==0x06)
{spi_RD_play_ptr();}
if(sate_temp==0x07)
{spi_pd();}
if(sate_temp==0x08)
{ spi_RD_rec_ptr();}
if(sate_temp==0x41)
{ spi_rec();}
if(sate_temp==0x42)
{ spi_erase();}
if(sate_temp==0x45)
{spi_wr_apc1 ();}
if(sate_temp==0x65)
{ spi_wr_apc2 ();}
展开阅读全文