|
樓主 |
發表於 2012-12-24 23:22:13
|
顯示全部樓層
ciko.ciko大:
問題已經解決,比較器不是問題,是時序上面的錯亂!!
程式如下:
一個D/A轉換給2個比較器達到2組A/D的功能,解析度 255階,大家參考
/* 20121224 P0 LCM display P1 DtoA convert mith R-2R+74LS373 P2^0 hi/lo active sent to LM4558 op amp volt ,34063 neg 5v generator LM393 comparator for P2^1 bit ,loop d/a must clear each cycle */
#define ADPortL P1//P1.0~P1.7 AD574 low 8bit
#include<reg52.h>
#include<stdio.h>
#include <intrins.h>
#define DataPort P0//P0.0~P0.7 1602 LCM顯示器
#define _Nop() _nop_() //定义空指令
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
sbit RS = P2^4;//P1^0;//LCM指令Lo/資料Hi
sbit RW = P2^5;//P1^1;//讀出 Hi/寫入Lo
sbit EN = P2^6;//P1^2;//動作觸發 Hi>>Lo
char DisplayWord[16];//顯示第一行工作的狀況
char Displaychar[16];// 顯示第二行工作的狀況
unsigned char counter; //T0使用的1/100計數器.
unsigned char TimeFlag; //T0計數1秒的使用旗標.
void DelayMs(unsigned char);
void DelayUs2x(unsigned char);
void Init_Timer0(void);//定?器初始化
void LCD_Write_String(char x,char y, char *s);
void LCD_Write_Char(char x,char y,char Data);
void LCD_Clear(void);
unsigned int ADget(void);
unsigned char ADT,ADTT;
//------------20121217------------------
unsigned char ADVL;//ADVL display AD data
sbit CMPDT= P2^1;//compare bit P2^2 for temperature
sbit CMPD = P2^2;//compare bit P2^1 for volt
sbit LTH = P2^0;//74ls373 latch bit
bit SHV_flag;// latch volt
bit SHT_flag;//latch temp
bit SH_flag;//clean show flag
//-----------------DAO-------------------
void DAO(void)//DA converter
{
unsigned char DA=0;
while(!CMPD)//compare bit P2^1
{
ADPortL=DA;
LTH=1;
LTH=0;
DelayMs(2);
DA++;
}
ADT=DA;//ADVL display AD data
ADPortL=0;
LTH=1;
LTH=0;
DelayMs(2);
SH_flag=1;// show flag
}
//-------------DAO2--------------------
void DAO2(void)//DA converter
{
unsigned char DA=0;
while(!CMPDT)//compare bit P2^1
{
ADPortL=DA;
LTH=1;
LTH=0;
DelayMs(2);
DA++;
}
ADTT=DA;//ADVL display AD data
ADPortL=0;
LTH=1;
LTH=0;
DelayMs(2);
SH_flag=1;// show flag
}
/*------------ LCM 顯示相關程式--------*/
bit LCD_Check_Busy(void) //檢查是否為"忙碌"
{
DataPort= 0xFF;
RS_CLR; // 指令模式
RW_SET; //寫入模式
EN_CLR; //***特別**** 啟動由LO變成HI **************
_nop_();
EN_SET; //***特別**** 啟動由LO變成HI **************
return (bit)(DataPort & 0x80);//若 讀出的資料bit7 =0 可以寫資料
}
void LCD_Write_Com(char com) //命令寫入
{
while(LCD_Check_Busy()); //忙则等待 1=while loop still;
RS_CLR; //指令功能
RW_CLR; //寫入
EN_SET; //下降緣 由HI變成LO
DataPort= com; // 指令設定
_nop_();
EN_CLR;//
}
void LCD_Write_Data(char Data) //資料寫入
{
while(LCD_Check_Busy()); //忙则等待
RS_SET; // 資料處理
RW_CLR;// 寫的動作
EN_SET; // 啟動下緣觸發
DataPort= Data; //輸入需要寫入的資料
_nop_();//延後一個時間
EN_CLR;//
}
void LCD_Clear(void)
{
LCD_Write_Com(0x01); //清屏指令
DelayMs(5);//時間延遲5ms.
}
void LCD_Write_String(char x,char y, char *s)
{
if (y == 0) //y 表示第一行或是第二行
{
LCD_Write_Com(0x80 + x); //表示第一行bit4 Hi+ x position
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行 bit4 Hi+40+x position
}
while (*s)
{
LCD_Write_Data( *s); // *s 和 s 不一樣,*s 應該是字串 s是字數
s ++;
}
}
/*
void LCD_Write_Char(char x, char y, char Data)
{
if (y == 0) //第一行
{
LCD_Write_Com(0x80 + x); //第幾個字的位置
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data); //字
}
*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38); //8bit data 2 line 5x7 character.
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/
}
void DelayUs2x(unsigned char t)
{
while(t--);
}
void DelayMs(unsigned char t)
{
while(t--);
{
DelayUs2x(245);//from245>>45
DelayUs2x(245);
}
}
//--------------------------------------------------------------------------------------------
void Init_Timer0(void)
{
TMOD |= 0x01; //使用模式1,16位定?器,使用"|"符?可以在使用多?定?器?不受影?
TH0= (65536-2000)/256; // 0x0D8 2ms if 12Mcristal
TL0= (65536-2000)%256;// 0x0F0
EA=1;
ET0=1;
TR0=1;
}
//--------------------------------------------------------------------------------------------
void Timer0_isr(void) interrupt 1
{
TH0= (65536-10000)/256; // 0x0D8 2ms if 12Mcristal
TL0= (65536-10000)%256;// 0x0F0
counter++;//counter is Global variable.
if(counter==30)
DAO2();
if(counter==60)
DAO();
if(counter==100) //200ms更新一次
{
counter=0;
TimeFlag=1; //計數器中斷約1秒時設定旗標為1,
}
}
void main(void)
{
Init_Timer0();//起始定時器
LCD_Init();// LCM 啟動
LCD_Clear();//LCM清屏
sprintf(DisplayWord," AD data %5d",00000);//顯示AD為零
while(1)
{
if(TimeFlag==1)//每1000Ms 更新一次
{
TimeFlag=0;//清除定時旗標
if(SH_flag==1)// show flag
{
SH_flag=0;
sprintf(DisplayWord,"AD1:%3d AD2:%3d",(int)ADT,(int)ADTT);//顯示第一組的計數 第二組的計數
LCD_Write_String(0,0, DisplayWord);//顯示在第一行
sprintf(DisplayWord,"v=%3.2f tmp=%2.1f" ,ADT*0.019,(193-ADTT)*0.5);//轉換成電壓 和 溫度
LCD_Write_String(0,1, DisplayWord);//顯示在第二行
}
}
}
}
|
|