//STC12C2052AD輸出PWM波 ,同時(shí)檢測(cè)電壓顯示,自動(dòng)穩(wěn)壓 。
//74HC164串入并出顯示數(shù)碼管,一位一位顯示,之后熄滅省電,根據(jù)我焊的板子確定的數(shù)碼管值。
#include <stc12c2052ad.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define AD_SPEED 0x60 //0110,0000 1 1 270個(gè)時(shí)鐘周期轉(zhuǎn)換一次,
//少占魚(yú)制作 河北正定歡迎您 長(zhǎng)沙航空職業(yè)技術(shù)學(xué)院 2010 年QQ:411656434
//京畿之地 魅力河北 河北歡迎您
//注意:74HC164是先發(fā)Qh 位最后發(fā)Qa位的。共陽(yáng)數(shù)碼管代碼要反過(guò)來(lái)寫。
//74HC164的Qa----Qh對(duì)應(yīng)數(shù)碼管a----dp各段。
uchar code tab[16]={0x02,0x9f,0x25,0x0d,0x99,
// 0 1 2 3 4
0x49, 0x41, 0x1f,0x01,0x09, 0x11,
// 5 6 7 8 9 A
0xc1,0x63,0x85,0x61,0x71}; //共y陽(yáng)數(shù)碼管
// b c d e f
uchar xianshi[4]={0x11,0xd7,0x25,0x45};
sbit OK=P1^1; //濃度正常指示燈
sbit BAOJING=P1^2; //報(bào)警指示燈
sbit sound=P1^0; //聲音報(bào)警
sbit PWM=P3^7;
sbit contrl=P1^7; //加熱控制端
sbit wei1=P3^3;
sbit wei2=P3^4;
sbit wei3=P3^2;
sbit wei4=P3^5;
bit high=1; //定義高5V加熱傳感器標(biāo)志
bit low=0; //定義低1.5V加熱傳感器標(biāo)志
bit START =0;
uint cnt=0;
uchar timeL=0x90;
uchar timeH=0x90;
/****************************************************************/
void pwm();
void delayms(uint);
void ADC(uchar port);
void InitADC();
//void baohu();
void ceshi();
void sendchar();
float voltage=0.0;
uint vol=0;
void run_t0();
//顯示測(cè)試
void ceshi()
{
uchar i;
TI=0;
OK=0;
BAOJING=0;
sound=1;
wei1=0;
wei2=0;
wei3=0;
wei4=0;
for(i=0;i<16;i++)
{
SBUF=tab[i];
while(!TI);
TI=0;
delayms(850);
}
wei4=1;
wei3=1;
wei2=1;
delayms(1600);
wei1=1;
}
void sendchar()
{
TI=0;
SBUF=tab[xianshi[0]];
while(!TI);
TI=0;
wei1=0;
wei1=0;
delayms(1200);
wei1=1;
SBUF=tab[xianshi[1]];
while(!TI);
TI=0;
wei2=0;
wei2=0;
delayms(1200);
wei2=1;
SBUF=tab[xianshi[2]];
while(!TI);
TI=0;
wei3=0;
wei3=0;
delayms(1200);
wei3=1;
SBUF=tab[xianshi[3]];
while(!TI);
TI=0;
wei4=0;
wei4=0;
delayms(1200);
wei4=1;
}
/*****************主程序***********************************************************/
void main()
{
uint a=0;
PWM=1;
pwm();
delayms(1000);//延時(shí)
InitADC();
contrl=0;
delayms(600);
ceshi();
delayms(600);
sound=0;
OK=1;
BAOJING=1;
START=0;
contrl=1;//初次開(kāi)機(jī)要先加熱一分鐘以上。在這里等待一分鐘
wei1=0;//開(kāi)啟顯示 數(shù)碼管,做指示用
for(a=0;a<53;a++)
{
delayms(1000);
ADC(6);
sendchar();
}
wei1=1;
contrl=0;//關(guān)閉5V,成為1.5V低電平加熱90S
wei2=0;
for(a=0;a<80;a++)
{
delayms(1000);
}
wei2=1;
a=0;
while(1)
{
ADC(6);
contrl=0;
run_t0();
if(START)
{
delayms(5);
}
a++;
if(a==6235)
{
a=0;
sendchar();
}
}
}
//
void run_t0()
{
cnt=0;
high=1;//首次啟動(dòng)加熱5V高電平。標(biāo)志位置1
low=0;//低電平1.5V加熱標(biāo)志
TMOD=0x01;
TH0=-(50000/256);
TL0=-(50000%256);
ET0=1;
EA=1;
contrl=1;//首次啟動(dòng)定時(shí)開(kāi)啟5V
TR0=1;
}
//
void time0() interrupt 1//using **
{
cnt++;
TR0=0;
if((cnt==120)&&high) //5V加熱達(dá)到60S,這里加括號(hào)為了閱讀方便。但是有時(shí)候要注意優(yōu)先級(jí)。==比&就高得多
{
TR0=0;
TH0=-(50000/256);
TL0=-(50000%256);
ADC(6);
}
if((cnt==600)&&high) //5V加熱達(dá)到60S,這里加括號(hào)為了閱讀方便。但是有時(shí)候要注意優(yōu)先級(jí)。==比&就高得多
{
TR0=0;
TH0=-(50000/256);
TL0=-(50000%256);
ADC(6);
}
if((cnt==1200)&&high) //5V加熱達(dá)到60S,這里加括號(hào)為了閱讀方便。但是有時(shí)候要注意優(yōu)先級(jí)。==比&就高得多
{
TR0=0;
contrl=0;//開(kāi)啟1.5V,即關(guān)閉5V
cnt=0;
high=0;//停止加熱高5V后清標(biāo)志位
low=1;
TH0=-(50000/256);
TL0=-(50000%256);
ADC(6);
}
if((cnt==180)&&low)//1.5V加熱達(dá)到90S
{
TH0=-(50000/256);
TL0=-(50000%256);
ADC(6);
}
if((cnt==1000)&&low)//1.5V加熱達(dá)到90S
{
TH0=-(50000/256);
TL0=-(50000%256);
ADC(6);
}
if((cnt==1800)&&low)//1.5V加熱達(dá)到90S
{
contrl=1;//開(kāi)啟5V
cnt=0;
low=0;
high=1;//
TH0=-(50000/256);
TL0=-(50000%256);
ADC(6);
}
TR0=1;
}
//
void pwm()
{
CR=0;
START=0;
//PCA模塊工作于PWM模式 C程序
CMOD = 0x02; //用定時(shí)器0溢出做PCA脈沖
CL = 0x00; //PCA定時(shí)器低8位 地址:E9H
CH = 0x00; //PCA高8位 地址 F9H
CCON=0x00;
CCAP0L = timeL; //PWM模式時(shí)他倆用來(lái)控制占空比
CCAP0H = timeH; //0xff-0xc0=0x3f 64/256=25% 占空比(溢出)
CCAPM0 = 0x42; //0100,0010 Setup PCA module 0 in PWM mode
// ECOM0=1使能比較 PWM0=1 使能CEX0腳用作脈寬調(diào)節(jié)輸出
/*********************
PCA 模塊工作模式設(shè)置 (CCAPMn 寄存器 n= 0-3四種)
7 6 5 4 3 2 1 0
- ECOMn CAPPn CAPNn MATn TOGn PWMn ECCFn
選項(xiàng): 0x00 無(wú)此操作
0x20 16位捕捉模式,由 CEXn上升沿觸發(fā)
0x10 16位捕捉模式,由CEXn下降沿觸發(fā)
0x30 16位捕捉模式,由CEXn的跳變觸發(fā)
0x48 16位軟件定時(shí)器
0x4c 16位高速輸出
0x42 8位PWM輸出
每個(gè)PCA模塊另外還對(duì)應(yīng)兩個(gè)寄存器:CCAPnH和CCAPnL 。 捕獲或者比較時(shí),它們用來(lái)
保存16位計(jì)數(shù)值,當(dāng)工作于PWM模式時(shí),用來(lái)控制占空比
*******************************/
CR=1; //Start PCA Timer.
}
//AD轉(zhuǎn)換初始化 ----打開(kāi)ADC電源,設(shè)置AD口開(kāi)漏狀態(tài)
void InitADC()
{
ADC_CONTR|=0x80;
delayms(12);
//這兩個(gè)寄存器用來(lái)設(shè)置 P1口四種狀態(tài),每一位對(duì)應(yīng)一個(gè)P1引腳 ,按狀態(tài)組合操作
/*****************
P1M0 和P1M1 寄存器位 7 6 5 4 3 2 1 0
P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
同理P3M0 P3M0 也是。因?yàn)镾TC12C2052AD只有兩個(gè)P口,所以只有這倆組 STC12C5410AD還多P2M0 P1M0 有三組
P1M0 P1M1 高
0 0 普通I0口 (準(zhǔn)雙向) P1寄存器位 7 6 5 4 3 2 1 0
0 1 強(qiáng)推挽輸出 (20MA電流 )盡量少用 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
1 0 僅做輸入 A/D轉(zhuǎn)換時(shí)可用此模式
1 1 開(kāi)漏 ,A/D轉(zhuǎn)換時(shí)可用此模式
例如:
要設(shè)置P1.1為 AD 輸入口
則 P1M0=0X02 ;
P1M1=0X02; 開(kāi)漏即可
當(dāng)不用AD時(shí),最好 關(guān)閉ADC電源 ,恢復(fù)為IO口狀態(tài)
********************************/
P1M0=0x40;//這兩個(gè)寄存器用來(lái)設(shè)置 P1口四種狀態(tài),每一位對(duì)應(yīng)一個(gè)P1引腳 ,按狀態(tài)組合操作
P1M1=0x40;//P1.6位AD輸入端
delayms(12);
}
// AD轉(zhuǎn)換程序
void ADC(uchar port)
{
uint V0;
ADC_DATA = 0; //清除結(jié)果
ADC_CONTR = 0x60; //轉(zhuǎn)換速度設(shè)置 0x60 最快速度
ADC_CONTR = 0xe0; //1110,0000 清 ADC_FLAG, ADC_START 位和低 3 位
ADC_CONTR |= port; //選擇 A/D 當(dāng)前通道 P1.6
// delayms(1); //使輸入電壓達(dá)到穩(wěn)定
ADC_CONTR |= 0x08; //0000,1000 令 ADCS = 1, 啟動(dòng)A/D轉(zhuǎn)換,
while(!(ADC_CONTR & 0x10)); //!的優(yōu)先級(jí)比&高太多了
//養(yǎng)成經(jīng)常加括號(hào)的習(xí)慣 ,沒(méi)壞處 。也不浪費(fèi)速度
/***************
這里while 不能改成while(ADC_CONTR & 0x10==0) ;就錯(cuò)誤了,因?yàn)閮?yōu)先級(jí) ==比&高 ,所以要加括號(hào)
while( (ADC_CONTR & 0x10) ==0) 或者非一下 while(!(ADC_CONTR & 0x10)); //!的優(yōu)先級(jí)比&高太多了
while()
******************************/
ADC_CONTR &= 0xE7; //1111,0111 清 ADC_FLAG 位, 關(guān)閉A/D轉(zhuǎn)換,
V0= ADC_DATA; //返回 A/D
voltage=V0*100.0/256.0*5.0;//注意每一步計(jì)算要考慮是否超了左邊變量的范圍,如果5.0放前面就有可能溢出
xianshi[0]=vol/1000;
xianshi[1]=vol%1000/100;
xianshi[2]=vol%100/10;
xianshi[3]=vol%10;
if(voltage<399.0)//危險(xiǎn)濃度以下
{
OK=0;
BAOJING=1;//報(bào)警燈滅
START=1;
sound=0;//聲音控制腳滅
}
if( voltage>399.0)//C0濃度過(guò)高
{
BAOJING=0;//報(bào)警燈亮
OK=1;
START=1;
sound=1;//聲音報(bào)警
}
}
// 延時(shí)
void delayms(uint k)
{
uint data i,j;
for(i=0;i<k;i++)
{
for(j=0;j<200;j++)
{;}
}
}