南 京 工 业 大
单 片 机 应 用 实
学生姓名: 学
号: 专
业: 班
级:
2014年6月
学习
一、实习地点
学科楼D30
1、D208
二、实习时间
2014-5-26——2014-6-6
三、实习项目
1.绘制学习板的电路图,熟悉Altium Designer软件。
2.利用STC89C52RC的定时器1实现:可调时电子钟(液晶显示)。
3.使用开发板上的DS18B20进行环境温度测量,并将测量到的温度值显示(七段码显示),小数点后一位有效数字,单位为C。
4.熟悉STC89C52RC的定时器2,并用定时器2实现可调时电子钟(七段码显示器)。
5.第3题基础上实现:当温度大于等于28.0℃时,蜂鸣器鸣叫,同时,继电器闭合;当温度小于28.0℃时,蜂鸣器停止鸣叫,同时,继电器断开。 6.在第3题基础上增加一个温度报警点设置界面(七段数码显示),例如第5题中的28.0℃报警点可通过按键进行设置任意修改,修改后的温度报警值不需要存储,每次开机后先进行报警值的设置,程序其他功能与第5题相同。 7.利用24C02芯片,对第3题中开机1分钟内的环境温度测量值进行永久保存。 8.将第7题中保存的温度值利用按键操作依次进行读取,利用数码管显示。
四、实习项目完成情况
1.电路图能够很好的完成,在老师进行了该软件的大概讲解后,对软件有一定的了解,但是在应用过程中遇到了问题有:找不到该放置的元器件,网络标识的放置等等。在自己的摸索下能够很好的完成该电路图,但是完成后出现警告,仔细检查后解决了该问题。评价——优秀
2.定时器1实现可调电子钟,在液晶屏上显示。这个项目是在课堂例题定时器实现可调电子钟的基础上修改的。采用一个动态显示函数就可以实现,将数据送入液晶显示即可。 评价——良好
3使用开发板上的DS18B20进行环境温度测量,并将测量到的温度值显示在数码管上。这个DS18B20之前没有接触过,自己能力毕竟有限。所以就从网上找了相关的程序。有的地方不合适的改进了一下,最终完成了这个项目。评价——及格
4用定时器2实现可调电子钟。这个项目是在课堂案例里面的定时器实现电子钟的基础上修改的。用定时器2取代定时器1。但是定时器2没有学过,于是参考课本上的讲解,实现它的初始化,打开,清零等功能。但是在52单片机里面没有定时器2,所以头文件还是应该换成52单片机的。 评价——良好
5.这个项目是在第三个项目的基础之上,加个报警程序就好了。这个报警程序之前不会,从网上参考了一些,实现了该功能。评价——及格
6.显示当前的温度并设置报警温度:该程序主要是几个小程序的组合,最初整合以后会有些功能无法实现,错误在于几个小程序整合的位置不正确,纠正各部分的位置,将显示整合为一个,程序运行还是不满意,还是有点问题。 评价——及格
以下项目根据自己完成情况进行描述: 7.................................8.................................
五、典型项目实习报告
1.项目描述
项目2:
功能:利用STC89C52RC的定时器1实现:可调时电子钟(液晶显示)。 操作说明书:
① 上电后液晶正常显示,显示时间。
② 左起第一个按键(S17)作为调整时间切换按键。
③ 下左起第二个按键(S18),为递增;左起第三个按键(S19),为递减。 ④ 调整完成后,按下S17,时间修改完成。 附实物图:
2.学习板电路图
3.程序清单 #include //头文件
#include "lcd12232.h" #include "delay.h" #define KEY_PIN P3
SHOW_MIN_ADJ,SHOW_HOUR_ADJ, }ShowState; enum {
LED_GOOUT = 10, CHAR_DEC = 12,
unsigned char GetKey(void);
//取键值
unsigned char LEDBuffer[8];
//显示缓冲区
unsigned char Second;
//秒
unsigned char Minute;
//分
unsigned char Hour;
//时
bit Timer1sFlg;
//定时1秒标志位 bit Timer05sFlg;
//定时0.5秒标志位
typedef enum
//枚举 状态法 { NULL, KEY_ENTER, KEY_UP, KEY_DOWN }TYPEDEF_KEY;
enum SHOW_STATE
{ SHOW_NORMAL,
SHOW_SEC_ADJ,
};
/*函数声明*/
void AT89S51Config(void);
void VariableInitial(void); void ShowNormal(void);
void ShowSecondAdj(void); void ShowMinuteAdj(void);
void ShowHourAdj(void); /*主函数*/
void main() {
LcdConfig();
//AT89S51配置
AT89S51Config(); //AT89S51配置
VariableInitial(); 量初始化
while(1)
{
switch(ShowState) 示按键对应状态
{
变
显
// // case SHOW_NORMAL:
ShowNormal(); break; case SHOW_SEC_ADJ:
ShowSecondAdj(); break; case SHOW_MIN_ADJ:
ShowMinuteAdj(); break; case SHOW_HOUR_ADJ:
ShowHourAdj(); break; default:
break; } DrawWord(LEDBuffer[7],0,29,8); //送LCD显示
DrawWord(LEDBuffer[6],0,37,8); DrawWord(LEDBuffer[2],0,45,8); DrawWord(LEDBuffer[4],0,53,8); DrawWord(LEDBuffer[3],0,61,8); DrawWord(LEDBuffer[5],0,69,8);
DrawWord(LEDBuffer[1],0,77,8);
DrawWord(LEDBuffer[0],0,85,8);
Delay_ms(5); // 延时若干
毫秒
}
}
/*AT89S51配置*/
void AT89S51Config(void) { TMOD = 0x01; //* TL0 = (6553650000)/256; //*
TR0 = 1; //* IE = 0x82;
} /*
* TMOD(89H):GATE C//T M1 M0 GATE C//T M1 M0
默认:0x00
其中:C//T:定时计数选择
M1-0: 工作方式选择
GATE:启动方式设定
0:软件启动(常用)
1:外部中断启动
* 工作方式1: TL0和TH0组成16位的定
时器
* TR0(TR1): 1: 启动定时计数器0(1);
0: 关闭定时计数器0(1) * IE(0A8H): EA / / ES ET1 EX1 ET0 EX0
默认:0x00
*/
/*变量初始化*/
void VariableInitial(void) {
ShowState = 0;
Second = 0;
Minute = 0;
Hour = 0;
Timer1sFlg = 0; Timer05sFlg = 1;
}
/************************************ *********************/ /*正常显示界面*/
/************************************ *********************/ void ShowNormal(void) {
TYPEDEF_KEY key;
//1秒钟到,显示值更新
if(Timer1sFlg)
{ Timer1sFlg = 0;
Second++;
if(Second >= 60)
{
Second = 0;
Minute ++;
if(Minute >= 60)
{
Minute = 0;
Hour ++;
if(Hour >= 24)
{
Hour = 0;
}
}
}
}
//界面显示
LEDBuffer[0] = Second % 10; //秒个位送显示缓冲区 LEDBuffer[1] = Second / 10; //秒十位送显示缓冲区 LEDBuffer[3] = Minute % 10; LEDBuffer[4] = Minute / 10; LEDBuffer[6] = Hour % 10; LEDBuffer[7] = Hour / 10; if(Timer05sFlg) { LEDBuffer[2] = CHAR_DEC; LEDBuffer[5] = CHAR_DEC;
} else
{
LEDBuffer[2] = LED_GOOUT; LEDBuffer[5] = LED_GOOUT; }
//正常显示界面下响应按键
key = GetKey(); if(key == KEY_ENTER) { ShowState = SHOW_SEC_ADJ; }
}
/*********************************************************/ /*秒针调整界面*/ /*********************************************************/ void ShowSecondAdj(void) { TYPEDEF_KEY key; unsigned char i;
//界面显示
for(i = 0; i
=
LED_GOOUT; //熄灭
} LEDBuffer[0] = Second % 10; //秒个位送显示缓冲区
LEDBuffer[1] = Second / 10; //秒十位送显示缓冲区
//秒针调整界面下响应按键
key = GetKey(); switch(key) {
case KEY_ENTER:
ShowState = SHOW_MIN_ADJ;
break;
case KEY_UP:
Second++;
if(Second >= 60)
{
Second = 0;
}
break;
case KEY_DOWN:
if(0 == Second)
{
Second = 59;
}
else
{
Second--;
}
break;
}
} /*********************************************************/ /*分针调整界面*/ /*********************************************************/ void ShowMinuteAdj(void) { TYPEDEF_KEY key; unsigned char i; //界面显示
for(i = 0; i
=
LED_GOOUT; //熄灭
} LEDBuffer[3] = Minute % 10; //分个位送显示缓冲区
LEDBuffer[4] = Minute / 10; //分十位送显示缓冲区
//分针调整界面下响应按键
key = GetKey(); switch(key) { case KEY_ENTER:
ShowState = SHOW_HOUR_ADJ; break; case KEY_UP:
Minute++; if(Minute >= 60)
{
Minute = 0;
}
break;
case KEY_DOWN:
if(0 == Minute)
{
Minute = 59;
}
else
{
Minute--;
}
break;
}
}
/*********************************************************/ /*小时调整界面*/
/*********************************************************/ void ShowHourAdj(void) { TYPEDEF_KEY key; unsigned char i; //界面显示
for(i = 0; i
LEDBuffer[i]
=
LED_GOOUT;//熄灭
} LEDBuffer[6] = Hour % 10; //小时个位送显示缓冲区 LEDBuffer[7] = Hour / 10; //小时十位送显示缓冲区
//小时调整界面下响应按键 key = GetKey(); switch(key) { case KEY_ENTER: ShowState = SHOW_NORMAL; break; case KEY_UP: Hour++; if(Hour >= 24) {
Hour = 0; } break; case KEY_DOWN:
if(0 == Hour) {
Hour = 23; } else { Hour--; }
break;
}
}
/*定时中断0的中断函数*/ Timer0() interrupt 1
//*
{ static unsigned char count_1s; static unsigned char count_05s; TL0 = (6553650000)/256;
count_1s++; count_05s++; if(count_1s >= 20) {
Timer1sFlg = 1;
count_1s =0;
}
if(count_05s >= 10) {
Timer05sFlg = !Timer05sFlg;
count_05s =0;
}
} /*
*
0-4号中断分别为:外部中断0
定时中断0 外部中断1 定时中断1 串
行中断
*/
/*得到按键值*/
TYPEDEF_KEY GetKey(void)
{
TYPEDEF_KEY key = NULL;
if( ~KEY_PIN & 0x1c)
//有键按下
{ Delay(1000);
//去抖动
if(~KEY_PIN & 0X04)
{
key = KEY_UP;
}
else if(~KEY_PIN & 0X08)
{
key = KEY_DOWN;
}
else if(~KEY_PIN & 0X10)
{
key = KEY_ENTER;
}
else
{
return(NULL);
}
while( ~KEY_PIN & 0x1c) //等待键抬起
{
Delay(2);
}
return(key);
}
return(NULL);
}
//---------------------- //文件名称:lcd12232.c #include
#include "delay.h" #include "lcd12232.h"
//LCD接口定义
#define LCD12232_A0 P2_7 #define LCD12232_E1 P2_6 #define LCD12232_E2 P2_5
#define LCD12232_DATA P0
void
out_major_instruction(unsigned
char i);
void out_major_data(unsigned char i); void
out_secondary_instruction(unsigned
char i);
void out_secondary_data(unsigned char i);
void out_data(unsigned char
page,unsigned char addre,unsigned char dat);
//字库(纵向取模,倒序,宋体,12号) unsigned char code wordBmp[]= {
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, //0 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00, //1 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00, //2 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00, //3 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00, //4 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00, //5 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00, //6 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00, //7 0x00,0x70,0x88,0x08,0x08,0x88,0x7
0,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00, //8
0x00,0xE0,0x10,0x08,0x08,0x10,0xE
0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00, //9
0x00,0x00,0x00,0x00,0x00,0x00,0x0
0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //10 清0
0x00,0x00,0x00,0x00,0x00,0x00,0x0
0,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00, //11 小数点
0x00,0x00,0x00,0x18,0x18,0x00,0x0
0,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00, //12 杠
};
//12232点阵液晶配置,开机后仅调用一次 void LcdConfig(void) { out_major_instruction(0XE2); // 复位 (13)
out_secondary_instruction(0XE2); // 复位 (13)
Delay_ms(1500);
out_major_instruction(0XA9); //1/32占空比(10)
out_secondary_instruction(0XA9); //1/32占空比(10)
out_major_instruction(0XA4); //正常驱动 (9)
out_secondary_instruction(0XA4); //正常驱动 (9)
out_major_instruction(0XA0); //设置显示方向为正向(8); OCM12232-1 out_secondary_instruction(0XA0); //设置显示方向为正向(8); OCM12232-1 //out_major_instruction(0XA1); //设置显示方向为反向(8); HDM32GS12-B //out_secondary_instruction(0XA1); //设置显示方向为反向(8); HDM32GS12-B
out_major_instruction(0X00); //设置起始列为第0列 (4)
out_major_instruction(0XC0); //设置起始行为第0行 (2)
out_secondary_instruction(0X00); //设置起始列为第0列 (4)
out_secondary_instruction(0XC0); //设置起始行为第0行 (2)
out_major_instruction(0XEE); //关闭"读-修改-写"模式(11)
out_secondary_instruction(0XEE); //关闭"读-修改-写"模式(11)
out_major_instruction(0XAF); //开屏幕显示(不影响显示内容)
out_secondary_instruction(0XAF); //开屏幕显示(不影响显示内容)
ClrScreen();
}
//------------------------------ //清屏
//------------------------------ void ClrScreen(void) { unsigned char page,addre; for (page=0;page
for
(addre=0;addre
out_data(page,addre,0x00);
}
}
//--------- //函数说明:显示汉字
//参数说明:汉字在字表中的位置;显示的行位置;显示的列位置;汉字宽度 //--------- void DrawWord(unsigned
char wordPosition,unsigned
char layer,unsigned char addre,unsigned char width) //(内容,行,列,字的宽度) { unsigned char i; unsigned char word_position = (int)wordPosition
for(i = 0; i
out_data(layer * 2 + 1, addre + i, wordBmp[word_position + i + width]);
}
} /* * proteus存在bug:需一页一页的写,不上下跳着写,显示才正常。
*/
////////////////////////////////////////////////////////////// ///////内部函数
//发指令i到主窗口(内部函数) void
out_major_instruction(unsigned
char i) { LCD12232_E1 = 1;
//选择
LCD12232_A0 = 0;
LCD12232_DATA = i;
LCD12232_E1 = 0;
}
//发数据i到主窗口(内部函数) void out_major_data(unsigned char i) {
LCD12232_E1 = 1;
LCD12232_A0 = 1;
LCD12232_DATA = i; LCD12232_E1 = 0;
}
//发指令i到从窗口(内部函数) void
out_secondary_instruction(unsigned char i) { LCD12232_E2 = 1;
LCD12232_A0 = 0;
LCD12232_DATA = i; } LCD12232_E2 = 0;
{
out_major_instruction(0xB8
|page);
LCD12232_E2 = 1; LCD12232_A0 = 1; LCD12232_DATA = i; LCD12232_E2 = 0;
out_secondary_instruction(0xB8 out_major_instruction(addre); } else {
out_major_data(dat); //发数据i到从窗口(内部函数) void out_secondary_data(unsigned char i) {
} //将数据写到指定行和列(内部函数) void out_data(unsigned
char
|page);
out_secondary_instruction(addre page,unsigned char addre,unsigned char dat) {
- 61);
}
}
out_secondary_data(dat); if(addre
六、实习感受和总结
两周短暂而又充实的实习,我觉得硬件的理解难度比软件难。但是通过自己对有的项目的理解,还是能看懂的。通过自己的双手却难敲出自己想要实现的功能。
单片机的编程对C语言的要求比较高,若能很好的掌握C语言的话,编程起来很迅速也很熟练。设计到中断那边的话,要懂得查阅相关书籍,了解每个部分的作用,如何打开中断,如何实现,如何初始化等等。在此期间,我更加懂得和别人合作,善于借鉴别人的思想和思路,共同完成一个项目。
当然,在实习过程中我们也遇到了各种问题,比如学习陌生的软件及元器件,对自主学习能力也是一种考验,在难度比较大的项目上我选择了放弃,远远超出了自己的能力范围。在以后的学习中,懂得适当的割舍还是比较好的,搞清楚最基本的原理,才能为以后的学习做铺垫。
时间: 年签名:
月 日