最新版本最新版本:
(原文件名:STC免手动烧写+逻辑分析仪电路图(初始版).jpg)
(原文件名:STC免手动烧写+逻辑分析仪电路图(改进版).jpg)
(原文件名:a.jpg)
(原文件名:20111229019.jpg)
// 作品:STC免手动烧写(自适应波特率自动冷启) + 简易逻辑分析仪 // 芯片:STC15F104E // 晶振:45MHz // 编译:Keil uVision4 V9.00 // // 说明:自适应STC-ISP软件最低波特率(1200bps/2400bps/4800bps) //3种模式:①自动烧写(默认) //②逻辑分析仪(正向波形) //③逻辑分析仪(反向波形) //①②③模式下,系统板都可以正常串口通信。 //②③模式下,也可以烧写程序(手动烧写),不过正在“采样”时请不要烧写程序以及系统板串口通信。 // // 注:建议烧写程序时启动看门狗(预分频数256,约2.2S @ 45MHz) // //另:关于STC-ISP V4.88版本,发现用PL2303HX芯片烧写STC15系列很难成功,最低/高波特率都选用4800bps才可以烧写。 //关于STC-ISP V6.06版本,用PL2303HX芯片烧写STC15系列非常好(直接用默认的最低/高波特率), //但V6.06版本内部R/C振荡器最高只可以选33.1776MHz。 //用FT232芯片烧写,则通杀STC-ISP所有版本(直接用默认的最低/高波特率)。 //
#include "STC15F104E.H" #include "MY_SET.h"
sbit LED= P3^0;//指示灯 sbit KEY= P3^1;//按键 sbit RXB= P3^2; sbit TXB= P3^3; sbit PNP= P3^4;//PNP三极管 sbit IO_in = P3^5;//分析仪采样引脚
uint8Mode;//模式 bitB_init;//初始化标志 uint8KEY_Value; //按键消抖计数 bitON;//按键标志 bitOver; bitLED_key;//模式指示灯(在按键上扩展) uint16Count;//闪烁计数 bitP_N;//正向标志 uint8BIT8,cnt,Dat; uint16Time;
uint8 TBUF,RBUF;//发送/接收缓存 uint8 TDAT,RDAT;//发送/接收数据暂存 uint8 TCNT,RCNT;//发送/接收计数器 uint8 TBIT,RBIT;//发送/接收比特数 bitTING,RING;//开始发送/接收标志 bitTEND,REND;//发送/接收完成标志
bitSTART;//重启标志 uint8 Correct_nums;//『连续正确』计数器 uint8 Error_nums;//错误累加计数器 uint8 Status;//波特率状态
void YS(uint8 n) { uint8 a,b,c;
while(n--) { for(c=66;c>0;c--) for(b=100;b>0;b--) for(a=100;a>0;a--); } }
void UART_INIT() { TING = 0; RING = 0; TEND = 1; REND = 0; TCNT = 0; RCNT = 0; }
void Analyzer_Init() { TR1 = 0; TF1 = 0; Time = 0; BIT8 = 0; TL0 = 0x7E; //初始化T0和设定重载值 TH0 = 0xFF;//修改成 115200bps LED = 0;//指示灯开 }
void UART_Change() { if(++Status > 2)Status=0; switch(Status) { case 0: TL0=(65536-15000000/1200); TH0=(65536-15000000/1200)>>8; break; // 1200bps case 1: TL0=(65536-15000000/2400); TH0=(65536-15000000/2400)>>8; break; // 2400bps case 2: TL0=(65536-15000000/4800); TH0=(65536-15000000/4800)>>8; break; // 4800bps } }
void Restart() { if(START) { START = 0;
TR0 = 0; PNP = 1;//关电 LED = 1; YS(10);//从『加载HEX』到『提示上电』有5秒,但不必等到『提示上电』 WDT_CONR |= 0x10;//清看门狗(预分频数256,约2.2S @ 45MHz) PNP = 0;//通电 LED = 0; YS(30); WDT_CONR |= 0x10;//清看门狗(预分频数256,约2.2S @ 45MHz)
TR0 = 1; RING = 0; REND = 0; RCNT = 0; } }
void main() { uint8 i;
P33 = 1; WDT_CONR |= 0x10; //清看门狗(预分频数256,约2.2S @ 45MHz) PNP = 0;//通电 LED= 0; LED_key = 1;//关
for(i=0;i<30;i++){ YS(1); LED = ~LED; } //冷启/低压复位 指示 WDT_CONR |= 0x10; //清看门狗(预分频数256,约2.2S @ 45MHz)
TMOD = 0x00;//T0、T1处于16位自动重装模式 AUXR = 0xC0;//T0、T1工作在1T模式 TL1 = (65536-903); TH1 = (65536-903)>>8; UART_Change(); TR0 = 1; EA= 1; ET0 = 1; PT0 = 1;//提高T0的中断优先级 ET1 = 1; UART_INIT();
Mode = 0;
while(1) { switch(Mode) { case 0: if(B_init) { B_init=0; TR1=0; PNP = 0;//通电 LED=0; UART_Change(); UART_INIT(); } Restart(); LED_key = 1; break;
case 1: if(B_init){ B_init=0; P_N=1; Analyzer_Init(); } if(!IO_in){ TR1=1; LED=1;}//启动定时器1,采样开始 if(Over) { Over=0; if(++Time > 3320)Analyzer_Init();//约16.6秒(5ms * 3320),即每次采集完,过4秒(16.6S-12.6S)后重新工作 } LED_key = 0; break;
case 2: if(B_init){ B_init=0; P_N=0; Analyzer_Init(); } if(!IO_in){ TR1=1; LED=1;} if(Over) { Over=0; if(++Time > 3320)Analyzer_Init(); } if(++Count >10000){ Count=0; LED_key=!LED_key;} //闪烁 break;
default:Mode=0; break; }
//按键检测 KEY = 1;//拉高电平 NOP12();//稍微延时 if(!KEY) { if(ON==0)KEY_Value++; if(KEY_Value > 200) { KEY_Value = 0; ON = 1;//按键标志置“1” if(++Mode > 2)Mode=0; B_init = 1;//『初始化标志』置“1” } } else { KEY_Value=0; ON=0; }
//恢复指示灯状态 if(LED_key)KEY=1; elseKEY=0;
WDT_CONR |= 0x10;//清看门狗(预分频数256,约2.2S @ 45MHz) } }
void tm0() interrupt 1 using 1 { if(RING) { if(--RCNT == 0) { RCNT = 3;//复位接收波特率计数器 if(--RBIT == 0) { RBUF = RDAT;//保存数据到RBuf管理 RING = 0;//停止接收 REND = 1;//设置接收完成标志 } else { RDAT >>= 1; if(RXB) RDAT |= 0x80; //RX数据转移到RX缓冲区 } } } else if(!RXB)//是否检测到低电平 { RING = 1;//设置开始接收标志 RCNT = 4;//初始接收波特率计数器 RBIT = 9;//初化始接收比特数(8个数据位+1个停止位) }
if(--TCNT == 0) { TCNT = 3;//复位发送波特率计数器 if(TING)//判断是否发送 { if(TBIT == 0) { TXB = 0;//发送起始位 TDAT = TBUF;//加载数据从TBUF至TDAT TBIT = 9;//初化始发送比特数(8位数据位+1个停止位) } else { TDAT >>= 1;//位移数据至CY if(--TBIT == 0) { TXB = 1; TING = 0;//停止发送 TEND = 1;//设置发送完成标志 } else { TXB = CY;//写CY至TX端口 } } } }
if((Mode==0) && REND) { REND = 0; if(RBUF == 0x7F) { if(++Correct_nums > 10) { START=1; Correct_nums=0; Error_nums=0; } } else { Correct_nums=0; if(++Error_nums > 6) { TR0 = 0; Error_nums=0; Correct_nums=0; UART_Change(); RING = 0; REND = 0; RCNT = 0; TR0 = 1; } } } }
void tm1() interrupt 3 { if(IO_in)Dat |= 0x01; if(++BIT8 == 8) //每采集8次发送一次 { if(P_N)TBUF =Dat;//正向输出 elseTBUF = ~Dat;//反向输出 TING = 1; BIT8 = 0; } Dat <= 1; if(++cnt == 0)Over=1;//约5ms置1一次 } 那个是旧版本,电路图也有些不妥(应该把10Ω电阻去掉),下载“最低波特率”固定,而且没有逻辑分析仪功能
在旧版上改进:自动适应STC-ISP软件中的“最低波特率” 3种波特率,可选“1200bps/2400bps/4800bps” 但也没有逻辑分析仪功能
程序全新修改; 自动适应STC-ISP软件中的“最低波特率” 3种波特率,可选“1200bps/2400bps/4800bps”; 增加简易单路逻辑分析仪。
PS: STC-ISP软件中选用不同型号的STC时,默认的下载“最低波特率”不同,比如: STC89系列:默认 最低波特率 1200bps STC12系列:默认 最低波特率 2400bps STC15系列:默认 最低波特率 4800bps 懒得每次选择,所以增加自适应3种最低波特率“1200bps/2400bps/4800bps”功能
另: 在STC单片机中有两个程序区,用户程序区与ISP程序区。单片机上电后(冷启动,并非外部手动复位或看门狗复位),先会运行ISP程序,检测是否有合法的下载命令流,占时几十毫秒到几百毫秒,如果没有合法的下载命令流,则立即运行用户程序。 如果有合法的下载命令流,则ISP监控程序开始与ISP下载软件通信,软件也会进入编程模式,向监控程序发送程序码,监控程序接收程序码,并将其写入用户程序区中。在编程完毕,对程序校验成功后,用户程序立即生效,开始运行用户程序。 STC-ISP尝试与MCU握手连接的时候,是以“最低波特率”设置项中的波特率不断的从串口发送“0x7F”信号,直到MCU上电冷启(或者软复位至ISP)经几十毫秒到几百毫秒检测下载命令流后,MCU做出响应,STC-ISP才停止发送“0x7F”信号开始烧写。
用简易单路逻辑分析仪捕捉,STC-ISP下载程序前的串口命令流 这个程序构思不完善,主要是自动适应波特率部分有些BUG, 如果是固定程序中的最低波特率(对应STC-ISP的最低波特率选项,最高波特率选项任意),这个程序就运行很好, 但这样就不方便了,因为STC-ISP不同版本及不同型号默认最低波特率选项不同,懒得每次更换都改下STC-ISP的最低波特率选项。
所以使用新方案解决: 不再用硬件串口/模拟串口捕捉数据,先直接用计时器捕捉TXD上一定数量的连续电平数据,然后分析电平数据(比如:低电平时间相等,0x7F次数,……等等多重验证), 如果符合条件就重启(断电几百ms后上电,隔>1.5S恢复监测); 如果不符合条件则重新监测。
上面这个方案几近完美,负责监控的STC15F104E也不需要超频到45M了,22.1184M就可以, 同时自动适STC-ISP的最低波特率选项范围更宽1200bps/2400bps/4800bps/9600bps, 完美版的方案就是这样,挺简单的,程序就不传了
|