📄 znjh.c~
字号:
//修改纪录:
//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.5 = OUT;
PORTB.5 = 1;
}
void SetOffComLed(void)
{
DDRB.5 = OUT;
PORTB.5 = 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 + -