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

📄 znjh.c

📁 1.atmegal 16单片机程序。编译环境为codevisionAVR C, 1)单总线方式采集温湿度。 2)A/D转换 3)屏幕显示和LED灯闪烁。 4)按键控制
💻 C
📖 第 1 页 / 共 4 页
字号:
//修改纪录:
//2008.5.8  1、增加复位ETR186的功能。复位来源:
//                     1).定时监测串口。如果5分钟内收不到消息,则复位186CPU.
//                     2).ETR186通过串口发复位消息过来。
//             复位时,会点亮复位灯。一分钟后熄灭。
//          2、增加看门狗功能。2秒内复位
//          3、收到串口通信信息会闪亮通信指示灯 


#include <stdio.h>
#include <mega16.h>
#include <string.h>
#include <delay.h>
#include <stdlib.h>

#define FUNC_DATE
#define FUNC_SETUP

#define OUT 1
#define IN 0

#define INTER 0
#define OUTER 1


char str[80],tmpstr[40];
unsigned char errflag=0,errno;
unsigned char sample_flag=1;
unsigned long sample_interval=3600,sample_timer=0;
unsigned short readinterval=1; //读取传感器间隔

unsigned long UARTRecvCount;


#define SIZE_OF_INBUF 100
#define SIZE_OF_OUTBUF 100
unsigned char inbuf[SIZE_OF_INBUF];
unsigned short inhead=0,intail=0;
unsigned char outbuf[SIZE_OF_OUTBUF];
unsigned short outhead=0,outtail=0;
unsigned long recvnum=0,procnum=0;

unsigned char recvtime=0;
unsigned long recvtime_timer=0;

unsigned char nMaintainFlag = 0;
unsigned long nLastAirConEndTime=0;



void keyfunc(void);
//unsigned char UARTSendChar(unsigned char cChar);
void put_buf(char *msg);
//void proc_send(void);
void ProcessTempDevice(unsigned int nWind,unsigned int nLetDown,unsigned int nRise);
void ProcessHumiDevice(unsigned int nAddHumi,unsigned int nClearHumi);
void GetErrorState(unsigned char errno);
int ReadADCTempHumi(float *wd,float *sd);
void InitADC(void);
void SetCalibration(void);  //调整时钟


//通信命令
#define COM_OprFlow 100  //send
#define COM_Alarm 101    //send
#define COM_UpdData 102  //send,recv
#define COM_GetData 103   //recv
#define COM_GetDataResp 104   //send
#define COM_StartSample 105   //recv
#define COM_SendSample  106   //send
#define COM_EndSample   107   //recv
#define COM_GetStatus   108    //recv
#define COM_GetStatusResp 109   //send
#define COM_SendClock 110       //recv
#define COM_GetClock 111        //recv
#define COM_GetClockResp 112    //send
#define COM_AdjustClock 113     //send
#define COM_AdjustClockRsp 114   //recv
#define COM_SetDevice 115       //recv
#define COM_SetAlarmCondition 116 //recv
#define COM_GetAlarmCondition 117 //recv
#define COM_GetAlarmConditionResp 118 //send
#define COM_ReadSensorInterval    119 //recv


#define COM_ResetEtr186  120    //复位ETR186
#define COM_LinkMsg   121       //定时通信信息 


#define COM_UpdTel 150   //recv
#define COM_SendError 151
#define COM_SendResp  152

#define COM_RespOK 500
#define COM_RespError 400



//------------------------------定时器中断--------------------------------------------
                      
// bit definitions for the TIMSK register (定时器/计数器中断屏蔽寄存器)
#define TOIE0 0           //Timer/Counter0 Overflow Interrupt Enable,bit 0
#define OCIE0 1           //Timer/Counter0 Output Compare Match Interrupt Enable,bit 1
#define AS0 3         

//Timer/Counter Control Register - TCCR0
//bit7  6      5     4     3     2    1   0
//FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00      
//Bit 2:0 - CS02:0: Clock Select
/*----------------------------------
CS02 CS01 CS00 Description
  0   0    0       No clock source (Timer/counter stopped)
  0   0    1       clkT0S/(No prescaling)
  0   1    0       clkT0S/8 (From prescaler)
  0   1    1       clkT0S/32 (From prescaler)
  1   0    0       clkT0S/256 (From prescaler)
  1   0    1       clkT0S/1024 (From prescaler)
  1   1    0       
  1   1    1       
----------------------------------*/          

//ASSR: Asynchronous Status Register
//  Bit  7 6 5 4  3    2       1     0
//       - - - - AS0 TCN0UB OCR0UB TCR0UB
//AS0位: Asynchronous Timer/Counter0
//When AS0 is written to zero, Timer/Counter0 is clocked from the I/O clock, clkI/O. When
//AS0 is written to one, Timer/Counter 0 is clocked from a crystal oscillator connected to
//the Timer Oscillator 1 (TOSC1) pin. When the value of AS0 is changed, the contents of
//TCNT0, OCR0, and TCCR0 might be corrupted.
                                           


//初始化定时器/计数器0中断

void InitTimer0(void)
{
    TIMSK &= ~((1<<TOIE0)|(1<<OCIE0));     //Disable TC0 interrupt
    ASSR &= ~(1<<AS0);           //选择时钟源,AS0位等于0,set Timer/Counter0 to be synchronous from the I/0 clock 
                                
    TCNT0 = 0x00;//f0;//0x00;
    //TCCR0 = 0x05;        //prescale the timer to be clock source / 1024 to make it
	                     //如果晶振是8M,则溢出中断的时间大概为 1秒*256/(8000000/1024)=32.768毫秒
	                     //如果晶振是4M,则溢出中断的时间大概为 1秒*256/(4000000/1024)=65.536毫秒
	TCCR0 = 0x04;        //如果晶振是1M,则溢出中断的时间大概为 1秒*256/(1000000/256)=65.536毫秒
                         //如果晶振是11.0592M(外接),则溢出中断的时间大概为 1秒*256/(11059200/1024)=23.7037毫秒=640/27


                         //exactly 1 second for every overflow to occur

    while(ASSR&0x07);      //Wait for TCN0UB=0, OCR0UB=0, and TCR0UB=0. Wait until TC0 is updated
    TIMSK |= (1<<TOIE0);    //set 8-bit Timer/Counter0 Overflow Interrupt Enable        
    //设置状态寄存器中断位
    SREG |= 0x80;
}

//////////////
//#ifdef FUNC_DATE
typedef struct{ 
	unsigned char second;   //enter the current time, date, month, and year
	unsigned char minute;
	unsigned char hour;                                     
	unsigned char date;       
	unsigned char month;
	unsigned int year;
} time;
time t;     

char not_leap(void)      //check for leap year
{
    if (!(t.year%100))
        return (char)(t.year%400);
    else
        return (char)(t.year%4);
}         
//#endif

//65.536毫秒中断一次
unsigned long nSecondCount;
unsigned long n100msCount;
unsigned char nMsFlag;
unsigned char nSeFlag;
                                  

unsigned char nHopFlag;
interrupt [TIM0_OVF] void counter(void) //overflow interrupt vector
{ 
	static unsigned short count1=0;
	static unsigned short count2=0;
                  
    if ( ++count1 == 2 ) {
        n100msCount++;
        count1 = 0;
        nMsFlag = 1;
    }
	
	++count2;
	
	if ( (t.second+1)%2 == 0 ) {         //用于内部晶振4M和1M
		if ( count2 != 16 ) return; //秒
		nHopFlag = 1;
	} else {		
		if ( count2 != 15 ) return; //秒
		nHopFlag = 0;
	}

	//if ( count2 != 42 ) return; //秒   //用于晶振为11.0592MHZ


	nSecondCount++;
    count2 = 0;
	nSeFlag = 1;

//#ifdef FUNC_DATE
    if (++t.second>=60) {         //keep track of time, date, month, and year    
        t.second=0;
        if (++t.minute>=60) {
            t.minute=0;
            if (++t.hour>=24) {
                t.hour=0;
                if (++t.date>=32) {
                    t.month++;
                    t.date=1;
                } else if (t.date>=31) {                    
                    if ((t.month==4) || (t.month==6) || (t.month==9) || (t.month==11)) {
                        t.month++;
                        t.date=1;
                    }
                } else if (t.date>=30) {
                    if(t.month==2) {
                       t.month++;
                       t.date=1;
                    }
                } else if (t.date>=29) {
                    if((t.month==2) && (not_leap())) {
                        t.month++;
                        t.date=1;
                    }                
                }                          
                if (t.month>=13) {
                    t.month=1;
                    t.year++;
                }
            }
        }
    }  
//#endif
}  
 
//------------------------------定时器中断--------------------------------------------



//------------------------------LCD---------------------------------------------------
//;位定义

//   SID BIT P1.0 ;串行数据线
//   SCLK BIT P1.1 ;串行时钟线
#define SID PORTC.1 
#define SLCK PORTC.6
//#define CS   PORTC.0
#define SID_DDR DDRC.1 
#define SLCK_DDR DDRC.6
//#define CS_DDR   DDRC.0



//;内存数据定义
//	START EQU 30H ;起始字节
//	COM EQU 31H ;命令/数据
//	HDATA EQU 32H ;命令/数据字节高位
//	LDATA EQU 33H ;命令/数据字节低位
//	ASC EQU 34H ;ASCII数据单元

#define START 0x30
#define COM 0x31
#define HDATA 0x32
#define LDATA 0x33
#define ASC 0x34


//初始化子程序:
//串行字节数据发送子程序:
void lcd_sendbyte(unsigned char code)
{    
//	SENDBYTE:
//	   MOV R7,#08H ;发送8位

//LOOP1:
//     RLC A
//     MOV SID,C ;数据送数据线
//	   CLR SCLK ;产生同步时钟
//	   SETB SCLK
//	   DJNZ R7,LOOP1 ;未发送完8位继续
//	   RET
	int i;
	unsigned char ch;

    //CS = 1;
	for(i=0;i<8;i++) {
		ch = code << i;
		ch &= 0x80;
		if ( ch ) SID = 1;
		else SID = 0;
		//delay_us(1);
		SLCK = 1;  
		delay_us(1000);//delay_ms(1); //delay_us(1);		测使用2004.8.4
		SLCK = 0;
		delay_us(1000);//delay_ms(1); //delay_us(1);		测使用2004.8.4
		//SID = 0;
		//delay_us(1);
	}
	//CS = 0;

}

void lcd_write(unsigned char startbyte,unsigned char ch);
void lcd_init(void)
{
//INILCM:
//	LCALL DL40MS ;延时等待内部复位
//	delay_ms(40);
//  MOV COM,#30H ;使用8位控制界面
//  LCALL WRITE
//	MOV COM,#30H ;使用基本指令集
//	LCALL WRITE
//	MOV COM,#0CH
//	LCALL WRITE ;整体显示ON
//	MOV DL1MS
//	MOV COM,#01H ;清屏
//	LCALL WRITE
//	LCALL DL40MS
//	MOV COM,#06H ;显示右移
//	LCALL WRITE
//  LCALL DL1MS
//	RET

	SID_DDR = OUT;
    SLCK_DDR = OUT;
    //CS_DDR = OUT;

	//CS = 0;  //低电平无效
	SLCK = 0;
	SID = 0;

	delay_ms(40);
	lcd_write(0xf8,0x30); //设基本指令集动作
	delay_us(1000);//delay_ms(1);
	lcd_write(0xf8,0x0c); //设整体显示On
	delay_us(1000);//delay_ms(1);
	lcd_write(0xf8,0x01); //清屏
	delay_us(1000);//delay_ms(1);
	lcd_write(0xf8,0x06); //显示右移
	delay_us(1000);//delay_ms(1);
}


void lcd_DisplayCursor(void)
{
    lcd_write(0xf8,0x0e); //设整体显示On
	delay_us(1000);//delay_ms(1);
}

void lcd_CloseCursor(void)
{
	lcd_write(0xf8,0x0c); //设整体显示On
    delay_us(1000);//delay_ms(1);
}

//模块写入子程序:
//WRITE:
void lcd_write(unsigned char startbyte,unsigned char ch)
{
	unsigned char code;
	//MOV A,COM ;送待发数据命令A
	//MOV A,#0F0H ;屏蔽低4位
	//MOV HDATA,A ;将高4位送HDATA单元
	//MOV A,COM ;取低4位
	//SWAP A ;高低4位互换
	//MOV A,#0F0H
	//MOV LDATA,A ;将低4位送LDATA单元

	//MOV A,START ;取起始字节
	//LCALL SENDBYTE ;发送
	//LCALL DL1MS ;延时1ms
	//MOV A,HDATA
	//LCALL SENDBYTE
	//LCALL DL1MS
	//MOV A,LDATA
	//LCALL SENDBYTE
	//LCALL DL1MS
	//RET
   	
	lcd_sendbyte(startbyte); //送起始字节
	delay_us(1000);//delay_ms(1);
	code = ch & 0xf0;   
    lcd_sendbyte(code); //送字符高字节
    delay_us(1000);//delay_ms(1);
	code = ch & 0x0f;
	code <<= 4;
	lcd_sendbyte(code); //送字符低字节
	delay_us(1000);//delay_ms(1);
}

void clearscreen(void)
{
	lcd_write(0xf8,0x01); //清屏
	delay_us(1000);//delay_ms(1);
}


//显示汉字子程序:
void lcd_str(/*unsigned int x,*/unsigned int y,char *string)
{
// x为水平位置, 取值0-7
// y为竖向位置, 取值0-3

//HZDISP:
//	MOV START,#0F08H 写入命令 (应该是#f8h?)
//	MOV COM,#80H 设定显示位置 (位置为0)
//	LCALL WRITE
//	MOV DPTR,#TABLE 指向文字型代码表
//	MOV A,#00H 取汉字代码低位
//	LOOP2:MOVC A,A+@DPTR
//	CJNE A,#0,DISP ;遇“0”结束显示
//	RET 写完一行则结束

//DISP:
//	MOV START,#0FAH ;写数据
//	MOV COM,A
//	LCALL WRITE ;写入显示模块
//	INC DPTR ;取汉字代码高位
//	AJMP LOOP2 ;未显示完则继续

//TABLE:
//  DB“中文图形点阵”,0;汉字代码表
//	DB“液晶显示模块”,0;

    unsigned int pos;
	int i,len;
    unsigned char ch;
	
	if ( y == 1 ) pos = 0x80+2*8;
	else if ( y == 2 ) pos = 0x80+1*8;
	else pos = 0x80+ y*8;//+x+y*8;
    lcd_write(0xf8,pos); //设定显示位置
	len = strlen(string);
	for(i=0;i<16;i++)
		if ( i<len ) {
			ch = string[i];
			lcd_write(0xfa,string[i]);
		}
		else lcd_write(0xfa,' ');
}




//运行状态指示灯
#define __runled_port PORTD.6
#define __runled_ddr  DDRD.6
/*
void runled_init(void)
{
	__runled_ddr = OUT; //输出
	__runled_port = 1; //低电平,不亮
}
*/
void runled_opr(unsigned char flag)
{
	__runled_ddr =	OUT;
	if ( flag == 0 ) __runled_port = 0;
	else __runled_port = 1;
}

//PB5,告警复位指示灯
void SetOnResetLed(void)
{
	DDRB.5 = OUT;
	PORTB.5 = 1;
}
void SetOffResetLed(void)
{
	DDRB.5 = OUT;
	PORTB.5 = 0;
}

//PB6,收到串口信息指示灯
void SetOnComLed(void)
{
	DDRB.6 = OUT;
	PORTB.6 = 1;
}
void SetOffComLed(void)
{
	DDRB.6 = OUT;
	PORTB.6 = 0;
}


//PB5,PB6是另外两个灯,现没用
#define __errled_port PORTB.7
#define __errled_ddr  DDRB.7

//------------------------------运行状态指示灯-----------------------------------------------


float T_out=0,T_in=0;
//float T_ref,TH_ref,TL_ref,TDualOn_ref;

float H_out=0,H_in=0;
//float H_ref,HLow_ref,HHigh_ref;

      
void FloatToStr(float f,char *str2)
{
	int a,b;

	a = f;
	b = (f*10);
	if ( b<0 ) b = 0-b;
	b %= 10;
	sprintf(str2,"%d.%d",a,b);
}


void DisplayTemp(float wd,float sd,unsigned char flag)
{
	int a,b,c,d;	

	//显示第一条
	a = wd;
	wd *= 10;	
	b = wd;
	if ( b<0 ) b = 0-b;
	b = b % 10;
	//sprintf(str,"室内:%d.%d",a,b);
	//lcd_str(0,str);

	c = sd;
	sd *= 10;
	d = sd;
	if ( d<0 ) d = 0-d;
	d = d % 10;

⌨️ 快捷键说明

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