challis 发表于 2024-2-1 10:48:58

学习串口调用STC调试接口

之前研究了如何通过串口命令来进行不断电烧录程序,减少了每次烧录测试代码之前需要手动重启mcu的工作量后,调试代码功能舒服多了!

接下来进行测试STC的各个调试接口
这块STC已有封装好的库,但是自己再实现一遍,能锻炼能力的同时,加深对串口通信的理解
STC调试接口协议是模态对话框,用着不方便,我直接拿到了对应的html文件

challis 发表于 2024-2-1 11:00:32

先实现串口通信中的缓存数据模块C_BUFF.h
定义BUFF_DATA的结构体,并实现对其的pop,push,reset,Has_Data,copy的操作
pop:读取1字节数据
push:写入1字节数据
has_data:判断是否有数据
reset:清空数据
cpy:复制一个buff_data的数据到另一个buff_data
#ifndef C_BUFF_H
#define C_BUFF_H

#include "STC\STC8H.h"

#define uchar unsigned char
#define uint unsigned int

//buff_size 必须是2的倍数-1
#define BUFF_SIZE 0x0f
struct BUFF_DATA
{
    uchar rptr;
    uchar wptr;
    char buff;
};
#define BUFF_POP(x,d) d=x.buff;x.rptr&=BUFF_SIZE
#define BUFF_PUSH(x,d) x.buff = d;x.wptr&=BUFF_SIZE
#define BUFF_HAS_DATA(x) (x.rptr != x.wptr)
#define BUFF_RESET(x) x.rptr=0;x.wptr=0
#define BUFF_CPY(src,dest) while(BUFF_HAS_DATA(src)){dest.buff = src.buff;src.rptr&=BUFF_SIZE;dest.wptr&=BUFF_SIZE;}

#define PBUFF_POP(x,d) d=x->buff;x->rptr&=BUFF_SIZE
#define PBUFF_PUSH(x,d) x->buff = d;x->wptr&=BUFF_SIZE
#define PBUFF_HAS_DATA(x) (x->rptr != x->wptr)
#define PBUFF_RESET(x) x->rptr=0;x->wptr=0
#define PBUFF_CPY(src,dest) while(PBUFF_HAS_DATA(src)){dest->buff = src->buff;src->rptr&=BUFF_SIZE;dest->wptr&=BUFF_SIZE;}


#endif //C_BUFF_H

challis 发表于 2024-2-1 11:03:12

串口通信模块的头文件C_UART.h:
UartSend 是发送1字节的数据
UartSendStr 是发送字符串数据,以\0结尾
UartSendData 是发送指定长度的数据
UartReceived 是接收串口数据,如果返回1,则表示有数据,返回0表示未收到数据,接收的数据储存在str_buff中
#ifndef C_UART_H
#define C_UART_H

#include "C_BUFF.h"

extern struct BUFF_DATA xdata str_buff;

void Delay1ms(void);        //@5.5296MHz

void Delay_ms(uint times);        //@5.5296MHz

void Uart1_Init(void);        //19200bps@5.5296MHz

void UartSend(char dat);

void UartSendStr(const char *p);

void UartSendData(const char *p,uchar len);

bit UartReceived(); //串口接收数据,如果返回1,则表示有数据,返回0表示未收到数据,接收的数据储存在str_buff中
#endif //C_UART_H

challis 发表于 2024-2-1 11:06:52

串口通信模块的实现:C_UART.c
send_busy 用来判断是否发送繁忙
recv_timeout 用来检测一次数据是否接收完成

uart_buff 是串口数据缓存
str_buff 是接收的数据的缓存

UartReceived中会判断,如果recv_timeout>0,则代表接收到了数据,然后循环将数据存入str_buff中,直到对方发送结束,并返回1代表有数据
#include "C_UART.h"
#include "INTRINS.H"

bit send_busy;
uchar recv_timeout;
struct BUFF_DATA xdata uart_buff,xdata str_buff;

void Delay1ms(void)        //@5.5296MHz
{
        unsigned char data i, j;

        _nop_();
        _nop_();
        i = 8;
        j = 43;
        do
        {
                while (--j);
        } while (--i);
}

void Delay_ms(uint times)        //@5.5296MHz
{
        unsigned char data i, j;
    while (times-->0)
    {
       _nop_();
      _nop_();
      i = 8;
      j = 43;
      do
      {
            while (--j);
      } while (--i);
    }
}


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;
        }
}

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);
}

void UartSend(char dat)
{
    while(send_busy);
    send_busy = 1;
    SBUF = dat;
}

void UartSendStr(const char *p)
{
    while(*p)
      UartSend(*p++);
}

void UartSendData(const char *p,uchar len)
{
    while (len-->0)
      UartSend(*p++);
}

//串口接收数据,如果返回1,则表示有数据,返回0表示未收到数据,接收的数据储存在str_buff中
bit UartReceived()
{
    if(recv_timeout>0)
    {
      BUFF_RESET(str_buff);
      while(recv_timeout>0)
      {
            BUFF_CPY(uart_buff,str_buff)
            recv_timeout--;
            Delay1ms();
      }
      BUFF_PUSH(str_buff,0);
      return 1;
    }
    return 0;
}

challis 发表于 2024-2-1 11:09:05

主函数中循环接收,并调用UartSendStr处理数据
#include "C_UART.h"
#include "C_STC_TOOLS.h"
#include <STRING.H>

void DealString(char *p)
{
    if(strcmp(p,"hello") == 0)
    {
      UartSendStr("world!");
    }
    else if(strcmp(p,"reboot") == 0)
    {
      Delay_ms(1000);
      UartSendStr("bye!");
      IAP_CONTR = 0x60;
    }
    else
    {
      UartSendStr(p);
    }
}

void main()
{
    Uart1_Init();
   
    UartSendStr("Uart Test!\r\n");

    while(1)
    {
      if(UartReceived())
            DealString(str_buff.buff);
      Delay1ms();
    }
}

challis 发表于 2024-2-1 11:13:43

现在先测试STC调试接口的 功能1:        在数码管上显示字符串
新建C_STC_TOOLS.h
添加函数void STC_SEG7_ShowString(const char *str);
#ifndef C_STC_TOOLS_H
#define C_STC_TOOLS_H

//功能1:        在数码管上显示字符串
void STC_SEG7_ShowString(const char *str);

#endif //C_STC_TOOLS_H

challis 发表于 2024-2-1 11:17:42

在C_STC_TOOLS.c中发送对应的数据
先设置8位的头信息,然后复制需要发送的数据,因为数码管只能显示8个数字,所以我们最多复制8字节数据就break,然后将最后一位置0,并调用串口发送
这里一定要调用UartSendData函数,而不是UartSendStr函数,因为UartSendStr会在字符串有'\0'的时候就停止发送,导致实际发送的数据只有 37H 53H 45H 47H 53H
之前我就是犯了这个错误,导致一直不显示
#include "C_STC_TOOLS.h"
#include "C_UART.h"

#define L_BUFF_LEN 64
char xdata stc_buff;
uchar pos;
//功能1:        在数码管上显示字符串
void STC_SEG7_ShowString(const char *str)
{
    stc_buff = 0x37;
    stc_buff = 0x53;
    stc_buff = 0x45;
    stc_buff = 0x47;
    stc_buff = 0x53;
    stc_buff = 0x00;
    stc_buff = 0x00;
    stc_buff = 0x00;

    for(pos=8;pos<16;pos++)
    {
      if(*str)
            stc_buff = *str++;
      else
            break;
    }
    stc_buff = 0;
    UartSendData(stc_buff,pos+1);
}

challis 发表于 2024-2-1 11:19:49

主函数中接收串口信息判断,如果是以seg开头,则测试数码管的功能
void DealString(char *p)
{
    if(strcmp(p,"hello") == 0)
    {
      UartSendStr("world!");
    }
    else if(strcmp(p,"reboot") == 0)
    {
      Delay_ms(1000);
      UartSendStr("bye!");
      IAP_CONTR = 0x60;
    }
    else if(strncmp(p,"seg",3) == 0)
    {
      STC_SEG7_ShowString(p+3);
    }
    else
    {
      UartSendStr(p);
    }
}

challis 发表于 2024-2-1 11:20:53

烧录,打开串口测试,发送seg12.3.3后,能正常在数码管上显示

challis 发表于 2024-2-1 11:24:43

我发现数据中的.不进行占位,且不管多少'.'连一起就只显示一个'.',如果强制按只发送8位来算,那么无法输出1.2.3.4.5.6.7.8这样的数据,我们得对应修改下STC_SEG7_ShowString的逻辑
页: [1] 2
查看完整版本: 学习串口调用STC调试接口