STC8H8K64U-软件实现串口不断电烧录程序
本帖最后由 challis 于 2024-2-1 08:45 编辑主要原理是利用识别串口命令后进行软件复位,操作IAP_CONTR寄存器来重启芯片后从ISP区开始执行代码,来实现不断电烧录程序
完整代码在14楼
首先,利用STC工具,生成5.5296MHz,波特率为19200的串口代码
void Uart1_Isr(void) interrupt 4
{
if (TI) //检测串口1发送中断
{
TI = 0; //清除串口1发送中断请求位
}
if (RI) //检测串口1接收中断
{
RI = 0; //清除串口1接收中断请求位
}
}
void Uart1_Init(void) //19200bps@5.5296MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xFA; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
}
构造结构体做缓存,用来缓存接收的数据
struct BUFF_DATA
{
uchar rptr;
uchar wptr;
char buff;
}; 定义如果5ms没有收到数据,则输出传输完成.
使用双缓冲机制,uart_buff用来缓存串口接收到的信息,str_buff用来储存一条一条的命令
新建2个BUFF_DATA的对象,并且定义一些常用操作宏
struct BUFF_DATA xdata uart_buff,xdata str_buff;
#define BUFF_POP(x) x.buff
#define BUFF_PUSH(x,d) x.buff = d
#define BUFF_HAS_DATA(x) (x.rptr != x.wptr)
#define BUFF_RESET(x) x.rptr=0;x.wptr=0 串口中断中逻辑为:如果发送完成,则将TI置0,且设置send_busy=0;
如果接收到数据,则将RI置0,且将数据存入缓存,将timeout置为5;
void Uart1_Isr(void) interrupt 4
{
if (TI)
{
TI = 0;
send_busy = 0;
}
if (RI)
{
RI = 0;
BUFF_PUSH(uart_buff,SBUF);
recv_timeout = 5;
}
} 串口初始化中添加设置send_busy=0;且初始化uart_buff
void Uart1_Init(void) //19200bps@5.5296MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xFA; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
EA = 1;
send_busy = 0;
BUFF_RESET(uart_buff);
}
实现串口发送函数,发送前检测,如果send_busy,则等待
void UartSend(char dat)
{
while(send_busy);
send_busy = 1;
SBUF = dat;
}
void UartSendStr(char *p)
{
while(*p)
UartSend(*p++);
} 主函数中循环处理,如果recv_timeout>0,则证明接收到了数据,这时,循环将串口缓存的数据取出,放入字符串缓存中,直到传输超时.传输超时则认为命令传输完成,则调用DealString函数进行处理
while(1)
{
if(recv_timeout>0)
{
BUFF_RESET(str_buff);
while(recv_timeout>0)
{
while(BUFF_HAS_DATA(uart_buff))
{
tmp = BUFF_POP(uart_buff);
BUFF_PUSH(str_buff,tmp);
}
recv_timeout--;
Delay1ms();
}
BUFF_PUSH(str_buff,0);
DealString(str_buff.buff);
}
/*if(BUFF_HAS_DATA(uart_buff))
{
UartSend(BUFF_POP(uart_buff));
}*/
} DealString函数中,判断接收到的字符串,如果是hello,则发送world,如果是reboot,则等待2s后复位到ISP模式,其余情况则将字符串原封不动发送回去
void DealString(char *p)
{
if(strcmp(p,"hello") == 0)
{
UartSendStr("world!");
}
else if(strcmp(p,"reboot") == 0)
{
Delay_ms(2000);
IAP_CONTR = 0x60;
}
else
{
UartSendStr(p);
}
} 烧录程序,打开STC的串口助手测试一下,发送hello,能正确收到world,发送123,能正确收到123
页:
[1]
2