您的当前位置:首页正文

单片机课程设计

来源:小奈知识网


单片机课程设计

姓 名 张广亮 学 号 0906022237 年级专业 电气工程及其自动化 所在院系 电子与电气工程系 指导教师 徐敏、关健生

提交日期 2012 年 6月12 日

《单片机原理及应用》课程设计任务书

学年学期:2011-2012第2学期 专业班级:09级电气A,B 指导教师:

设计时间:第16周 学时周数:每班/周 一、设计目的

课程设计是单片机课程教学的最后一个环节,是对学生进行全面的系统的训练,让学生把学过的比较零碎的知识系统化,真正的能够把学过的知识落到实处,能够开发简单的系统,也进一步激发了学生再深一步学习的热情,进一步掌握和利用C语言进行单片机程序设

计的能力,熟练掌握键盘、显示、A/D输入输出,I2C总线,温度传感器等知识点。

二、设计任务及要求

本课程设计的题目设计内容自选,学生可以根据平时的观察,了解单片机实验的应用系统,弄清其结构和功能,结合单片机课程及其相关的知识,充分发挥自身的想象力和创造力,自行选定设计项目,但总体应达到以下要求:

1、用89C51CPU,12M时钟,常规的上电和手动复位电路 2、包括3×4矩阵键盘 3、LCD显示显示器及接口 4、一路蜂鸣器输出

5.至少有2路输入信号,可以是模拟量或数字量

三、设计时间进度安排

时间 周一 内容 一、布置设计内容和要求 1、 实习内容介绍、实习安排、实习纪律、注意事项 2、 根据所选题的要求,进行总体设计,确定程序总体框架 二、系统设计 1) 利用单片机实验箱,进行AD微调, AD微调的结果在LCD上显示, 2)在LCD上有上下限值,通过矩阵键盘来设置。 3)若AD微调的值超过上限或是下限则蜂鸣器发出声音。 周二、三 (2天) 周四 (1天) 三、系统调试 1)矩阵键盘加防抖程序测试 2)AD两路输入分别调试最大值和最小值,观察系统的变化 3)蜂鸣器要在上下限超出时分别发出不同的声音。 四、测试完整程序与报告上交 1、要求功能完整,结果符合设计要求,并进行程序验收。(答辩) 2、完成实习报告的编写,并打印上交报告。 周五 (1天) 四、报告书写格式

1、课程设计任务书 2、设计项目简介 3、电路原理图

蜂鸣器 STC89C51 键盘输 入模块 LCD液晶显示屏显示 复位

1、STC89C51单片机

2、内部接线图

3、蜂鸣器

矩阵键盘

LCD

AD-DA转化

实体液晶屏电路图

4、系统功能描述

系统可以通过AD-DA模块进行采样,通过液晶屏显示出来,并对采样的数据与之前设定的上下限做比较,且如果采样的两路值的任何一路大于或小于设定的上限或下限,蜂鸣器会发出报警的声音。 5、程序框图

6、

蜂鸣器

LCD初始化: 检查LCD状态:

写指令到LCD: 写数据到LCD:

键盘扫描: 判断键盘是否有键按下

AD转换值比较:

I2C启动: I2C终止:

I2C接收: I2C发送:

六、程序清单:

/****************************************************************************** * 矩阵键盘1602液晶显示最大最小值 * * 数模转换AD/DA显示当前值 * * 比较当前值与最大最小值 *

* 超出范围则蜂鸣器报警 * ********************************************************************************/

#include #include

#define uint unsigned int #define uchar unsigned char

#define nop(); {_nop_();_nop_();_nop_();_nop_();}; /* 定义空指令 */ sbit BEE=P1^5; sbit scl=P2^1; sbit sda=P2^0; sbit RW=P2^5; sbit RS=P2^6; sbit EN=P2^7;

uchar dis_buf; //显示缓存 uchar temp;

uchar key; //键顺序吗 void delay0(uchar x); //x*0.14MS

uchar keybuf;//键盘号码缓冲器

uchar ascii[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43}; //ASCII数字表 0 1 2 3 4 5 6 7 8 9 A B C

/*************************************************************/ /* */ /* 延时子程序 */ /* */ /*************************************************************/ void delay(uchar x) { uchar j;

while((x--)!=0)

{ for(j=0;j<125;j++) {;} } }

/*************************************************************/ /* */

/*检查LCD忙状态 */ /*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据 */ /* */ /*************************************************************/ bit lcdbusy() {

bit result; P0=0xff; RS=0; RW=1; EN=1; nop();

result=(bit)(P0&0x80); EN=0;

return(result); }

/**************************************************************/ /* */ /*写指令数据到LCD */ /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */ /* */ /**************************************************************/ void lcdwcmd(uchar cmd) {

while(lcdbusy()); RS=0; RW=0; EN=1; P0=cmd; EN=0; }

/**************************************************************/ /* */ /*写显示数据到LCD */ /*RS=H,RW=L,E=高脉冲,D0-D7=数据 */ /* */ /**************************************************************/ void lcdwdat(uchar dat) {

while(lcdbusy()); RS=1; RW=0; EN=1; P0=dat;

EN=0; }

/*************************************************************/ /* */ /* LCD初始化设定 */ /* */ /*************************************************************/ void lcdinit() {

delay(15);

lcdwcmd(0x38); //16*2显示,5*7点阵,8位数据 delay(5);

lcdwcmd(0x38); /*显示模式设置*/ delay(5);

lcdwcmd(0x0f); /*开显示,显示光标,光标闪烁*/ delay(5);

lcdwcmd(0x06); /*读写后,地址和指针都加一*/ delay(5);

lcdwcmd(0x01); /*数据指针清零,所有显示清零*/ delay(5); }

/********************此部分为I2C总线的驱动程序**********************/ /******************************************************************* 起动总线函数 函数原型: void Start_I2c();

功能: 启动I2C总线,即发送I2C起始条件.

********************************************************************/ void i2c_start()//起始 { scl=0; sda=0; scl=1; sda=1; delay(5); sda=0; delay(5); scl=0; }

/******************************************************************* 结束总线函数 函数原型: void Stop_I2c();

功能: 结束I2C总线,即发送I2C结束条件.

********************************************************************/ void i2c_stop()//终止 { scl=0; sda=0; scl=1; delay(5); sda=1; delay(5); sda=0; // scl=1; }

/******************************************************************* 字节数据发送函数 函数原型: void SendByte(UCHAR c);

功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0)

发送数据正常,ack=1; ack=0表示被控器无应答或损坏。

********************************************************************/ void i2cbsend(uchar value) //I2C发送字节子程序 { uchar i; for (i=0;i<8;i++) { scl=0; delay(5); sda=value&0x80; value=value<<1; delay(5); scl=1; delay(5); scl=0; } }

/******************************************************************* * 字节数据接收函数 * *函数原型: UCHAR RcvByte(); * *功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),* * 发完后请用应答函数应答从机。 * ********************************************************************/

uchar i2cbrece() //I2C接受字节子程序 {

uchar i,value; for (i=0;i<8;i++) { scl=0; delay(5); scl=1; delay(5); if (sda==1) { value=(value<<1)|1; } if (sda==0) { value=(value<<1)|0; } delay(5); scl=0; delay(5); } return value; }

/******************************************************************** * 应答子函数 * *函数原型: void Ack_I2c(bit a); * *功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)* ********************************************************************/ void i2csack() //I2C发送应答位子程序 {

sda=1; nop(); scl=1;

nop(); /*时钟低电平周期大于4μs*/ scl=0; nop_(); }

bit i2crack() //I2C接受应答位子程序 {

bit ack;

sda=1; /*在此发出应答或非应答信号 */

scl=1; if(sda==1) ack=1; else ack=0;

scl=0; /*清时钟线,钳住I2C总线以便继续接收*/ return(ack); }

/*************************************************************/ /* */ /*判断键是否按下 */ /* */ /*************************************************************/ void keydown() //按键是否按下 {

P1=0xf0;

while(P1==0xf0) { ; } }

/*************************************************************/ /* 键扫描子程序 (3*4 的矩阵) P1.4 P1.5 P1.6 P1.7为 列 */ /* P1.1 P1.2 P1.3为行 */ /*************************************************************/ void keyscan() {loop:keydown(); delay(1); keydown(); temp=0;

P1=0x0f; //高四位输入 行为高电平 列为低电平 delay(1);

temp=P1; //读P1口 temp=temp&0x0f; //屏蔽低四位 temp=~(temp|0xf0); switch(temp)

{case 2:key=0;break; case 4:key=4;break; case 8:key=8;break; default:key=0; goto loop; }

P1=0xf0; //低四位输入 列为高电平 行为低电平 delay(1);

temp=P1; //读P1口 temp=temp&0xf0;

temp=~((temp>>4)|0xf0); switch(temp)

{case 1:key=key+0;break; case 2:key=key+1;break; case 4:key=key+2;break; case 8:key=key+3;break; goto loop; }

while(P1!=0xf0) keybuf=key; }

uchar ad(uchar add,uchar road) {

uchar ad; i2c_start(); do{

i2cbsend(add); }while(i2crack()); do{

i2cbsend(road); }while(i2crack()); i2c_stop(); i2c_start(); do{

i2cbsend(add+1); }while(i2crack()); ad=i2cbrece(); i2csack(); i2c_stop();

lcdwdat(ascii[ad/100]); lcdwdat(ascii[ad%100/10]); lcdwdat(ascii[ad%10]); return(ad); }

//3位数输入 uchar input() {

uchar x; keyscan();

lcdwdat(ascii[keybuf]);

//AD转换子程序 x=keybuf*100; keyscan();

lcdwdat(ascii[keybuf]); x=x+keybuf*10; keyscan();

lcdwdat(ascii[keybuf]); x=x+keybuf; return(x); }

//蜂鸣器报警 void fmq(uchar t) {

uchar lon;

for(lon=0;lon<9;lon++) {

BEE=~BEE; /*蜂鸣器需要得到类似矩形波的型号才会响*/ delay(t); } }

//比较上下限子程序

void cmp(uchar top,uchar dow,uchar now) {

if(now>top) {fmq(0xA0);} else BEE=1; if(now/*************************************************************/ /* */ /* 设定显示位置 */ /* void lcd_pos(uchar pos) {

lcdwcmd(pos | 0x80); //数据指针=80+地址变量

} */ /*************************************************************/

/*************************************************************/ /* */ /* 主程序 */ /* */ /*************************************************************/

void main() { int m=0;

uchar max,min,ad0,ad1;

P0=0xFF; //置P0口 P1=0xFF; //置P1口 lcdinit();

lcdwcmd(0x80); /*首行首地址*/ lcdwdat(0x54); /*显示TOP*/ lcdwdat(0x4f); lcdwdat(0x50); lcdwdat(0x3a);

lcdwcmd(0x88); lcdwdat(0x44); lcdwdat(0x4f); lcdwdat(0x57); lcdwdat(0x3a);

lcdwcmd(0xc0); lcdwdat(0x41); lcdwdat(0x44); lcdwdat(0x30); lcdwdat(0x3a);

lcdwcmd(0xc8); lcdwdat(0x41); lcdwdat(0x44); lcdwdat(0x31); lcdwdat(0x3a);

lcdwcmd(0x84); max=input(); lcdwcmd(0x8c); min=input();

while(1) {

lcdwcmd(0xc4); ad0=ad(0x90,0x41); cmp(max,min,ad0);

lcdwcmd(0xcc); ad1=ad(0x90,0x40);

/*显示DOW*/ /*第二行首地址*/ /*显示AD0*/ /*显示AD1*/ cmp(max,min,ad1); } }

七、收获与体会:

通过近两个星期的单片机课程设计,我终于完成了“基于单片机的数字温度计设计”,心中不免有些高兴,但高兴之余也有我值得深思的。

虽然以前做过类似的实验,但这次的课程设计还是让我学到了很多东西,单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法。有好多的东西,只有我们去试着做了,才能真正的掌握,只学习理论有些东西是很难理解的,更谈不上掌握。通过这次的单片机课程设计我认识到了,学习要理论联系实际,把学到的理论知识同实际运用相结合,才能是我们的知识融汇贯通,才能真正的学到知识,真正的做到学以致用。

因篇幅问题不能全部显示,请点此查看更多更全内容