单片机多路数据采集控制系统—软件仿真 - 图文

更新时间:2023-12-30 23:12:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

一、课程设计的目的和要求

1、目的

运用单片机原理及其应用等课程知识,根据题目要求进行进行软件仿真的设计和调试,从而加深对本课程知识的理解, 把学过的比较零碎的知识系统化,比较系统的学习开发单片机应用系统的基本步骤和基本方法,使学生应用知识能力、设计能力、调试能力以及报告撰写能力等有一定的提高。 2、要求

用8051单片机设计数据采集控制系统,基本要求如下: 1、 可实现8路数据的采集,假设8路信号均为0-5V的电压信号;

2、 采集数据可通过LCD显示,显示格式为:[通道号] 电压值,如[01]: 4.5V 3、 可通过键盘设置采集方式;(单点采集、多路巡测、采集时间间隔)

4、 具有异常数据声音报警功能:对第一路数据可设置正常数据的上限值和下限值,当采

集的数据出现异常,发出报警信号。 选做功能: 1、 异常数据音乐报警

2、可输出8路顺序控制信号,设每路顺序控制信号为一位,顺序控制的流程为:

二、总体设计

图1 原理框图

分析:选择AT89C52单片机、ADC0809和LCD1602显示器作为主要器件来实现本次设计。

图2 电路仿真图

图3 AT89C52单片机部分

分析:通过单片机的I/O口来控制AD转换和显示器。因为AT89C52的P0是漏极开路,因此要有排阻接电源,形成弱上拉结构,增强控制能力。

图4 AD转换部分

分析:ADC0808AD转换芯片通过IN口采集模拟量,转换后通过out口输出数字量数据。具体介绍见图5和图6.

图5 ADC0808引脚图

图6 ADC0808采集通道选择方式

图7 LCD1602显示器部分

分析:LCD1602详细介绍见图8和图9

图8 LCD1602引脚功能

图9 LCD1602引脚功能

图10 按键部分

分析:检测单片机引脚是否为低电平来判断是否按键按下。

图11 警报部分 分析:通过检测IN2口电压来警报,当电压大于上限制或者低于下限值会LED亮和蜂鸣器报警。 三、程序设计 1、程序框图: 开始 按键扫描 k0 显示设定的通道电压 K1 快速依次显示八通道各电压 K2 间隔一定时间显示各通道电压 K3 选择要显示的通道 K4 对IN2口进行报警控制 #define uchar unsigned char voidinit(); voidwrite_com(uchar); voidwrite_data(uchar); 2、程序代码: #include #include #include #define uint unsignedint void delay(uint);

voidwrite_sfm(uchar,uchar); void read(uint i); void display(uint i); void key(); ucharnum,shuju;

uint i=0,ii=0,b1,b2,t=3,tt,fre,flag; float b;

uchar code table[]=%uchar code table1[]=%uchar code

tab[8]={0x00,0x20,0x40,0x60,0x80,0xa0,0xc0,0xe0}; sbit RW=P1^7; sbit RS=P1^6; sbit EN=P1^5; sbit START=P3^6; sbit AD_INT=P3^2; sbit AD_ENA=P3^7; sbit k0=P1^0; sbit k1=P1^1; sbit k2=P1^2; sbit k3=P1^3; sbit k4=P1^4; sbit LED1=P3^5; sbit SPEAK=P3^4; /*****************主程序*****************/ void main() { init(); while(1) { key();

}

}

/*****************初始化LCD1602和中断服务*****************/ voidinit() { RW=0; //进入写操作

write_com(0x38); //显示十六位液晶

write_com(0x0c); //打开十六位液晶,不显示光标

write_com(0x06); //写下一个数右移以为 write_com(0x01); //清屏 write_com(0x80); //第一行写 for(num=0;num<15;num++) {

write_data(table[num]); //第一行写数据 delay(5);

}

write_com(0x80+0x40);

for(num=0;num<12;num++) //第二行写数据 {

write_data(table1[num]); delay(5); }

fre=50000; SPEAK=1; TMOD=0x11;

TH0=(65536-fre)/256; TL0=(65536-fre)%6; TH1=(65536-50000)/256; TL1=(65536-50000)%6; EA=1; ET0=1; ET1=1; TR1=0; TR0=0;

}

/*****************中断服务子程序*****************/ void timer0() interrupt 1 { TR0=0;

TH0=(65536-fre)/256; TL0=(65536-fre)%6; tt++; if(flag<40)

{

if(tt==0) { tt=0;

tt=50000;

SPEAK=~SPEAK; }

}

if(flag>=40&&flag<80) { tt=0; fre=50000; SPEAK=~SPEAK; }

if(flag>=80&&flag<120) { tt=0; fre=10000; SPEAK=~SPEAK; }

if(flag>=120&&flag<160) { tt=0; fre=5000; SPEAK=~SPEAK; }

if(flag>=160&&flag<200) { tt=0; fre=2500; SPEAK=~SPEAK; }

if(flag>=200&&flag<240) { tt=0; fre=1250; SPEAK=~SPEAK; }

if(flag>=240&&flag<280) { tt=0; fre=625; SPEAK=~SPEAK; }

if(flag>=280&&flag<320) { tt=0; fre=312; SPEAK=~SPEAK;

}

if(flag>=320&&flag<360) { tt=0; fre=156; SPEAK=~SPEAK; } TR0=1;

}

void timer1() interrupt 3 { TH1=(65536-50000)/256; TL1=(65536-50000)%6; flag++; if(flag==360) { flag=0; fre=50000;

} }

/*****************LCD1602设置*****************/ voidwrite_com(uchar com) { RS=0;

//写指令

EN=0; //使能端拉低 delay(5);

P0=com; //输入地址,就是命令 EN=1; //使能端拉高,工作

delay(5);

EN=0;

//使能端拉低停止工作 delay(5);

}

voidwrite_data(uchar date) { RS=1; EN=0;

//使能端拉低

delay(5);

P0=date; //输入数据,就是你要在液晶上显示什么

EN=1;

//使能端拉高,开始输入

数据 delay(5);

EN=0; //拉低使能端,停止工作

delay(5);

}

void delay(uint z) //延时函数 { uintj,k;

for(j=0;j

大约一毫秒

}

voidwrite_sfm(ucharadd,uchar date)

{ write_com(0x80+0x40+add); //写完光标自动到下一位

write_data(0x30+date);

}

/*****************ADC转换和数据采集****************/ void read(uint a) { START=0; P2=0x00; P2=tab[a]; _nop_(); _nop_(); _nop_(); _nop_(); START=1; _nop_(); START=0; _nop_(); delay(5); while(!AD_INT); P2 = 0xff; _nop_(); _nop_(); AD_ENA=1; _nop_();

shuju=P2;

_nop_(); AD_ENA=0; _nop_(); P2 = 0xff;

b1 = shuju/51; //整数部分 b2 = (shujuQ)*10/51;//小数部

分 }

/*****************显示数据*****************/ void display(uint a) { write_sfm(0x04,a); write_sfm(0x07,b1); write_sfm(0x09,b2);

}

/*****************按键扫描*****************/ void key() { if(k0!=1) { read(ii); display(ii); delay(5);

}

if(k1!=1) { for(i=0;i<8;i++) { read(i); display(i); delay(500);

}

}

if(k2!=1) { for(i=0;i<8;i++) { read(i);

display(i);

delay((t+t*(i%2))*1000);

}

}

if(k3!=1) { }

if(k4!=1) {

b=b1+0.1*b2;

if(b<=1.8||b>=2.2)

{

delay(5);

while(1) {

read(2); display(2);

ii++;

delay(500); if(ii>=8) { }

write_sfm(0x04,ii);

ii=0;

}

LED1=0; TR0=1; TR1=1; flag=0; LED1=1; TR0=0; TR1=0; }

}

} } else {

fre=50000;

四、调试及结果

1、可以单点采集、多路巡测、采集时间间隔:

图12 运行显示结果图

2、可以实现IN2通道采集电压报警功能:

图13 IN2通道电压大于等于2.2V报警

图14 IN2通道电压小于等于1.8V报警

五、结束语

通过这次课程设计巩固了自己的单片机编程能力,扎实了自己的专业能力。在程序

设计中由于自己不够细心,在一些很细小的错误中耗费了很多时间,使得在完成课程设计时很赶。因此,在以后程序编写时应该更加认真,做到高效率完成任务。另外,感觉自己的专业十分强大,如果好好学以后会有很好的发展。

六、参考文献

百度文库

本文来源:https://www.bwwdw.com/article/psmx.html

Top