前几天移植好了modbus程序,今天再来增加一些功能:
1,参数存储
2,参数设置
3,测试
第一步,移植STMH7 裸机工程的w25q256驱动程序,不过这里有个需要注意的点就是,他每次写之前要擦除4K的扇区,后边再AT指令里边会用到
第二步,移植H7 TOOL的param文件,修改modify_param文件,这里我只保留了网络和modbus,输入和输出的参数部分,代码如下:
[C] 纯文本查看 复制代码 #define PARAM_ADDR 0 /* 基本参数区地址 */
#define PARAM_SIZE 256 /* 最大空间,用于编译查错 */
#define PARAM_VER 0x00000101 /* 基本参数版本 100 */
/* 暂未启用 程序缓存 */
#define APP_BUF_ADDR 0x08000000 + 1 * 1024 * 1024
enum
{
LINK_NONE = 0, /* 无连接 */
LINK_USB_OK = 1, /* USB连接中 */
LINK_RJ45_OK = 2, /* RJ45连接中 */
LINK_WIFI_OK = 3, /* WiFi连接中 */
};
/* 全局参数 */
typedef struct
{
uint32_t UpgradeFlag; /*升级标记,0x55AAA55A表示需要更新APP,0xFFFF表示更新完毕*/
uint32_t ParamVer; /* 参数区版本控制(可用于程序升级时,决定是否对参数区进行升级) */
uint8_t flag;
uint8_t Addr485;
uint8_t LocalIPAddr[4]; /* 本机IP地址 */
uint8_t NetMask[4]; /* 子网掩码 */
uint8_t Gateway[4]; /* 网关 */
uint16_t LocalTCPPort; /* 本机TCP端口 */
uint16_t LocalUDPPort; /* 本机UDP端口 */
uint8_t RemoteIPAddr[4]; /* 远端(前置)IP地址 */
uint16_t RemoteTcpPort; /* 远端(前置)TCP端口 */
uint8_t APSelfEn; /* 本机扮演AP */
uint8_t AP_SSID[32 + 1]; /* AP名字 */
uint8_t AP_PASS[16 + 1]; /* AP密码 */
uint8_t WiFiIPAddr[4]; /* IP地址 192.168.1.50 */
uint8_t WiFiNetMask[4]; /* 子网掩码 255.255.255.0 */
uint8_t WiFiGateway[4]; /* 网关 192.168.1.1 */
uint8_t DHCPEn; /* DHCP使能 */
uint8_t WiFiMac[6];
} PARAM_T;
/* 全局变量 */
typedef struct
{
/* MCU ID */
uint32_t CPU_Sn[3];
uint8_t WiFiDebugEn;
uint8_t RemoteTCPServerOk;
uint8_t HomeWiFiLinkOk;
uint8_t WiFiRecivedIPD;
uint8_t MACaddr[6]; /* 以太网MAC地址 */
uint8_t InputState[32];
uint8_t RelayState[32];
float CH1Volt;
float CH2Volt;
uint8_t GpioMode[16]; /* 保存GPIO模式参数、输入、输出或特殊功能 */
} VAR_T;
[C] 纯文本查看 复制代码 /*
*********************************************************************************************************
*
* 模块名称 : 应用程序参数模块
* 文件名称 : param.c
* 版 本 : V1.0
* 说 明 : 读取和保存应用程序的参数
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2013-01-01 armfly 正式发布
*
* Copyright (C), 2012-2013, 安富莱电子 [url]www.armfly.com[/url]
*
*********************************************************************************************************
*/
#include "main.h"
PARAM_T g_tParam; /* 基本参数 */
VAR_T g_tVar; /* 全局变量 */
/*
*********************************************************************************************************
* 函 数 名: LoadParam
* 功能说明: 从eeprom读参数到g_tParam
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void load_param(void)
{
/* 读取EEPROM中的参数 */
qspi_read_buffer((uint8_t *)&g_tParam, PARAM_ADDR, sizeof(PARAM_T));
if (sizeof(PARAM_T) > PARAM_SIZE)
{
/* 基本参数分配空间不足 */
while(1);
}
#if 1
if (g_tParam.ParamVer != PARAM_VER)
{
load_base_param();
}
#else
if(g_tParam.flag==0)
{
load_base_param();
}
#endif
bsp_get_cpu_id(g_tVar.CPU_Sn); /* 读取CPU ID */
/* 自动生成以太网MAC */
g_tVar.MACaddr[0] = 0xC8;
g_tVar.MACaddr[1] = 0xF4;
g_tVar.MACaddr[2] = 0x8D;
g_tVar.MACaddr[3] = g_tVar.CPU_Sn[0] >> 16;
g_tVar.MACaddr[4] = g_tVar.CPU_Sn[0] >> 8;
g_tVar.MACaddr[5] = g_tVar.CPU_Sn[0] >> 0;
g_tVar.RelayState[0]=1;
g_tVar.RelayState[1]=1;
g_tVar.RelayState[2]=1;
g_tVar.RelayState[3]=1;
// SaveParam();
}
uint8_t load_realy_state(uint8_t num)
{
return g_tVar.RelayState[num];
}
/*
*********************************************************************************************************
* 函 数 名: SaveParam
* 功能说明: 将全局变量g_tParam 写入到eeprom
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void SaveParam(void)
{
/* 将全局的参数变量保存到EEPROM */
qspi_erase_sector(0);
qspi_write_buffer((uint8_t *)&g_tParam,PARAM_ADDR,sizeof(PARAM_T));
}
/*
*********************************************************************************************************
* 函 数 名: InitBaseParam
* 功能说明: 初始化基本参数为缺省值
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void load_base_param(void)
{
g_tParam.UpgradeFlag = 0; /*升级标记,0x55AAA55A表示需要更新APP,0xFFFF表示更新完毕*/
g_tParam.ParamVer = PARAM_VER; /* 参数区版本控制(可用于程序升级时,决定是否对参数区进行升级) */
g_tParam.flag=1;
g_tParam.Addr485 = 1;
g_tParam.LocalIPAddr[0] = 192; /* 本机IP地址 */
g_tParam.LocalIPAddr[1] = 168;
g_tParam.LocalIPAddr[2] = 1;
g_tParam.LocalIPAddr[3] = 111;
g_tParam.NetMask[0] = 255; /* 子网掩码 */
g_tParam.NetMask[1] = 255;
g_tParam.NetMask[2] = 255;
g_tParam.NetMask[3] = 0;
g_tParam.Gateway[0] = 192; /* 网关 */
g_tParam.Gateway[1] = 168;
g_tParam.Gateway[2] = 1;
g_tParam.Gateway[3] = 1;
g_tParam.LocalTCPPort = 30010; /* 本机TCP端口和UDP端口号,相同 */
g_tParam.RemoteIPAddr[0] = 192; /* 远端(前置)IP地址 */
g_tParam.RemoteIPAddr[1] = 168;
g_tParam.RemoteIPAddr[2] = 1;
g_tParam.RemoteIPAddr[3] = 8;
g_tParam.RemoteTcpPort = 30000; /* 远端(前置)TCP端口 */
g_tParam.APSelfEn = 0; /* 0作为客户端,1作为AP */
memset(g_tParam.AP_SSID, 0, 32 + 1); /* AP名字 */
memset(g_tParam.AP_PASS, 0, 16 + 1); /* AP密码 */
g_tParam.WiFiIPAddr[0] = 192; /* 静态IP地址 */
g_tParam.WiFiIPAddr[1] = 168;
g_tParam.WiFiIPAddr[2] = 1;
g_tParam.WiFiIPAddr[3] = 105;
g_tParam.WiFiNetMask[0] = 255; /* 子网掩码 255.255.255.0 */
g_tParam.WiFiNetMask[1] = 255;
g_tParam.WiFiNetMask[2] = 255;
g_tParam.WiFiNetMask[3] = 0;
g_tParam.WiFiGateway[0] = 192; /* 网关 192.168.1.1 */
g_tParam.WiFiGateway[1] = 168;
g_tParam.WiFiGateway[2] = 1;
g_tParam.WiFiGateway[3] = 1;
g_tParam.DHCPEn = 0; /* DHCP使能 */
SaveParam();
}
void restroe_factory_param_setting(void)
{
load_base_param();
}
void param_rs485_addr_set(uint8_t addr)
{
g_tParam.Addr485=addr;
SaveParam();
}
uint8_t param_rs485_addr_get(void)
{
return g_tParam.Addr485;
}
void printf_param_info(void)
{
uint32_t var;
var=*(unsigned int*)(0x08000000+28);
printf("设备固件版本:%X.%02X\r\n",var>>8,var&0xFF);
printf("设备参数版本:%X.%02X\r\n",g_tParam.ParamVer>>8,g_tParam.ParamVer&0xFF);
printf("MODBUS地址 :%d\r\n",g_tParam.Addr485);
printf("本地IP地址 :%d.%d.%d.%d\r\n",g_tParam.LocalIPAddr[0],g_tParam.LocalIPAddr[1],g_tParam.LocalIPAddr[2],g_tParam.LocalIPAddr[3]);
printf("子网掩码 :%d.%d.%d.%d\r\n",g_tParam.NetMask[0],g_tParam.NetMask[1],g_tParam.NetMask[2],g_tParam.NetMask[3]);
printf("本地网关 :%d.%d.%d.%d\r\n",g_tParam.Gateway[0],g_tParam.Gateway[1],g_tParam.Gateway[2],g_tParam.Gateway[3]);
printf("本地端口 :%d\r\n",g_tParam.LocalTCPPort);
printf("服务器IP地址:%d.%d.%d.%d\r\n",g_tParam.RemoteIPAddr[0],g_tParam.RemoteIPAddr[1],g_tParam.RemoteIPAddr[2],g_tParam.RemoteIPAddr[3]);
printf("服务器端口 :%d\r\n",g_tParam.RemoteTcpPort);
printf("开关状态 :%d %d %d %d\r\n",g_tVar.RelayState[0],g_tVar.RelayState[1],g_tVar.RelayState[2],g_tVar.RelayState[3]);
printf("*************************************************************\n\r");
}
/***************************** 安富莱电子 [url]www.armfly.com[/url] (END OF FILE) *********************************/
其中,void restroe_factory_param_setting(void); void param_rs485_addr_set(uint8_t addr);uint8_t param_rs485_addr_get(void); void printf_param_info(void);这几个函数是新增的,作用是为了后边通过debug 串口来设置参数。
开机打印:
第三步,增加串口设置功能
485的部分,只设置了设备地址,后期可以增加一个波特率的设置
第四步,修改之前遗留的问题
1,modbus_rev_new
2,modbus地址判断的部分
第四步,测试
1,设备固件版本和参数版本查询
2,通过串口AT指令更改设备ID
查询下是不是更改成功
w25q256重启是不丢失的,重启再验证一下
3,测试更改以后主机给从机发送命令
以modbus从机地址4测试情况
log
从机返回
|