dsp课程设计 万年历设计.docx
《dsp课程设计 万年历设计.docx》由会员分享,可在线阅读,更多相关《dsp课程设计 万年历设计.docx(34页珍藏版)》请在冰豆网上搜索。
dsp课程设计万年历设计
课程设计说明书
(学年第二学期)
课程名称:
DSP控制器及其应用
题目:
万年历设计
专业班级:
学生姓名:
学号:
指导教师:
设计周数:
2周
设计成绩:
年月日
1课程设计目的……………………………………………………………………………………1
2硬件设计…………………………………………………………………………………………1
2.1硬件方案设计…………………………………………………………………………………1
2.2单元电路设计…………………………………………………………………………………2
2.2.1控制部件………………………………………………………………………………2
2.2.2时钟芯片………………………………………………………………………………3
2.2.3显示模块………………………………………………………………………………5
2.3电路原理图……………………………………………………………………………………6
2.4硬件调试………………………………………………………………………………………6
3软件设计…………………………………………………………………………………………7
3.1系统分析……………………………………………………………………………………7
3.2软件系统设计…………………………………………………………………………………7
3.3软件代码实现…………………………………………………………………………………10
3.4软件调试………………………………………………………………………………………22
4课程设计体会总结………………………………………………………………………………22
5参考文献…………………………………………………………………………………………23
1课程设计目的
课程设计的主要目的是用tms320f2812芯片为核心控制部件,设计一个能用LCD液晶显示屏显示当前年,月,日,时,分,秒以及星期的具有电子时钟功能的万年历。
⑴学习并了解ICETEK-F2812-A板及教学实验箱的使用;
⑵学习DSP芯片的I/O端口的控制方法;
⑶熟悉字模的简单构建和使用;
⑷熟悉Emulator方式下的程序调试规程,并最终能够熟练掌握在DSP软硬件环境下的程序开发流程;能够对现有器件进行简单地编程,实现各种简单地显示控制。
2硬件设计
2.1硬件方案设计
本系统以TMS2812为核心控制部件,利用软件编程,通过DS1302进行时钟控制,使用12864LCD液晶显示器进行时钟显示,能实现题目的基本要求,尽量做到硬件电路简单稳定,减小电磁干扰和其他环境干扰,充分发挥软件编程的优点,减小因元器件精度不够引起的误差。
由于时间有限和本身知识水平的发挥,我们认为本系统还有需要改进和提高的地方,例如选用更高精度的元器件,硬件电路更加精确稳定,软件测量算法进一步的改进与完善等。
总体框图如图1所示。
图1电路总体框图
2.2单元电路设计
2.2.1控制部件TMS320F2812结构及性能
本次课设所使用的TMS320F2812是ICETEK-F2812-A型DSP用户板中集成试验箱,所以下面主要对该板各个板块及其功能的描述。
图3-1F2812-A板的实物图
下面说明该些接口及其功能如表3-1:
在本次设计中主要用到P1口中的pwm引脚作为I/O口来传送数据。
P1接口主要是扩展评估板上空闲的DSP外设引脚,以便于定制用户的硬件环境。
由于这组引脚是直接来自于F2812DSP芯片,因此,这些引脚为TTL3.3V标准,其输出最高电压为3.3V。
所以在ds1302中要用四个二极管来降压,关于其接口的设置可以用软件对每个引脚功能设计。
表3-1接口和功能分类
功能分类
接口名称
接口定义
电源接口
POWER
5V电源输入
外设接口
DB9
九针D型串口
总线接口
P1
34芯外扩总线
P2
34芯外扩总线
P3
34芯外扩总线
P4
34芯外扩总线
指示灯
POW_LED
电源指示灯
USER_LED
用户使用的发光管
辅助接口
DSP_JTAG
:
DSP仿真器接口
开关
USER_SW
用户使用的开关
RESET
手动复位开关
JP3
SCI选择
AD参考电压选择
ADREFLO1
AD参考低电压输入
ADREFIN1
测试端,必须悬空
模式选择跳线
MP/MC1
MP/MC方式选择
MDXA1
SCITXDA1
SPICLKA1
SPISTEA1
2.2.2时钟芯片DS1302结构及其功能
⑴DS1302的引脚
图3-2DS1302的引脚图
图3-2DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768kHz晶振。
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc≥2.5V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
I/O为串行数据输入输出端(双向),后面有详细说明。
SCLK始终是输入端。
⑵DS1302的结构及工作原理
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
⑶DS1302的控制字节
表3-2DS1302的控制字节
1
RAM
CK
A4
A3
A2
A1
A0
RAM
K
DS1302的控制字如图2所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
⑷数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
⑸DS1302的连接
DS1302与CPU的连接需要三条线,即SCLK(7)、I/O(6)、RST(5)。
如图3-3:
图3-3DS1302连接图
2.2.3显示模块LCD12864液晶显示
采用LCD12864液晶显示。
液晶显示器(LCD)具有功耗低、体积小、重量轻、超薄等许多其它显示器无法比拟的优点。
12864分左屏和右屏是由两块64*64的液晶组成,有CS1和CS2左右屏使能引脚。
64*64的共分8页,8行led液晶是一页,每行分别是由DB0_DB7控制,也就是从单片机中发64次8位的二进制数可以扫一页,发64(8页)次的二进制数可以扫一个半屏,再乘以二就可以扫全屏,当把二进制数全发完了,才可以控制液晶开始显示。
单片机可以通过数据总线与控制信号直接采用存储器访问形式、I/O设备访问形式控制该液晶显示模块。
液晶显示模块的访问、控制是由2812DSP对扩展扩展接口的操作完成。
控制扩展口的寻址:
命令控制扩展接口的地址为0x,数据控制扩展接口的地址为0x和0x,辅助控制扩展接口的地址为0x。
显示控制方法:
液晶显示模块中有两片显示缓冲存储器,分别对应屏幕显示的象素,向其中写入数值将改变显示,写入“1”则显示一点,写入“0”则不显示。
发送控制命令:
向液晶显示模块发送控制命令的方法是通过向命令控制扩展接口写入命令控制字,然后再向辅助控制接口写入0;显示开关:
0x3f打开显示;0x3e关闭显示;设置显示起始行:
0x0c0+起始行取值,其中起始行取值为0至63;设置操作页:
0x0b8+页号,其中页号取值为0-7;设置操作列:
0x40+列号,其中列号为取值为0-63;写显示数据:
在使用命令控制字选择操作位置(页数、列数)之后,可以将待显示的数据写入液晶显示模块的缓存。
将数据发送到相应数据控制扩展接口即可。
2.3电路原理图
电路原理图如图3所示。
图3电路原理图
2.4硬件调试
硬件调试可分为静态调试与动态调试两步进行。
静态调试是在用户系统未工作时的一种硬件检测。
第一步:
目测。
检查外部的各种元件或者是电路是否有断点。
第二步:
用万用表测试。
先用万用表复核目测中有疑问的连接点,再检测各种电源线与地线之间是否有短路现象。
第三步:
加电检测。
给板加电,检测所有插座或是器件的电源端是否符合要求的值。
第四步:
联机检查。
因为只有用单片机开发系统才能完成对用户系统的调试。
动态调试是在用户系统工作的情况下发现和排除用户系统硬件中存在的器件内部故障、器件连接逻辑错误等的一种硬件检查。
动态调试的一般方法是由近及远、由分到合。
由分到合是指首先按逻辑功能将用户系统硬件电路分为若干块,当调试电路时,与该元件无关的器件全部从用户系统中去掉,这样可以将故障范围限定在某个局部的电路上。
当各块电路无故障后,将各电路逐块加入系统中,在对各块电路功能及各电路间可能存在的相互联系进行调试。
由分到合的调试既告完成。
由近及远是将信号流经的各器件按照距离单片机的逻辑距离进行由近及远的分层,然后分层调试。
调试时,仍采用去掉无关元件的方法,逐层调试下去,就会定位故障元件了。
在这个过程之中,首先要考虑所有器件的大小,从而能够在电路板上正确安排足够的空间,此外还要考虑器件只能装的方向以及引脚的位置,尽可能的使引脚的连接简单明了,减少错误的出现。
最后更要通过整个电路板的测试,来确定是否达到要求,只有每个节点的线路状况完全良好,才能继续以后的步骤。
并且在软件调试阶段要维护电路板的完整性以及正确性,因为在软件测试时需要不断的测试系统,而不断的移动电路板,可能会导致线路连接的可靠性,还可能有人为的原因造成连接不够良好,或者节点之间的连接脱落等状况,因而在整个试验过程中都要保持电路板的正常工作。
最重要的是电源的连接正确,否则可能导致期间的烧毁。
在老师的监督下以及同学的帮助下,几经波折的调试后,我们的系统圆满的实现预定的要求:
准确显示当前时间。
3软件设计
3.1系统分析
根据本系统设计要求和硬件连接电路,软件实现主要包括三个主要部分:
1302时钟芯片的读写程序,液晶显示程序和主函数部分。
首先应该对1302芯片进行检测,对其进行初始化设置,比如设置运行位,选择12小时还是24小时计数制。
设置完成以后,便可以写入读写程序。
1302是通过I/O口一位一位地写入与读出数据。
在此需要设置读写时序,选择I/O端口为输入还是输出。
液晶显示部分,主要是利用通过字模提取软件计算出来的数组矩阵,选择要显示的汉字、数字或者字符。
显示每一个汉字、数字或字符时,应先设置起始页,起始列,然后将所对应的数组中的数据按序写入到LCD数据控制扩展接口中,其中写入左屏的数据地址为0x,写入右屏的数据地址为0x,依次分别写入年、月、日、星期、时、分、秒。
主程序的编写,首先要对2812DSP芯片的寄存器进行设置,选择输入输出方式。
设置完成,打开显示器,清除显示器显示内存,设置起始行,然后循环读取1302中指示的当前时间。
便可以在12864液晶显示屏上准确读出当前时刻。
3.2软件系统设计
时钟芯片1302程序流程图如图4所示。
图4时钟芯片1302程序流程图
液晶显示程序流程图如图5所示。
图5液晶显示程序流程图
主函数流程图如图6所示。
图6主函数流程图
3.3系统实现代码
//主函数
voidmain()
{
EALLOW;
GpioMuxRegs.GPAMUX.all=0x0000;//io
GpioMuxRegs.GPADIR.all=0x000d;//输出pwm1pwm2pwm3pwm4
EDIS;
InitDS1302();
settime_ds1302();//设置时间
InitSysCtrl();
*(int*)0x=0x80;//初始化ICETEK-CTR0x:
全局控制寄存器
Delay(LCDDELAY);
*(int*)0x=0x0;
Delay(LCDDELAY);
*(int*)0x=0x80;
Delay(LCDDELAY);
*(int*)0x=0;//关闭东西方向的交通灯
Delay(LCDDELAY);
*(int*)0x=0x40;//关闭南北方向的交通灯
Delay(LCDDELAY);
TurnOnLCD();//打开显示
LCDCLS();//清除显示内存
*(int*)0x=LCDCMDSTARTLINE;//设置显示起始行命令控制接口的地址为0x
Delay(LCDDELAY);
*(int*)0x=0;//辅助控制接口的地址为0x向液晶显示模块发送控制命令的方法是通过向命令控制扩展接口写入命令控制字,然后再向辅助控制接口
写入0
Delay(LCDDELAY);
xingqi_display();
for(;;)
{
readtime_ds1302();//读出当前时间,读出7个字节
time_display();
}
}
//初始化1302
voidInitDS1302(void)
{
GpioDataRegs.GPADAT.bit.GPIOA2=0;
GpioDataRegs.GPADAT.bit.GPIOA0=0;
WriteDataToDS1302(0x8E,0x00);//写保护关闭
//Sec=ReadDataDS1302(0x81);
WriteDataToDS1302(0x80,0x7F);//设置运行位sec位
WriteDataToDS1302(0x84,0x00);//设置为24小时制
//WriteDataToDS1302(0x90,0xAB);//启用电池充电,双二极管,8K电阻。
WriteDataToDS1302(0x8E,0x80);//写保护开启
}
//向1302中写入一字节
voidSetByte(ucharDSAdree)
{
uchari,DS;
DS=DSAdree;
Ioout();//设置端口为输出
for(i=8;i>0;i--)
{
if(DS&0x01)
{
GpioDataRegs.GPADAT.bit.GPIOA1=1;//I/O
}else
{
GpioDataRegs.GPADAT.bit.GPIOA1=0;
}
GpioDataRegs.GPADAT.bit.GPIOA2=1;
Delay
(1);
GpioDataRegs.GPADAT.bit.GPIOA2=0;
Delay
(1);
DS=DS>>1;
}
Ioin();
}
//从1302中读一字节
ucharGetByte(void)
{
uchari,DS;
Ioin();//设置端口为输入
DS=0;
for(i=8;i>0;i--)
{
DS=(DS>>1);
if(GpioDataRegs.GPADAT.bit.GPIOA1)
{
DS|=0x80;
}
else
{
DS&=0x7f;
}
GpioDataRegs.GPADAT.bit.GPIOA2=1;
Delay
(1);
GpioDataRegs.GPADAT.bit.GPIOA2=0;
Delay
(1);
}
return(DS);
}
//写数据
voidWriteDataToDS1302(ucharDSAdree,ucharDSData)
{
GpioDataRegs.GPADAT.bit.GPIOA0=0;
GpioDataRegs.GPADAT.bit.GPIOA2=0;
Delay
(1);
GpioDataRegs.GPADAT.bit.GPIOA0=1;
SetByte(DSAdree);//地址,命令
SetByte(DSData);//写1Byte数据
GpioDataRegs.GPADAT.bit.GPIOA2=1;
GpioDataRegs.GPADAT.bit.GPIOA0=0;
}
//读数据
ucharReadDataDS1302(ucharDSAdree)
{
ucharDSData;
GpioDataRegs.GPADAT.bit.GPIOA0=0;
GpioDataRegs.GPADAT.bit.GPIOA2=0;//SCLK
Delay
(1);
GpioDataRegs.GPADAT.bit.GPIOA0=1;//RST
SetByte(DSAdree);//地址,命令
DSData=GetByte();//读1Byte数据
GpioDataRegs.GPADAT.bit.GPIOA2=1;
GpioDataRegs.GPADAT.bit.GPIOA0=0;
return(DSData);
}
//设定时间
voidsettime_ds1302()
{
uchari;
WriteDataToDS1302(0x8e,0x00);//writeenable
for(i=0;i<7;i++)//settime--second,munite,hour,day,month,week,year
{
WriteDataToDS1302(0x80+i*2,timedata[i]);
}
WriteDataToDS1302(0x8e,0x80);//writeprotect
}
//读时间
voidreadtime_ds1302()
{
intn;
for(n=0;n<7;n++)
{
timedata[n]=ReadDataDS1302(0x81+n*2);
}
}
//设置端口为输入
voidIoin()
{
EALLOW;
GpioMuxRegs.GPADIR.bit.GPIOA1=0;
EDIS;
}
//设置端口为输出
voidIoout()
{
EALLOW;
GpioMuxRegs.GPADIR.bit.GPIOA1=1;
EDIS;
}
//固定汉字显示
voidxingqi_display()
{
inti,nBW=0;
*(int*)0x=LCDCMDPAGE+1;//设置操作页=1
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
*(int*)0x=LCDCMDVERADDRESS;//起始列=0
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
for(i=0;i<8;i++)
{
*(int*)0x=(nBW==0)?
(ledkey[2][i]):
(~ledkey[2][i]);//在左屏第1页第0行第0列显示数字‘20’
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
}
for(i=0;i<8;i++)
{
*(int*)0x=(nBW==0)?
(ledkey[0][i]):
(~ledkey[0][i]);
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
}
display1Cha(1,32,0,nian);//在指定位置显示汉字‘年’
display1Cha(1,0,1,yue);//在指定位置显示汉字‘月’
display1Cha(1,32,1,ri);//在指定位置显示汉字‘日’
display1Cha(5,0,0,xing);//在指定位置显示汉字‘星’
display1Cha(5,16,0,qi);//在指定位置显示汉字‘期
//display1Cha(0,0,0,huabian);//在指定位置显示花边
*(int*)0x=LCDCMDPAGE+3;//设置操作页=3
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
*(int*)0x=LCDCMDVERADDRESS+16;//起始列=16
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
for(i=0;i<8;i++)//在指定位置显示第一个':
'
{
*(int*)0x=maohao[i];
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
}
*(int*)0x=LCDCMDVERADDRESS+40;//在指定位置显示第二个':
'
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
for(i=0;i<8;i++)
{
*(int*)0x=maohao[i];
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
}
*(int*)0x=LCDCMDPAGE;//设置操作页
Delay(LCDDELAY);
*(int*)0x=0;
Delay(LCDDELAY);
*(int*)0x=LCDCMDVERADDRESS;//起始列
Delay(LCDDELAY);
*(int*)0x=0;
D