STC89C51单片机通讯协议

本文详细介绍了STC单片机的ISP(In-System Programming)及IAP(In-Application Programming)通信协议的具体实现过程,包括引导码、设置通讯速率、通讯同步、擦除命令、编程及重启动等步骤,并提供了具体的数据帧结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:

         ISPSTC单片机的编程软件;

         IAPCTC单片机固化的烧写软件;

1、引导码

ISP7F 7F 7F 7F 7F 

ISP一直发送0x7F,直到收到IAP的回复帧;

IAP68 00 39 00 09 7A 09 7A 09 7A 

     09 76 09 7A 09 76 09 7A 09 7A 

     38 43 FD F1 10 82 00 00 00 00 

     00 00 00 00 00 00 00 00 00 00 

     00 00 00 00 00 00 00 00 00 00 

     00 00 00 00 00 AC 16 

IAP回复帧:没有帧头,有帧尾0x16,校验0xAC,

校验方式:从0x680xAC前面一个数加和,再加1,取低8位;

IAP的回复帧根据单片机的晶振不同,回复的也不同,上面的是11.0592的晶振;

2、设置通讯速率

ISP46 B9 6A 00 0C 8F FF 7D 00 FE 78 80 77 16

IAP46 B9 68 00 0C 8F FF 7D 00 FE 78 80 75 16 

ISP46 B9 6A 00 0B 8E FF 7D 00 FF 78 F6 16

IAP46 B9 68 00 0B 8E FF 7D 00 FF 78 F4 16

结构:Head(2) sign(1) reserve(1) length(1) frame(1) data(x) checksum(1) trail(1)

Head(2) 0x46 0xb9

Sign (1) 0x6a  pc->mcu

       0x68  mcu->pc

Reserve (1) 0x00

Length(1) 0x0c = head + sign + reserve + length + frame + data

Frame(1) 0x8F0x8E 不同的数表示不同的操作

Data(x) 

Checksum(1) 0x77 headchecksum前一个字节的加和,再加1,取低8位;

Trail1) 0x16

3、通讯同步

ISP46 B9 6A 00 0C 80 02 00 36 01 F1 10 30 16

IAP46 B9 68 00 06 80 EE 16

收发同步5

ISP结构:Head(2) sign(1) reserve(1) length(1) frame(1) data(x) checksum(1) trail(1)

IAP结构:Head(2) sign(1) reserve(1) length(1) frame(1) checksum(1) trail(1)

Frame10x80 

4、擦出命令

ISP46 B9 6A 00 0D 84 0B 33 33 33 33 33 33 38 16

IAP46 B9 68 00 06 80 EE 16

ISP结构:Head(2) sign(1) reserve(1) length(1) frame(1) data(x) checksum(1) trail(1)

IAP结构:Head(2) sign(1) reserve(1) length(1) frame(1) checksum(1) trail(1)

Frame10x84 擦出命令

          0x80  

5、编程

ISP46 B9 6A 00 8C 00 00 00 00 00 00 80 02 0D 2F 12 13 AD 02 15 22 FF FF 02 12 B9 FF E4 33 FE E4 2F F5 82 74 F0 3E F5 83 E0 FA 12 14 55 AF 02 22 02 08 48 E4 90 00 B7 F0 90 00 B7 E0 C3 94 04 40 03 02 02 39 E0 FF 75 F0 07 A4 24 05 F5 82 E4 34 00 F5 83 E0 FE EF 75 F0 07 A4 24 67 F5 82 E4 34 00 F5 83 E0 FF 6E 60 1F EF 24 C6 90 00 B8 F0 C3 94 00 40 10 E0 FD 94 20 50 0A 90 00 B7 E0 FF 12 13 65 80 03 7F 01 22 90 00 B7 E0 FF 75 46 16

IAP46 B9 68 00 07 80 D0 BF 16

结构:Head(2) sign(1) reserve(1) length(1) frame(1) data(x) checksum(1) trail(1)

Frame(1) 0x00 编程命令

ISP帧中data结构:addr(4) lenght(2)programe(128)

Addr(4) 0x00 0x00 0x00 0x00 地址高位->低位,这个地址是写入单片机编程的起始地址,第1帧的地址是0x00000000,第2帧的地址是0x00000080,第3帧的地址是0x00000100,因为每一帧的编程数据长度是0x80,每发一帧地址+0x80

Lenght20x00 0x80 每一帧的编程数据长度都是0x0080

Programe128) 编程数据内容

IAP帧中的data10xD0  ISP帧中datax)数据的加和值,取低8位,不要加1

把要编程的内容全部发完,如果发送的编程数据不够0x80个字节,则在后面填充0x00,不齐0x80个字节;

6、重启动

ISPFE FE FE FE 

         46 B9 6A 00 06 82 F2 16

ISP发送上面的内容两次

IAP没有回复

结构:Head(2) sign(1) reserve(1) length(1) frame(1) checksum(1) trail(1)

Frame0x82) 重启命令

/*---------------------------------------------------------------------*/ /* --- STC MCU Limited ------------------------------------------------*/ /* --- 使用主芯片对从芯片(限STC15系列)进行ISP下载举例 -----------------*/ /* --- Mobile: (86)13922805190 ----------------------------------------*/ /* --- Fax: 86-755-82905966 -------------------------------------------*/ /* --- Tel: 86-755-82948412 -------------------------------------------*/ /* --- Web: www.STCMCU.com --------------------------------------------*/ /* 如果要在程序中使用此代,请在程序中注明使用了宏晶科技的资料及程序 */ /* 如果要在文章中应用此代,请在文章中注明使用了宏晶科技的资料及程序 */ /*---------------------------------------------------------------------*/ //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译 //假定测试芯片的工作频率为11.0592MHz //注意:使用本代STC15系列的单片机进行下载时,必须要执行了Download代之后, //才能给目标芯片上电,否则目标芯片将无法正确下载 #include "reg51.h" typedef bit BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; //宏、常量定义 #define FALSE 0 #define TRUE 1 #define LOBYTE(w) ((BYTE)(WORD)(w)) #define HIBYTE(w) ((BYTE)((WORD)(w) >> 8)) #define MINBAUD 2400L #define MAXBAUD 115200L #define FOSC 11059200L //主控芯片工作频率 #define BR(n) (65536 - FOSC/4/(n)) //主控芯片串口波特率计算公式 #define T1MS (65536 - FOSC/1000) //主控芯片1ms定时初值 #define FUSER 24000000L //15系列目标芯片工作频率 #define RL(n) (65536 - FUSER/4/(n)) //15系列目标芯片串口波特率计算公式 //SFR定义 sfr AUXR = 0x8e; //变量定义 BOOL f1ms; //1ms标志位 BOOL UartBusy; //串口发送忙标志位 BOOL UartReceived; //串口数据接收完成标志位 BYTE UartRecvStep; //串口数据接收控制 BYTE TimeOut; //串口通讯超时计数器 BYTE xdata TxBuffer[256]; //串口数据发送缓冲区 BYTE xdata RxBuffer[256]; //串口数据接收缓冲区 char code DEMO[256]; //演示代数据 //函数声明 void Initial(void); void DelayXms(WORD x); BYTE UartSend(BYTE dat); void CommInit(void); void CommSend(BYTE size); BOOL Download(BYTE *pdat, long size); //主函数入口 void main(void) { while (1) { Initial(); if (Download(DEMO, 0x0100)) { //下载成功 P3 = 0xff; DelayXms(500); P3 = 0x00; DelayXms(500); P3 = 0xff; DelayXms(500); P3 = 0x00; DelayXms(500); P3 = 0xff; DelayXms(500); P3 = 0x00; DelayXms(500); P3 = 0xff; } else { //下载失败 P3 = 0xff; DelayXms(500); P3 = 0xf3; DelayXms(500); P3 = 0xff; DelayXms(500); P3 = 0xf3; DelayXms(500); P3 = 0xff; DelayXms(500); P3 = 0xf3; DelayXms(500); P3 = 0xff; } } } //1ms定时器中断服务程序 void tm0(void) interrupt 1 using 1 { static BYTE Counter100; f1ms = TRUE; if (Counter100-- == 0) { Counter100 = 100; if (TimeOut) TimeOut--; } } //串口中断服务程序 void uart(void) interrupt 4 using 1 { static WORD RecvSum; static BYTE RecvIndex; static BYTE RecvCount; BYTE dat; if (TI) { TI = 0; UartBusy = FALSE; } if (RI) { RI = 0; dat = SBUF; switch (UartRecvStep) { case 1: if (dat != 0xb9) goto L_CheckFirst; UartRecvStep++; break; case 2: if (dat != 0x68) goto L_CheckFirst; UartRecvStep++; break; case 3: if (dat != 0x00) goto L_CheckFirst; UartRecvStep++; break; case 4: RecvSum = 0x68 + dat; RecvCount = dat - 6; RecvIndex = 0; UartRecvStep++; break; case 5: RecvSum += dat; RxBuffer[RecvIndex++] = dat; if (RecvIndex == RecvCount) UartRecvStep++; break; case 6: if (dat != HIBYTE(RecvSum)) goto L_CheckFirst; UartRecvStep++; break; case 7: if (dat != LOBYTE(RecvSum)) goto L_CheckFirst; UartRecvStep++; break; case 8: if (dat != 0x16) goto L_CheckFirst; UartReceived = TRUE; UartRecvStep++; break; L_CheckFirst: case 0: default: CommInit(); UartRecvStep = (dat == 0x46 ? 1 : 0); break; } } } //系统初始化 void Initial(void) { UartBusy = FALSE; SCON = 0xd0; //串口数据模式必须为8位数据+1位偶检验 AUXR = 0xc0; TMOD = 0x00; TH0 = HIBYTE(T1MS); TL0 = LOBYTE(T1MS); TR0 = 1; TH1 = HIBYTE(BR(MINBAUD)); TL1 = LOBYTE(BR(MINBAUD)); TR1 = 1; ET0 = 1; ES = 1; EA = 1; } //Xms延时程序 void DelayXms(WORD x) { do { f1ms = FALSE; while (!f1ms); } while (x--); } //串口数据发送程序 BYTE UartSend(BYTE dat) { while (UartBusy); UartBusy = TRUE; ACC = dat; TB8 = P; SBUF = ACC; return dat; } //串口通讯初始化 void CommInit(void) { UartRecvStep = 0; TimeOut = 20; UartReceived = FALSE; } //发送串口通讯数据包 void CommSend(BYTE size) { WORD sum; BYTE i; UartSend(0x46); UartSend(0xb9); UartSend(0x6a); UartSend(0x00); sum = size + 6 + 0x6a; UartSend(size + 6); for (i=0; i<size; i++) { sum += UartSend(TxBuffer[i]); } UartSend(HIBYTE(sum)); UartSend(LOBYTE(sum)); UartSend(0x16); while (UartBusy); CommInit(); } //对STC15系列的芯片进行数据下载程序 BOOL Download(BYTE *pdat, long size) { BYTE arg; BYTE cnt; WORD addr; //握手 CommInit(); while (1) { if (UartRecvStep == 0) { UartSend(0x7f); DelayXms(10); } if (UartReceived) { arg = RxBuffer[4]; if (RxBuffer[0] == 0x50) break; return FALSE; } } //设置参数(设置从芯片使用最高的波特率以及擦除等待时间等参数) TxBuffer[0] = 0x01; TxBuffer[1] = arg; TxBuffer[2] = 0x40; TxBuffer[3] = HIBYTE(RL(MAXBAUD)); TxBuffer[4] = LOBYTE(RL(MAXBAUD)); TxBuffer[5] = 0x00; TxBuffer[6] = 0x00; TxBuffer[7] = 0xc3; CommSend(8); while (1) { if (TimeOut == 0) return FALSE; if (UartReceived) { if (RxBuffer[0] == 0x01) break; return FALSE; } } //准备 TH1 = HIBYTE(BR(MAXBAUD)); TL1 = LOBYTE(BR(MAXBAUD)); DelayXms(10); TxBuffer[0] = 0x05; CommSend(1); while (1) { if (TimeOut == 0) return FALSE; if (UartReceived) { if (RxBuffer[0] == 0x05) break; return FALSE; } } //擦除 DelayXms(10); TxBuffer[0] = 0x03; TxBuffer[1] = 0x00; CommSend(2); TimeOut = 100; while (1) { if (TimeOut == 0) return FALSE; if (UartReceived) { if (RxBuffer[0] == 0x03) break; return FALSE; } } //写用户代 DelayXms(10); addr = 0; TxBuffer[0] = 0x22; while (addr < size) { TxBuffer[1] = HIBYTE(addr); TxBuffer[2] = LOBYTE(addr); cnt = 0; while (addr = 128) break; } CommSend(cnt + 3); while (1) { if (TimeOut == 0) return FALSE; if (UartReceived) { if ((RxBuffer[0] == 0x02) && (RxBuffer[1] == 'T')) break; return FALSE; } } TxBuffer[0] = 0x02; } ////写硬件选项 ////如果不需要修改硬件选项,此步骤可直接跳过,此时所有的硬件选项 ////都维持不变,MCU的频率为上一次所调节频率 ////若写硬件选项,MCU的内部IRC频率将被固定写为24M, ////建议:第一次使用STC-ISP下载软件将从芯片的硬件选项设置好 //// 以后再使用主芯片对从芯片下载程序时不写硬件选项 //DelayXms(10); //for (cnt=0; cnt<128; cnt++) //{ // TxBuffer[cnt] = 0xff; //} //TxBuffer[0] = 0x04; //TxBuffer[1] = 0x00; //TxBuffer[2] = 0x00; //TxBuffer[34] = 0xfd; //TxBuffer[62] = arg; //TxBuffer[63] = 0x7f; //TxBuffer[64] = 0xf7; //TxBuffer[65] = 0x7b; //TxBuffer[66] = 0x1f; //CommSend(67); //while (1) //{ // if (TimeOut == 0) return FALSE; // if (UartReceived) // { // if ((RxBuffer[0] == 0x04) && (RxBuffer[1] == 'T')) break; // return FALSE; // } //} //下载完成 return TRUE; } char code DEMO[256] = { 0x02,0x00,0x5E,0x12,0x00,0x4B,0x75,0xB0, 0xEF,0x12,0x00,0x2C,0x75,0xB0,0xDF,0x12, 0x00,0x2C,0x75,0xB0,0xFE,0x12,0x00,0x2C, 0x75,0xB0,0xFD,0x12,0x00,0x2C,0x75,0xB0, 0xFB,0x12,0x00,0x2C,0x75,0xB0,0xF7,0x12, 0x00,0x2C,0x80,0xDA,0xE4,0xFF,0xFE,0xE4, 0xFD,0xFC,0x0D,0xBD,0x00,0x01,0x0C,0xBC, 0x01,0xF8,0xBD,0xF4,0xF5,0x0F,0xBF,0x00, 0x01,0x0E,0xBE,0x03,0xEA,0xBF,0xE8,0xE7, 0x02,0x00,0x4B,0x75,0x80,0xFF,0x75,0x90, 0xFF,0x75,0xA0,0xFF,0x75,0xB0,0xFF,0x75, 0xC0,0xFF,0x75,0xC8,0xFF,0x22,0x78,0x7F, 0xE4,0xF6,0xD8,0xFD,0x75,0x81,0x07,0x02, 0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值