⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dac0808.c

📁 用PROTUES仿真温度控制电机正反转!
💻 C
字号:
//adc转化一定要有一定的时间,不要一转化完成后立即就再ADC=0转化.这样可能会出错
//adc的转化后最高值是OUT0非OUT7所以接线要注意.但也可通过程序转化.?
//74LS373内部本身有上位电阻,所以电路中,外接的SLED无需再接上上位电阻,接了会出错的
#include"reg51.h"
#include"intrins.h"
#include"absacc.h"
#define uchar unsigned char
#define uint unsigned int

void shift8(unsigned char temp);	//移位程序
char rd8(void);						//移位写入程序

sbit set=P2^0;						//SET KEY
sbit up=P2^1;						//UP KEY
sbit down=P2^2;						//DOWN KEY
//24c02
sbit sda=P3^5;
sbit sck=P3^4;
sbit cc=PSW^7;
//24c02
bit up_ed;							//UP KEY PRESSED
bit down_ed;						//DOWN KEY PRESSED
bit set_ed;
bit set_over;						//SET KEY PRESSED
bit timer_beg;						//TIMER FLAG

sbit hot=P3^0;						//HOT CONTROL
sbit cold=P3^1;						//COLD CONTROL

//小数显示
sbit pp0=P2^3;
sbit pp1=P2^4;
sbit pp2=P2^5;
sbit pp3=P3^3;

uchar w4;
uchar w3;
uchar w2;
uchar w1;							//显示电压(小数显示)
uchar rota=0;
uchar ad_data;						//AD转化成的值
uchar set_deg;						//设定的温度					
uchar rel_deg;						//实际温度
uchar second;						//秒计时
uchar ms_100;						//MS计时
uchar timer_100;					//MS计时
char set_var;						//设定温度差值
uchar change;						//设定后按下SET的有效时间

#define adc XBYTE[0X7FF8]			//AD Change adrress

//延时子程序
void delay(void)
{
uint i;
for(i=0;i<30000;i++)
{
_nop_();
}
}

//开机按下SET自检子程序
void check_self(void)
{
uint i;
uchar j;
uchar array[10]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99};
while(i<20000)
{
i++;
if(~set)
{
for(j=0;j<10;j++)
{
P1=array[j];
delay();
}
i=49999;
}
}
}

//按键子程序
void key(void)
{
uchar i;
uchar temp;
if(~up)
{
for(i=0;i<50;i++) _nop_();
if(up) {up_ed=0;return;}
if(up_ed) return;
beep();
ms_100=0;
second=0;
timer_beg=1;				
up_ed=1;
temp=set_deg;
set_deg++;
if(set_deg>=100) set_deg=99;
set_var=set_var+(set_deg-temp);
}
else
up_ed=0;


if(~down)
{
for(i=0;i<50;i++) _nop_();
if(down) {down_ed=0;return;}
if(down_ed) return;
beep();
ms_100=0;
second=0;
timer_beg=1;
temp=set_deg;
down_ed=1;
if(set_deg<=1) set_deg=1;
set_deg--;
set_var=set_var-(temp-set_deg);
}
else
down_ed=0;

if(~set)
{
for(i=0;i<50;i++) _nop_();
if(set) {set_ed=0;return;}
if(set_ed) return;
set_ed=1;
beep();
if(timer_beg==0) return;								//只有在按下UP/DOWN之后按下SET,SET才有效
timer_beg=0;
change=0;
if(second<=7) {set_over=1;second=0;ms_100=0;} 			//在一定的时间内按下SET则显示LED灯
}
else 
set_ed=0;
}

//制热/冷子程序
void fan_ctrl(void)
{
if(change<30) return;
change=0;
if(timer_beg) return;			//设定未确定前输入无法控制FAN;
if(rel_deg>set_deg) {cold=1;hot=0;}
else				{hot=1;cold=0;}
}

//初始化子程序
void init(void)
{
second=0;
ms_100=0;
set_var=0;
timer_beg=0;
change=29;

pp0=pp1=pp2=pp3=0;

EA=1;
EX0=1;
IT0=1;

ET0=1;
TMOD=0X1;
TH0=0X0ec;
TL0=0X78;
TR0=1;			//Start timer

hot=0;
cold=0;
up_ed=0;
down_ed=0;
//set_deg=50;
}

void start(void)
{
sck=1;
_nop_();
_nop_();
sda=1;
_nop_();
_nop_();
sda=0;
_nop_();
_nop_();
sck=0;	
_nop_();
_nop_();
}

void stop(void)
{
sda=0;
_nop_();
_nop_();
sck=1;
_nop_();
_nop_();
sda=1;
_nop_();
_nop_();
}

void ack(void)
{
sck=1;
_nop_();
_nop_();
sck=0;
_nop_();
_nop_();
}

//24c02写子程序
void write(void)
{
start();
shift8(0xa0);
ack();
shift8(0x00);
ack();
shift8(set_deg);
ack();
stop();
}

//24c02读子程序
void read(void)
{
start();
shift8(0xa0);
ack();
shift8(0x00);				//地址
ack();
start();
shift8(0xa1);
ack();
set_deg=rd8();
}

//显示转化子程序
void dis(void)
{
uint temp=ad_data;
uchar gw,sw;
temp=ad_data*(0x63);
temp=temp/(0x0ff);		//得出实际温度
rel_deg=temp;

if(second>7) {set_deg-=set_var;set_var=0;timer_beg=0;second=0;ms_100=0;}
if(set_over) {set_deg+=0;set_over=0;write();set_var=0;}
temp=set_deg;	
sw=temp/10;
gw=temp%10;
sw<<=4;
sw|=0x0f;
gw|=0x0f0;
sw&=gw;
temp=sw;
P1=temp;
}

//将得到的ADC转化为电压(小娄)
void proc(void)
{
unsigned int temp;
temp=ad_data;
w4=temp/51;
w3=(temp%51)*10/51;
w2=(((temp%51)*10)%51)*10/51;
w1=((((temp%51)*10)%51)*10%51)*10/51;
}

void dis_proc(void)
{
uchar array[10]={0xc0,0xF9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
rota++;
if(rota>=4) rota=0;
pp0=pp1=pp2=pp3=0;

switch(rota)
{
case 0:P0=array[w4]&0x7f;pp0=1;break; 
case 1:P0=array[w3];pp1=1;break;
case 2:P0=array[w2];pp2=1;break;
case 3:P0=array[w1];pp3=1;break;
default:rota=0;break;
}
}

//AD转化中断程序
void adc0808(void) interrupt 0
{
EA=0;
ad_data=adc;
EA=1;
}

//timer 0 100MS
void timer0(void) interrupt 1
{
EA=0;
dis_proc();
key();
dis();
timer_100++;
if(timer_100>=50) {change++;timer_100=0;}
if(!timer_beg) ms_100=0;
ms_100++;
if(ms_100>=50) 
{second++;ms_100=0;}		//1秒
TH0=0X0fc;
TL0=0X78;
EA=1;
}		

//-----------------------------主函数-----------------------------//
void main(void)
{
uint i;
init();
EA=0;
check_self();
EA=1;
read();
timer_beg=0;
while(1)
{
adc=0;
proc();

//AD转化次后值给P0,同时也给了SLED显示,所以减少ADC可以减少SLED显示出ADC的值
//只要FOR大点,可以减少ADC,但是太大了,ADC转化速度又变慢.

for(i=0;i<20000;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
fan_ctrl();
}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -