📄 function.c
字号:
#include <./Atmel/at89x52.h>
#include <stdio.h>
#include <absacc.h>
#include <intrins.h>
#include <string.h>
#include "source.h"
#define FSUCCESS 0
#define FERROR 1
#define FDOVER 2
bit TDBdata_over;
unsigned char dst_buf[DST_LEN];/*为数据传输口的发送缓冲区.*/
unsigned char dst_head; /*为目前要发送数据存储的位置*/
unsigned char dst_tail; /*为真正发送数据存储的位置,当head和tail相等时表明发送数据缓冲区无数据*/
unsigned char dsr_buf[DSR_LEN];/*接收数据缓冲区*/
unsigned char dsr_head; /*从串口接收到的数据存储的位置*/
unsigned char dsr_tail; /*从串口接收缓冲区读取数据的位置,当tail和head相等时间标兵接收缓冲区无数据*/
void delay_macnine_ncircle(unsigned char cnt){//11+6*cnt machin circle.
while(cnt--);
}
void delay_10us(unsigned char tus){/*在C51时钟的频率为18.432MHZ时,延时10微秒*/
tus--;
while(tus--){
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
}
void print_sbuf(unsigned char c){/*向串口发送缓冲区中写数据*/
dst_buf[dst_head]=c;
dst_head ++;
dst_head %=DST_LEN;
}
#define REPLAY_LEN 9
void reply_dwn(unsigned char flag,unsigned char *rbuf){/*rbuf 是下载的数据的指针,此函数是对下载的数据进行应答*/
unsigned char reply[REPLAY_LEN];
struct yushi rply_crc;
unsigned char i;
reply[0]=FDWN_FHD;
reply[1]=flag;
reply[2]=rbuf[2];
reply[3]=rbuf[3];
reply[4]=rbuf[4];
reply[5]=0x00;
reply[6]=0x00;
init_crccheck(&rply_crc);
for(i=0;i<7;i++){
crccheck(reply[i],&rply_crc);
}
reply[7]=rply_crc.h;
reply[8]=rply_crc.l;
for(i=0;i<REPLAY_LEN;i++){
print_sbuf(*(reply+i));
}
TI=1;
}
#define ERASE_SECTOR
void flash_download(void){/*数据下载,等在数据下载完毕后此函数才退出*/
union SFADD dwn_adres;
unsigned char fdata[FDWN_LEN];
unsigned char fsm_fdl;
unsigned char cnt;
unsigned char erase_sec=0;
unsigned int sector_section=0;
unsigned char temp;
struct yushi fcrc;
fsm_fdl=0;
while(1){/*进入死循环,只有计算机把所有的数据下载完毕才推出*/
if(dsr_tail!=dsr_head){/*串口接收缓冲区中有数据*/
if(fsm_fdl==0){/*串口接收在寻找帧头(0X7E)的状态*/
if(dsr_buf[dsr_tail]==FDWN_FHD){/*串口接收的数据是帧头*/
fsm_fdl=1;/*把串口接收的状态设置为接收数据*/
fdata[0]=FDWN_FHD;/*把接收到的字节存储在接收的数据中*/
cnt=1;
}
}
else if(fsm_fdl==1){/*串口的状态在接受数据状态*/
if(cnt<FDWN_LEN-1){/*135个字节的帧还没有接收完毕*/
fdata[cnt]=dsr_buf[dsr_tail];
cnt++;
}
else{/*一帧数据接收完毕*/
fdata[cnt]=dsr_buf[dsr_tail];
if(1){//mult_crccheck(fdata,FDWN_LEN,struct &fcrc)==0){/*由于串口出错的概率比较小,没有进行CRC效验*/
dwn_adres.c[1]=fdata[2];/*提取出要写到flash的地址字节*/
dwn_adres.c[2]=fdata[3];
dwn_adres.c[3]=fdata[4];
#ifdef ERASE_SECTOR
sector_section=dwn_adres.c[1];/*把地址字节转化为扇区地址*/
sector_section <<=8;
sector_section &=0xff00;
sector_section |=dwn_adres.c[2];
sector_section >>=5;
if(((dwn_adres.c[2]&0x1f)==0x00)&&(dwn_adres.c[3]==0x00)){/*如果A0~A11为0,那么就表明要写的数据跨越扇区了,需要对扇区进行擦除*/
if(sector_section<8){/*是扇区0~7(SA0~SA7)*/
erase_sec=(unsigned char)sector_section;/*设置要擦除的扇区*/
delay_10us(15);
if(erase_sector(erase_sec)){/*返回1表明擦除成功*/
}
else{
reply_dwn(erase_sec,fdata);
}
}
else if((sector_section&0x7)==0){/*表明要跨越64K字节大小的扇区,扇区是SA8-SA70*/
sector_section >>=3;
erase_sec=(unsigned char)(sector_section&0xff);
erase_sec +=7;/*计算出要擦除的扇区*/
delay_10us(15);
if(erase_sector(erase_sec)){/*返回1表明擦除成功*/
}
else{
reply_dwn(erase_sec,fdata);
}
}
}
#endif
for(cnt=0;cnt<128;cnt++){/*把128字节的数据写到Flash中*/
write_flash(&dwn_adres,fdata[5+cnt]);
dwn_adres.l ++;/*没写一个字节,写falsh的地址增加1*/
}
if(fdata[1]==0x00){/*收到计算机的是数据下载类型,返回接收数据成功*/
reply_dwn(FSUCCESS,fdata);
}
else if(fdata[1]==0x01){/*计算机通知所有数据下载完毕*/
reply_dwn(FDOVER,fdata);/*对帧进行应答*/
return;/*函数返回*/
}
}
else{//CRC error
reply_dwn(FERROR,fdata);
}
fsm_fdl=0;/*继续搜索下一帧的帧头*/
}
}
dsr_tail++;
dsr_tail %=DSR_LEN;
}
else{/*等待串口中断接收新的数据到数据接收缓冲区中*/
}
}
}
void init_serial(void)/*串行异步口初始化*/
{
unsigned char ch;
SCON = 0x50; // SCON / MODE 1 /* setup serial port control /
ch=TMOD;
ch=ch&0x0f;
TMOD=ch|0x20;
PCON=0XF0; // DIV 16
#ifdef FOSC18432
TH1=251;
TH0=TH1; /**hardware (19.2k baud @18.432)***/
TR1=1; // let timer 1 run // TCON /
#else
#ifdef FOSC24M
TH1=243;
TH0=TH1; /**hardware (9.6k baud @24M) infect is 9.61k*/
TR1=1; // let timer 1 run // TCON /
#else
//nothing
#endif
#endif
ES=1;//serial interrupt
}
#define ULWRCYCLE FLASHADD=0X00;XBYTE[0X4AAA]=0XAA;XBYTE[0X4555]=0X55 /*Flash的非锁定写周期*/
#define WRITE_CMD ULWRCYCLE;FLASHADD=0X00;XBYTE[0X4AAA]=0XA0 /*Flash的写命令*/
#define ERASE_CMD ULWRCYCLE;FLASHADD=0X00;XBYTE[0X4AAA]=0X80;ULWRCYCLE /*Flash的擦除扇区命令*/
#define ERASE_CHIP ERASE_CMD;FLASHADD=0X00;XBYTE[0X4AAA]=0X10 /*Flash的擦除整个芯片命令*/
bit erase_sector(unsigned char sa){/*扇区擦除命令,参数sa为要擦除的扇区为0~70*/
unsigned int n;
unsigned char cnt;
unsigned char temp;
unsigned char rybystat;
ERASE_CMD;
temp=sa;
if(sa<8){/*是flash中的boot扇区,每个扇区的大小为8K字节*/
cnt=temp;
temp >>=1;
FLASHADD=temp;
if(cnt%2){/*扇区不同扇区的扇区地址是不同的*/
XBYTE[0X2000+FLASH_MEM_SPACE_START]=0X30;/*擦除扇区命令*/
}
else{
XBYTE[FLASH_MEM_SPACE_START]=0X30;/*擦除扇区命令*/
}
}
else{/*是每个扇区为64K字节的扇区*/
cnt=temp-7;
temp=cnt <<2;
FLASHADD=temp;
XBYTE[FLASH_MEM_SPACE_START]=0X30;/*擦除扇区命令*/
}
rybystat=FLASHRYNBY;
for(n=0;n<2000;n++){/*如果RY/BY#管脚变低,表明擦除命令真正开始*/
if(rybystat&0x01==0x00){//start erase.
goto my_exit;//break;
}
rybystat=FLASHRYNBY;
}
my_exit:
while(1){
rybystat=FLASHRYNBY;
if(rybystat&0x01==0x01){/*如果RY/BY#变低表明擦除完毕*/
break;
}
}
if(n>=2000){/*擦除命令由于某种原因不能开始,退出程序*/
return 0;
}
return 1;
}
void erase_flash(unsigned char flag,unsigned char sa){/*flag为0,擦除整个芯片,flag为1,擦除sa指定的扇区,可以由外部命令调用*/
unsigned char cnt;
unsigned char temp;
unsigned char rybystat;
if(flag==0){
ERASE_CHIP;/*擦除整个芯片*/
}
else{
ERASE_CMD;
temp=sa;
if(sa<8){//this is boot sector and is 8k pre sector.
cnt=temp;
temp >>=1;
FLASHADD=temp;
if(cnt%2){
XBYTE[0X2000+FLASH_MEM_SPACE_START]=0X30;//erase sector of flash cmd.
}
else{
XBYTE[FLASH_MEM_SPACE_START]=0X30;//erase sector of flash cmd.
}
}
else{//it is 64k pre sector.
cnt=temp-7;
temp=cnt <<2;
FLASHADD=temp;
XBYTE[FLASH_MEM_SPACE_START]=0X30;//erase sector of flash cmd.
}
}
for(cnt=0;cnt<250;cnt++){
rybystat=FLASHRYNBY;
if((rybystat&0x01)==0x00){/*擦除开始*/
goto exit_for;
}
}
exit_for:
if(cnt>=250){/*擦除出错*/
}
else{
while(1){
rybystat=FLASHRYNBY;
if((rybystat&0x01)==0x01){/*擦除完成*/
break;
}
else{
cnt++;/*正在擦除中*/
}
}
}
}
void write_flash(union SFADD *p_add,unsigned char dat){/*向p_add指向的地址中写数据dat*/
unsigned int flashspace;
union SFADD dwn_adres;
dwn_adres.l=p_add->l;
flashspace=dwn_adres.i[1];
flashspace &=0x3fff;
flashspace +=FLASH_MEM_SPACE_START;
dwn_adres.l <<=2;
WRITE_CMD;
FLASHADD=dwn_adres.c[1];
XBYTE[flashspace]=dat;
}
void read_flash(unsigned char hadd,unsigned int ladd,unsigned char len,unsigned char *buf){/*从flash的hadd和ladd组成地址中读取len个数据到buf中*/
unsigned char cnt;
unsigned int flashspace;
flashspace=0x4000;
flashspace +=ladd&0x3fff;
FLASHADD=hadd;
for(cnt=0;cnt<len;cnt++){
buf[cnt]=XBYTE[flashspace+cnt];
}
}
void draw_picture(unsigned char orgx,unsigned int orgy){/*把存储在flash中的图片使用显示出来*/
unsigned char row;
unsigned int basex;
unsigned int ladd;
union SFADD offset;
basex=0x8000+SCREEN_WIDTH*orgy+orgx;/*在显存储中的位置*/
offset.l=FLASH_ADD_PICTURE_START; /*图片在flash中的位置*/
ladd=offset.i[1];
ladd &=0x3fff;
ladd |=FLASH_MEM_SPACE_START; /*把图片在flash中的位置转换为单片机能表示的寻址的地址*/
offset.l <<=2; /*flash地址的A0~A13*/
FLASHADD=offset.c[1]; /*flash地址的A14~A21地址*/
for(row=0;row<PICTURE_HEIGHT;row++){/*约定存储的图片宽度为PICTURE_WIDTH*8 高度为PICTURE_HEIGHT*/
memcpy((unsigned char *)basex,(unsigned char *)ladd,PICTURE_WIDTH);/*显示图片中的一行,相当于写1行图片数据到显存中*/
ladd +=PICTURE_WIDTH;/*图片数据指向下一行*/
basex +=SCREEN_WIDTH;/*显存指向下一行*/
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -