?? main.c
字號:
/* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <joerg@FreeBSD.ORG> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
* ----------------------------------------------------------------------------
*
* Simple AVR demonstration. Controls a LED that can be directly
* connected from OC1/OC1A to GND. The brightness of the LED is
* controlled with the PWM. After each period of the PWM, the PWM
* value is either incremented or decremented, that's all.
*
* $Id: demo.c,v 1.6.2.3 2006/01/05 21:33:08 joerg_wunsch Exp $
RJMP MAIN ;
RETI ;External Interrupt Request 0
RJMP INT1 ;External Interrupt Request 1
RJMP TIMER1CE ;Timer/Counter1 Capture Event
RETI ;Timer/Counter1 Compare Match A
RETI ;Timer/Counter1 Compare Match B
RETI ;Timer/Counter1 Overflow
RJMP TIMER0 ;Timer/Counter0 Overflow
RJMP INTCOM ;Serial Transfer Complete
RETI ;UART Receive Complete
RETI ;UART Data Register Empty
RETI ;UART Transmit Complete
RETI ;Analog Comparator
01 0x000(1) RESET 外部引腳,上電復位,掉電檢測復位,看門狗復位
02 0x001 INT0 外部中斷請求0
03 0x002 INT1 外部中斷請求1
04 0x003 TIMER2 COMP 定時器/ 計數器2 比較匹配
05 0x004 TIMER2 OVF 定時器/ 計數器2 溢出
06 0x005 TIMER1 CAPT 定時器/ 計數器1 捕捉事件
07 0x006 TIMER1 COMPA 定時器/ 計數器1 比較匹配 A
08 0x007 TIMER1 COMPB 定時器/ 計數器1 比較匹配B
09 0x008 TIMER1 OVF 定時器/ 計數器1 溢出
10 0x009 TIMER0 OVF 定時器/ 計數器0 溢出
11 0x00A SPI, STC SPI 串行傳輸結束
12 0x00B USART, RXC USART, Rx 結束
13 0x00C USART, UDRE USART 數據寄存器空
14 0x00D USART, TXC USART, Tx 結束
15 0x00E ADC ADC 轉換結束
16 0x00F EE_RDY EEPROM 就緒
17 0x010 ANA_COMP 模擬比較器
18 0x011 TWI 兩線串行接口
19 0x012 SPM_RDY 保存程序存儲器內容就緒
*/
#define F_CPU 8000000 //11059200
//#include <inttypes.h>
//#include <avr/io.h>
//#include <avr/signal.h>
#include <avr/interrupt.h>
//#include <avr/pgmspace.h>
//#include <avr/sleep.h>
#include "iocompat.h" /* Note [1] */
//#include <avr/sfr_defs.h>
//#include <avr/wdt.h>
//#include <avr/eeprom.h>
#include <util/delay.h>
#include "main.h"
int main (void)
{
Byte i;
ioinit();
parainit();
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0); //SPI_MasterInit();
//Init AD
#if AD10
// ADMUX=0xE0; //b5=0-靠右 1-靠左
ADMUX=0x40; //高2位 11-2.56V參考 01-Vcc參考
adm=0;
ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADFR)|(1<<ADIF)|(0<<ADIE)|5; //+ADPS 分頻 //16分頻
#else
// ADMUX=0xE0; //b5=0-靠右 1-靠左
ADMUX=0x60; //高2位 11-2.56V參考 01-Vcc參考
adm=0;
ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADFR)|(1<<ADIF)|(0<<ADIE)|4; //+ADPS 分頻 //16分頻
#endif
#if 0
//weinatronics才可以用
for(i=0;i<16;i++)
{
if(MY_EEPROM_read(i)!=weina[i])
break;
}
if(i<16)
{
PORTB|=4; //LATCH PB2=1
SPI_MasterTransmit(0xef);
for(i=16;i<200;i--) //16~0
{
SPI_MasterTransmit(0xff);
}
PORTB&=(~4); //LATCH PB2=0
_delay_us(2);
PORTB|=4; //LATCH PB2=1
while(1)
WDR; // PORTC^=0x04;
}
#endif
// 亮度調節
lum=(MY_EEPROM_read(ADDLUM)<<8)+MY_EEPROM_read(ADDLUM+1);
if(lum>1023)
{
lum=700;
OCR1A=lum; //占空比 700/1024
}
t=MY_EEPROM_read(ADDHOUR);
if(t==0xff)
t=0;
totalt[0]=t;
t=MY_EEPROM_read(ADDHOUR1);
if(t>99)
t=0;
totalt[1]=t;
t=MY_EEPROM_read(ADDHOUR2);
if(t>99)
t=0;
totalt[2]=t;
// 在使用時間<100小時情況下,同時按住F1和F2鍵開機可清除累計運行時間(只有三次機會)
// My_EEPROM_write(ADDCLEA,3);
cleatime=MY_EEPROM_read(ADDCLEA); // 可清totaltime次數
if(cleatime>3)
cleatime=3;
if(((PIND&0x0c)==0)&&(cleatime>0)&&(totalt[0]==0)&&(totalt[1]==0))
{
_delay_ms(5);
if((PIND&0x0c)==0)
{
cleatime--;
My_EEPROM_write(ADDCLEA,cleatime);
My_EEPROM_write(ADDHOUR,0);
My_EEPROM_write(ADDHOUR1,0);
My_EEPROM_write(ADDHOUR2,0);
}
while((PIND&0x0c)!=0x0c)
WDR; // PORTC^=0x04;
}
#if JM //加密
My_EEPROM_write(ADDMIMAE,1);
for(i=0;i<10;i++)
My_EEPROM_write(ADDMIMAE+7+i,i+1);
#endif
// 對未解密的機器按住F2鍵開機可主動解密 在累計使用時間大于500小時時必須輸入密碼解密
for(i=0;i<7;i++)
mimainp[i]=0;
for(i=0;i<17;i++)
mima[i]=MY_EEPROM_read(ADDMIMAE+i);
if(((totalt[1]>5)||(totalt[0]>0))&&(mima[0]!=0))
status=MIMA;
//if(((PIND&0x08)==0)&&(mima[0]!=0))
if((PIND&0x08)==0)
{
_delay_ms(5);
if((PIND&0x08)==0)
{
if(mima[0]!=0)
status=MIMA;
else
status=SN;
}
}
// 對未解密的機器按住F2鍵開機可主動解密 在累計使用時間大于500小時時必須輸入密碼解密
minuteadd=MY_EEPROM_read(ADDMINUTEP);
if(minuteadd>0x4f)
minuteadd=0x44;
minute=MY_EEPROM_read(ADDMINUTE);
if(minute>0x60)
minute=0x0;
WDR; // PORTC^=0x04;
// 對未設置的機器設置機器參數
// 按住F1鍵開機可更改設置機器參數
t=0;
setdy=MY_EEPROM_read(ADDDY);
pl=MY_EEPROM_read(ADDPL);
gl=10*MY_EEPROM_read(ADDGL);
if(setdy>6)
{
setdy=4;
t=1;
}
if(pl==0)
pl=600;
else
pl=500;
if(gl>990)
{
t=1;
gl=10;
}
mdy=setdy_code[setdy];
mpl=pl;
dy=mdy;
mdl=Getdl();
WDR; // PORTC^=0x04;
maxmdy=mdy*11/10;
minmdy=mdy*9/10;
maxmdl=mdl*11/10;
maxmpl=mpl+50;
minmpl=mpl-30;
WDR; // PORTC^=0x04;
if((PIND&0x04)==0)
{
_delay_ms(5);
if((PIND&0x04)==0)
status=SETUP;
}
if((t==1)||(status==SETUP))
{
status=SETUP;
setdy=MY_EEPROM_read(ADDDY);
pl=MY_EEPROM_read(ADDPL);
gl=10*MY_EEPROM_read(ADDGL);
if(setdy>6)
setdy=4;
if(pl==0)
pl=600;
else
pl=500;
if(gl>990)
gl=10;
dy=setdy_code[setdy];
dl=Getdl();//dl=gl*1000/dy;
}
else if((status==MIMA)||(status==SN))
posi=1;
else //顯示4秒機器設置數據后進入備用狀態
{
dy=mdy;
dl=mdl;
status=WORK;
Show();
status=STOP;
for(t=0;t<40;t++)
{
WDR; // PORTC^=0x04;
_delay_ms(100);
}
}
Set_AD();
#if WENDU
clr_ds18b20_dq();
set_ds18b20_dq_ddr();
convert_ds18b20();
Show();
read_temperature();
#else
Show();
#endif
sei(); /* 置位全局中斷使能標志*/
/* loop forever, the interrupts are doing the rest */
//status=WORK;
while(1)
{
WDR; // PORTC^=0x04;
if(status<SETUP)
{
if(((ADCSRA>>ADIF)&1)==1) //AD轉換完成
{
_delay_us(30);
if(adm==0)
{
adm=1;
cf=1;
}
else
{
#if AD10
advalue=ADCL;
advalue+=(ADCH<<8);
#else
advalue=ADCH;
#endif
if(curadch==4) //檢測充電電壓 AD4 cddy=電壓值*10
{
#if 0
#if AD10
cddy=(5+advalue*2)/10; //1023->20.00V
#else
cddy=(5+advalue*8)/10; //255->20.00V
#endif
pl=curpl;
if(status==WORK)
{
adm=0;
curadch=13-lastch;
Set_AD();
#else
if(cf==1)
{
dlt=advalue;
dlc=1;
cf=0;
}
else
{
dlt+=advalue;
dlc++;
}
if(adm>=4)
{
cddy=(5+(dlt*2)/dlc)/10;
cf=1;
}
pl=curpl;
if(status==WORK)
{
if(adm>=4)
{
adm=0;
curadch=13-lastch;
Set_AD();
}
#endif
#if BH
//頻率在直流檢測時判斷
if(pl>maxmpl) //超頻
{
if(plerror!=1)
{
if(ssecond<QDSJ)
//plerrt=CPSJ;
plerrt=ssecond-QDSJ;
else
plerrt=0;
}
plerror=1;
}
else if(pl<minmpl) //欠頻
{
if(plerror!=2)
{
if(ssecond<QDSJ)
plerrt=ssecond-QDSJ;
else
plerrt=0;
}
plerror=2;
}
else //正常
{
plerrt=0;
plerror=0;
}
#endif
}
}
#if FF //峰峰值檢測
else if(curadch==6) //檢測輸出電壓 AD6
{
if(maxdy<advalue)
maxdy=advalue;
if(mindy>advalue)
mindy=advalue;
if((adm%2)==1)
{
if(cf==0)
{
v=maxdy-mindy;
if(maxv<v)
maxv=v;
if(minv>v)
minv=v;
dydlt=dydlt+v;
maxdy=0;
mindy=1023;
cf=1;
}
}
else
cf=0;
if(adm>ADDYTIMES)
{
adm=0;
dydlt=dydlt-maxv-minv;
#if AD10
dydlt/=4; //2.2V->220V 1023->5V->500V or 50A 采樣2次
#endif
dy=dydlt;
testdy();
lastch=curadch;
curadch=4;
Set_AD();
dydlt=0;
maxv=0;
minv=1023;
maxdy=0;
mindy=1023;
Getgl();
}
}
else //檢測輸出電流 AD7 dl=電流值*10
{
if(advalue>512)
advalue-=512;
else
advalue=512-advalue;
if(cf==1)
{
dlt=advalue;
dlc=1;
cf=0;
}
else
{
dlt+=advalue;
dlc++;
}
if(adm>ADDLTIMES)
{
adm=0;
#if PJ
dlvt[dlp]=dlt/dlc;
dlp++;
dlp%=6;
dlt=(dlvt[0]+dlvt[1]+dlvt[2]+dlvt[3]+dlvt[4]+dlvt[5])/6;
#endif
dlt=dlt/dlc;
dlt*=1732;
dlt/=1000;
dl=dlt;
testdl();
lastch=curadch;
curadch=4;
Set_AD();
Getgl();
}
}
#else //有效值檢測
else //檢測輸出電壓 AD6 //檢測輸出電流 AD7 dl=電流值*10
{
if(advalue>512)
advalue-=512;
else
advalue=512-advalue;
if(cf==1)
{
dlt=advalue;
dlc=1;
cf=0;
}
else
{
dlt+=advalue;
dlc++;
}
if(adm>ADDLTIMES)
{
adm=0;
#if PJ
dlvt[dlp]=dlt/dlc;
dlp++;
dlp%=6;
dlt=(dlvt[0]+dlvt[1]+dlvt[2]+dlvt[3]+dlvt[4]+dlvt[5])/6;
#endif
dlt*=1732;
dlt=dlt/dlc;
lastch=curadch;
if(curadch==6)
{
dlt+=500;
dlt/=1000;
dy=dlt;
testdy();
}
else
{
dlt/=1000;
dl=dlt;
testdl();
}
curadch=4;
Set_AD();
Getgl();
}
#endif
}
}
}
Detect(); //檢測START 機油 蓄電池電壓
}
#if BH
if(key!=0) // 有按鍵
{
if(key&1)
{
if(status==SETUP)
{
posi++;
posi%=5;
My_EEPROM_write(ADDDY,setdy);
if(pl==600)
My_EEPROM_write(ADDPL,0);
else
My_EEPROM_write(ADDPL,1);
My_EEPROM_write(ADDGL,gl/10);
}
else if(status==MIMA)
{
posi++;
if(posi==7)
{
for(i=1;i<7;i++)
{
if(mima[i]!=mimainp[i])
{
posi=1;
break;
}
}
if(i==7)
{
My_EEPROM_write(ADDMIMAE,0);
status=STOP;
}
else
{
for(i=1;i<7;i++)
mimainp[i]=0;
}
}
}
}
if(key&2)
{
if(status==MIMA) //輸密碼
{
mimainp[posi]++;
mimainp[posi]%=10;
}
else if(status==SETUP)
{
if(posi==0)
{
setdy++;
setdy%=7;
dy=setdy_code[setdy];
}
else if(posi==1)
pl=1100-pl;
else if(posi==2)
{
gl+=100;
gl%=1000;
}
else
{
gl+=10;
if(gl%100==0)
gl-=100;
}
dl=Getdl();//dl=gl*1000/dy;
}
else
{
seleLedv++;
#if WENDU
seleLedv%=3;
#else
seleLedv&=1;
#endif
seleLed=seleLed_buffer[seleLedv];
}
}
key=0;
}
#endif
if(time)
{
time=0;
if(status<SETUP)
{
if(plcount>10)
pl=0;
else
plcount++;
}
if(status==STOP)
{
if(!startkey)
{
startcount++;
if((startcount==20)&&(oilLed==0)) //xs
{
plcount=0;
plerror=0;
dyerror=0;
dlerror=0;
plerrt=0;
dyerrt=0;
dlerrt=0;
ssecond=0;
seleLedv=0;
seleLed=seleLed_buffer[seleLedv];
PORTC&=~(3); //開始工作
status=WORK;
TCNT2=130; //126
pltc=0;
TCNT0=254;
startcount=0;
lastch=6;
dl=0;
dy=0;
pl=0;
gl=0;
}
}
}
count++;
if(adm!=0)
adm++;
#if BH
//iftest=0; //不保護
if(status==WORK)
{
if((PIND&0x80)==0x80) //START按鍵 松開后關閉啟動電機
{
startcount++;
if(startcount==30)
PORTC|=2;
}
else
startcount=0;
if((iftest)&&(count==31))
{
if(ssecond<QDSJ)
ssecond++;
if(dyerror!=0)
{
dyerrt++;
if(((dyerrt>QYSJ)&&(dyerror==2))||((dyerrt>CYSJ)&&(dyerror==1)))
status=STOP;
}
if(dlerror!=0)
{
dlerrt++;
if(((dlerrt>CZSJ)&&(dlerror==2))||((dlerrt>CCZSJ)&&(dlerror==1)))
status=STOP;
}
if(plerror!=0)
{
plerrt++;
if(((plerrt>QPSJ)&&(plerror==2))||((plerrt>CPSJ)&&(plerror==1)))
status=STOP;
}
if(status==STOP)
{
bhdy=dy;
bhdl=dl;
bhpl=pl;
Stop(); //停止工作
}
}
}
#endif
if(count>=62)
{
#if WENDU
read_temperature();
#endif
count=0;
if(status==WORK) //工作
{
second++;
if(second>=60) //1分鐘60秒
{
second=0;
minute++;
if(minute>=60) //1小時60分
{
minute=0;
totalt[2]++;
if(totalt[2]==100)
{
totalt[2]=0;
totalt[1]++;
if(totalt[1]>=100)
{
totalt[1]=0;
totalt[0]++;
My_EEPROM_write(ADDHOUR,totalt[0]);
}
My_EEPROM_write(ADDHOUR1,totalt[1]);
if(totalt[1]%50==0) //50*256時 改變一次10分的位置
{
if(minuteadd<0x4f)
{
minuteadd++;
My_EEPROM_write(ADDMINUTEP,minuteadd);
}
}
}
My_EEPROM_write(ADDHOUR2,totalt[2]);
}
cminute++;
if(cminute>=60) //1小時60分
{
cminute=0;
curt[2]++;
if(curt[2]==100)
{
curt[2]=0;
curt[1]++;
if(curt[1]==100)
{
curt[1]=0;
curt[0]++;
}
}
}
if(minute%10==0) //每10分記一次
{
My_EEPROM_write(minuteadd,minute);
}
}
}
}
if(count%16==1)
{
runLed^=0x10; //心跳
Show();
}
}
}
}
void ioinit (void) /* Note [6] */
{
/* Timer 1 is 10-bit PWM */
TCCR1A=0x83; //分頻系數
TCCR1B|=3; //分頻系數
OCR1A=700;//lum; //占空比 700/1024
TCNT0=0x10;
TCNT1=0x40;
TCNT2=0x10;
//上電默認DDRx=0x00,PORTx=0x00 輸入,無上拉電阻
PORTB=0xFF; //管腳使能內部上拉電阻。
PORTC=0x0F;
PORTD=0xFF;
DDRB=0xff; //B端口輸出 PB0 輸入 其他 輸出
DDRC=0x0f; //C0-3 端口輸出 4-7輸入
DDRD=0x00; //D端口輸入
PORTC|=3; //stop
PORTB|=4; //LATCH PB2=1
MCUCR=(1<<ISC11)|(0<<ISC10)|(1<<ISC01)|(0<<ISC00); //注意該寄存器有多個功能
//ISCx1:0=00 INTx引腳為低電平時產生中斷請求
//ISCx1:0=01 INTx引腳上任意的邏輯電平變化都將引發中斷
//ISCx1:0=10 INTx引腳的下降沿產生中斷請求 √
//ISCx1:0=11 INTx引腳的上升沿產生中斷請求
GIFR=(1<<INTF1)|(1<<INTF0); //寫1清除標志位,在使能中斷前最好先把對應的標志位清除,以免誤觸發
GICR=(1<<INT1)|(1<<INT0); //使能二個外部中斷
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -