找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1465|回复: 0
打印 上一主题 下一主题
收起左侧

单片机单字节并用送出数据和多字节并用送出数据程序

[复制链接]
跳转到指定楼层
楼主
ID:444712 发表于 2018-12-24 09:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单字节并用送出数据和多字节并用送出数据



单字节操作并用串送出数据

/本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz

单片机源码:
  1. #include "reg51.h"
  2. #include "intrins.h"

  3. typedef unsigned char BYTE;
  4. typedef unsigned int WORD;

  5. //-----------------------------------------------

  6. sfr P1M1 = 0x91;    //PxM1.n,PxM0.n     =00--->Standard,    01--->push-pull
  7. sfr P1M0 = 0x92;    //                  =10--->pure input,  11--->open drain
  8. sfr P0M1 = 0x93;
  9. sfr P0M0 = 0x94;
  10. sfr P2M1 = 0x95;
  11. sfr P2M0 = 0x96;
  12. sfr P3M1 = 0xB1;
  13. sfr P3M0 = 0xB2;
  14. sfr P4M1 = 0xB3;
  15. sfr P4M0 = 0xB4;
  16. sfr P5M1 = 0xC9;
  17. sfr P5M0 = 0xCA;
  18. sfr P6M1 = 0xCB;
  19. sfr P6M0 = 0xCC;
  20. sfr P7M1 = 0xE1;
  21. sfr P7M0 = 0xE2;

  22. sfr IAP_DATA    =   0xC2;           //IAP数据寄存器
  23. sfr IAP_ADDRH   =   0xC3;           //IAP地址寄存器高字节
  24. sfr IAP_ADDRL   =   0xC4;           //IAP地址寄存器低字节
  25. sfr IAP_CMD     =   0xC5;           //IAP命令寄存器
  26. sfr IAP_TRIG    =   0xC6;           //IAP命令触发寄存器
  27. sfr IAP_CONTR   =   0xC7;           //IAP控制寄存器

  28. #define CMD_IDLE    0               //空闲模式
  29. #define CMD_READ    1               //IAP字节读命令
  30. #define CMD_PROGRAM 2               //IAP字节编程命令
  31. #define CMD_ERASE   3               //IAP扇区擦除命令

  32. #define     URMD    0           //0:使用定时器2作为波特率发生器
  33.                                 //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
  34.                                 //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器

  35. sfr T2H   = 0xd6;               //定时器2高8位
  36. sfr T2L   = 0xd7;               //定时器2低8位

  37. sfr  AUXR       =   0x8e;       //辅助寄存器                              

  38. //#define ENABLE_IAP 0x80           //if SYSCLK<30MHz
  39. //#define ENABLE_IAP 0x81           //if SYSCLK<24MHz
  40. #define ENABLE_IAP  0x82            //if SYSCLK<20MHz
  41. //#define ENABLE_IAP 0x83           //if SYSCLK<12MHz
  42. //#define ENABLE_IAP 0x84           //if SYSCLK<6MHz
  43. //#define ENABLE_IAP 0x85           //if SYSCLK<3MHz
  44. //#define ENABLE_IAP 0x86           //if SYSCLK<2MHz
  45. //#define ENABLE_IAP 0x87           //if SYSCLK<1MHz

  46. //测试地址
  47. #define IAP_ADDRESS 0x0400

  48. void Delay(BYTE n);
  49. void IapIdle();
  50. BYTE IapReadByte(WORD addr);
  51. void IapProgramByte(WORD addr, BYTE dat);
  52. void IapEraseSector(WORD addr);
  53. void InitUart();
  54. BYTE SendData(BYTE dat);

  55. void main()
  56. {
  57.     WORD i;

  58.     P0M0 = 0x00;
  59.     P0M1 = 0x00;
  60.     P1M0 = 0x00;
  61.     P1M1 = 0x00;
  62.     P2M0 = 0x00;
  63.     P2M1 = 0x00;
  64.     P3M0 = 0x00;
  65.     P3M1 = 0x00;
  66.     P4M0 = 0x00;
  67.     P4M1 = 0x00;
  68.     P5M0 = 0x00;
  69.     P5M1 = 0x00;
  70.     P6M0 = 0x00;
  71.     P6M1 = 0x00;
  72.     P7M0 = 0x00;
  73.     P7M1 = 0x00;

  74.     P1 = 0xfe;                      //1111,1110 系统OK
  75.     InitUart();                     //初始化串口
  76.     Delay(10);                      //延时
  77.     IapEraseSector(IAP_ADDRESS);    //扇区擦除
  78.     for (i=0; i<512; i++)           //检测是否擦除成功(全FF检测)
  79.     {
  80.         if (SendData(IapReadByte(IAP_ADDRESS+i)) != 0xff)
  81.             goto Error;             //如果出错,则退出
  82.     }
  83.     P1 = 0xfc;                      //1111,1100 擦除成功
  84.     Delay(10);                      //延时
  85.     for (i=0; i<512; i++)           //编程512字节
  86.     {
  87.         IapProgramByte(IAP_ADDRESS+i, (BYTE)i);
  88.     }
  89.     P1 = 0xf8;                      //1111,1000 编程完成
  90.     Delay(10);                      //延时
  91.     for (i=0; i<512; i++)           //校验512字节
  92.     {
  93.         if (SendData(IapReadByte(IAP_ADDRESS+i)) != (BYTE)i)
  94.             goto Error;             //如果校验错误,则退出
  95.     }
  96.     P1 = 0xf0;                      //1111,0000 测试完成
  97.     while (1);
  98. Error:
  99.     P1 &= 0x7f;                     //0xxx,xxxx IAP操作失败
  100.     while (1);
  101. }

  102. /*----------------------------
  103. 软件延时
  104. ----------------------------*/
  105. void Delay(BYTE n)
  106. {
  107.     WORD x;

  108.     while (n--)
  109.     {
  110.         x = 0;
  111.         while (++x);
  112.     }
  113. }

  114. /*----------------------------
  115. 关闭IAP
  116. ----------------------------*/
  117. void IapIdle()
  118. {
  119.     IAP_CONTR = 0;                  //关闭IAP功能
  120.     IAP_CMD = 0;                    //清除命令寄存器
  121.     IAP_TRIG = 0;                   //清除触发寄存器
  122.     IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
  123.     IAP_ADDRL = 0;
  124. }

  125. /*----------------------------
  126. 从ISP/IAP/EEPROM区域读取一字节
  127. ----------------------------*/
  128. BYTE IapReadByte(WORD addr)
  129. {
  130.     BYTE dat;                       //数据缓冲区

  131.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  132.     IAP_CMD = CMD_READ;             //设置IAP命令
  133.     IAP_ADDRL = addr;               //设置IAP低地址
  134.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  135.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  136.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  137.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  138.     dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
  139.     IapIdle();                      //关闭IAP功能

  140.     return dat;                     //返回
  141. }

  142. /*----------------------------
  143. 写一字节数据到ISP/IAP/EEPROM区域
  144. ----------------------------*/
  145. void IapProgramByte(WORD addr, BYTE dat)
  146. {
  147.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  148.     IAP_CMD = CMD_PROGRAM;          //设置IAP命令
  149.     IAP_ADDRL = addr;               //设置IAP低地址
  150.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  151.     IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
  152.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  153.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  154.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  155.     IapIdle();
  156. }

  157. /*----------------------------
  158. 扇区擦除
  159. ----------------------------*/
  160. void IapEraseSector(WORD addr)
  161. {
  162.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  163.     IAP_CMD = CMD_ERASE;            //设置IAP命令
  164.     IAP_ADDRL = addr;               //设置IAP低地址
  165.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  166.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  167.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  168.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  169.     IapIdle();
  170. }

  171. /*----------------------------
  172. 初始化串口
  173. ----------------------------*/
  174. void InitUart()
  175. {
  176.     SCON = 0x5a;                //设置串口为8位可变波特率
  177. #if URMD == 0
  178.     T2L = 0xd8;                 //设置波特率重装值
  179.     T2H = 0xff;                 //115200 bps(65536-18432000/4/115200)
  180.     AUXR = 0x14;                //T2为1T模式, 并启动定时器2
  181.     AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
  182. #elif URMD == 1
  183.     AUXR = 0x40;                //定时器1为1T模式
  184.     TMOD = 0x00;                //定时器1为模式0(16位自动重载)
  185.     TL1 = 0xd8;                 //设置波特率重装值
  186.     TH1 = 0xff;                 //115200 bps(65536-18432000/4/115200)
  187.     TR1 = 1;                    //定时器1开始启动
  188. #else
  189.     TMOD = 0x20;                //设置定时器1为8位自动重装载模式
  190.     AUXR = 0x40;                //定时器1为1T模式
  191.     TH1 = TL1 = 0xfb;           //115200 bps(256 - 18432000/32/115200)
  192.     TR1 = 1;
  193. #endif
  194. }

  195. /*----------------------------
  196. 发送串口数据
  197. ----------------------------*/
  198. BYTE SendData(BYTE dat)
  199. {
  200.     while (!TI);                    //等待前一个数据发送完成
  201.     TI = 0;                         //清除发送标志
  202.     SBUF = dat;                     //发送当前数据

  203.     return dat;
  204. }


  205. //************************************************************************************************

  206. [size=4]多字节连续操作并用串口送出数据[/size]

  207. //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
  208. //若无特别说明,工作频率一般为11.0592MHz


  209. #include "reg51.h"
  210. #include "intrins.h"

  211. typedef bit BOOL;
  212. typedef unsigned char BYTE;
  213. typedef unsigned int WORD;

  214. #define ERROR   0
  215. #define OK      1

  216. //-----------------------------------------------

  217. sfr IAP_DATA    =   0xC2;           //IAP数据寄存器
  218. sfr IAP_ADDRH   =   0xC3;           //IAP地址寄存器高字节
  219. sfr IAP_ADDRL   =   0xC4;           //IAP地址寄存器低字节
  220. sfr IAP_CMD     =   0xC5;           //IAP命令寄存器
  221. sfr IAP_TRIG    =   0xC6;           //IAP命令触发寄存器
  222. sfr IAP_CONTR   =   0xC7;           //IAP控制寄存器

  223. sbit Begin_LED  =   P1^0;
  224. sbit ERROR_LED  =   P1^3;
  225. sbit OK_LED     =   P1^7;

  226. #define CMD_IDLE    0               //空闲模式
  227. #define CMD_READ    1               //IAP字节读命令
  228. #define CMD_PROGRAM 2               //IAP字节编程命令
  229. #define CMD_ERASE   3               //IAP扇区擦除命令

  230. #define     URMD    0               //0:使用定时器2作为波特率发生器
  231.                                     //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
  232.                                     //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器

  233. sfr P0M1 = 0x93;
  234. sfr P0M0 = 0x94;
  235. sfr P1M1 = 0x91;
  236. sfr P1M0 = 0x92;
  237. sfr P2M1 = 0x95;
  238. sfr P2M0 = 0x96;
  239. sfr P3M1 = 0xb1;
  240. sfr P3M0 = 0xb2;
  241. sfr P4M1 = 0xb3;
  242. sfr P4M0 = 0xb4;
  243. sfr P5M1 = 0xC9;
  244. sfr P5M0 = 0xCA;
  245. sfr P6M1 = 0xCB;
  246. sfr P6M0 = 0xCC;
  247. sfr P7M1 = 0xE1;
  248. sfr P7M0 = 0xE2;

  249. sfr T2H   = 0xd6;                   //定时器2高8位
  250. sfr T2L   = 0xd7;                   //定时器2低8位

  251. sfr  AUXR       =   0x8e;           //辅助寄存器                              

  252. //#define ENABLE_IAP 0x80           //if SYSCLK<30MHz
  253. //#define ENABLE_IAP 0x81           //if SYSCLK<24MHz
  254. #define ENABLE_IAP  0x82            //if SYSCLK<20MHz
  255. //#define ENABLE_IAP 0x83           //if SYSCLK<12MHz
  256. //#define ENABLE_IAP 0x84           //if SYSCLK<6MHz
  257. //#define ENABLE_IAP 0x85           //if SYSCLK<3MHz
  258. //#define ENABLE_IAP 0x86           //if SYSCLK<2MHz
  259. //#define ENABLE_IAP 0x87           //if SYSCLK<1MHz

  260. //测试地址
  261. #define IAP_ADDRESS 0x0400

  262. void IapIdle();
  263. BYTE IapReadByte(WORD addr);
  264. void IapProgramByte(WORD addr, BYTE dat);
  265. void IapEraseSector(WORD addr);
  266. BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
  267. BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
  268. void InitUart();
  269. BYTE SendData(BYTE dat);

  270. #define display_Begin_LED() Begin_LED = 0
  271. #define off_Begin_LED()     Begin_LED = 1
  272. #define display_OK_LED()    OK_LED = 0
  273. #define off_OK_LED()        OK_LED = 1
  274. #define display_ERROR_LED() ERROR_LED = 0
  275. #define off_ERROR_LED()     ERROR_LED = 1

  276. //#define USED_BYTE_QTY_IN_ONE_SECTOR   1
  277. //#define USED_BYTE_QTY_IN_ONE_SECTOR   2
  278. //#define USED_BYTE_QTY_IN_ONE_SECTOR   4
  279. //#define USED_BYTE_QTY_IN_ONE_SECTOR   8
  280. //#define USED_BYTE_QTY_IN_ONE_SECTOR   16
  281. //#define USED_BYTE_QTY_IN_ONE_SECTOR   32
  282. //#define USED_BYTE_QTY_IN_ONE_SECTOR   64
  283. #define USED_BYTE_QTY_IN_ONE_SECTOR     128
  284. //#define USED_BYTE_QTY_IN_ONE_SECTOR   256
  285. //#define USED_BYTE_QTY_IN_ONE_SECTOR   512

  286. #define DEBUG_Data_Memory_Begin_Sector_addr     0x0400

  287. BYTE xdata protect_buffer[USED_BYTE_QTY_IN_ONE_SECTOR];

  288. /* 测试常量数组 */
  289. BYTE code Test_array_total[512] =
  290. {
  291.     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
  292.     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
  293.     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
  294.     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
  295.     0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
  296.     0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
  297.     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  298.     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
  299.     0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
  300.     0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
  301.     0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
  302.     0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
  303.     0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
  304.     0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
  305.     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
  306.     0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
  307.     0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0,
  308.     0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0,
  309.     0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0,
  310.     0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,0xc1,0xc0,
  311.     0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0,
  312.     0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,0xa1,0xa0,
  313.     0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96,0x95,0x94,0x93,0x92,0x91,0x90,
  314.     0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80,
  315.     0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70,
  316.     0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60,
  317.     0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,
  318.     0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,
  319.     0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x33,0x36,0x35,0x34,0x33,0x32,0x31,0x30,
  320.     0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,
  321.     0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,
  322.     0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
  323. };

  324. void main()
  325. {
  326.     P0M0 = 0x00;
  327.     P0M1 = 0x00;
  328.     P1M0 = 0x00;
  329.     P1M1 = 0x00;
  330.     P2M0 = 0x00;
  331.     P2M1 = 0x00;
  332.     P3M0 = 0x00;
  333.     P3M1 = 0x00;
  334.     P4M0 = 0x00;
  335.     P4M1 = 0x00;
  336.     P5M0 = 0x00;
  337.     P5M1 = 0x00;
  338.     P6M0 = 0x00;
  339.     P6M1 = 0x00;
  340.     P7M0 = 0x00;
  341.     P7M1 = 0x00;

  342.     InitUart();

  343. //  if(sequential_write_flash_in_one_sector(DEBUG_Data_Memory_Begin_Sector_addr, USED_BYTE_QTY_IN_ONE_SECTOR, Test_array_total))
  344. //      display_OK_LED();
  345. //  else
  346. //      display_ERROR_LED();

  347.     if(write_flash_with_protect_in_one_sector(DEBUG_Data_Memory_Begin_Sector_addr+0x3, USED_BYTE_QTY_IN_ONE_SECTOR-0x30, Test_array_total))
  348.         display_OK_LED();
  349.     else
  350.         display_ERROR_LED();

  351.     while(1);
  352. }

  353. /*----------------------------
  354. 关闭IAP
  355. ----------------------------*/
  356. void IapIdle()
  357. {
  358.     IAP_CONTR = 0;                  //关闭IAP功能
  359.     IAP_CMD = 0;                    //清除命令寄存器
  360.     IAP_TRIG = 0;                   //清除触发寄存器
  361.     IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
  362.     IAP_ADDRL = 0;
  363. }

  364. /*----------------------------
  365. 从ISP/IAP/EEPROM区域读取一字节
  366. ----------------------------*/
  367. BYTE IapReadByte(WORD addr)
  368. {
  369.     BYTE dat;                       //数据缓冲区

  370.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  371.     IAP_CMD = CMD_READ;             //设置IAP命令
  372.     IAP_ADDRL = addr;               //设置IAP低地址
  373.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  374.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  375.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  376.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  377.     dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
  378.     IapIdle();                      //关闭IAP功能

  379.     return dat;                     //返回
  380. }

  381. /*----------------------------
  382. 写一字节数据到ISP/IAP/EEPROM区域
  383. ----------------------------*/
  384. void IapProgramByte(WORD addr, BYTE dat)
  385. {
  386.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  387.     IAP_CMD = CMD_PROGRAM;          //设置IAP命令
  388.     IAP_ADDRL = addr;               //设置IAP低地址
  389.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  390.     IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
  391.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  392.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  393.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  394.     IapIdle();
  395. }

  396. /*----------------------------
  397. 扇区擦除
  398. ----------------------------*/
  399. void IapEraseSector(WORD addr)
  400. {
  401.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  402.     IAP_CMD = CMD_ERASE;            //设置IAP命令
  403.     IAP_ADDRL = addr;               //设置IAP低地址
  404.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  405.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  406.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  407.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  408.     IapIdle();
  409. }

  410. /* 写数据进 数据Flash存储器, 只在同一个扇区内写,不保留原有数据 */
  411. /* begin_addr,被写数据Flash开始地址;counter,连续写多少个字节; array[],数据来源   */
  412. BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[])
  413. {
  414.     WORD i = 0;
  415.     WORD in_sector_begin_addr = 0;
  416.     WORD sector_addr = 0;

  417.     /* 判是否是有效范围,此函数不允许跨扇区操作 */
  418.     if(counter > USED_BYTE_QTY_IN_ONE_SECTOR)
  419.         return  ERROR;
  420.     in_sector_begin_addr = begin_addr & 0x01ff;
  421.     if((in_sector_begin_addr + counter) > USED_BYTE_QTY_IN_ONE_SECTOR)
  422.         return ERROR;

  423.     /* 擦除 要修改/写入 的扇区 */
  424.     IapEraseSector(begin_addr);

  425.     for(i=0; i<counter; i++)
  426.     {
  427.         /* 写一个字节 */
  428.         IapProgramByte(begin_addr, array[i]);
  429.         /*  比较对错 */
  430.         if (SendData(IapReadByte(begin_addr)) != array[i])
  431.         {
  432.             IapIdle();
  433.             return ERROR;
  434.         }
  435.         begin_addr++;
  436.     }
  437.     IapIdle();
  438.     return  OK;
  439. }

  440. /* 写数据进数据Flash存储器(EEPROM), 只在同一个扇区内写,保留同一扇区中不需修改的数据    */
  441. /* begin_addr,被写数据Flash开始地址;counter,连续写多少个字节; array[],数据来源       */
  442. BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[])
  443. {
  444.     WORD i = 0;
  445.     WORD in_sector_begin_addr = 0;
  446.     WORD sector_addr = 0;
  447.     WORD byte_addr = 0;

  448.     /* 判是否是有效范围,此函数不允许跨扇区操作 */
  449.     if(counter > USED_BYTE_QTY_IN_ONE_SECTOR)
  450.         return ERROR;
  451.     in_sector_begin_addr = begin_addr & 0x01ff;
  452.     /* 假定从扇区的第0个字节开始,到USED_BYTE_QTY_IN_ONE_SECTOR-1个字节结束,后面部分不用,程序易编写 */
  453.     if((in_sector_begin_addr + counter) > USED_BYTE_QTY_IN_ONE_SECTOR)
  454.         return ERROR;

  455.     /* 将该扇区数据 0 - (USED_BYTE_QTY_IN_ONE_SECTOR-1) 字节数据读入缓冲区保护 */
  456.     sector_addr = (begin_addr & 0xfe00);
  457.     byte_addr = sector_addr;

  458.     for(i = 0; i < USED_BYTE_QTY_IN_ONE_SECTOR; i++)
  459.     {
  460.         protect_buffer[i] = IapReadByte(byte_addr++);
  461.     }

  462.     /* 将要写入的数据写入保护缓冲区的相应区域,其余部分保留 */
  463.     for(i = 0; i < counter; i++)
  464.     {
  465.         protect_buffer[in_sector_begin_addr++] = array[i];
  466.     }

  467.     /* 擦除 要修改/写入 的扇区 */
  468.     IapEraseSector(sector_addr);

  469.     /* 将保护缓冲区的数据写入 Data Flash, EEPROM */
  470.     byte_addr = sector_addr;
  471.     for(i = 0; i< USED_BYTE_QTY_IN_ONE_SECTOR; i++)
  472.     {
  473.         /* 写一个字节 */
  474.         IapProgramByte(byte_addr, protect_buffer[i]);
  475.         /*  比较对错 */
  476.         if (SendData(IapReadByte(begin_addr)) != protect_buffer[i])
  477.         {
  478.             IapIdle();
  479.             return ERROR;
  480.         }
  481.         byte_addr++;
  482.     }
  483.     IapIdle();
  484.     return OK;
  485. }

  486. /*----------------------------
  487. 初始化串口
  488. ----------------------------*/
  489. void InitUart()
  490. {
  491.     SCON = 0x5a;                //设置串口为8位可变波特率
  492. #if URMD == 0
  493.     T2L = 0xd8;                 //设置波特率重装值
  494.     T2H = 0xff;                 //115200 bps(65536-18432000/4/115200)
  495.     AUXR = 0x14;                //T2为1T模式, 并启动定时器2
  496.     AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
  497. #elif URMD == 1
  498.     AUXR = 0x40;                //定时器1为1T模式
  499.     TMOD = 0x00;                //定时器1为模式0(16位自动重载)
  500.     TL1 = 0xd8;                 //设置波特率重装值
  501.     TH1 = 0xff;                 //115200 bps(65536-18432000/4/115200)
  502.     TR1 = 1;                    //定时器1开始启动
  503. #else
  504.     TMOD = 0x20;                //设置定时器1为8位自动重装载模式
  505.     AUXR = 0x40;                //定时器1为1T模式
  506.     TH1 = TL1 = 0xfb;           //115200 bps(256 - 18432000/32/115200)
  507.     TR1 = 1;
  508. #endif
  509. }

  510. /*----------------------------
  511. 发送串口数据
  512. ----------------------------*/
  513. BYTE SendData(BYTE dat)
  514. {
  515.     while (!TI);                 //等待前一个数据发送完成
  516.     TI = 0;                      //清除发送标志
  517.     SBUF = dat;                  //发送当前数据

  518.     return dat;
  519. }
复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表