⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 可以读写ID卡,利用AVR单片机.可以响应按键
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ----------------------------------------------------------------------------
 * "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 + -