关于#单片机#的问题:求大猿解决!

keil5,stc89c52rc,esp8266-01s,串口
用keil5写串口,以便发送AT指令,飞燕平台接收解析到温度值,实现用云智能远程查看温度值,当然,这只是串口的代码,

#include <reg52.h>
#include <stdio.h>
#include <string.h>
#include "DS18B20.h"

#define uchar unsigned char    //0-255

void UartInit(void)
{
    SCON =  0x50;     //串口工作模式1
    TMOD &= 0x0F;     //清空定时器1模式位
    TMOD |= 0x20;     //设置定时器1为模式2(8位自动重装载)
    TL1  =  0xFD;       //设置定时初始值
    TH1  =  0xFD;       //设置定时重载值
    TR1  =  1;         //启动定时器1
}

//串口延时
void delay_uart(short ms)
{
    short i, j;
    for (i = 0; i < ms; i++) 
    {
        for (j = 0; j < 1141; j++);
    }
}

// 串口发送单个字符
void uartSendChar(unsigned char c)
{
    SBUF = c;
    while (!TI);   // 等待发送完成
    TI = 0;        // 清除发送完成标志
}

// 串口发送字符串
void uartSendString(const char* str)
{
    while (*str)
    {
        uartSendChar(*str++);
    }
}

void Send_AT_Cmd()
{
    uartSendString("AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTUSERCFG=0,1,\"NULL\",\"vyjNlubh0QeZW06dprJi&a1EekF90GyL\",\"c199f60d4f0b08a7ca7e2ccbcb193b1e93ff8e10d677eebbb991fea908dd92c9\",0,0,\"\"\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTCLIENTID=0,\"a1EekF90GyL.vyjNlubh0QeZW06dprJi|securemode=2\\,signmethod=hmacsha256\\,timestamp=1681564451348|\"\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTCONN=0,\"a1EekF90GyL.iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883,1\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTSUB=0,\"/sys/a1EekF90GyL/vyjNlubh0QeZW06dprJi/thing/service/property/set\",1\r\n");
    delay_uart(300);
}

void printTemp(float temp)
{

    char String_temp_at[128] = "AT+MQTTPUB=0,\"/sys/a1EekF90GyL/vyjNlubh0QeZW06dprJi/thing/event/property/post\",\"{params:{temperature:%.1f}}\",1,0\r\n";//字符串格式
    char buffer[256];  // 缓冲区,用于存储转换后的字符串

    sprintf(buffer, String_temp_at, temp);  // 将温度值转换为字符串格式
    
    uartSendString(buffer);  // 发送字符串到串口
}

void main()
{
    UartInit();  // 初始化串口
    Send_AT_Cmd();
    
    while (1)
    {
        float temp = ReadTemp()/10.0;
        printTemp(temp);// 将温度值打印到串口
        delay_uart(600);  // 延时一段时间
    }
}

遇到的现象和发生背景,请写出第一个错误信息

img

在魔术棒中,memory model中的data改为xdata可以通过,但芯片不支持,要怎么解决?

img

1,换STC15F2K60S2系列单片机
2,如果有固定的数组变量,例如有些AT指令是固定的,将它的数组定义前面加上const,这样数组会存到FLASH,不会存到data与idata中

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:根据错误信息,您的代码中自动分配的内存段太大,导致编译失败。这可能是因为您的代码中使用了大量的局部变量和数组,导致栈空间不足。
为了解决这个问题,您可以考虑将一些局部变量和数组改为全局变量,并将其存储在外部RAM中(例如XRAM)。这样可以释放栈空间,从而避免自动分配的内存段过大的问题。
在Keil中,您可以使用"__xdata"关键字将变量定义为外部RAM中的变量。例如,以下代码定义了一个整数变量"count",并将其存储在外部RAM中:

__xdata int count;

请注意,在使用外部RAM时,需要将RAM的地址范围配置到您的芯片的存储器映射中。具体的配置方法和地址范围取决于您的芯片型号和硬件设计。

除了使用外部RAM,您还可以考虑优化代码结构和算法,以减少内存使用量。例如,您可以将一些重复执行的代码封装为函数,并尽可能避免使用大型数组和结构体。

【修改后的完整代码如下】:
为了解决自动分配的内存段太大的问题,您可以将一些局部变量和数组改为全局变量,并将其存储在外部RAM中。以下是可能的修改方案:

#include <reg52.h>
#include <stdio.h>
#include <string.h>
#include "DS18B20.h"

#define uchar unsigned char    //0-255

__xdata float temp;  // 将温度值定义为全局变量,并存储在外部RAM中

void UartInit(void)
{
    SCON =  0x50;     //串口工作模式1
    TMOD &= 0x0F;     //清空定时器1模式位
    TMOD |= 0x20;     //设置定时器1为模式2(8位自动重装载)
    TL1  =  0xFD;       //设置定时初始值
    TH1  =  0xFD;       //设置定时重载值
    TR1  =  1;         //启动定时器1
}

//串口延时
void delay_uart(short ms)
{
    short i, j;
    for (i = 0; i < ms; i++) 
    {
        for (j = 0; j < 1141; j++);
    }
}

// 串口发送单个字符
void uartSendChar(unsigned char c)
{
    SBUF = c;
    while (!TI);   // 等待发送完成
    TI = 0;        // 清除发送完成标志
}

// 串口发送字符串
void uartSendString(const char* str)
{
    while (*str)
    {
        uartSendChar(*str++);
    }
}

void Send_AT_Cmd()
{
    uartSendString("AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTUSERCFG=0,1,\"NULL\",\"vyjNlubh0QeZW06dprJi&a1EekF90GyL\",\"c199f60d4f0b08a7ca7e2ccbcb193b1e93ff8e10d677eebbb991fea908dd92c9\",0,0,\"\"\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTCLIENTID=0,\"a1EekF90GyL.vyjNlubh0QeZW06dprJi|securemode=2\\,signmethod=hmacsha256\\,timestamp=1681564451348|\"\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTCONN=0,\"a1EekF90GyL.iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883,1\r\n");
    delay_uart(300);
    uartSendString("AT+MQTTSUB=0,\"/sys/a1EekF90GyL/vyjNlubh0QeZW06dprJi/thing/service/property/set\",1\r\n");
    delay_uart(300);
}

void printTemp()
{
    char String_temp_at[128] = "AT+MQTTPUB=0,\"/sys/a1EekF90GyL/vyjNlubh0QeZW06dprJi/thing/event/property/post\",\"{params:{temperature:%.1f}}\",1,0\r\n";//字符串格式
    char buffer[256];  // 缓冲区,用于存储转换后的字符串

    sprintf(buffer, String_temp_at, temp);  // 将温度值转换为字符串格式

    uartSendString(buffer);  // 发送字符串到串口
}

void main()
{
    UartInit();  // 初始化串口
    Send_AT_Cmd();

    while (1)
    {
        temp = ReadTemp()/10.0;
        printTemp();// 将温度值打印到串口
        delay_uart(600);  // 延时一段时间
    }
}

在这个修改后的代码中,我们将温度值定义为全局变量"temp",并将其存储在外部RAM中。这样可以释放栈空间,避免自动分配的内存段过大的问题。我们还将"printTemp"函数的参数删除,因为它现在可以直接访问全局变量"temp"。

请注意,在使用外部RAM时,您需要将RAM的地址范围配置到您的芯片的存储器映射中。具体的配置方法和地址范围取决于您的芯片型号和硬件设计。

希望这个修改后的代码能够帮助您解决问题。如果您有其他问题或需要更多帮助,请随时提出。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:

第一个错误信息显示为“fatal error: #error directive: This memory model is not supported by this chip”, 这是因为选择的memory model与芯片不匹配导致的。需要根据芯片的内存结构来选择合适的memory model,否则会编译出错。

对于第二个问题,如果芯片不支持xdata类型,那么可以考虑使用其它的内存类型,如idata、pdata等。或者可以通过手动定义指针来操作需要使用xdata的变量,例如:

unsigned char xdata *p_xdata_var;
p_xdata_var = (unsigned char xdata *)0x8000; // 将指针指向xdata内存地址0x8000
*p_xdata_var = 0x12; // 将0x12写入xdata内存地址0x8000

这样可以在不使用xdata类型的情况下操作xdata内存,但需要注意指针的定义和使用。