单片微型机原理应用与实验.docx
《单片微型机原理应用与实验.docx》由会员分享,可在线阅读,更多相关《单片微型机原理应用与实验.docx(55页珍藏版)》请在冰豆网上搜索。
![单片微型机原理应用与实验.docx](https://file1.bdocx.com/fileroot1/2023-1/7/2ee7ae04-fe36-46b6-8950-00f4c3899d09/2ee7ae04-fe36-46b6-8950-00f4c3899d091.gif)
单片微型机原理应用与实验
单片微型机原理应用与实验
1(或绪论、概述)
背景:
电子时钟设计是基于日常生活人们对时间刻度必不可缺的需求。
比如跑步运动员需要秒表计时,学生需要闹钟提醒上课,等…..
目的:
设计一个电子时钟包括日期,秒表温度,音乐,闹钟,贪睡。
应解决的主要问题:
单片机程序的设计和改动I/o口的分配;硬件电路的设计和故障的的排除。
基本理论依据和主要容:
依据单片微型机原理,应用与实验(第【5】版)复旦大学学习的软件知识和华成英童诗白.模拟电子技术基础。
高等教育和阎石.数字电子技术基础.第【4】版.高等教育所提供的硬件知识。
2设计方案简述
在一般数字时钟的基础上加上闹钟,温度,秒表,音乐闹钟
3详细设计
3.1实现闹钟的设定
一,可以设置两个闹钟
二,off和on表示关掉还是开启
三,once表示只响一次,Repeat表示重复响,即每天都响一次
3.2实现一般时钟的功能年月日,时分秒,星期几
具体由DS1302控制实现,他即使一个时钟芯片,也是一个储存器。
3.3,.音乐的设定
一,包括,lovetransfer和FairyTale两首歌,由于单片机空间有限只放了两首歌。
软件方面是把乐谱编码后放在音乐功能程序块
二,硬件方面通过5v蜂鸣器和三极管放大电路实现
3.4贪睡模式设定
off和on实现贪睡功能的关闭与开启
贪睡延迟时间的设定(Delay—minutes)比如说你选择贪睡模式后并且设定延迟时间为10分钟,那么闹铃响完毕10分钟后再次响。
3.5秒表功能
一,精确到毫秒
二,可暂停并保持原有数据
三,可复位
3.6.掉电模式设定(LowPowerMode)
单片机工作在掉电模式下,可保持数据。
按复位键可恢复正常工作模式。
)
4设计结果及分析
结果如图所示
4.1显示模块
4.22温度处理采集模块
4.3时钟芯片模块
4.4声音模块
4.5单片机模块
5总结
通过本学期学习的单片机课我们学到了很多知识,虽然让自己写下来几乎不可能,但起码看得懂,还有会改动。
再加上模电;数电硬件知识,软硬结合并且通过以前的多次动手练习,有信心也有能力的搞好电子时钟的设计,通过电路的仿真实验,再加上程序的相应改动,大体规划出了大概。
由于资料上的功能太少于是我们添加了温度;贪睡;音乐功能,但是摆在我们面前的是两个问题,第一是程序的改动和添加;第二是硬件电路的设计;第三个问题是电路的焊接和调试。
第一个问题带来了很大的麻烦,比如I/O口的重新分配,空间的大小不够用,自变量太多而导致的部资源浪费。
在经过参考书的学习和自己的认真思考花了很大的时间终于调试成功。
第二个问题我们反复查阅各个单个功能的硬件电路,然后自己加以改造和整合。
最终获得仿真成功。
第三个问题,折磨了我们很长时间。
莫名其妙的各种问题层出不穷,经过多次排查总结规律,焊工的水平有限虚焊很多,还有在排查问题时发现问题我们应该遵从2个顺序去1先看现象分析问题可能有什么导致,是没加上电?
还是虚焊有的功能没实现/
2查找问题模块化,一个模块一个模块的的去检查这样有顺序不盲目或者遗漏!
经过多天的的课程设计我们学习到了很多,不仅是知识更宝贵的是经验!
感老师的辛苦辅导和同学的认真帮助。
参考文献
[序号]主要责任者.文献题名[Z].出版地:
出版者,出版年.
1.M华成英童诗白.模拟电子技术基础。
高等教育
2.M阎石.数字电子技术基础.第【4】版.高等教育
3.M自美.电子线路设计-实验-测试[M].:
华中科技大学,2000
4.M单片机程序设计【300】例教你你入门到精通
5,M友德.志英.徐时亮.单片微型机原理,应用与实验(第【5】版)复旦大学出版
社
附录
#include//2010.4.6-2010.4.13DesignedByLu.QQ:
4756005972010.6.14再次修改
#include
typedefunsignedcharuchar;
typedefunsignedintuint;
#defineLCD1602_DATAP0//1602液晶数据口
sbitLCD1602_RS=P1^0;
sbitLCD1602_RW=P1^1;
sbitLCD1602_EN=P1^2;//1602液晶使能控制
sbitDS1302_CLK=P3^0;//实时时钟时钟线引脚
sbitDS1302_IO=P3^1;//实时时钟数据线引脚
sbitDS1302_RST=P3^2;//实时时钟复位线引脚
sbitDQ=P2^3;//18B20接口
sbitBeepIO=P2^7;//蜂鸣器
sbitesc=P1^7;//取消播放音乐
sbitmode=P1^4;//模式键
sbitinc=P1^5;//增加键
sbitdec=P1^6;//减少键
sbitok=P1^7;//OK键
sbitlight=P2^0;//背光控制
sbitACC0=ACC^0;//累加器位定义
sbitACC7=ACC^7;
bitfirst_flag=1,//一级主界面显示标志
second_flag,//二级菜单显示标志
third_flag,//三级菜单显示标志
playmusic,//播放音乐的标志
light_flag1=1,//背光第一次计时标志
light_flag=1;//二三级界面开背光标志
ucharcount1,sec1,min1,hour1;//定时器2使用的变量停表用
ucharcount,sec,min;//定时器1使用的变量贪睡用
uchartemp;//温度暂存
//////以下为播放音乐的设置
#defineSYSTEM_OSC12000000
#defineSOUND_SPACE4/5
uintcodeFreTab[12]={262,277,294,311,330,349,369,392,415,440,466,494};//原始频率表
ucharcodeSignTab[7]={0,2,4,5,7,9,11};//1~7在频率表中的位置
ucharcodeLengthTab[7]={1,2,4,8,16,32,64};
ucharSound_Temp_TH0,Sound_Temp_TL0;//音符定时器初值暂存
ucharSound_Temp_TH1,Sound_Temp_TL1;//音长定时器初值暂存
bitstop;
charmenu_num;//菜单号
charnum;//按键加减调整暂存数
charposition1,position2,position3,position4,position5,position6,position7;//菜单1-7的光标位置标志
charcodemenu[][16]={"1.TimeSetting","2.AlarmSetting","3.AlarmMusic","4.Snooze",
"5.BackLight","6.StopWatch","7.LowPowerMode","8.Exit"};
charcodeon_off_flag[][4]={"OFF","ON"};
charcodealarm_times[][7]={"Once","Repeat"};
charcodeweek[][4]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
ucharcodeself_table[]={0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//年0
0x1f,0x11,0x1f,0x11,0x1f,0x11,0x15,0x17,//月1
0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00,//日2
0x01,0x0c,0x17,0x14,0x17,0x0c,0x01,0x00,//闹钟标志3
0x10,0x18,0x1c,0x1e,0x1f,0x1c,0x18,0x10,//三角形符号,第五个自定义字符4
0x1f,0x15,0x0a,0x04,0x0a,0x15,0x1f,0x00};//贪睡标志5
/***********************延时函数(单位ms)**************************/
voiddelay(uintz)
{
uintx;
uchary;
for(x=z;x>0;x--)
for(y=112;y>0;y--);
}
/***********************************************************
******************LCD1602驱动程序******************
************************************************************/
/***********************************************************
忙检测
************************************************************/
voidLCD1602_check_busy()
{
LCD1602_DATA=0xff;
LCD1602_RS=0;
LCD1602_RW=1;
LCD1602_EN=1;
while(LCD1602_DATA&0x80);
LCD1602_EN=0;
}
/**********************************************************
写指令
************************************************************/
voidLCD1602_write_cmd(ucharcmd)
{
LCD1602_check_busy();
LCD1602_RS=0;
LCD1602_RW=0;
LCD1602_DATA=cmd;
LCD1602_EN=1;
_nop_();
LCD1602_EN=0;
}
/***********************************************************
写数据
*************************************************************/
voidLCD1602_write_data(uchardat)
{
LCD1602_check_busy();
LCD1602_RS=1;
LCD1602_RW=0;
LCD1602_DATA=dat;
LCD1602_EN=1;
_nop_();
LCD1602_EN=0;
}
/***********************************************************
1602初始化
************************************************************/
voidLCD1602_init()
{
/****************写入自定义字符***************************/
uchari;
LCD1602_write_cmd(0x40);//CGRAM起始地址
for(i=0;i<48;i++)
LCD1602_write_data(self_table[i]);//写入6个自定义字符
/*********************************************************/
LCD1602_write_cmd(0x38);//8位数据,双列显示,5*7字形
LCD1602_write_cmd(0x0c);//开显示,关光标,光标不闪烁
LCD1602_write_cmd(0x01);//清屏
}
/************************************************************
设置显示坐标
************************************************************/
voidLCD1602_set_postion(ucharx,uchary)
{
if(!
y)
LCD1602_write_cmd(0x80+x);
elseif(y)
LCD1602_write_cmd(0xc0+x);
}
/************************************************************
指定位置写字符
*************************************************************/
voidLCD1602_write_char(ucharx,uchary,ucharchardata)
{
LCD1602_set_postion(x,y);
LCD1602_write_data(chardata);
}
/************************************************************
指定位置写字符串
*************************************************************/
voidLCD1602_write_string(ucharx,uchary,uchar*string)
{
LCD1602_set_postion(x,y);
while((*string)!
='\0')
{
LCD1602_write_data(*string);
string++;
}
}
/***********************************************************
******************DS1302驱动程序******************
************************************************************/
voidDS1302InputByte(unsignedchard)//实时时钟写入一字节(部函数)
{
unsignedchari;
ACC=d;
for(i=8;i>0;i--)
{
DS1302_IO=ACC0;//相当于汇编中的RRC
DS1302_CLK=1;
DS1302_CLK=0;
ACC=ACC>>1;
}
}
unsignedcharDS1302OutputByte(void)//实时时钟读取一字节(部函数)
{
unsignedchari;
for(i=8;i>0;i--)
{
ACC=ACC>>1;//相当于汇编中的RRC
ACC7=DS1302_IO;
DS1302_CLK=1;
DS1302_CLK=0;
}
return(ACC);
}
voidWrite1302(unsignedcharucAddr,unsignedcharucDa)//ucAddr:
DS1302地址,ucData:
要写的数据
{
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr);//地址,命令
DS1302InputByte(ucDa);//写1Byte数据
DS1302_CLK=1;
DS1302_RST=0;
}
unsignedcharRead1302(unsignedcharucAddr)//读取DS1302某地址的数据
{
unsignedcharucData;
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr|0x01);//地址,命令
ucData=DS1302OutputByte();//读1Byte数据
DS1302_CLK=1;
DS1302_RST=0;
return(ucData);
}
voidDS1302_init()
{
if(Read1302(0xc1)!
=0xf0)
{
Write1302(0x8e,0x00);//允许写操作
Write1302(0xc0,0xf0);//写入初始化标志,系统上电后检测此标志,即此子函数只会在第一次初始化一次。
/******时间初始值******/
Write1302(0x8c,0x10);//年
Write1302(0x8a,0x03);//星期
Write1302(0x88,0x05);//月
Write1302(0x86,0x26);//日
Write1302(0x84,0x22);//时
Write1302(0x82,0x59);//分
Write1302(0x80,0x55);//秒
///////////////////
Write1302(0xd2,0);//歌曲选择初始
Write1302(0xd4,5);//贪睡初始延时时间5分钟
Write1302(0xd6,0);//贪睡初始值关闭
/******闹钟初始值******/
Write1302(0xc2,0);//十时
Write1302(0xc4,0);//时
Write1302(0xc6,0);//闹钟标志
Write1302(0xc8,0);//闹钟次数标志
////第二个闹钟
Write1302(0xca,0);//十时
Write1302(0xcc,0);//时
Write1302(0xce,0);//闹钟标志
Write1302(0xd0,0);//闹钟次数标志
////////////
Write1302(0xd8,0);//背光控制开关
Write1302(0xda,0x10);//背光延时时间
Write1302(0x90,0xa4);//涓流充电
//////////////////
Write1302(0x8e,0x80);//禁止写操作
}
}
/***********************************************************
******************DS18B20驱动程序******************
************************************************************/
voiddelay_18b20(unsignedinti)//延时函数
{
while(i--);
}
/***************************************************************************************/
//18b20初始化函数
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
delay_18b20(8);//稍做延时
DQ=0;//单片机将DQ拉低
delay_18b20(80);//精确延时大于480us
DQ=1;//拉高总线
delay_18b20(10);
x=DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay_18b20(5);
}
//读一个字节
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay_18b20(5);
}
return(dat);
}
//写一个字节
voidWriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay_18b20(5);
DQ=1;
dat>>=1;
}
delay_18b20(5);
}
//读取温度
unsignedcharReadTemperature(void)
{
unsignedchara=0;
unsignedcharb=0;
unsignedchart=0;
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0x44);//启动温度转换
delay_18b20(200);
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器等(共可读9个寄存器)前两个就是温度
a=ReadOneChar();
b=ReadOneChar();
b<<=4;
b+=(a&0xf0)>>4;
t=b;
return(t);
}
/******************************************