|
本帖最後由 antlu 於 2013-10-13 01:19 AM 編輯
功能:
上一行
1.負載目前電源電壓
2.負載目前電流
3.已放電時間
下一行
0.@ 輸出
1.設定最低放電電壓
2.設定放電電流
3.設定放電時間
硬體電路
按鍵: 1 輸出 2.三個設定切換 3.數值 + 4.數值- 5. <移動 6.>移動
程式: 簡單功能 還需要在細調大家參考
/* 1. // 頭文字
2. 設定參數
3. 顯示部分
4. A/D 轉換程序(讀取 輸入,轉換程序)
5.掃描判斷
6.按鍵處理
7.計時與中斷
8.串並與輸出控制
9.主程式
*/
// 頭文字
#include<STC15F204EA.h>
#include<intrins.h>
//設定參數
bit Startflag;//start 1/ stop 0 開始放電旗標
bit VoI_flag;//volt 1 /current 0 設定終極放電電壓或放電電流
//bit Ts_flag;// down count second
bit TimeFlag; //T0 counter 中斷定時器
unsigned char Gcounter; //T0counter 計時器計數
unsigned char Tcount;//秒計數
//unsigned char Tcounter;//T1 counter no use
unsigned char Idata;//current setting data send to DAPort then I_SET & I_CLR 送到595 的放電電流設定值
unsigned char Vdata;//volt setting data send to DAPort then V_SET & V_CLR送到595 的終極放電電壓截止設定值
unsigned char Idigt;// LCM 3bit 0.00 ~ 1.00 000~100 設定電流 0~10.0A
unsigned char Vdigt;//LCM V 3bit 00.0~15.0 000~150 設定放電截止電壓25.5V
unsigned char Tdigt;//放電時間位數值
unsigned int Tdata;//放電時間數量
unsigned int KS,KSC;//按鍵掃描讀取DA值 data
bit Kinc;// + key 判斷按鍵按下後設此BIT為1
bit Kdec;// - key
bit Kls;// < key
bit Krs;//> key
unsigned char VoI;// volt 0 or Current 1 or Time 2 select
bit STRP;// start/stop
bit Khold;// 按鍵放開 key press/release
//顯示部分
sbit RS = P3^7; //LCM control
sbit RW = P3^6;
sbit EN = P3^5;
sbit LV= P0^1;//當電壓低於設定值會變lo 開始之後3秒再檢查連續檢查後再 動作
unsigned char LVcount;
char displayword[16];
#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
#define DataPort P2 //STC15F204EA P1 A/D P2 LCM P3^7--RS P3^6--W/R P3^5--E
//宣告
void DelayUs2x(unsigned char t);
void DelayMs(unsigned char t);
unsigned int Q,R,Dchg_T,Work_T,ADC_DATA,L,I,N;
/*------------------------------------------------
LCM driver
4bit 驅動線程式 需要把要顯示的資料放在變數裡面
char displayword[16];
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
void LCD_Write_Com(char com) // 4bit
{
while(LCD_Check_Busy());
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;//
com<<=4;
EN_SET; //
_nop_();
DataPort= com; //
EN_CLR;//
DelayMs(1);
}
void LCD_Write_Data(char Data) //for 4bit
{
while(LCD_Check_Busy()); //
RS_SET; //
RW_CLR;//
EN_SET; //
DataPort= Data; //
_nop_();//
EN_CLR;//
Data<<=4;
EN_SET; //
DataPort= Data; //
EN_CLR;//
DelayMs(1);//
}
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
void LCD_Write_FChar(unsigned char x,unsigned char y)
{ //write cursor flash
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Com(0x0f);
}
/*------------------------------------------------
initial LCM
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x28); /*4bit mode*/
DelayMs(5);
LCD_Write_Com(0x28);
DelayMs(5);
LCD_Write_Com(0x28);
DelayMs(5);
LCD_Write_Com(0x28);
LCD_Write_Com(0x08); /*?F?ü?×??*/
LCD_Write_Com(0x01); /*?F?ü2M?ì*/
LCD_Write_Com(0x06); /*?F?ü?ú?á2??e?|?m*/
DelayMs(5);
LCD_Write_Com(0x0C); /*?F?ü…{¤??ú?á?|?m*/
}
void Display_pros(void)
{//實際電壓電流讀值 xx.xV xx.xA 999s
displayword[0]= Q/100+'0';//百位
displayword[1]= (Q%100)/10+'0';//十位
displayword[2]= '.';
displayword[3]= (Q%10)+'0';//個位
displayword[4]= 'V';
displayword[5]= ' ';
displayword[6]= R/100+'0';
displayword[7]= (R%100)/10+'0';
displayword[8]= '.';
displayword[9]= (R%10)+'0';
displayword[10]='A';
displayword[11]= ' ';
displayword[12]= (Work_T /100)+'0' ;//工作秒數
displayword[13]=( Work_T %100)/10+'0';
displayword[14]= (Work_T %10)+'0';
displayword[15]='S';
LCD_Write_String(0,0, displayword);//以上為第一行顯示
DelayMs(50);
//設定值
if(Startflag) displayword[0]='@';
else displayword[0]=' ';
displayword[1]= Vdata/100+'0';//Vdata/100+'0';
displayword[2]= (Vdata%100)/10+'0';//Vdata /10%10+'0';
displayword[3]= '.';
displayword[4]= (Vdata%10)+'0';//Vdata %10%10+'0';//??? 怪怪的 Vdata%100/10+’0’;
displayword[5]= ' ';
displayword[6]= Idata/100+'0';
displayword[7]= Idata /10%10+'0';
displayword[8]= '.';
displayword[9]= Idata %10%10+'0';
displayword[10]= 'A';
displayword[11]= ' ';
displayword[12]= (Dchg_T/100)+'0' ;//放電秒數
displayword[13]= (Dchg_T %100)/10+'0';
displayword[14]= (Dchg_T %10)+'0';
displayword[15]='S';
LCD_Write_String(0,1, displayword);//以上為第二行顯示值
DelayMs(10);
if(VoI==0)
{
if(Vdigt==2) LCD_Write_FChar(1,1); //閃爍用來輸入flash for input
else if(Vdigt==1) LCD_Write_FChar(2,1);
else LCD_Write_FChar(4,1);
}
if(VoI==1)
{
if(Idigt==2) LCD_Write_FChar(6,1); //閃爍用來輸入flash for input
else if(Idigt==1) LCD_Write_FChar(7,1);
else LCD_Write_FChar(9,1);
}
if(VoI==2)
{
if(Tdigt==2) LCD_Write_FChar(12,1);
else if(Tdigt==1) LCD_Write_FChar(13,1);
else LCD_Write_FChar(14,1);
}
}
//A/D 轉換程序
//P1M0 = 0xff; //設定15f204ea 的起始參數
//P1M1 = 0x00;
//P1ASF=0xff; //all analog in put mode
/*******************************************************************
analog input DATA read
*******************************************************************/
unsigned int Read (unsigned char CHA)
{
unsigned char AD_FIN=0; //set ad work finish
CHA &= 0x07; //set channel to hi 0000 0111 只允許0~7
ADC_CONTR = 0x60; //ADC暫存0XX0 0000 取樣速度設定
_nop_();
ADC_CONTR |= CHA; //read port(CHA) 加入PORT選擇
_nop_();
ADC_CONTR |= 0x80; //ADC電源開啟
DelayMs(1); //¨
/******開始A/D動作 start A/D **************/
ADC_CONTR |= 0x08; //AD暫存0000 1000 啟動轉換
_nop_();
_nop_();
_nop_();
_nop_();
while (AD_FIN ==0){ //等待AD_FIN 變為1
AD_FIN = (ADC_CONTR & 0x10); //0001 0000ADC_FLAG=1;轉態完成
}
ADC_CONTR &= 0xE7; //1111 0111 把ADC_START=0;禁止再做ADC,
ADC_DATA=ADC_RES*4+ADC_RESL;//取出10位的資料
return (ADC_DATA);
}
unsigned int Mavg(unsigned char an)
// read 5 times data and average 讀5次求平均值
// an for analog input no.
{
unsigned char at;
unsigned int M;
M=0;
for (at=0;at<5;at++)
{
M=Read(an)+M;//analog 3 input
DelayMs(100);
}
M=M/5;
return M;
}
void transfer(void){
// 取參考電壓2.5V把電壓的值換算成數值並且以此為依據推展到其他類比輸入電壓
L= Mavg(0);//Read(0); // read volt analog 讀取0通道資料存到L變數
I= Mavg(1);//read (1) read current analog讀取1通道資料存到I變數
N=Read(2);//ref 2.5V讀取2通道這是參考電壓2.5V資料存到N變數
Q=(L*256/N); //Q=L~N/2.5 =L/(N/2.5)= 相對於 1V的倍數 若輸入1.3V 則要顯示1.3 但是整數變數所以要把他乘上10倍或是100倍 …
R=(I*128/(N));//R=display current data 1V=1A R=((I*1.25)/N)*100
DelayMs(1);
}
//按鍵掃描部分 6個按鍵 利用A/D 讀近來判斷數量這僅限於8bit 若是10bit 還需要再做判斷修改程式 讀取 A/D(3)
//convert 6 key to 1.on/off 2.VoI 3.inc 4.dec 5. < 6. >
// bit--on bit--inc bit--dec bit-off
void Keyscan(void)
{
KS=Read(3);//Read(3); //key scan read port3
if(KS>1000) Khold=0;//no key pressed
if((KS<915)&&(!Khold))
{
Khold=1;
DelayMs(20);
KS=Mavg(3);
KSC=Mavg(3);
if(KS==KSC)
{
if((KS<870)&&(KS>840)) //1st key > press
Krs=1;
else if((KS<839)&&(KS>810))//2nd key < press
Kls=1;
else if((KS<809)&&(KS>720))//3rd key Inc press
Kdec=1;
else if((KS<719) &&(KS>600)) //4th key Dec press
Kinc=1;
else if((KS<599)&&(KS>450))//5th key "VoI" press
VoI++;
if(VoI>2)
VoI=0;
else if(KS<100)// 6 th key "ON/OFF " press
STRP=1;
}
}
else //key release
{ //
Khold=0;
}
}
//按鍵處理程式 依據按鍵功能進行處理包刮按鍵後的數值處理和預先設定
void Key_Pros (void)
{
//---------------------------------------------------------------------------------------
if(STRP) {STRP=0;Startflag=!Startflag;}//ON/OFF
if(VoI==0) //執行電壓值設定
{ //{VoI=0;VoI_flag=~ VoI_flag;}// Volt or Current---- volt set mode
if (Kls) // shift left "<"
{
Kls=0;//
Vdigt++;
if(Vdigt>2) Vdigt=0;
}
if(Krs) //shift right ">"
{ Krs=0;//-----------------------------
Vdigt--;
if(Vdigt==255) Vdigt=2;
}
if(Kinc)//+
{ Kinc=0;//------------------------
if(Vdigt==0) Vdata=Vdata++;
if(Vdigt==1) Vdata=Vdata+10;
if(Vdigt==2) Vdata=Vdata+100;
if(Vdata>250) Vdata=250;
}
if(Kdec)//-
{ Kdec=0;//---------------------------
if(Vdigt==0) Vdata=Vdata--;
if(Vdigt==1) Vdata=Vdata-10;
if(Vdigt==2) Vdata=Vdata-100;
if(Vdata>250) Vdata=0;
}
//
// LCD_Clear();//test
//
}
//電流設定
if(VoI==1)
{
if (Kls) // shift left "<"
{
Kls=0;//
Idigt++;
if(Idigt>2) Idigt=0;
}
if(Krs) //shift right ">"
{ Krs=0;//-----------------------------
Idigt--;
if(Idigt==255) Idigt=2;
}
if(Kinc)//+
{ Kinc=0;//------------------------
if(Idigt==0) Idata=Idata++;
if(Idigt==1) Idata=Idata+10;
if(Idigt==2) Idata=Idata+100;
if(Idata>250) Idata=250;
}
if(Kdec)//-
{ Kdec=0;//---------------------------
if(Idigt==0) Idata=Idata--;
if(Idigt==1) Idata=Idata-10;
if(Idigt==2) Idata=Idata-100;
if(Idata>250) Idata=0;
}
//
// LCD_Clear();//test
//
}
if(VoI==2) //執行時間值設定
{
if (Kls) // shift left "<"
{
Kls=0;//
Tdigt++;
if(Tdigt>2) Tdigt=0;
}
if(Krs) //shift right ">"
{ Krs=0;//-----------------------------
Tdigt--;
if(Tdigt==255) Tdigt=2;
}
if(Kinc)//+
{ Kinc=0;//------------------------
if(Tdigt==0) Tdata=Tdata++;
if(Tdigt==1) Tdata=Tdata+10;
if(Tdigt==2) Tdata=Tdata+100;
if(Tdata>990) Tdata=990;
}
if(Kdec)//-
{ Kdec=0;//---------------------------
if(Tdigt==0) Tdata=Tdata--;
if(Tdigt==1) Tdata=Tdata-10;
if(Tdigt==2) Tdata=Tdata-100;
if(Tdata>990) Tdata=0;
}
Dchg_T=Tdata;
//
// LCD_Clear();//test
//
}
}
//定時與中斷
//--------------------------------------------------------------------------------------------
void Init_Timer0(void)
{
TMOD |= 0x01; //mode 1,16bit timer "|"can "OR"operation
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-2000)/256; // 0x0D8 2ms if 12Mcristal
TL0= (65536-2000)%256;// 0x0F0
Gcounter++;//counter is Global variable.
if(Gcounter==100)
{Tcount++;
if(Startflag)
{
if (Tcount>10)
{ Tcount=0;
Work_T++;
Dchg_T--;
if(LV==0)//電壓低於設定值
{
LVcount++;
}
else
LVcount=0;
/* if(LVcount>3)
{Startflag=0;
}
if(Dchg_T==0)
Startflag=0;*/
}
}
else//stop output
Tdata=Dchg_T;
}
if(Gcounter>150) //140ms update 1 time
{
TimeFlag=1; //
Gcounter=0;
}
}
/*------------------------------------------------
delay us
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
delay ms
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
DelayUs2x(245);
DelayUs2x(245);
}
}
//74hc595 D/A轉換的串—並處理
//*******************************************
sbit SER = P3^4;// 74hc595 control
sbit Latch = P3^3;
sbit Clk = P3^2;
void Send595(unsigned char Dat) //output data to D/A converter through the serial mode
{
unsigned char i;
for (i=0;i<8;i++)
{
Clk=0;
SER=Dat & 0x80;
_nop_();
Dat<<=1;
Clk=1;
_nop_();
}
Latch=0;
_nop_();
_nop_();
Latch=1;
_nop_();
_nop_();
}
void Send2byte(unsigned char Dat1,unsigned char Dat2)
{
Send595(Dat1);//Idata
Send595(Dat2);//Vdata
}
//輸出控制
//*******************???******************
void OP(bit K)//output control
{
if (K)// data op =set
{
Send2byte(Idata,Vdata);// volt & current data sent to i/o and latch
}
else //data output=0
{
// reset volt & current data sent to i/o and latch
Send2byte(0x00,0x00);
}
}
//主程式
void main(void)
{
P1M0 = 0xff;
P1M1 = 0x00;
P1ASF=0xff; //all analog in put mode
Init_Timer0();//initial timer0
LCD_Init();
DelayMs(10);
LCD_Clear();//2M?ì
DelayMs(10);
Idata=30;//default current 300mA
Vdata=50;//default volt 5.0v
Idigt=1;//default position
Vdigt=1;
VoI=0;
Dchg_T=900;
while (1)
{
if(TimeFlag==1)//140ms update
{
TimeFlag=0;
Display_pros();//display data
}
if(LVcount>3)
{Startflag=0;
LVcount=0;
}
if(Dchg_T==0)
Startflag=0;
if(Startflag)
{
OP(1); //out put on
}
else
{
OP(0); //output set volt & current to 0
}
DelayMs(10);
transfer();//do ADC & put to display
Keyscan();//read key press
Key_Pros ();// scan key and do something
}
}
|
評分
-
18
查看全部評分
-
|