dsp实验报告.docx
《dsp实验报告.docx》由会员分享,可在线阅读,更多相关《dsp实验报告.docx(16页珍藏版)》请在冰豆网上搜索。
dsp实验报告
2013届研究生
《DSP原理与嵌入式系统》实验报告
实验名称:
基于键盘、LCD等带有备忘录的
数字时钟设计
姓名:
刘静静
学号:
S1*******
专业:
控制科学与工程
导师:
夏伯锴
同组同学:
马明飞(定时器与外部中断嵌套实验)
实验时间:
2013年12月2日
一、实验内容简述
我们俩人分别独立完成了以下两个实验:
(1)基于键盘、LCD等带有备忘录的数字时钟设计:
利用定时器中断、外部中断、LCM模块、键盘、LED等,LCD采用并口连接,在液晶屏上实现可以显示年月日时分秒,并且可以调整的年月日时分。
带有备忘录得功能,并且备忘录月日时间可以调整。
当时钟运行后,当前日期与你备忘录时间相一致时,可在LCD上显示今天所做的时,程序中是显示“亲,你今天有会要开”。
(2)定时器与外部中断嵌套实验
2、实验功能介绍
实验中用到键盘上0——3这四个键,这四个键如图
(1)所示:
数字0键为模式选择键:
当按下模式选择键即进入时钟日历和备忘录的调整状态。
数字1键和数字2键,分别为上调键和下调键。
这三个键综合功能如下
按下1次模式选择键,时钟小时闪烁,按上调键,小时值增加,按下调键,小时值减小
按下2次模式选择键,时钟分钟闪烁,按上调键,分钟值增加,按下调键,分钟值减小
按下3次模式选择键,日历日期年闪烁,按上调键,年份值增加,按下调键,年份值减小
按下4次模式选择键,日历日期月闪烁,按上调键,月份值增加,按下调键,月份值减小
按下5次模式选择键,日历日期日闪烁,按上调键,日值增加,按下调键,日值减小
按下6次模式选择键,备忘录月份闪烁,按上调键,备忘录月份增加,按下调键,备忘录月份减小
按下7次模式选择键,备忘录日闪烁,按上调键,备忘录日增加,按下调键,备忘录日减小
按下8次模式选择键,返回时钟正常运行状态。
数字3为备忘录开关控制键。
当按下此键,若当前备忘录为关闭的状态,则打开备忘录功能。
若当前备忘录为打开的状态,则关闭备忘录功能。
程序运行后时钟正常运行,但不足的是键盘中断进不去(原因没有找出),没有达到预期的功能,但部分功能实现了。
如下是时钟初始化显示:
{"2013年12月2日"};
{"19:
18:
40"};
{"中国石油大学"}
{"备忘录"};
三、实验的部分程序及功能分析
interruptvoidint1()//中断1中断子程序
{
UINT16temp;
flag_key=1;
temp=*PVIR;
*IFR=0xFFFF;//清除所有中断标志,"写1清0"
if(temp==0x0001)
{
*XINT1CR=*XINT1CR|0x8000;//清xint1中断标志
send_buff=CMD_READ;//读键值指令
send();
receive();
asm("nop");
}
cs_high();//7279CS置高
asm("clrcINTM");//开总中断
return;
}
程序说明:
在原来中断1的中断服务程序中,增加了一个键盘标志位。
即当键盘上有按键按下时,flag_key被置1。
用以判断有没有按键按下,这样用来实现控时钟的运行和调节时间日期以及备忘录功能。
voidtimer1_init()//定时器1初始化子程序
{
………
/*约1ms产生一次中断*/
*T1PER=0x01CD;
/*计数器清零*/
*T1CNT=0x0000;
/*连续增计数模式,预分频为64,定时器计时使能,内部时钟,定时器1比较使能*/
*T1CON=0x164C;
………
}
interruptvoidtimer1()//定时器1中断子程序
{
/*记中断次数1000次,产生1秒延时*/
num++;
/*计数器清零*/
*T1CNT=0x0000;
/*清EVA中断标志*/
*EVAIFRA=0xFFFF;
return;
}
程序说明:
这两程序段将timer1设定为每隔1ms产生一次中断,定时器1的中断服务程序中全局变量num用来记录timer1中断发生的次数。
Num中的值会在后边的程序中用到。
即num值达到1000,就说明1S时间已经得到,对应的秒钟加1,实现时钟的运行。
以下几个函数是自己结合单片数字中时钟改编,然后在主函数调用的。
有voiddisplay_nyr(UCHARadd,UCHARdate),voiddisplay_sfm(UCHARadd,UCHARdate),voiddisplay_anyr(UCHARadd,UCHARdate),voidclock_run(),voidchange_time(),voidbeiwanglu()。
下面分别描述其功能。
voiddisplay_nyr(UCHARadd,UCHARdate)//显示年月日的函数在第一行
{
UCHARge,shi;
shi=date/10;
ge=date%10;
wcom(0x80+add);
delay_100us();
wram(0x30+shi);
delay_100us();
wram(0x30+ge);
delay_100us();
}
程序说明:
这是用以在LCD上显示年月日的函数。
add是显示的位置。
date是显示的数据。
在程序中把date分成个位数字和十位数字分别送到LCD进行显示。
年、月、日的地址分别是0x80+1、0x80+3、0x80+5。
同样对应这有送时分秒及备忘录年月日的子函数。
差别在于地址不一样,只需把地址改变一下。
interruptvoidnothing(void)
{
*IFR=0xFFFF;//清除所有中断标志,"写1清0"
asm("clrcINTM");//开总中断
return;
}
voidclock_run()
{
if(num>=1000)
{
num=0;
second++;
show=~show;
}
if(second>=60)
{
second=0;
minute++;
if(minute>=60)
{
minute=0;
hour++;
if(hour>=24)
{
hour=0;
day++;
if(day>=32)
{
day=0;
month++;
if(month>=13)
{
month=0;
year++;
display_nyr(1,year);
}
display_nyr(3,month);
}
display_nyr(5,day);
}
display_sfm(1,hour);
}
display_sfm(3,minute);
}
display_sfm(5,second);
}
程序说明:
此函数为时钟运行的必需函数。
当num计数次数达到1000次,就说明1S的计时时间已经得到。
此时num清零,秒钟加1。
当秒钟达到59时,下一秒秒钟清零,分钟加1.同理后边的年、月、日、小时也有相似的运行方式。
voidchange_time()
{
if(flag_key==1)
{
if(rece_buff==0x00)
{
mode++;
if(mode>8)
mode=0;
}
if(mode==1)
{
wcom(0x90+1);//hour的位
delay_100us();
wcom(REVERSE);
delay_100us();
if(flag_key==1)
{
if(rece_buff==0x01)
{
hour++;
if(hour>=24)
hour=0;
}
if(rece_buff==0x02)
{
hour--;
if(hour<0)
hour=0;
}
}
display_sfm(1,hour);
}
if(mode==2)//调整分钟
{
wcom(0x90+3);
delay_100us();
wcom(CURSOR);
delay_100us();
if(flag_key==1)
{
if(rece_buff==0x01)
{
minute++;
if(minute>=60)
minute=0;
}
if(rece_buff==0x02)
{
minute--;
if(minute<0)
minute=0;
}
}
display_sfm(3,minute);
}
if(mode==3)//调整年
{
……
display_nyr(1,year);
}
if(mode==4)//调整月
{
……
}
display_nyr(3,month);
}
if(mode==5)//调整日
{
……
}
if(mode==6)//调整备忘录月
{
……
display_anyr(3,a_month);
}
if(mode==7)//调整备忘录日
{
……
flag_key=0;
}
voidbeiwanglu()
{UINT16i;
if(a_month-month==0&&a_day-day==0)
{wcom(0x0098);
delay_100us();
for(i=0;i<16;i++)
{
wram(data_buff5[i]);
delay_100us();
}
asm("nop");
}
}
程序说明:
此程序实现年月日时分,以及备忘录月日值的调整。
在此程序的开始部分会判断有没有按键按下,如果有按键按下对应的flag_key置1。
然后判断从7279读进的键值。
从而识别当前按下的是模式键还是其他的调整键。
如果按下的是模式键,变量mode用来指示当前模式键按下的次数,或当前时间调整的位置。
例如:
按下一次模式键,mode的值变成1,在LCD液晶屏上小时的位置会反白显示。
用以指示此时将要调节小时。
在此种状态下按下上调或者下调键,对应的小时会增加或者减小,从而完成小时的调整,其他值类似。
当调整的备忘录日期与当前日期一致,则在LCD上显示提示语。
voidmain()
{
UINT16temp,i;
//----------初始化-------------------------------
……//CPU,中断,IO口,7279等的初始化工作//
//------------在第一行显示"2013年12月2日"
wcom(0x0080);//设定DDRAM的地址在第一行80H
delay_100us();
for(i=0;i<16;i++)
{
wram(data_buff1[i]);
delay_100us();
asm("nop");
}
asm("nop");
//--------------在第二行显示"00:
00:
00"----------------
wcom(0x0090);//设定DDRAM的地址在第二行90H
delay_100us();
for(i=0;i<16;i++)
{
wram(data_buff2[i]);
delay_100us();
}
asm("nop");
//----------------在第三行显示"中国石油大学"----------------
wcom(0x0088);//设定DDRAM的地址在第三行88H
delay_100us();
for(i=0;i<16;i++)
{
wram(data_buff3[i]);
delay_100us();
}
asm("nop");
wcom(0x0098);//设定DDRAM的地址在第四行98H
delay_100us();
for(i=0;i<16;i++)
{
wram(data_buff4[i]);
delay_100us();
}
asm("nop");
//-------------------
while
(1)
{
display_nyr(1,year);
display_nyr(3,month);
display_nyr(5,day);
display_sfm(1,hour);
display_sfm(3,minute);
display_sfm(5,second);
if(flag_key==0)
{
clock_run();
}
if(flag_key==1)
{
change_time();
}
beiwanglu();
}
}
程序说明:
主要完成以下功能:
(1)主函数开始部分,完成一些初始化工作:
时钟初始化、IO初始化、外部中断定时器中断初始化、7279初始化、LCD初始化工作。
调用相关功能函数即可完成。
(2)完成时钟的初始化
(3)进入while循环。
实现时钟运行,调整,闹钟调整和闹钟的功能。
在while循环中,首先将初始化的年月日时分秒等显示出来。
增加了判断语句if()用来判断程序是执行clock_run()函数还是执行change_time()函数。
这就做到了,只有在按键按下的时候去执行change_time()函数,从而保证在调整时钟的时候闹钟“停止”。
避免了一些意想不到的事件的发生。
直接调用beiwanglu()函数,实验备忘录功能。
关于本课程学习及实验心得
DSP原理与嵌入式系统的学习不但需要扎实的理论知识,更需要反复的实践和上机操作,这与以前学习51单片机方法类似,但2407相对来说还是比较复杂的。
仅仅三次实验,两次调试时间,有一种意犹未尽的感觉,总是觉得还能把程序完善一点,进而再完善一些,虽然程序没有达到预期功能但还是收获很大。
这门课程给我的另一个启发是要提高阅读芯片DATASHEET的能力,尤其是英文DATASHEET,像本实验中的tms320lf2407a,HD7279A,实验中遇到的许多问题其实都可以在DATASHEET中找到答案,想学好一种芯片,必须潜下心来读懂芯的
英文DATASHEET,拿串行接口的8位LED数码管及8*8矩阵键盘智能控制芯片HD7279来说。
在弄清楚7279的工作原理之前,光看给出的例程,即便是在知道例程运行结果的情况下,还是存在很大的疑惑。
当读懂7279的数据手册之后,此时不但看懂例程不是问题,编写相应的程序也不在话下。
相比对矩阵键盘的扫描方式的控制,7279的确给键盘的控制带来很大的方便。
我也体会到老师上课
用英文PPT的用心良苦。
我认为关于DSP的课程应该更注重于实践,希望以后能留给同学们更多操作实践的机会。