/****************************************/
/* 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);