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

📄 main._c

📁 AVRMega16单片机的项目
💻 _C
📖 第 1 页 / 共 2 页
字号:
functionName:void start_timer0(void)
description:定时器0初始化
            desired value: 20mSec
			actual value:  19.861mSec (0.7%)
**********************************************************************/
void start_timer0(uint _20ms)
{
    TCCR0 = 0x00;       //stop
    TCNT0 = 0x71;
	
	TIMSK |= 0x01;      // 定时器0溢出中断
	OCR0  = 0x8F;       // 定时器比较值
	
	gTmr0OvrCount = _20ms;
	
	TCCR0 = 0x05;	  	// Count clock/1024, start Timer0
}

/**********************************************************************
functionName:void stop_time0(void)
description:停止定时器0
**********************************************************************/
void stop_time0(void)
{
    TCCR0 = 0x00; //stop
    
    gTmr0OvrCount = 0;  
}


/**********************************************************************
functionName:void start_timer2(void)
description:定时器2初始化
            desired value: 20mSec
			actual value:  19.861mSec (0.7%)
**********************************************************************/
void start_timer2(uint _20ms)
{
    TCCR2 = 0x00;       //stop
	ASSR  = 0x00;       //set async mode
    TCNT2 = 0x71;
	
	TIMSK |= 0x40;      // 定时器2溢出中断
	OCR2  = 0x8F;       // 定时器比较值
	
	gTmr2OvrCount = _20ms;
	
	TCCR2 = 0x07;	  	// Count clock/1024, start Timer0
}

/**********************************************************************
functionName:void stop_time2(void)
description:停止定时器2
**********************************************************************/
void stop_time2(void)
{
    TCCR0 = 0x00; //stop
    	
    gTmr2OvrCount = 0;  
}













/**********************************************************************
functionName:void main(void)
description:主函数
**********************************************************************/
void main(void)
{
	  uchar counter;
      char  tempbuf[5];
	  
	  //键盘
	  uchar cKeyCode = 0;	  
	  uchar OpCardOk = 0;
	  uint leftMoney = 0;
	  uchar statusOfIC = 0;
      uchar cardserialno[4];
	  //从M41T0器件中读取的当前时间信息
	  uchar M41T0Data[8];
	  uchar CurrTimeInfo[12];
	  
	  //完整的一条消费信息字节
	  uchar szRecordInfoBytes[20];
      uchar blockdata[16];
	  
	  ///////////////////////////////////////////////////////////////////
	  //初始化硬件资源
	  all_init();
	  
	  //得到FLASH的历史数据页号和字节地址
	  GetHistoryPageAndBytesAddr(&gnHistoryFlashPage, &gnHistoryBytesBlock);
	  
      while(1)
      {			
	           ////////////////////////////////////////////////////////   
			   //当有用户选择用水模式时
			   if (cKeyRiseEvent == 1)
			   {  
			       //屏蔽int1、int0中断和UART中断,定时器Timer0,Timer2仍开始
				   DISINT01INT()
				   DISRXINT()
				   
				   //清除用水标记
			       cKeyRiseEvent = 0;
				   
				   //判断出出水模式
	               cKeyCode = Zlg7290_ReadKey();				   
				   
				   //启动定时器0,等待5秒内刷卡
				   start_timer0(2000);
				   
				   //若超时
				   while (gTmr0OvrCount>0)
				   {		          	                                   
						        leftMoney = blockdata[0];
								leftMoney = leftMoney<<8+blockdata[1];
								
								if (leftMoney < 50) //蜂鸣器响2次
						        {
								   		SETBIT(PORTD,6);
								   		SoftDelay();//每次循环延时0.8秒
										CLRBIT(PORTD,6);
										
										SoftDelay();
										SETBIT(PORTD,6);
										
										SoftDelay();
										CLRBIT(PORTD,6);
										break;
								}
								
								//
							    leftMoney   -= 50;
		  	                    blockdata[0] = (uchar)((leftMoney&0xFF00)>>8);
								blockdata[1] = leftMoney&0xFF;
								
								//
								for (counter=0; counter<4; counter++)
						          szRecordInfoBytes[counter] = cardserialno[counter];							
								//2.>金额部分
								memcpy((void *)&szRecordInfoBytes[4], (void *)utoa(tempbuf/*暂存缓冲区*/, leftMoney, 10), 4);
								//3.>时间部分
								for (counter=0; counter<12; counter++)
								  szRecordInfoBytes[8+counter] = CurrTimeInfo[counter];
								
								//计算出当前消费的数据页和字节块号
								CalcNextPageAndBytesAddr(gnHistoryFlashPage, gnHistoryBytesBlock, 
														&gnCurrentFlashPage, &gnCurrentBytesBlock);	
								
								//先写入FLASH中,并确认已正确写入消费记录
								OpCardOk = CommitPaidSuccess(gnCurrentFlashPage, gnCurrentBytesBlock, 
										   				szRecordInfoBytes, 20);
							
								//若写入则成功,则产生下一个新页和字节块的地址,否则维持历史页和字节块地址
								if (OpCardOk == TRUE)
								{
									 //写入0页,记录已消费的记录和字节信息
									 WriteContextInfo(gnCurrentFlashPage, gnCurrentBytesBlock);
									 
									 //提前取出FLASH中记录的历史数据页号和字节地址,为新消费准备
	  						    	 GetHistoryPageAndBytesAddr(&gnHistoryFlashPage, &gnHistoryBytesBlock);
									 							 
									 SETBIT(PORTC, cKeyCode);
								}
								else  //写入操作失败,则蜂鸣器响3次
								{									 
								 	 SETBIT(PORTD,6);
								   	 SoftDelay();     //每次循环延时0.8秒
									 CLRBIT(PORTD,6);
									 
									 SoftDelay();									 
									 SETBIT(PORTD,6);
									 
									 SoftDelay();
									 CLRBIT(PORTD,6);
									 
									 SoftDelay();
									 SETBIT(PORTD,6);
									 
									 SoftDelay();
									 CLRBIT(PORTD,6);
								}
						 }//end of if
						 
						 //开启int1、int0中断和UART中断
						 ENINT01INT()
						 ENRXINT()
						 
						 //规定时间内完成当前操作模式,则退出操作卡限时						 
						 break;
				    }
					
					stop_time0();
			   }//end if while
			   
			   ///////////////////////////////////////////////////////
			   //1.当操作员要求读取FLASH内的消费记录时,开始传送数据,
			   //结束后操作员要复位重启。
			   //2.当操作员校定M41T0时间时,直接写I2C器件M41T0
			   if (gbRecvPCFrameCmd == 1)
			   {
			        gbRecvPCFrameCmd = 0;
					
					//读取Flash数据并上传命令
			   	  	
					
					//向M41T0写校定时间
					M41T0Data[0] = 0x12;
					M41T0_SendInfo(M41T0Data, 8);
			   }
			   
			   //读取M41T0时间
			   M41T0_ReadInfo(M41T0Data, 8);
			   CurrTimeInfo[0] = M41T0Data[0];
	   }
}     

/**********************************************************************
functionName:void int0_isr(void)
description:外部键盘中断0函数
**********************************************************************/
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
 	cKeyRiseEvent = 1;
}

/**********************************************************************
functionName:void int2_isr(void)
description:外部中断2函数
**********************************************************************/
#pragma interrupt_handler int2_isr:19
void int2_isr(void)
{}

/**********************************************************************
functionName:void timer0_ovf_isr(void)
description:定时器0溢出中断,20mSec
**********************************************************************/
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
 	TCNT0 = 0x71;   //溢出时,重新加载新值
	
	if (gTmr0OvrCount)
	  gTmr0OvrCount --;
}

/**********************************************************************
functionName:void timer0_ovf_isr(void)
description:定时器0比较中断
**********************************************************************/
#pragma interrupt_handler timer0_comp_isr:20
void timer0_comp_isr(void)
{}


/**********************************************************************
functionName:void timer2_ovf_isr(void)
description:定时器2溢出中断,500mSec
**********************************************************************/
#pragma interrupt_handler timer2_ovf_isr:10
void timer2_ovf_isr(void)
{
 	TCNT2 = 0x71;   //溢出时,重新加载新值
	
	if (gTmr2OvrCount)
	  gTmr2OvrCount --;
}

/**********************************************************************
functionName:void spi_stc_isr(void)
description:SPI中断函数
**********************************************************************/
#pragma interrupt_handler spi_stc_isr:11
void spi_stc_isr(void)
{}

/**********************************************************************
functionName:void uart0_rx_isr(void)
description:串口接受中断函数,完成上位机的回传全部消费记录数据
**********************************************************************/
#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr(void)
{
     //接收数据后清零RXC标记
	 UartRecvBuffer[UartRecvIndex++] = UDR;
	 if (UartRecvIndex >= RECVBUFFERLEN)
	 {
	     gbRecvPCFrameCmd   = 1;  //接收完整一桢数据标记
	     UartRecvIndex = 0;
     }
	 //RXC位清零	   	 
	 UCSRA  &= ~(1<<RXC);
}

/**********************************************************************
functionName:void uart0_tx_isr(void)
description:串口发送中断函数
**********************************************************************/
#pragma interrupt_handler uart0_tx_isr:14
void uart0_tx_isr(void)
{}

/**********************************************************************
functionName:void adc_isr(void)
description:ADC中断函数
**********************************************************************/
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{}

#pragma interrupt_handler twi_isr:18
void twi_isr(void)		//通信模式为主机发送和接收模式
{
    unsigned char status; 
    status = TWSR & 0xf8;
	
    switch(status) 
	{      
  	 case TW_START:                   //0x08: START 已发送 
  	 case TW_REP_START:               //0x10: 重复START 已发送
        i2cSendByte(I2cSendData[0]);  //开始传送从地址
        break;
     
	 // 主机发送模式,接收状态码	 
     case TW_MT_SLA_ACK:              //0x18: SLA+W 已发送;接收到从机ACK	 	  
     case TW_MT_DATA_ACK:             //0x28: 数据已发送;接收到从机ACK        
   	 	if(I2cSendDataIndex < I2cSendDataLength) 
		{ 
		    gbi2cSendByteStatus  = TRUE;
            i2cSendByte(I2cSendData[1+I2cSendDataIndex] );
			I2cSendDataIndex++; 
        }
		else
		{
             i2cSendStop();
        }
        break;
		
	 
     case TW_MTR_ARB_LOST:             //0x38: SLA+W 或数据的仲裁失败  
        gbi2cSendCmdStatus = FALSE;
        TWCR = (TWCR&0x0F)|(1<<TWINT); // 释放总线
        break;	 
	 
	 
	 // 主机接收模式时的状态码
     case TW_MR_DATA_NACK:            //0x58: 主机接收到从机数据;主机未给从机ACK        
        // 保存数据
        I2cReceiveData[I2cReceiveDataIndex++] = TWDR; 
        //继续发送条件
	 case TW_MR_SLA_NACK:             //0x48: 主机已发送SLA+R,主机未接收到从机ACK
	 case TW_MT_SLA_NACK:             //0x20: SLA+W 已发送,未接收到从机ACK
     case TW_MT_DATA_NACK:            //0x30: 数据已发送,未接收从机ACK
	    gbi2cSendCmdStatus = FALSE;    
        // 发送停止条件
        i2cSendStop(); 
        break; 
	 
	 
     case TW_MR_DATA_ACK:             //0x50: 主机接收到从机数据,主机已给从机ACK信号
	    gbi2cRecvByteStatus  = TRUE;    
        // 保存接收到的数据位
        I2cReceiveData[I2cReceiveDataIndex++] = TWDR;
		
        // 检查是否接收完
		//if(I2cReceiveDataIndex < (I2cReceiveDataLength-1)) 
           // 数据位将接收 , 回复 ACK (传送更多字节) 
           //i2cAckSignal(TRUE);
        //else
		if(I2cReceiveDataIndex >= I2cReceiveDataLength )           
		   { // 数据位将接收 , 主机先回复 从机NACK (传送最后字节)
             i2cAckSignal(FALSE);
		     // 主机再发送停止条件
		     i2cSendStop();
		   }
	  case TW_MR_SLA_ACK:              //0x40: 主机已发送SLA+R,从机已ACK,主机准备接收数据
	     break;    
	}	
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -