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

📄 monitor.c

📁 51单片机C语言常用模块与综合系统设计实例精讲
💻 C
字号:
/****************************************/
/* Copyright (c) 2004, 通信工程学院     */
/* All rights reserved.                 */                   
/****************************************/

#include <at898252.h>
#include "vehicle.h"

#define LIMIT 60
#define uint unsigned int
#define uchar unsigned char

#define CSA P2_1
#define CSB P2_0
#define DI P2_6
#define RW P2_5

sbit uip_bit=ACC^7;//ds12c887 register a bit 7
sbit busy_bit=ACC^7;//lcd state byte bit 7
sbit run_bit=P3^3; 

uchar timer0_flag=0;
uchar int0_flag=0;
uchar active_buffer=1;

uint page_counter=0;
uint buffer_counter=0;
//uchar active_buffer=1;
uchar circle=0;
uchar time_counter=0;
uchar year,month,day,hour,min,sec;
unsigned long ttcy=0;

//delay 100ms,should be adjusted for frequency and compile
void dl_100ms(void)
{
	unsigned char i,j;
	for (i=10;i>0;i--) for (j=0;j<250;j++) ; 
}

/*下面是对液晶屏gxm12864d操作的函数,其内置的控制器是hd61202,
  128x64点阵,汉字显示,CSA,CSB用来进行左右显示区的选择。
  R/W,D/I两个信号我没有接在地址线上,而是用单独的端口控制,
  数据访问通过对外部数据区的0xffff访问实现。E信号由地址译码产生
*/

/*  发命令i到主窗口*/
void lcd_mwc(uchar i)
{
     CSA=1;
     CSB=0;
     RW=1;
     DI=0;
     do {ACC=LCD;} 
	 while (busy_bit) ;//wait for lcd not busy
     RW=0;
     LCD=i;
}

/*  写数据i到主窗口*/
void lcd_mwd(uchar i)
{
     CSA=1;
     CSB=0;
     RW=1;
     DI=0;
     do {ACC=LCD;} while (busy_bit);//wait for lcd not busy
     RW=0;
     DI=1;
     LCD=i;
}

/*   清屏                                */
void lcd_clear(void)
{
     uchar i;
     uchar page;
     for (page=0xb8;page<0xc0;page++)
         {
             lcd_mwc(page);       /*设置显示页面*/

             lcd_mwc(0x40);          /*设置列地址*/
 
             for (i=0;i<64;i++)
             {
   
                 lcd_mwd(0);
             }
         }
}

//初始化lcd
void lcd_init(void)
{
	lcd_mwc(0xc0);

	lcd_mwc(0x3f);

}

//dispm_hz_up() display up half of a hanzi in left area
void dispm_hz_up(uchar code * hz)
{
	uchar i;
	for (i=0;i<16;i++) lcd_mwd(*(hz+i));
}

//dispm_hz_down() display down half of a hanzi in left area
void dispm_hz_down(uchar code * hz)
{
	uchar i;
	for (i=16;i<32;i++) lcd_mwd(*(hz+i));
}

void disp_num(uchar i)
{
	uchar j;
	for (j=0;j<8;j++) lcd_mwd(ARAB[j+i*8]);
}


/*set mcu counter0 as 5s timer,clk is 500ms*/

void set_5s_counter(void)
{
	TMOD=0x16;//counter0 mode 2 
	TH0=-10;
	TL0=-10;
	IP=0x01;//int0 high,counter0 low
	IT0=1;
	EA=1;//enable interrupt
	ET0=1;
	EX0=1;
	TR0=1;
}

/*下面是对flash存储卡at45d041的操作,数据接口为spi接口,
  卡共2048页,每页264字节
*/

void write_spi(uchar dat)
{
       SPDR = dat;
       while (!(SPSR & 0x80)) ;             // wait for data transfer to be completed
}

uchar df_busy(void)
{
    P1 &= ~DF_CHIP_SELECT;               // enable DataFlash
    
   write_spi(STAT_REG_READ);
   write_spi(0x00);                       // don't cares
   
   P1 |= DF_CHIP_SELECT;                // disable DataFlash 
   return SPDR;
}

//write_to_flash write data to buffer,if buffer is full write buffer to memory page
void write_to_flash(uchar flash_data)
{ 
    //  checking if flash is busy
    while (!(df_busy()&0x80)) ;
    P1 &= ~DF_CHIP_SELECT;               // enable DataFlash
     
    if (active_buffer==1) write_spi(BUFFER_1_WRITE);
    else write_spi(BUFFER_2_WRITE);
    write_spi(0x00);                       // don't cares
    write_spi((uchar)(buffer_counter>>8)); // don't cares plus first bit of buffer address
    write_spi((uchar)buffer_counter);      // buffer address 
    write_spi(flash_data);                   // write data into SPI Data Register
        
    P1 |= DF_CHIP_SELECT;                // disable DataFlash 
    
    buffer_counter++; 
        
    if (buffer_counter > 263)               // if buffer full write buffer into memory page
    {
        buffer_counter = 0;
        if (page_counter < 2047)            // if memory is not full   
        { 
            P1 &= ~DF_CHIP_SELECT;       // enable DataFlash

            if (active_buffer==1) write_spi(B1_TO_MM_PAGE_PROG_WITHOUT_ERASE);// write data from buffer1 to page 
            else write_spi(B2_TO_MM_PAGE_PROG_WITHOUT_ERASE);//write data from buffer2 to page
            write_spi((uchar)(page_counter>>7));
            write_spi((uchar)(page_counter<<1));
            write_spi(0x00);                    // don't cares
        
            P1 |= DF_CHIP_SELECT;        // disable DataFlash
            page_counter++;              //page_counter 指向下一可用页
        }
        if (active_buffer==1) active_buffer=0;
        else active_buffer=1;
    }  
}

uchar cardin(void)
{
	SPCR=0x5d;//interrupt disabled,spi enabled,master,msb first,spi mode 3,Fosc/16
	
	P1 &= ~DF_CHIP_SELECT;               // enable DataFlash
	
	write_spi(MAIN_MEMORY_PAGE_READ) ;
	write_spi(0x00) ;
	write_spi(0x00) ;
	write_spi(0x00) ;
	write_spi(0x00) ;
	write_spi(0x00) ;
	write_spi(0x00) ;
	write_spi(0x00) ;
	write_spi(0xff) ;//write dummy value to start register shift
	
	P1 |= DF_CHIP_SELECT ;//disable flash card
	return SPDR;
}

/*下面是对日历时钟芯片ds12c887的部分操作,芯片初始化的操作在settime.c中实现*/

//getlstpage()从DS12C887中读取最近可用页地址
uint getcurpage(void)
{
	uchar i=0;
	uint j=0;
	i=TIME_LSTPGH;
	j=i+j;//maybe wrong
	i=TIME_LSTPGL;
	j=j<<8;
	j=j+i;
	return j;
}

//getfrnpg()从DS12C887中读取最近可用的存放终止页地址的页地址
uint getfrnpg(void)
{
	uchar i=0;
	uint j=0;
	i=TIME_FRNPGH;
	j+=i;
	i=TIME_FRNPGL;
	j=j<<8;
	j+=i;
	return j;
}

//storetime() read time from ds12887 then store in flash card
void storetime(void)
{
//	uchar year,month,day,hour,min,sec;
	do {ACC=TIME_A;} while (uip_bit) ;//wait for UIP bit turn 0
	sec=TIME_SEC;
	min=TIME_MIN;
	hour=TIME_HOUR;
	day=TIME_DAY;
	month=TIME_MONTH;
	year=TIME_YEAR;
	write_to_flash(year);
	write_to_flash(month);
	write_to_flash(day);
	write_to_flash(hour);
	write_to_flash(min);
	write_to_flash(sec);
}

/*下面是键盘扫描和给键赋值的操作*/

//keyscan() scan keyboard and return key code
uchar keyscan(void)	
{
	uchar sccode,recode;
	P2=0x78;
	if ((P2&0x78)!=0x78)
	{
		dl_100ms();
		if ((P2&0x78)!=0x78)
		{
			sccode=0xfe;
			while ((sccode&0x08)!=0)
			{
				P2=sccode;
				if((P2&0x78)!=0x78)
				{
					recode=(P2&0x78)|0x87;
					return ((~sccode)+(~recode));
				}
				else sccode=(sccode<<1)|0x01;
			}
		}
	}
	return (0);
}


//getkey() translate key code to number ,return keyboard input number
uint getkey(void)
{
	uchar num1=0;
	uint num2=0;
	while (num1!=0x44)
	{
		num1=keyscan();
		switch(num1)
		{
			case 0x09:
				num1=0;
				num2=num2*10;
				disp_num(num1);
				break;
			case 0x11:
				num1=1;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x21:
				num1=2;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x41:
				num1=3;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x0a:
				num1=4;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x12:
				num1=5;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x22:
				num1=6;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x42:
				num1=7;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x0c:
				num1=8;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x14:
				num1=9;
				num2=num2*10+num1;
				disp_num(num1);
				break;
			case 0x24:
				num1=0;
				num2=0;
				lcd_mwc(0xba);
				lcd_mwc(0x40);
				for (num1=0;num1<8;num1++) disp_num(10);
				lcd_mwc(0xba);
				lcd_mwc(0x40);
				break;
			case 0x44:
				lcd_mwc(0xba);
				lcd_mwc(0x40);
				for (num1=0;num1<8;num1++) disp_num(10);
				lcd_mwc(0xba);
				lcd_mwc(0x40);
				break;
		}
	}
	return(num2);
}

/*两个中断处理函数*/

void timer0(void) interrupt 1 using 1
{
	EA=0;//diable interrupt
	time_counter++;
	P3_5=0;//enable cpld
	circle=P0;
	P3_5=1;
	ttcy+=circle;
	timer0_flag=1;
	EA=1;
}


void int0(void) interrupt 0 using 2
{
	EA=0;
	WMCON=WMCON&0xfe;
	int0_flag=1;
}

void main(void)
{
	uint a;
	uchar m,n,l;
	for (m=0;m<200;m++) for (n=0;n<250;n++) ; //delay 200ms,should be adjusted to be not less then 200ms
				//in order to wait peripheral to be ready

	P3_0=0;//turn alarm off
	P3_5=1;//diable cpld output
	P3_2=1;//ready for int0
	buffer_counter=6;
	
	lcd_clear();
	lcd_init();

	lcd_mwc(0xb8);
	lcd_mwc(0x40);
	dispm_hz_up(&QING);
	dispm_hz_up(&CHA);
	dispm_hz_up(&KA);
	lcd_mwc(0xb9);
	lcd_mwc(0x40);
	dispm_hz_down(&QING);
	dispm_hz_down(&CHA);
	dispm_hz_down(&KA);//display "请插卡"
	
	P1=0xff;
	while (cardin()&0xa0) ;//这个地方,用什么来表示已经插卡需要商量。
	
	page_counter=getcurpage();
	
	lcd_mwc(0xb8);
	lcd_mwc(0x50);
//	dispm_hz_up(&QING);
	dispm_hz_up(&SHU);
	dispm_hz_up(&CHE);
	dispm_hz_up(&HAO);
	lcd_mwc(0xb9);
	lcd_mwc(0x50);
//	dispm_hz_down(&QING);
	dispm_hz_down(&SHU);
	dispm_hz_down(&CHE);
	dispm_hz_down(&HAO);//display "请输车号"
	
	lcd_mwc(0xba);
	lcd_mwc(0x40);
	a=getkey();
	write_to_flash((uchar)(a>>8));
	write_to_flash((uchar)a);//store 车号
	
	lcd_mwc(0xb8);
	lcd_mwc(0x60);
//	dispm_hz_up(&QING);
//	dispm_hz_up(&SHU);
	dispm_hz_up(&ZHAN);
//	dispm_hz_up(&HAO);
	lcd_mwc(0xb9);
	lcd_mwc(0x60);
//	dispm_hz_down(&QING);
//	dispm_hz_down(&SHU);
	dispm_hz_down(&ZHAN);
//	dispm_hz_down(&HAO);//display "请输站号"
	
	lcd_mwc(0xba);
	lcd_mwc(0x40);
	a=getkey();
	write_to_flash((uchar)(a>>8));
	write_to_flash((uchar)a);//store 站号
	
//	buffer_counter=0;
	
	set_5s_counter();
	
	lcd_mwc(0xb8);
	lcd_mwc(0x40);
	dispm_hz_up(&SU);
	dispm_hz_up(&DU);
	lcd_mwc(0xb9);
	lcd_mwc(0x40);
	dispm_hz_down(&SU);
	dispm_hz_down(&DU);//display "速度"
	
	lcd_mwc(0xbc);
	lcd_mwc(0x40);
	dispm_hz_up(&LI);
	dispm_hz_up(&CHENG);
	lcd_mwc(0xbd);
	lcd_mwc(0x40);
	dispm_hz_down(&LI);
	dispm_hz_down(&CHENG);//display "里程"
	
	
	
	while (!run_bit) ;//wait for vehicle move
	storetime();
	buffer_counter=10;
	
	WMCON=0xe0;//2.048s watchdog timer
	WMCON=WMCON|0x01;//enable watchdog
	
	while (1)//sycling wait
	{
		for (m=0;m<250;m++) for (n=0;n<250;n++) ;
		for (m=0;m<250;m++) for (n=0;n<250;n++) ;//should be adjusted for 500ms delay
		WMCON=WMCON|0x02;//reset watchdog
		
		if (circle>LIMIT) P3_0=1;
		else P3_0=0;//if overspeed then alarm
		
		if (timer0_flag==1) 
		{
			write_to_flash(circle);
			timer0_flag=0;
		}

		WMCON=WMCON|0x02;//reset watchdog		
		if (time_counter>=120)//if 10 min,show speed and distance
		{
			time_counter=0;
			m=36*circle/35;
			n=m/100;
			
			lcd_mwc(0xba);
			lcd_mwc(0x40);
			disp_num(n);
			
			l=(m-n*100)/10;
			disp_num(l);
			
			disp_num(m-n*100-l*10);
			disp_num(11);
			
			n=(36*circle-35*m)*10/35;
			disp_num(n);//以上计算速度并显示
			
			a=ttcy/700;
			m=a/100;
			
			lcd_mwc(0xbd);
			lcd_mwc(0x40);
			disp_num(m);
			n=(a-m*100)/10;
			disp_num(n);
			disp_num(a-m*100-n*10);
			disp_num(11);
			m=(ttcy-700*a)*10/700;
			disp_num(m);//以上计算并显示里程
		}

		WMCON=WMCON|0x02;//reset watchdog

		if (int0_flag==1) 
		{
			write_to_flash(0xf0);
			write_to_flash(0xf1);
			storetime();
			
			lcd_clear();
			lcd_init();
			lcd_mwc(0xb8);
			lcd_mwc(0x40);
			dispm_hz_up(&QING);
			dispm_hz_up(&SHU);
			dispm_hz_up(&ZHAN);
			dispm_hz_up(&HAO);
			lcd_mwc(0xb9);
			lcd_mwc(0x40);
			dispm_hz_down(&QING);
			dispm_hz_down(&SHU);
			dispm_hz_down(&ZHAN);
			dispm_hz_down(&HAO);//display "请输站号"
			
			lcd_mwc(0xba);
			lcd_mwc(0x40);
			a=getkey();
			write_to_flash((uchar)(a>>8));
			write_to_flash((uchar)a);//store 站号
			
			if (buffer_counter!=0)
			{
				while (!(df_busy()&0x80)) ;
				P1 &= ~DF_CHIP_SELECT;               // enable DataFlash
     
				if (active_buffer==1) write_spi(B1_TO_MM_PAGE_PROG_WITHOUT_ERASE);
				else write_spi(B2_TO_MM_PAGE_PROG_WITHOUT_ERASE);
				write_spi(0x00);                       // don't cares
				write_spi((uchar)(page_counter>>7)); // don't cares plus first 4 bits of page address
				write_spi((uchar)(page_counter<<1));      // page address 
				write_spi(0x00);                   // don't cares
				       
				P1 |= DF_CHIP_SELECT;                // disable DataFlash
				if (active_buffer==1) active_buffer=0;
				else active_buffer=1;
				buffer_counter=0;
			}
			
			
			a=getfrnpg();
			write_to_flash((uchar)(page_counter>>8));
			write_to_flash((uchar)page_counter);
			while (!(df_busy()&0x80)) ;
			P1 &= ~DF_CHIP_SELECT;               // enable DataFlash
     
			if (active_buffer==1) write_spi(B1_TO_MM_PAGE_PROG_WITHOUT_ERASE);
			else write_spi(B2_TO_MM_PAGE_PROG_WITHOUT_ERASE);
			write_spi(0x00);                       // don't cares
			write_spi((uchar)(a>>7)); // don't cares plus first 4 bits of page address
			write_spi((uchar)(a<<1));      // page address 
			write_spi(0x00);                   // don't cares
			   
			P1 |= DF_CHIP_SELECT;                // disable DataFlash				

            		page_counter++;
            		TIME_LSTPGH=(uchar)(page_counter>>8);
            		TIME_LSTPGL=(uchar)(page_counter);
            		a--;            		
            		TIME_FRNPGH=(uchar)(a>>8);
            		TIME_FRNPGL=(uchar)a;			
		}	
	}
}

⌨️ 快捷键说明

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