Слияние кода завершено, страница обновится автоматически
C51 COMPILER V9.59.0.0 MAIN 12/30/2020 22:25:38 PAGE 1
C51 COMPILER V9.59.0.0, COMPILATION OF MODULE MAIN
OBJECT MODULE PLACED IN .\Objects\main.obj
COMPILER INVOKED BY: C:\Keil_v5\C51\BIN\C51.EXE main.c OPTIMIZE(8,SPEED) BROWSE DEBUG OBJECTEXTEND PRINT(.\Listings\main
-.lst) OBJECT(.\Objects\main.obj)
line level source
1 /*-------------------------------------------头文件-------------------------------------------*/
2 #include <STC8.H>
3 #include "intrins.h" //单片机C语言使用汇编指令的头文件。
4 /*-------------------------------------------宏定义-------------------------------------------*/
5 typedef unsigned char u8; //无符号的 8位变量。
6 typedef unsigned int u16; //无符号的16位变量。
7 typedef unsigned long u32; //无符号的32位变量。
8 /*-----------------------------------------BOOT脚定义-----------------------------------------*/
9 #define BOOT_PIN P00 //BOOT脚设置为P0.0脚。
10 #define BOOT_RUN_APP 0 //BOOT脚为低电平的时候运行APP。
11 /*------------------------------------------功能定义------------------------------------------*/
12 sfr IAP_TPS =0xf5; //EEPROM擦除等待时间控制寄存器
13 u8 code INIT_MASK[6] ={0xff,0xff,0xff,0xff,0xff,0xff};//初始化掩码,对于FLASH而言就是0xFF。
14 void (* jmp_app)(void); //跳转函数。
15 #define BOOT_STATUS 0xFE00 //FE00 :BootLoader区状态
16 #define BOOT_JMP_ADDR 0xFE01 //FE01~FE02 :BootLoader的跳转地址
17
18 #define APP_START 0xFE03 //FE03 :APP区起始地址
19 #define APP_MAX 5 //APP区占用空间为6字节
20 #define APP_STATUS 0xFE03 //FE03 :APP区状态
21 #define APP_SIZE 0xFE04 //FE04~FE05 :APP区大小
22 #define APP_JMP_ADDR 0xFE06 //FE06~FE07 :APP地址
23
24 #define DATA_MAX 124 //APP区的最大值,单位为扇区数。一扇区为512字节。
25 #define FLASH_SIZE (DATA_MAX*512) //APP区的最大值,单位为字节。
26
27 #define read_jmp__addr (*(unsigned int code *)(0x0001)) //读取整个程序的跳转地址。
28 #define read_jmp__addr_h (*(unsigned char code *)(0x0001))
29 #define read_jmp__addr_l (*(unsigned char code *)(0x0002))
30
31 #define read_boot_addr (*(unsigned int code *)(BOOT_JMP_ADDR))//读取Bootloader的跳转地址。
32 #define read_boot_addr_h (*(unsigned char code *)(BOOT_JMP_ADDR))
33 #define read_boot_addr_l (*(unsigned char code *)(BOOT_JMP_ADDR+1))
34
35 #define read_app__addr (*(unsigned int code *)(APP_JMP_ADDR)) //读取APP的跳转地址。
36 #define read_app__addr_h (*(unsigned char code *)(APP_JMP_ADDR))
37 #define read_app__addr_l (*(unsigned char code *)(APP_JMP_ADDR+1))
38
39 #define read_app__size (*(unsigned int code *)(APP_SIZE)) //读取APP的大小。
40 #define read_app__size_h (*(unsigned char code *)(APP_SIZE))
41 #define read_app__size_l (*(unsigned char code *)(APP_SIZE+1))
42
43 #define read_app__flag (*(unsigned char code *)(APP_STATUS)) //读取APP的状态。
44 #define read_boot_flag (*(unsigned char code *)(BOOT_STATUS)) //读取BootLoader的状态。
45 //位定义 [ D7 ][ D6 ][ D5 ][ D4 ][ D3 ][ D2 ][ D1 ][ D0 ]
46 //APP [ 使能标志位 ][ 安装 完成标志位 ][ 预留 ]
47 //BOOT [ 使能标志位 ][ 初始化完成标志位 ][ 预留 ]
48 #define BIT_ENABLE 0x80 //使能位。
49 #define SET_ENABLE (~(u8)(BIT_ENABLE)) //使能该区域。
50 #define GET_ENABLE ( (u8)(BIT_ENABLE)) //查询使能位。
51
52 #define BIT_DONE 0x40 //完成位。
53 #define SET_DONE (~(u8)(BIT_DONE)) //该区域完成了设定功能。
54 #define GET_DONE ( (u8)(BIT_DONE)) //查询完成位。
C51 COMPILER V9.59.0.0 MAIN 12/30/2020 22:25:38 PAGE 2
55
56 #define PD_APP__OK (GET_ENABLE|GET_DONE) //判断APP区是否有合法的程序。
57 #define APP__OK (0) //APP区是合法的程序。
58 /*------------------------------------------函数定义------------------------------------------*/
59 #if 1//串口部分
60 /*-------------------------------------------------------
61 函数名:hard_init
62 描 述:硬件外设初始化函数。
63 创建者:奈特
64 调用例程:无
65 创建日期:2020-11-30
66 修改记录:
67 2020-12-08:合并了串口和定时器的初始化。更名为hard_init。
68 -------------------------------------------------------*/
69 void hard_init(void){
70 1 SCON = 0x50; //8位数据,可变波特率
71 1 AUXR = 0x40; //定时器1时钟为Fosc,即1T
72 1 TMOD = 0x00; //设定定时器1为16位自动重装方式
73 1 TL0 = 0xC0; //设置定时初值
74 1 TH0 = 0x63; //20ms
75 1 TL1 = 0xCC; //设定初值
76 1 TH1 = 0xFF; //设定初值
77 1 TF0 = 0; //清除TF0标志
78 1 TF1 = 0; //清除TF1标志
79 1 TR0 = 0;
80 1 TR1 = 1; //启动定时器1
81 1 ET1 = 0; //禁止定时器1中断
82 1 }
83 /*-------------------------------------------------------
84 函数名:send_data
85 描 述:串口发送单字节函数。
86 输 入: dat - 要发送的字节。
87 创建者:奈特
88 调用例程:无
89 创建日期:2020-11-30
90 修改记录:
91 -------------------------------------------------------*/
92 void send_data(u8 dat){
93 1 SBUF=dat; //发送一个数据。
94 1 while(!TI); //等待数据发完。
95 1 TI=0; //清除发送标志位。
96 1 }
97 /*-------------------------------------------------------
98 函数名:send_string
99 描 述:串口发送字符串函数。
100 输 入: str - 要发送的字符串。
101 创建者:奈特
102 调用例程:无
103 创建日期:2020-11-30
104 修改记录:
105 2020-12-08:优化了函数的占用空间。
106 -------------------------------------------------------*/
107 void send_string(u8 code * str){
108 1 while(*str){ //判断字符串是否到头,
109 2 SBUF=*str++;//发送一个数据。
110 2 while(!TI); //等待数据发完。
111 2 TI=0; //清除发送标志位。
112 2 }
113 1 }
114 /*-------------------------------------------------------
115 函数名:send_num
116 描 述:串口发送16位数据函数,发送格式为%u。
C51 COMPILER V9.59.0.0 MAIN 12/30/2020 22:25:38 PAGE 3
117 输 入: dat - 要发送的数据。
118 创建者:奈特
119 调用例程:无
120 创建日期:2020-12-03
121 修改记录:
122 -------------------------------------------------------*/
123 void send_num(u16 dat){
124 1 u8 n[5],i;
125 1 for(i=0;i<5;i++){
126 2 n[i]=dat%10;
127 2 dat/=10;
128 2 }
129 1 if(n[4]){
130 2 send_data('0'+n[4]);
131 2 }
132 1 if(n[4]|n[3]){
133 2 send_data('0'+n[3]);
134 2 }
135 1 if(n[4]|n[3]|n[2]){
136 2 send_data('0'+n[2]);
137 2 }
138 1 if(n[4]|n[3]|n[2]|n[1]){
139 2 send_data('0'+n[1]);
140 2 }
141 1 send_data('0'+n[0]);
142 1 }
143 #endif
144 #if 1//FLASH操作部分
145 /*-------------------------------------------------------
146 函数名:eeprom_off
147 描 述:eeprom关闭函数。
148 创建者:奈特
149 调用例程:无
150 创建日期:2020-11-30
151 修改记录:
152 -------------------------------------------------------*/
153 void eeprom_off(void){
154 1 IAP_CONTR = 0; //关闭IAP功能
155 1 IAP_CMD = 0; //清除命令寄存器
156 1 IAP_TRIG = 0; //清除触发寄存器
157 1 IAP_ADDRH = 0xff;//将地址设置到非IAP区域
158 1 IAP_ADDRL = 0xff;//将地址设置到非IAP区域
159 1 }
160 /*-------------------------------------------------------
161 函数名:eeprom_erase
162 描 述:eeprom擦除函数,用于擦除一个扇区。
163 输 入: addr - 要擦除的地址。
164 创建者:奈特
165 调用例程:无
166 创建日期:2020-11-30
167 修改记录:
168 -------------------------------------------------------*/
169 void eeprom_erase(u16 addr){
170 1 IAP_CONTR = 0x81; //使能IAP
171 1 IAP_CMD = 3; //设置IAP擦除命令
172 1 IAP_ADDRL = addr; //设置IAP低地址
173 1 IAP_ADDRH = addr >> 8; //设置IAP高地址
174 1 IAP_TRIG = 0x5a; //写触发命令(0x5a)
175 1 IAP_TRIG = 0xa5; //写触发命令(0xa5)
176 1 _nop_(); //稍稍等待一下
177 1 eeprom_off(); //关闭IAP功能
178 1 }
C51 COMPILER V9.59.0.0 MAIN 12/30/2020 22:25:38 PAGE 4
179 /*-------------------------------------------------------
180 函数名:eeprom_write
181 描 述:eeprom单字节写函数,用于向指定地址写一个数据。
182 输 入: addr - 要写入的地址;
183 dat - 要写入的数据。
184 创建者:奈特
185 调用例程:无
186 创建日期:2020-11-30
187 修改记录:
188 -------------------------------------------------------*/
189 void eeprom_write(u16 addr,u8 dat){
190 1 IAP_CONTR = 0x81; //使能IAP
191 1 IAP_CMD = 2; //设置IAP写命令
192 1 IAP_ADDRL = addr; //设置IAP低地址
193 1 IAP_ADDRH = addr >> 8; //设置IAP高地址
194 1 IAP_DATA = dat; //写IAP数据
195 1 IAP_TRIG = 0x5a; //写触发命令(0x5a)
196 1 IAP_TRIG = 0xa5; //写触发命令(0xa5)
197 1 _nop_(); //稍稍等待一下
198 1 eeprom_off(); //关闭IAP功能
199 1 }
200 /*-------------------------------------------------------
201 函数名:eeprom_write_boot_area
202 描 述:eeprom多字节写系统区函数,用于向指定区域写多个数据。
203 输 入: addr - 要写入的地址,必须要系统区域内;
204 buf - 要写入的数据缓存;
205 len - 要写入的数据数量。
206 创建者:奈特
207 调用例程:无
208 创建日期:2020-11-30
209 修改记录:
210 2020-12-03:优化了功能,现在只为固定区域服务已减小占用空间,
211 改名为eeprom_write_boot_area。
212 -------------------------------------------------------*/
213 volatile u8 xdata eeprom_buf[512];//用于整合数据的缓存
214 void eeprom_write_boot_area(u16 addr,u8 * buf,u16 len){
215 1 u16 i,ad;
216 1 for(i=0;i<512;i++){ //将系统区原本的数据读出来,放到缓存当中。
217 2 eeprom_buf[i]=(*(unsigned char code *)(BOOT_STATUS+i));
218 2 }
219 1 eeprom_erase(BOOT_STATUS); //清除系统区。
220 1 ad=addr-BOOT_STATUS; //获取地址的偏移量。
221 1 for(i=0;i<len;i++){ //将数据写入到缓存。
222 2 eeprom_buf[i+ad]=buf[i];
223 2 }
224 1 for(i=0;i<512;i++){ //将缓存写回到单片机。
225 2 eeprom_write(BOOT_STATUS+i,eeprom_buf[i]);
226 2 }
227 1 }
228 #endif
229
230 volatile u16 data_count=0,proj_count=0;//包内数据计数器和总数据计数变量。
231 /*-------------------------------------------------------
232 函数名:data_save
233 描 述:数据保存函数,用于保存从串口接收到的数据。
234 创建者:奈特
235 调用例程:无
236 创建日期:2020-12-24
237 修改记录:
238 -------------------------------------------------------*/
239 void data_save(void){
240 1 u16 i;
C51 COMPILER V9.59.0.0 MAIN 12/30/2020 22:25:38 PAGE 5
241 1 if(proj_count<=256){ //如果总计数小于256,说明是第一包数据。
242 2 eeprom_write(APP_JMP_ADDR ,eeprom_buf[1]); //第一包数据通常都包含了跳转地址,
243 2 eeprom_write(APP_JMP_ADDR+1,eeprom_buf[2]); //把跳转地址保存起来。
244 2 for(i=3;i<proj_count;i++){ //然后写入剩下的数据。
245 3 eeprom_write(i,eeprom_buf[i]);
246 3 }
247 2 }else{ //如果不是第一包数据,
248 2 for(i=0;i<data_count;i++){ //那就直接保存到flash就行了。
249 3 eeprom_write(i+(proj_count-data_count),eeprom_buf[i]);
250 3 }
251 2 }
252 1 }
253
254 void main(void){
255 1 u16 i; //16位临时变量。
256 1 u8 timeout; //时间超时计数器。
257 1 IAP_TPS=24; //STC8G和STC8H的设置,默认24MHz。
258 1 /*------------------------------------------BootLoader初始化-------------------------------*/
259 1 if(read_boot_flag&GET_ENABLE){ //判断是不是第一次运行bootloader,
260 2 eeprom_write(BOOT_STATUS, SET_ENABLE); //是的话就置位使能标志。
261 2 eeprom_write( APP_JMP_ADDR, (*(unsigned char code *)(0x0001))); //初始化APP的跳转地址。
262 2 eeprom_write( APP_JMP_ADDR+1, (*(unsigned char code *)(0x0002))); //
263 2 eeprom_write(BOOT_JMP_ADDR, (*(unsigned char code *)(0x0001))); //初始化BOOT的跳转地址。
264 2 eeprom_write(BOOT_JMP_ADDR+1, (*(unsigned char code *)(0x0002))); //
265 2 eeprom_write(BOOT_STATUS, SET_DONE); //置位初始化完毕标志。
266 2 } //至此BootLoader初始化完成。
267 1 /*------------------------------------------APP检测---------------------------------------*/
268 1 jmp_app=(u32)read_boot_addr; //默认把BootLoader的地址给APP地址。防止乱跳转。
269 1 if((read_app__flag&PD_APP__OK)==APP__OK){ //判断程序是否合法。
270 2 jmp_app=(u32)read_app__addr; //程序合法,则将APP跳转地址给跳转函数。
271 2 if(BOOT_PIN==BOOT_RUN_APP){jmp_app();} //BOOT脚是能跳转到APP的电平就跳转到APP。
272 2 }
273 1 /*-----------------------------------BootLoader界面--------------------------------------*/
274 1 hard_init(); //初始化串口和定时器。
275 1 send_string("[Boot](0)\r\n"); //提示进入了BOOT状态。
276 1 while(!RI); //等待接收解锁码。
277 1 RI=0; //置零接收标志位。
278 1 if(SBUF!='!'){ //如果不是解锁码,说明串口此时是乱传数据的。
279 2 send_string("[Lock](1)\r\n");//提示要锁定单片机。
280 2 while(1); //死循环,锁定单片机不能继续下载。
281 2 }
282 1 /*--------------------------------------下载界面------------------------------------------*/
283 1 send_string("[Erase](2)\r\n"); //提示开始擦除。
284 1 eeprom_erase(0x0000); //先擦第一扇区。
285 1 eeprom_write(0x0000,0x02); //立刻写入跳转指令。
286 1 eeprom_write(0x0001,(*(unsigned char code *)(BOOT_JMP_ADDR))); //取出BOOT的跳转地址高8位,写入到指定地址
-小
287 1 eeprom_write(0x0002,(*(unsigned char code *)(BOOT_JMP_ADDR+1)));//取地址低8位,分成两个单字节写函数,可以
-加快运行速度。
288 1 eeprom_write_boot_area(APP_START,INIT_MASK,APP_MAX); //初始化APP状态区。
289 1 eeprom_write(APP_STATUS,SET_ENABLE); //写入APP使能标志位。
290 1 for(i=512;i<FLASH_SIZE;i+=512){ //擦除后面的扇区。
291 2 eeprom_erase(i);
292 2 }
293 1 data_count=0; //清零单包数据计数器。
294 1 proj_count=0; //清零总体数据计数器。
295 1 send_string("[Start](3)"); //提示开始下载。
296 1 TR0=1; //打开定时器,即启用超时判断。
297 1 timeout=250; //第一次超时时间为250*20ms=5000ms=5s,上位机点击操作需要时间,第一次超时判断要久一些。
298 1 while(1){ //在循环里接收数据。
299 2 while(!RI){ //等待串口来数据。
300 3 if(TF0){ //每当定时器溢出时,
C51 COMPILER V9.59.0.0 MAIN 12/30/2020 22:25:38 PAGE 6
301 4 TF0=0; //清零标志位。
302 4 timeout--; //超时时间-1。
303 4 if(timeout==0){ //当时间减到0的时候,说明超时了。
304 5 TR0=0; //关闭定时器。
305 5 if(proj_count){ //如果期间接收了数据,
306 6 send_string("\r\n[Get "); //显示接收了多少数据。
307 6 send_num(proj_count);
308 6 send_string(" Byte](4)\r\n"); //单位是字节。
309 6 data_save(); //保存这些数据,在这里保存的通常是最后一包的数据。
310 6 eeprom_write(APP_SIZE, (u8)(proj_count>>8)); //读取APP的大小高8位,写入到指定地址中。
311 6 eeprom_write(APP_SIZE+1,(u8)(proj_count)); //读取APP的大小低8位,分成两个单字节写函数,可以加快运行
-速度。
312 6 eeprom_write(APP_STATUS,SET_DONE); //安装完成,写完成标志位。
313 6 jmp_app=(u32)read_app__addr; //将APP跳转地址给跳转函数。
314 6 }else{ //如果期间没有接收到数据,
315 6 send_string("\r\n[Time Out](5)\r\n"); //显示超时。
316 6 jmp_app=(u32)read_boot_addr; //将BOOT的跳转地址给跳转函数。
317 6 }
318 5 jmp_app(); //下载进程完毕,跳转。
319 5 }
320 4 }
321 3 }
322 2 TF0=0; //如果接收到串口数据,也要清零定时器标志位。
323 2 RI=0; //同时清零接收标志位。
324 2 eeprom_buf[data_count++]=SBUF; //将接收的数据保存下来。
325 2 proj_count++; //统计目前已接收的数据大小。
326 2 if(data_count==256){ //sscom5上位机是256字节分一包,所以每收到256字节的时候,
327 3 data_save(); //就要把数据保存下来。
328 3 data_count=0; //同时清零数据统计标志位。
329 3 }
330 2 if(proj_count>FLASH_SIZE){ //如果接收到的大小大于总的空间,
331 3 send_string("\r\n[Overflow](6)\r\n"); //提示容量溢出。
332 3 while(1); //死循环,锁定单片机。
333 3 }
334 2 timeout=50; //超时时间为50*20ms=1000ms=1s
335 2 }
336 1 }
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 977 ----
CONSTANT SIZE = 110 ----
XDATA SIZE = 512 ----
PDATA SIZE = ---- ----
DATA SIZE = 7 19
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )