前言
前段时间高中同学让我帮忙给她做一个数电课设,反正也没事做就随便做了做,现在总结一下,话不多说直接上效果。
一、课设要求
二、设计步骤
1.proteus设计
最终效果如下:
2.keil5代码编程设计
代码如下:
main.c
//废气检测。
#include <reg52.h>
#include <intrins.h>
#include <I2C.h>
#define uchar unsigned char
#define uint unsigned int
#define _Nop( ) _nop_( ) //定义空操作,1μs
sbit oe=P1^3; //数码管段选、位选锁存器输出控制信号
sbit dula=P1^4; //数码管段选锁存器控制信号
sbit wela=P1^5; //数码管位选锁存器控制信号
sbit LED=P2^0;
sbit k3=P3^2; //定义按键K3
sbit k4=P3^3; //定义按键K4
uchar j=0;
int s,t,k,flag=1;
uchar code sled_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义点亮数码管位选码
data uchar disp[8]={1,6,16,16,16,16,16,16}; // 8位数码管都不亮
uchar code table[18]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; //共阴极数码管显示段码(0-F)
sbit P3_5=P3^5;
void delay(u16 i)
{
while(i--);
}
void Int0Init()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
void Int1Init()
{
//设置INT1
IT1=1;//跳变沿出发方式(下降沿)
EX1=1;//打开INT1的中断允许。
EA=1;//打开总中断
}
void main(void)
{
unsigned long d;
P3_5=0;
TMOD=0x01; // 设置定时器T0为方式1定时
TH0=(65536-500)/256; // 给T0装入初值
TL0=(65536-500)%256; // 给T0装入初值
ET0=1; // 允许T0中断
EA=1; // CPU开中断
TR0=1; // 启动T0
oe=0;
Int0Init();
Int1Init(); // 设置外部中断1
LED=0;
sen: erflags=0;
Start( ); //发送起始信号
SendByte(0x90); //发送写PCF8591的寻址字节(写)
cAck( ); //检查应答
if(erflags) goto sen; //无应答,重来
SendByte(0x00); //发送写入PCF8591的控制字,选择0通道
cAck( ); //检查应答
if(erflags) goto sen; //无应答,重来
sen1: Start( ); //发送起始信号
SendByte(0x91); //发送写PCF8591的寻址字节(读)
cAck( ); //检查应答
if(erflags) goto sen1; //无应答,重来
d=RcvByte( ); //第1次读的数据无效
Ack( ); //应答位函数,
while(1)
{
d=RcvByte( );
Ack( ); //应答位函数,
d=(d*5*1000)/256; //电压值
disp[0]=(int)d/1000;
disp[1]=(int)d%1000/100;
s = (disp[0]*10+disp[1])*2+2;
if(s>=100)
s=99;
if(s<=50&&flag)
LED=1;
else if(s>50&&flag)
LED=0;
t = s/10;
k = s%10;
}
}
void T0_int(void) interrupt 1
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
oe=1; // 关闭2个573输出,防止在送数据时相互影响
switch(j)
{
case 0:P0 = table[0];break;
case 1:P0 = 0xe6;break;
case 2:P0 = table[5];break;
case 3:P0 = table[0];break;
case 4:P0 = table[2];break;
case 5:P0 = 0x40;break;
case 6:P0 = table[t];break;
case 7:P0 = table[k];break;
}
dula=1;
dula=0; // 锁存段码
P0=sled_bit[j]; // 选择相应数码管位选
wela=1;
wela=0; // 锁存位码
oe=0; // 打开2个573三态门,输出段码和位码
j++; // 为下一个显示做准备
if(j>=8)j=0;
}
void Int0() interrupt 0 //外部中断0的中断函数
{
delay(1000); //延时消抖
if(k3==0)
{
if(flag==1)
{
flag=0;
LED=0;
}
else if(flag==0)
flag=1;
}
}
void Int1() interrupt 2 //外部中断1的中断函数
{
int i;
delay(1000); //延时消抖
if(k4==0)
{
while(1)
{
for(i=0;i<8;i++)
{
oe=1; // 关闭2个573输出,防止在送数据时相互影响
P0 = 0x40;
dula=1;
dula=0; // 锁存段码
P0=sled_bit[i]; // 选择相应数码管位选
wela=1;
wela=0; // 锁存位码
oe=0; // 打开2个573三态门,输出段码和位码
delay(500);
}
}
}
}
?I2C.c
#include <reg52.h>
#include <intrins.h>
#include "I2C.h"
#define uchar unsigned char
#define uint unsigned int
#define _Nop( ) _nop_( ) //定义空操作,1μs
bdata uchar b;
sbit b_7=b^7;
sbit SDA=P3^4; //模拟I2C数据传送位
sbit SCL=P3^6; //模拟I2C时钟控制位
void Start(void) //起始位函数
{
SDA=1;
SCL=1;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
SDA=0;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
SCL=0;
}
void Stop(void) //终止位函数,
{ SDA=0;
SCL=1;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
SDA=1;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
}
void Ack(void ) //应答位函数,
{ SDA=0;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
SCL=1;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
SCL=0;
SDA=1;
}
void NoAck(void ) //非应答位函数
{ SDA=1;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
SCL=1;
_Nop( ); _Nop( ); _Nop( ); _Nop( );
SCL=0;
}
void cAck( void ) //检查应答函数
{
uchar i=0;
SCL=1;
while((SDA==1)&&(i<255)) i++;
erflags=SDA;
SCL=0; //函数结束,使SCL=0
}
void SendByte(uchar temp) //写入1字节数据函数
{
uchar i;
b=temp;
for(i=0; i <8; i++) // 8位数据长度
{
SCL=0;
SDA=b_7; //发送数据最高位送到SDA
b= b<<1; //左移一位,准备下一发送位
SCL=1; //SCL↑送入
_Nop( ); _Nop( );
_Nop( ); _Nop( );
}
SCL=0;
SDA=1; //发送完后使SDA=1,等待应答
}
uchar RcvByte(void) //读出1字节数据函数
{ uchar i,temp;
SCL=0;
SDA=1; //作输入先输出1
for(i=0; i <8; i++) // 8位数据长度
{
SCL=1; //SCL↑数据输入到SDA
_Nop( ); _Nop( );
_Nop( ); _Nop( );
temp<<=1; //接收数据变量左移一位,最低位腾空
if(SDA) temp|=0x01; //读1位数据到最低位
SCL=0; //SCL=0,为SCL↑作准备
}
return temp; //返回接收数据
}
I2C.h
#ifndef __I2C_H__
#define __I2C_H__
sbit erflags=P3^7; //检查应答错误标志
extern void Start(void); //起始位函数
extern void Stop(void); //终止位函数,
extern void Ack(void ); //应答位函数
extern void NoAck(void); //非应答位函数
extern void cAck( void ); //检查应答函数
extern void SendByte(unsigned char temp); //写入1字节数据函数
extern unsigned char RcvByte(void); //读出1字节数据函数
#endif
总结
本课设是涉及到了51的AD转换,数码管显示,I2C,中断等的综合实验,需要学习的同学呢麻烦点赞关注,然后在评论区留下邮箱有空我就会私发,当然工程下载链接等审核通过后我也会附上。
工程链接:基于51单片机的废气检测proteus仿真
|