现代电子技术综合实验报告熊万安.docx
《现代电子技术综合实验报告熊万安.docx》由会员分享,可在线阅读,更多相关《现代电子技术综合实验报告熊万安.docx(36页珍藏版)》请在冰点文库上搜索。
现代电子技术综合实验报告熊万安
电子科技大学通信与信息工程学院
实验报告
实验名称现代电子技术综合实验
姓名:
学号:
评分:
教师签字
电子科技大学教务处制
电子科技大学
实验报告
学生姓名:
学号:
指导教师:
熊万安
实验地点:
科A333实验时间:
2016.3.7-2016.3.17
一、实验室名称:
电子技术综合实验室
二、实验项目名称:
电子技术综合实验
三、实验学时:
32
四、实验目的与任务:
1、熟悉系统设计与实现原理
2、掌握KEILC51的基本使用方法
3、熟悉SMARTSOPC实验箱的应用
4、连接电路,编程调试,实现各部分的功能
5、完成系统软件的编写与调试
五、实验器材
1、PC机一台
2、SMARTSOPC实验箱一套
六、实验原理、步骤及内容
试验要求:
1.数码管第1、2位显示“1-”,第3、4位显示秒表程序:
从8.0秒到1.0秒不断循环倒计时变化;同时,每秒钟,蜂鸣器对应发出0.3秒的声音加0.7秒的暂停,对应第8秒到第1秒,声音分别为“多(高音1)西(7)拉(6)索(5)发(4)米(3)莱
(2)朵(中音1)”;数码管第5位显示“-”号,数码管第6、7、8位显示温度值,其中第6、7位显示温度的两位整数,第8位显示1位小数。
按按键转到任务2。
2.停止声音和温度。
数码管第1、2位显示“2-”,第3、4位显示学号的最后2位,第5位显示“-”号,第6到第8位显示ADC电压三位数值,按按鍵Key后转到任务3,同时蜂鸣器发出中音2的声音0.3秒;
3.数码管第1、2位显示“3-”,第3、4位显示秒表程序:
从8.0秒到1.0秒不断循环倒计时变化;调节电压值,当其从0变为最大的过程中,8个发光二极管也从最暗(或熄灭)变为最亮,当电压值为最大时,秒表暂停;当电压值为最小时,秒表回到初始值8.0;当电压值是其他值时,数码管又回到第3、4位显示从8.0秒到1.0秒的循环倒计时秒表状态。
按按鍵Key回到任务1,同时蜂鸣器发出中音5的声音0.3秒。
1、硬件设计
核心板硬件资源如下:
(1)50MHz晶振;
(2)5V、3.3V、2.5V和1.2V电源;
(3)一个Xilinx公司Spartan3E系列的FPGA器件,型号为XC3S250E-144;
(4)一片32KB的SRAM存储IS61LV256AL;
(5)基于JTAG的FPGA配置器件XCF02S/04S;
(6)基于SPI(SerialPeripheralInterface)的FPGA配置器件M25P16,含2MB空间;
(7)JTAG接口,可下载配置数据到FPGA和调试程序;
(8)Flash编程接口,对SPIFlash器件编程;
(9)8个用户LED灯和8位数码管;
(10)8位拨码开关和4个用户按键;
(11)配置成功指示LED;
(12)重新配置按键,按下此按键后,FPGA将重新配置;
(13)一个全局时钟输入和输入/输出接口;
(14)通过2个60针接口将用户I/O口、8位数据总线、15位地址总线和读/写信号引出,用于实验底板的各外设功能扩展。
硬件结构图如下图1:
图1实验平台核心板硬件结构
Quick51电路原理图为下图2:
图2Quick51电路原理图
MC51单片机定制在FPGA芯片内实现,如下图3所示,在MC8051外添加了地址地址锁存模块,形成对单片机数据总线的拓展。
添加了一个地址译码模块,形成了数据总线的复用,实验平台上的多种应用模块,可敬数据总线,通过外部寻址的方式进行访问。
图3片内MC8051单片机原理图
其中FPGA与51单片机的引脚对应为下表一:
2、各部分硬件原理
(1)数码管动态扫描原理:
图4数码管的动态扫描
动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。
选亮数码管采用动态扫描显示。
所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
先把第一个数码管的显示数据送到数据线,同时打开第一个三极管,而其他数码管的对应的三极管关闭;延迟一段时间(通常不超过10ms),再把第二个数码管的显示数据送到数据线,同时打开第二个三极管,而其他数码管的对应的三极管关闭;延时一段时间,在显示下一个。
注意:
整个数码管的扫描频率应当大于50Hz,防止出现明显的闪烁。
(2)I2C工作原理:
图5I2C电路图
为了使这些相似之处对系统设计者和器件厂商都得益而且使硬件效益最大电路最简单Philips开发了一个简单的双向两线总线实现有效的IC之间控制这个总线就称为InterIC或I2C总线现在Philips包括超过150种CMOS和双极性兼容I2C总线的IC可以执行前面提到的三种类型的功能所有符合I2C总线的器件组合了一个片上接口使器件之间直接通过I2C总线通讯这个设计概念解决了很多在设计数字控制电路时遇到的接口问题。
(3)LM75特征及应用:
图4LM75应用电路
LM75A是一个使用了内置带隙温度传感器和∑-△模数转换技术的温度-数字转换器。
它也是一个温度检测器,可提供一个过热检测输出。
LM75A包含许多数据寄存器:
配置寄存器(Conf),用来存储器件的某些配置,如器件的工作模式、OS工作模式、OS极性和OS故障队列等(在功能描述一节中有详细描述);温度寄存器(Temp),用来存储读取的数字温度;设定点寄存器(Tos&Thyst),用来存储可编程的过热关断和滞后限制,器件通过2线的串行I2C总线接口与控制器通信。
LM75A还包含一个开漏输出(OS),当温度超过编程限制的值时该输出有效。
LM75A有3个可选的逻辑地址管脚,使得同一总线上可同时连接8个器件而不发生地址冲突。
LM75A可配置成不同的工作条件。
它可设置成在正常工作模式下周期性地对环境温度进行监控或进入关断模式来将器件功耗降至最低。
OS输出有2种可选的工作模式:
OS比较器模式和OS中断模式。
OS输出可选择高电平或低电平有效。
故障队列和设定点限制可编程,为了激活OS输出,故障队列定义了许多连续的故障。
温度寄存器通常存放着一个11位的二进制数的补码,用来实现0.125℃的精度。
这个高精度在需要精确地测量温度偏移或超出限制范围的应用中非常有用。
(4)按键原理:
图7按键原理图
由原理图可知,按键的另一端接地,当按键按下时,按键对应的接口对应低电平,为逻辑0,当按键抬起时,由于上拉电阻的存在,接口为高电平,为逻辑1,因此可以通过查询对应的接口状态来判断是否按键是否按下。
(5)蜂鸣器工作原理:
图8蜂鸣器电路原理图
三极管有两个作用:
一是根据开通或者关闭控制蜂鸣器发生与否;二是驱动蜂鸣器工作,因为单片机的IO口驱动能力不够让蜂鸣器发出声音,所以通过三极管放大驱动电流,从而可以让蜂鸣器发出声音。
输出高电平,三极管导通,集电极电流蜂鸣器让蜂鸣器发出声音;当输出低电平时,三极管截止,没有电流流过蜂鸣器,不会发出声音。
(6)LED显示原理:
图9LED显示原理
由原理图可知,当输出低电压时,LED亮;输出高电平时,LED灭。
在一个很短的时间间隙循环时,LED亮的时间占比越多,LED呈现的亮度越亮,从而可以通过亮的时间的占比达到控制亮度的目的。
(7)AD实现原理:
图10 TLC549串行ADC
当/CS变为低电平后,TLC549芯片被选中,同时前次转换结果的最高有效位MSB(A7)自DATAOUT端输出,接着要求自I/OCLOCK端输入8个外部时钟信号,前7个I/OCLOCK信号的作用,是配合TLC549输出前次转换结果的A6-A0位,并为本次转换做准备:
在第4个I/OCLOCK信号由高至低的跳变之后,片内采样/保持电路对输入模拟量采样开始,第8个I/OCLOCK信号的下降沿使片内采样/保持电路进入保持状态并启动A/D开始转换。
转换时间为36个系统时钟周期,最大为17us。
直到A/D转换完成前的这段时间内,TLC549的控制逻辑要求:
或者/CS保持高电平,或者I/OCLOCK时钟端保持36个系统时钟周期的低电平。
由此可见,在自TLC549的I/OCLOCK端输入8个外部时钟信号期间需要完成以下工作:
读入前次A/D转换结果;对本次转换的输入模拟信号采样并保持;启动本次A/D转换开始。
3、软件设计
思考题:
按键改用外部中断模式,电路如何修改(画示意图)?
程序如何修改,写出中断服务程序。
答:
若按键改用外部中断模式,可以使用INT0、INT1,需要将按键(如按键KEY1、KEY2)分别用杜邦线连到INT0、INT1外部中断口,如下图11:
图11 外部中断
程序则做如下修改:
各个函数无需调用按键扫描函数,但在主函数或者系统初始化函数,添加几段语句进行外部中断的初始化:
EX0=1;//使能/INT0中断;
EX1=1;//使能/INT1中断;
EA=1//使能总中断;
中断服务程序为:
voidINT0SVC()interrupt0
{
task++;
for(;Key1==0;)
Delay(81);
}
七、总结及心得体会
八、对本实验过程及方法、手段的改进建议
九、附录
1、程序
程序包括main.c文件和修改过的Disp.c和Disp.h文件,其中Disp.c添加了利用定时器1的软件延时函数voidDelay(unsignedintt),而Disp.h添加了该函数的声明。
main.c文件:
/*
main.c
现代电子综合实验
*/
#include"VolTab.h"
#include"Disp.h"
#include"I2C.h"
#include
#include
#defineM20xFCEF//587.33
#defineM30xFD45//659.26
#defineM40xFD6C//698.46
#defineM50xFDB4//783.99
#defineM60xFDF4//880.00
#defineM70xFE2D//987.77
#defineH10xFE48//1046.5
sbitBUZZER=P1^0;//交流蜂鸣器由P1.0管脚控制
sbitKEY1=P2^0;//按键1
//定义TLC549操作接口
sbitCS=P1^5;
sbitDAT=P1^7;
sbitCLK=P1^6;
//定义PWM最大级数
#definePWM_MAX26
//定义PWM级数,分为0~PWM_MAX-1级
unsignedcharPwmValue;
unsignedintMusicTab[]=
{
H1,M7,M6,M5,M4,M3,M2
};
//定义定时器T1重装值
volatilecharReloadH;
volatilecharReloadL;
//定义任务、中断标志位
unsignedinttask,flg;
/*
函数:
T0INTSVC()
功能:
定时器T0中断服务函数
*/
voidT0INTSVC()interrupt1
{
staticunsignedchartemp=0;
if(flg==3)
{
TR0=0;
TH0=0xFF;
TL0=0x00;
TR0=1;
temp++;
if(temp>=PWM_MAX)temp=0;
if(temp{
P0=0x00;
}
else
{
P0=0xff;
}
}
else
{
TR0=0;
TH0=ReloadH;
TL0=ReloadL;
TR0=1;
BUZZER=!
BUZZER;
}
}
/*
函数:
Sound()
功能:
演奏一个音符
参数:
*note:
音符指针,指向要演奏的音符
*/
voidSound(unsignedintnote)
{
//利用定时器T1发出音符的频率
if(note!
=0)
{
ReloadH=(unsignedchar)(note>>8);
ReloadL=(unsignedchar)(note);
TR0=0;
TH0=0xFF;
TL0=0xF0;
TR0=1;
flg=1;
EA=1;
ET0=1;
}
}
/*
函数:
Delay()
功能:
延时1ms~65.536s
本函数只是简单延时函数,非秒表使用
*/
voidDelays(unsignedintt)
{
unsignedintt1;
do
{
for(t1=1200;t1>0;t1--);
}while(--t!
=0);
}
//按键扫描函数
voidKeyScan()
{
if(KEY1==0)task++;
for(;KEY1==0;)
Delay(81);
}
/*
函数:
SysInit()
功能:
系统初始化
*/
voidSysInit()
{
TMOD&=0xF0;
TMOD|=0x01;//设置T0为16位定时器
DispInit();//数码管扫描显示初始化
I2C_Init();//初始化I2C总线
}
/*
函数:
LM75A_GetTemp
功能:
读出LM75A的温度值
返回:
LM75A温度寄存器的数值(乘以0.125可得到摄氏度值)
*/
intLM75A_GetTemp()
{
unsignedcharbuf[2];
intt;
I2C_Gets(0x90,0x00,2,buf);
t=buf[0];
t<<=8;
t+=buf[1];
t>>=5;//去掉无关位
returnt;
}
/*
函数:
ByteToStr()
功能:
字节型变量c转换为十进制字符串
*/
voidByteToStr(unsignedcharidata*s,unsignedcharc)
{
codeunsignedcharTab[]={10,1};
unsignedchari;
unsignedchart;
for(i=0;i<2;i++)
{
t=c/Tab[i];
*s++='0'+t;
c-=t*Tab[i];
}
*s='\0';
}
/*
函数:
DispTemp()
功能:
在数码管上显示出温度值
参数:
t:
补码,除以8以后才是真正温度值
*/
voidDispTemp(intt)
{
codeunsignedcharTab[8]=
{
'0',
'1',
'3',
'4',
'5',
'6',
'8',
'9'
};
unsignedcharbuf[3];
unsignedchari;//整数部分
unsignedchard;//小数部分
//分离出整数和小数部分
i=t/8;
d=t%8;
//整数部分转换成字符串
ByteToStr(buf,i);
//显示整数部分
DispStr(5,buf);
//显示小数点
DispDotOn(6);
//显示小数部分
DispChar(7,Tab[d]);
}
/*
函数:
ReadAdc()
功能:
读取A/D转换结果
返回:
8位ADC代码
*/
unsignedcharReadAdc()
{
unsignedchard;
unsignedcharn;
CS=0;
n=5;
while(--n!
=0);
n=8;
do
{
d<<=1;
if(DAT)d++;
CLK=1;
CLK=0;
}while(--n!
=0);
CS=1;
returnd;
}
/*
函数:
AdcInit()
功能:
初始化ADC接口
*/
voidAdcInit()
{
CS=1;
CLK=0;
DAT=1;
ReadAdc();
}
/*
函数:
DispVol()
功能:
将ADC值转换成电压值,并显示
参数:
v:
8位ADC结果
*/
voidDispVol(unsignedcharv)
{
DispStr(5,VolTab[v]);
DispDotOn(5);
}
//任务一
voidfirstf()
{
unsignedcharT1[]="87654321";
unsignedcharT2[]="0987654321";
unsignedintt,t1=0,t2=0,msh=0;
P0=0xff;//关闭LED
DispChar(0,'1');
DispChar(1,'-');
DispChar(4,'-');
for(;;)
{
//显示秒表
DispChar(2,T1[t1]);
DispChar(3,T2[t2]);
DispDotOn
(2);
//温度读取和显示
t=LM75A_GetTemp();
DispTemp(t);
//发音
if(T1[t1]!
='1'&&T2[t2]=='0')
{
Sound(MusicTab[msh]);
msh++;
if(msh==7)
msh=0;
}
if(T2[t2]=='7')
{
TR0=0;
BUZZER=1;
}
//秒表实现
Delay(81);
if(!
(T1[t1]=='1'&&T2[t2]=='0'))
{
t2++;
if(t2==10)
{
t2=0;
}
if(t2==1)
{
t1++;
if(t1==8)
t1=0;
}
if(t1==0&&t2==1)
t1++;
}
else
{
t1=0;
t2=0;
}
//按键扫描
Delay(81);
KeyScan();
if(task%3!
=0)break;
}
}
//任务2
voidtwof()
{
unsignedcharv;//电压值
DispInit();
AdcInit();
TR0=0;
BUZZER=1;
//短暂停顿
Delay(10);
P0=0xff;
DispChar(0,'2');
DispChar(1,'-');
DispChar(4,'-');
DispChar(2,'1');
DispChar(3,'4');
for(;;)
{
v=ReadAdc();//读取ADC值
DispVol(v);//显示成电压值
Delay(80);//延时50ms
KeyScan();
if(task%3!
=1)break;
}
}
//任务3
voidthreef()
{
unsignedcharT1[]="87654321";
unsignedcharT2[]="0987654321";
unsignedcharv;//电压值
unsignedintt1=0,t2=0;
AdcInit();
flg=3;
Delay(10);
TR0=1;
ET0=1;
BUZZER=1;
DispChar(0,'3');
DispChar(1,'-');
for(;;)
{
//显示秒表
DispChar(2,T1[t1]);
DispChar(3,T2[t2]);
DispDotOn
(2);
//读取显示温度
v=ReadAdc();//读取ADC值
DispVol(v);//显示成电压值
//控制LED
PwmValue=v/10;
//秒表实现
Delay(81);
if(v==0)
{
t1=0;
t2=0;
}
elseif(v>235)
Delay(81);
else
{
if(!
(T1[t1]=='1'&&T2[t2]=='0'))
{
t2++;
if(t2==10)
{
t2=0;
}
if(t2==1)
{
t1++;
if(t1==8)
t1=0;
}
if(t1==0&&t2==1)
t1++;
}
else
{
t1=0;
t2=0;
}
}
//按键扫描
Delay(81);
KeyScan();
if(task%3!
=2)break;
}
}
voidmain()
{
for(;;)
{
SysInit();
switch(task%3)
{
case0:
firstf();
break;
case1:
twof();
if(task%3==2)
{
Sound(MusicTab[6]);
Delay(486);
}
break;
case2:
threef();
if(task%3==0)
{
Sound(MusicTab[3]);
Delay(486);
}
break;
}
}
}
Disp.h:
添加了软件延时函数的定义voidDelay(unsignedintt);
/*
Disp.h
数码管扫描显示驱动程序头文件
*/
#ifndefDisp_h_
#defineDisp_h_
/清除数码管的所有显示
voidDispClear();
//在数码管位置x(0~7)处显示字符c(仅限十进制数字和减号)
voidDispChar(unsignedcharx,unsignedcha