📄 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 + -