Initial commit: my SECS2 project

This commit is contained in:
2026-06-12 14:19:01 +08:00
commit 2c3e2c4dc2
1138 changed files with 603966 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
#include "algo_queue.h"
/* 计算队列中第i个元素的地址 */
#define at(i) (((char *)(queue->base))+(i)*(queue->dsize))
/* 数据赋值:将源地址s的数据复制到目标地址d */
#define assign(d, s) memcpy((d), (s), queue->dsize)
/* 获取队列中逻辑位置i的元素地址(考虑循环队列) */
#define qa(i) at((queue->head + queue->capacity + (i)) % (queue->capacity))
/* 简易内存复制函数 */
static void* memcpy(void* dest, const void* src, int n)
{
char* dst = dest;
const char* s = src;
while (n--) *dst++ = *s++;
return dest;
}
/* 将队列中从index开始的size个元素向前移动一位 */
static void move_forward(queue queue, int index, int size)
{
for (int i = index; i < index + size; i++) assign(qa(i - 1), qa(i));
}
/* 将队列中从index开始的size个元素向后移动一位 */
static void move_backward(queue queue, int index, int size)
{
for (int i = index + size; i > index; i--) assign(qa(i), qa(i - 1));
}
/**
* \brief 标准入队操作(队尾添加)
* \param[in] queue: 队列对象指针
* \param[in] data: 待添加数据地址(NULL表示仅移动指针)
* \return 1=成功, 0=失败(队列无效或已满)
*
* \details 在队列尾部添加新元素。如果队列已满则操作失败。
* 当data不为NULL时,将数据复制到队列存储区。
* 更新尾指针和队列大小。
*/
int queue_push(queue queue, void* data)
{
if (!queue) return 0; // 检查队列指针有效性
if (queue->size == queue->capacity) return 0; // 队列已满
if (data) assign(at(queue->tail), data); // 数据复制到队尾
queue->tail = (queue->tail + 1) % queue->capacity; // 更新尾指针(循环)
queue->size++; // 更新元素数量
return 1;
}
/**
* \brief 强制入队操作(覆盖式添加)
* \param[in] queue: 队列对象指针
* \param[in] data: 待添加数据地址(NULL表示仅移动指针)
* \return 1=成功, 0=失败(仅当队列无效时)
*
* \details 当队列未满时等同于queue_push()。
* 当队列已满时覆盖最旧数据(队头数据),
* 实现循环缓冲效果。
*/
int queue_push2(queue queue, void* data)
{
if (!queue) return 0;
if (queue->size < queue->capacity) return queue_push(queue, data); // 队列未满时调用标准入队
// 队列已满时覆盖队头数据(实现循环覆盖)
if (data) assign(at(queue->tail), data);
queue->tail = (queue->tail + 1) % queue->capacity;
queue->head = (queue->head + 1) % queue->capacity; // 头指针后移(覆盖最旧数据)
return 1;
}
/**
* \brief 出队操作(队头移除)
* \param[in] queue: 队列对象指针
* \param[out] data: 数据接收地址(NULL表示丢弃数据)
* \return 1=成功, 0=失败(队列无效或为空)
*
* \details 从队列头部移除元素。如果data不为NULL,
* 将移除的元素复制到指定地址。
* 更新头指针和队列大小。
*/
int queue_pop(queue queue, void* data)
{
if (!queue) return 0;
if (queue->size == 0) return 0; // 队列为空
if (data) assign(data, at(queue->head)); // 复制队头数据到输出
queue->head = (queue->head + 1) % queue->capacity; // 更新头指针(循环)
queue->size--; // 更新元素数量
return 1;
}
/**
* \brief 指定位置插入元素
* \param[in] queue: 队列对象指针
* \param[in] index: 插入位置索引(0=队头, size=队尾)
* \param[in] data: 待插入数据地址(NULL表示仅空出位置)
* \return 1=成功, 0=失败(索引越界或队列已满)
*
* \details 在指定位置插入新元素,后续元素后移。
* 自动选择最优移动方向(前移或后移元素)。
* 时间复杂度O(min(index, size-index))。
*/
int queue_insert(queue queue, int index, void* data)
{
if (!queue) return 0;
if (index < 0 || index > queue->size) return 0; // 索引越界检查
if (queue->size == queue->capacity) return 0; // 队列已满
// 根据插入位置选择最优移动方向
if (index <= queue->size / 2) {
// 向前移动前半部分元素
move_forward(queue, 0, index);
queue->head = (queue->head + queue->capacity - 1) % queue->capacity; // 头指针前移
} else {
// 向后移动后半部分元素
move_backward(queue, index, queue->size - index);
queue->tail = (queue->tail + 1) % queue->capacity; // 尾指针后移
}
// 在空出的位置插入数据
if (data) assign(at((queue->head + index) % (queue->capacity)), data);
queue->size++;
return 1;
}
/**
* \brief 指定位置删除元素
* \param[in] queue: 队列对象指针
* \param[in] index: 删除位置索引(0=队头, size-1=队尾)
* \param[out] data: 数据接收地址(NULL表示丢弃数据)
* \return 1=成功, 0=失败(索引越界或队列为空)
*
* \details 删除指定位置元素,后续元素前移。
* 自动选择最优移动方向。
* 时间复杂度O(min(index, size-index))。
*/
int queue_erase(queue queue, int index, void* data)
{
if (!queue) return 0;
if (index < 0 || index >= queue->size) return 0; // 索引越界检查
if (queue->size == 0) return 0; // 队列为空
// 保存被删除元素(如果需要)
if (data) assign(data, at((queue->head + index) % (queue->capacity)));
// 根据删除位置选择最优移动方向
if (index <= queue->size / 2) {
// 向后移动前半部分元素
move_backward(queue, 0, index);
queue->head = (queue->head + 1) % queue->capacity; // 头指针后移
} else {
// 向前移动后半部分元素
move_forward(queue, index + 1, queue->size - index - 1);
queue->tail = (queue->tail + queue->capacity - 1) % queue->capacity; // 尾指针前移
}
queue->size--;
return 1;
}
/**
* \brief 清空队列
* \param[in] queue: 队列对象指针
*
* \details 重置队列状态(头尾指针归零,大小归零)。
* 不释放存储内存,保持队列容量不变。
*/
void queue_clear(queue queue)
{
if (!queue) return;
queue->tail = 0;
queue->head = 0;
queue->size = 0;
}
/**
* \brief 获取元素地址
* \param[in] queue: 队列对象指针
* \param[in] index: 元素索引(0=队头, size-1=队尾)
* \return 元素地址(失败返回NULL
*
* \details 获取队列中指定位置元素的直接指针。
* 可用于直接修改元素值(无需复制)。
* \warning 返回的指针在队列结构修改后可能失效。
*/
void* queue_data(queue queue, int index)
{
if (!queue) return 0;
if (index < 0 || index >= queue->size) return 0; // 索引越界检查
return (void*)at((queue->head + index) % (queue->capacity));
}
+119
View File
@@ -0,0 +1,119 @@
#ifndef _ALGO_QUEUE_H_
#define _ALGO_QUEUE_H_
/* 队列类型定义 */
typedef struct QUEUE
{
void* base; /* 数据存储区的基地址 */
int dsize; /* 每个数据元素的大小(字节) */
int capacity; /* 队列的总容量(最大元素数量) */
int size; /* 当前队列中的元素数量 */
int head; /* 队头索引(指向第一个元素) */
int tail; /* 队尾索引(指向下一个插入位置) */
} *queue; // 定义queue为指向该结构的指针类型
/**
* \brief 创建并初始化一个队列
* \param[in] type: 队列元素的数据类型
* \param[in] capacity: 队列容量
* \return 初始化完成的队列对象
*
* \note 使用复合字面量在栈上创建队列对象
* \example queue(int, 10) 创建容量为10的整型队列
*/
#define queue(type, capacity) (&(struct QUEUE){(type[capacity]){0},sizeof(type),capacity,0,0,0})
// 函数声明
int queue_push(queue queue, void* data);
int queue_push2(queue queue, void* data);
int queue_pop(queue queue, void* data);
int queue_insert(queue queue, int index, void* data);
int queue_erase(queue queue, int index, void* data);
void queue_clear(queue queue);
void* queue_data(queue queue, int index);
/**
* \brief 访问队列指定位置的元素
* \param[in] queue: 队列对象
* \param[in] type: 元素数据类型
* \param[in] i: 元素位置索引(0-based
* \return 指定元素的左值引用
*
* \example queue_at(q, int, 0) = 42; // 设置队首元素
*/
#define queue_at(queue, type, i) (*(type *)queue_data((queue),(i)))
/**
* \brief 在队头插入元素
* \param[in] queue: 队列对象
* \param[in] data: 待插入数据地址(NULL表示不赋值)
* \return 操作成功状态(1成功/0失败)
*/
#define queue_push_front(queue, data) queue_insert((queue), 0, data)
/**
* \brief 在队尾插入元素
* \param[in] queue: 队列对象
* \param[in] data: 待插入数据地址(NULL表示不赋值)
* \return 操作成功状态(1成功/0失败)
*/
#define queue_push_back(queue, data) queue_push2((queue), data)
/**
* \brief 从队头弹出元素
* \param[in] queue: 队列对象
* \param[out] data: 接收弹出数据的地址(NULL表示不保存)
* \return 操作成功状态(1成功/0失败)
*/
#define queue_pop_front(queue, data) queue_pop((queue), data)
/**
* \brief 从队尾弹出元素
* \param[in] queue: 队列对象
* \param[out] data: 接收弹出数据的地址(NULL表示不保存)
* \return 操作成功状态(1成功/0失败)
*/
#define queue_pop_back(queue, data) queue_erase((queue), (queue)->size - 1, data)
/**
* \brief 获取队列当前元素数量
* \param[in] queue: 队列对象
* \return 队列中的元素数量
*/
#define queue_size(queue) ((queue)->size)
/**
* \brief 获取队列总容量
* \param[in] queue: 队列对象
* \return 队列的最大容量
*/
#define queue_capacity(queue) ((queue)->capacity)
/**
* \brief 检查队列是否为空
* \param[in] queue: 队列对象
* \return 0表示非空,非0表示空
*/
#define queue_empty(queue) ((queue)->size == 0)
/**
* \brief 检查队列是否已满
* \param[in] queue: 队列对象
* \return 0表示未满,非0表示已满
*/
#define queue_full(queue) ((queue)->size == (queue)->capacity)
/**
* \brief 创建字面量的地址包装
* \param[in] type: 数据类型(如int/float等)
* \param[in] value: 字面量值
* \return 包含该值的临时数组地址
*
* \note 用于将字面量转换为指针参数
* \example queue_push(q, literal(int, 42));
*/
#ifndef literal
#define literal(type, value) ((type[1]){value})
#endif
#endif
+96
View File
@@ -0,0 +1,96 @@
#include "GasData.h"
#include "stdio.h"
#include "bsp_Print.h"
#include "dsp_Demod.h"
#include "bsp_TEC.h"
#include "bsp_ADC.h"
#include "laser.h"
#include "algo_Laser.h"
#include "bsp_Uart.h"
#include "algo_Calib.h"
#include "GasData.h"
#include "algo_Filter.h"
#include "dsp_Demod.h"
#include "app.h"
#include "bsp_Flash.h"
#include "bsp_print.h"
static void GasData_Task(void);
static char *GasData_GetName(u8 GasType);
static char *GasData_GetUnit(u8 Unit);
GasData_t GasData=
{
.Task = GasData_Task,
.GetName = GasData_GetName,
.GetUnit = GasData_GetUnit,
};
GasData_t *pGasData = &GasData;
static void GasData_Task(void)
{
// if(BSP_PRINT_CURDATA == bsp_Print_DataTyppe)
// {
// printf("R_AD,%u,Cal_AD,%u,M_AD,%u,C_AD,%u,C_Val,%d,Val,%d\n",
// pGasData->Gas_1.R_AD,pGasData->Gas_1.R_AD_Cal,pGasData->Gas_1.Measur_AD,pGasData->Gas_1.Cali_AD,pGasData->Gas_1.Fac_Value,pGasData->Gas_1.Usr_Value);
// }
pGasData->Gas_1.Left = LaserSensor.SHG.Pix_Light_Max;
pGasData->Gas_1.Mid = LaserSensor.SHG.Pix_Light_Min;
pGasData->Gas_1.Light_AD = LaserSensor.ORI.Light_AD;
pGasData->Gas_1.TempAD = ADC.AD[ADC_BOARD];
pGasData->Gas_1.Temp = ADC.Value[ADC_BOARD] * 100;
pGasData->Gas_1.TECAD = ADC.AD[ADC_TEC];
pGasData->Gas_1.TECTemp = ADC.Value[ADC_TEC] * 100;
pGasData->Gas_1.Slope = FilterMeasur.Slope;
pGasData->Gas_1.FastFlag = FilterMeasur.FastFlag;
if(BSP_PRINT_CURDATA == bsp_Print_DataTyppe)
{
printf("f2pp=%u,caliAD=%u,RRtestAD=%u,cr=%d,con=%d,Cz=%d,left=%u,mid=%u,light_AD=%u,T=%d,TAD=%u,TECTemp=%d,TECAD=%u,Slope=%f,Fast=%d\n",
pGasData->Gas_1.Measur_AD, pGasData->Gas_1.Cali_AD, pGasData->Gas_1.R_AD_Cal,
pGasData->Gas_1.R_Value, pGasData->Gas_1.Fac_Value, pGasData->Gas_1.Usr_Value,
pGasData->Gas_1.Left, pGasData->Gas_1.Mid, pGasData->Gas_1.Light_AD,
pGasData->Gas_1.Temp, pGasData->Gas_1.TempAD, pGasData->Gas_1.TECTemp, pGasData->Gas_1.TECAD,
pGasData->Gas_1.Slope, pGasData->Gas_1.FastFlag
);
}
}
static char *GasData_GetName(u8 GasType)
{
switch(GasType)
{
case GASDATA_TYPE_CH4 : return "CH4 ";
case GASDATA_TYPE_CO2 : return "CO2 ";
case GASDATA_TYPE_CO : return "CO2 ";
case GASDATA_TYPE_CnHm: return "CnHm";
case GASDATA_TYPE_SO2 : return "SO2 ";
case GASDATA_TYPE_H2S : return "H2S ";
case GASDATA_TYPE_H2 : return "H2 ";
case GASDATA_TYPE_O2 : return "O2 ";
case GASDATA_TYPE_HF : return "HF ";
case GASDATA_TYPE_NH3 : return "NH3 ";
default : return "unknow";
}
}
static char *GasData_GetUnit(u8 Unit)
{
switch(Unit)
{
case GASDATA_UNIT_PPM : return "ppm ";
case GASDATA_UNIT_MG_M3 : return "mg/m3";
case GASDATA_UNIT_PERCENT : return "% ";
case GASDATA_UNIT_M_S : return "m/s ";
case GASDATA_UNIT_M3_H : return "m3/h ";
default : return "unknow";
}
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef _GASDATA_H_
#define _GASDATA_H_
#include "main.h"
#define GASDATA_TYPE_CH4 (0x00)
#define GASDATA_TYPE_CO2 (0x01)
#define GASDATA_TYPE_CO (0x02)
#define GASDATA_TYPE_CnHm (0x03)
#define GASDATA_TYPE_SO2 (0x04)
#define GASDATA_TYPE_H2S (0x05)
#define GASDATA_TYPE_H2 (0x06)
#define GASDATA_TYPE_O2 (0x07)
#define GASDATA_TYPE_HF (0x1C)
#define GASDATA_TYPE_NH3 (0x1D)
#define GASDATA_UNIT_PPM (0)
#define GASDATA_UNIT_MG_M3 (1)
#define GASDATA_UNIT_PERCENT (2)
#define GASDATA_UNIT_M_S (3)
#define GASDATA_UNIT_M3_H (4)
typedef struct
{
u8 GasType;
u8 Uint;
u8 Point;
u16 Range;
}GasData_Flash_t;
typedef struct
{
GasData_Flash_t FlashData; /*气体组分相关信息*/
float Slope; /*斜率*/
u8 FastFlag; /*快速响应标志位*/
u16 Left,Mid; /*找峰*/
u16 Light_AD; /*光功率*/
u16 TempAD; /*温度AD*/
s16 Temp; /*温度*/
u16 TECAD; /*TEC AD*/
s16 TECTemp; /*TEC 温度*/
u16 R_AD; /*原始AD值*/
u16 R_AD_Cal; /*原始AD值*/
u16 Cali_AD; /*校准时的滤波AD值*/
u16 Measur_AD; /*正常测量时的滤波AD值*/
s16 R_Value; /*滤波前拟合浓度*/
s16 Fac_Value; /*厂家拟合的浓度*/
s16 Usr_Value; /*用户校准后的浓度*/
}GasDataClass_t;
typedef struct
{
GasDataClass_t Gas_1,Gas_2;
void (*Task)(void);
char *(*GetName)(u8);
char *(*GetUnit)(u8);
}GasData_t;
extern GasData_t GasData;
#endif
+62
View File
@@ -0,0 +1,62 @@
#include "app.h"
#include "os_timer.h"
#include "stdio.h"
#include "bsp_Uart.h"
#include "bsp_iap.h"
/*协议转换程序*/
const char SwVersion[20] = "V0.001.0";
void TASK_Idle(void);
void Task_10ms(void);
void Task_50ms(void);
void Task_100ms(void);
void Task_200ms(void);
void Task_500ms(void);
void Task_1s(void);
void Task_2s(void);
/******************************************
* 函数: AppInit
* 功能: 初始化
* 参数: 无
* 返回: 无
* 描述: 无
******************************************/
void App_Init(void)
{
OsTimer_Init(); /*分时复用*/
// COM_Uart1.Init(&COM_Uart1);
COM_Uart2.Init(&COM_Uart2);
iap.init();
}
/******************************************
* 函数: App_Task
* 功能: 分时复用
* 参数: 无
* 返回: 无
* 描述: 主循环中调用
******************************************/
void App_Task(void)
{
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_10ms, osTime_MSecTick, 10))
{
OsTimeTick_10ms = osTime_MSecTick;
Task_10ms();
}
TASK_Idle();
}
/*空闲执行的函数*/
void TASK_Idle(void)
{
COM_Uart1.Rx_Task(&COM_Uart1);
COM_Uart2.Rx_Task(&COM_Uart2);
iap.task();
}
void Task_10ms(void)
{
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef _APP_H_
#define _APP_H_
extern const char SwVersion[20];
void App_Init(void);
void App_Task(void);
#endif
+131
View File
@@ -0,0 +1,131 @@
#include "laser.h"
#include "algo_Laser.h"
#include "stdio.h"
#include "string.h"
#include "bsp_DriveWave.h"
#include "bsp_ADS8864.h"
#include "dsp_Demod.h"
#include "wk_usart.h"
#include "algo_Calib.h"
#include "algo_Filter.h"
#include "GasData.h"
#include "proto_Transform.h"
/*采集次数 为2的指数倍,方便求平均*/
#define LASER_SAMPLE_LSH (3U)
#define LASER_SAMPLE_NUM (8)
/*采集到的波形*/
static u32 Laser_WaveSample[DRIVEWAVE_VALID_NUM];
static void Laser_Task(void);
static void Laser_WaveIO_Int(void);
static void Laser_Init(void);
Laser_t Laser =
{
.pWaveSample = Laser_WaveSample,
.Init = Laser_Init,
.WaveIO_Int = Laser_WaveIO_Int,
.Task = Laser_Task,
};
/*开始采样*/
void Laser_Sample_Start(void)
{
tmr_counter_value_set(TMR1,0);
tmr_interrupt_enable(TMR1,TMR_OVF_INT,TRUE);
tmr_counter_enable(TMR1,TRUE);
}
static void Laser_Init(void)
{
Laser_Sample_Start();
}
/*停止采样*/
void Laser_Sample_Stop(void)
{
tmr_counter_enable(TMR1,FALSE);
tmr_interrupt_enable(TMR1,TMR_OVF_INT,FALSE);
}
static void Laser_Task(void)
{
/*采集完成*/
if(DriveWave.DriveCount >= LASER_SAMPLE_NUM)
{
u16 i;
float x;
/*数据滤波*/
for(i=0;i<DRIVEWAVE_VALID_NUM;i++)
{
Laser_WaveSample[i] >>= LASER_SAMPLE_LSH;
Demod.inWave[i] = Laser_WaveSample[i];
}
/*信号解调处理*/
Demod.Task();
/*二次谐波相关参数计算*/
LaserSensor.Calculate();
/*数据滤波*/
GasData.Gas_1.R_AD = LaserSensor.SHG.PP_Ori;
GasData.Gas_1.R_AD_Cal = LaserSensor.SHG.PP_CalLight;
LaserSensor.SHG.PP_MeasurAvg = FilterMeasur.FastFilter(&FilterMeasur,LaserSensor.SHG.PP_CalLight);
GasData.Gas_1.Measur_AD = LaserSensor.SHG.PP_MeasurAvg;
LaserSensor.SHG.PP_CalibAvg = FilterCalib.FastFilter(&FilterCalib,LaserSensor.SHG.PP_CalLight);
GasData.Gas_1.Cali_AD = LaserSensor.SHG.PP_CalibAvg;
/*浓度计算*/
x = LaserSensor.SHG.PP_CalLight;
GasData.Gas_1.R_Value = Calib.FacCalibCoeff[3] * x * x * x + Calib.FacCalibCoeff[2] * x * x + Calib.FacCalibCoeff[1] * x + Calib.FacCalibCoeff[0];
x = LaserSensor.SHG.PP_MeasurAvg;
GasData.Gas_1.Fac_Value = Calib.FacCalibCoeff[3] * x * x * x + Calib.FacCalibCoeff[2] * x * x + Calib.FacCalibCoeff[1] * x + Calib.FacCalibCoeff[0];
x = GasData.Gas_1.Fac_Value;
GasData.Gas_1.Usr_Value = Calib.UsrCalibCoeff[0] * (x + Calib.UsrCalibCoeff[1]);
GasData.Task();
proto_Transform_Task();
memset(Laser_WaveSample,0,sizeof(Laser_WaveSample));
/*数据解调完成,开始采样*/
DriveWave.DriveCount = 0;
Laser_Sample_Start();
}
}
/*探测器采样、驱动波形输出、放入80k中断*/
static void Laser_WaveIO_Int(void)
{
static u16 AD_index;
u16 AD;
DriveWave.DacOut(AD_index);
if(AD_index < DRIVEWAVE_VALID_NUM)
{
AD = ADS8864.ADRead();
Laser_WaveSample[AD_index] += AD;
}
if(DRIVEWAVE_NUM - 1 == AD_index)
{
AD_index = 0;
DriveWave.DriveCount++;
if(DriveWave.DriveCount >= LASER_SAMPLE_NUM)
{
/*停止采样*/
Laser_Sample_Stop();
}
}
else
{
AD_index++;
}
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef _LASER_H_
#define _LASER_H_
#include "main.h"
typedef struct
{
u8 SampleCompleteFlag;
u32 *pWaveSample;
void (*Init)(void);
void (*WaveIO_Int)(void);
void (*Task)(void);
}Laser_t;
extern Laser_t Laser;
#endif
+121
View File
@@ -0,0 +1,121 @@
#include "os_timer.h"
unsigned short osTime_MSecTick = 0; /*滴答时钟*/
unsigned short osTime_SecTick = 0;
unsigned short osTime_10SecTick = 0; /*10s记一次 用于自动调零周期时间记录*/
static unsigned short osTimer_MSec1 = 0;
static unsigned short osTimer_MSec2 = 0;
unsigned short OsTimeTick_10ms;
unsigned short OsTimeTick_50ms;
unsigned short OsTimeTick_100ms;
unsigned short OsTimeTick_200ms;
unsigned short OsTimeTick_500ms;
unsigned short OsTimeTick_1s;
unsigned short OsTimeTick_2s;
/****************************************************************************
* NAME: OsTimer_Init
* CALLED BY: Application
* PRECONDITIONS:
* INPUT PARAMETERS: None
* RETURN VALUES: None
* DESCRIPTION: OsTimer initialization
*
****************************************************************************/
void OsTimer_Init(void)
{
osTimer_MSec1 = 0;
osTimer_MSec2 = 0;
osTime_SecTick = 0;
osTime_MSecTick = 0;
OsTimeTick_10ms = osTime_MSecTick;
OsTimeTick_50ms = osTime_MSecTick;
OsTimeTick_100ms = osTime_MSecTick;
OsTimeTick_200ms = osTime_MSecTick;
OsTimeTick_500ms = osTime_MSecTick;
OsTimeTick_1s = osTime_MSecTick;
}
/****************************************************************************
* NAME: OsTimer_Increment
* CALLED BY: ISR
* PRECONDITIONS:
* INPUT PARAMETERS: msec - millisecond to increase
* RETURN VALUES: None
* DESCRIPTION: Increase the Timer
*
****************************************************************************/
void OsTimer_Increment(unsigned short msec)
{
osTime_MSecTick += msec;
osTimer_MSec1 += msec;
osTimer_MSec2 += msec;
if (osTimer_MSec1 >= 1000U) /*1s*/
{
osTimer_MSec1 = 0U;
osTime_SecTick++;
}
if (osTimer_MSec2 >= 10000U) /*10s*/
{
osTimer_MSec2 = 0U;
osTime_10SecTick++;
}
}
/****************************************************************************
* NAME: OsTimer_CheckTimeOut
* CALLED BY: Application
* PRECONDITIONS:
* INPUT PARAMETERS: timeStart - start tick
* timeNow - current tick
* timeOut - expired tick
* RETURN VALUES: whether timer is expired
* DESCRIPTION: check if specified time is expired
*
****************************************************************************/
unsigned char OsTimer_CheckTimeOut(unsigned short timeStart, unsigned short timeNow, unsigned short timeOut)
{
unsigned short timerActivateVal;
timerActivateVal = timeOut + timeStart;
if (timerActivateVal > timeStart)
{
if ((timeNow >= timerActivateVal) || (timeNow < timeStart))
{
return TIME_TRUE;
}
}
else if ((timeNow >= timerActivateVal) && (timeNow < timeStart))
{
return TIME_TRUE;
}
return TIME_FALSE;
}
/*
离结束运行还有多少时间 配合OsTimer_CheckTimeOut函数使用
*/
unsigned short OsTimer_CheckRunTime(unsigned short timeStart, unsigned short timeNow, unsigned short timeOut)
{
unsigned short timerActivateVal;
timerActivateVal = timeOut + timeStart;
if (timerActivateVal > timeStart)
{
return (timerActivateVal - timeNow);
}
else
{
return (65535U - timeNow + timerActivateVal);
}
}
/*阻塞式延时*/
void Delay_ms(unsigned short delay)
{
HAL_Delay(delay);
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef _OSTIMER_H_
#define _OSTIMER_H_
#include "main.h"
#define TIME_TRUE 1U
#define TIME_FALSE 0U
extern unsigned short osTime_MSecTick;
extern unsigned short osTime_SecTick;
extern unsigned short osTime_10SecTick; // 10s记一次 用于自动调零周期时间记录
extern unsigned short OsTimeTick_10ms;
extern unsigned short OsTimeTick_50ms;
extern unsigned short OsTimeTick_100ms;
extern unsigned short OsTimeTick_200ms;
extern unsigned short OsTimeTick_500ms;
extern unsigned short OsTimeTick_1s;
extern unsigned short OsTimeTick_2s;
void OsTimer_Init(void);
void OsTimer_Increment(unsigned short msec);
unsigned char OsTimer_CheckTimeOut(unsigned short timeStart, unsigned short timeNow, unsigned short timeOut);
unsigned short OsTimer_CheckRunTime(unsigned short timeStart, unsigned short timeNow, unsigned short timeOut);
void Delay_ms(unsigned short delay);
#endif
+14
View File
@@ -0,0 +1,14 @@
#ifndef _USR_CONFIG_H_
#define _USR_CONFIG_H_
#define USR_TRUE (1U)
#define USR_FALSE (0U)
#define USR_ENABLE (1U)
#define USR_DISENABLE (0U)
#define U64_MAX (0xffffffffffffffff)
#define U32_MAX (0xffffffff)
#define U16_MAX (0xffff)
#endif
+247
View File
@@ -0,0 +1,247 @@
#include "bsp_DS1302.h"
#define bsp_DS1302_DELAY() do{ \
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
}while(0)
#define RST_CLR HAL_GPIO_WritePin(DS1302_RST_GPIO_Port, DS1302_RST_Pin, GPIO_PIN_RESET )
#define RST_SET HAL_GPIO_WritePin(DS1302_RST_GPIO_Port, DS1302_RST_Pin, GPIO_PIN_SET )
#define IO_CLR HAL_GPIO_WritePin(DS1302_DIO_GPIO_Port, DS1302_DIO_Pin, GPIO_PIN_RESET )
#define IO_SET HAL_GPIO_WritePin(DS1302_DIO_GPIO_Port, DS1302_DIO_Pin, GPIO_PIN_SET )
#define IO_READ HAL_GPIO_ReadPin (DS1302_DIO_GPIO_Port, DS1302_DIO_Pin )
#define SCK_CLR HAL_GPIO_WritePin(DS1302_CLK_GPIO_Port, DS1302_CLK_Pin, GPIO_PIN_RESET )
#define SCK_SET HAL_GPIO_WritePin(DS1302_CLK_GPIO_Port, DS1302_CLK_Pin, GPIO_PIN_SET )
static void bsp_DS1302Init(void);
static void bsp_DS1302_Task(void);
static u8 bsp_DS1302_Set(bsp_DS1302_Time_t *pTime);
bsp_DS1302_t DS1302 =
{
.Init = bsp_DS1302Init,
.Task = bsp_DS1302_Task,
.Set = bsp_DS1302_Set,
};
bsp_DS1302_t *pDS1302 = &DS1302;
static void bsp_DS1302DataInput(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO结构体
GPIO_InitStruct.Pin = DS1302_DIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DS1302_DIO_GPIO_Port, &GPIO_InitStruct);
}
static void bsp_DS1302DataOutput(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO结构体
GPIO_InitStruct.Pin = DS1302_DIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DS1302_DIO_GPIO_Port, &GPIO_InitStruct);
}
/*向bsp_DS1302写入一字节数据*/
static void bsp_DS1302_write_byte(u8 Addr, u8 Data)
{
u8 i;
RST_SET; /*启动bsp_DS1302总线*/
bsp_DS1302_DELAY();
/*写入目标地址:addr*/
Addr = Addr & 0xFE;/*最低位置零*/
for (i = 0; i < 8; i++)
{
if (Addr & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
Addr = Addr >> 1;
}
/*写入数据:d*/
for (i = 0; i < 8; i++)
{
if (Data & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
Data = Data >> 1;
}
RST_CLR; /*停止bsp_DS1302总线*/
bsp_DS1302_DELAY();
}
/*从bsp_DS1302读出一字节数据*/
static u8 bsp_DS1302_read_byte(u8 Addr)
{
u8 i;
u8 temp;
RST_SET; /*启动bsp_DS1302总线*/
bsp_DS1302_DELAY();
/*写入目标地址:addr*/
Addr = Addr | 0x01;/*最低位置高*/
for (i = 0; i < 8; i++)
{
if (Addr & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
Addr = Addr >> 1;
}
bsp_DS1302DataInput();
/*输出数据:temp*/
for (i = 0; i < 8; i++)
{
temp = temp >> 1;
if (IO_READ)
{
temp |= 0x80;
}
else
{
temp &= 0x7F;
}
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
}
RST_CLR; /*停止bsp_DS1302总线*/
bsp_DS1302_DELAY();
bsp_DS1302DataOutput();
return temp;
}
static u8 HexToBCD(u8 code)
{
u8 temp;
temp = ((code / 10) << 4) + (code % 10);
return temp;
}
static u8 bsp_DS1302_Set(bsp_DS1302_Time_t *pTime)
{
if ((pTime->Year > 99) || (pTime->Month > 12) || (pTime->Day > 31) ||
(pTime->Hour > 23) || (pTime->Minute > 59) || (pTime->Second > 59))
{
return USR_FALSE;
}
else
{
bsp_DS1302_write_byte(BSP_DS1302_CONTROL_ADDR, 0x00); //关闭写保护
bsp_DS1302_write_byte(BSP_DS1302_SEC_ADDR, 0x80); //暂停
bsp_DS1302_write_byte(BSP_DS1302_YEAR_ADDR, HexToBCD(pTime->Year));
bsp_DS1302_write_byte(BSP_DS1302_MONTH_ADDR, HexToBCD(pTime->Month));
bsp_DS1302_write_byte(BSP_DS1302_DATA_ADDR, HexToBCD(pTime->Day));
bsp_DS1302_write_byte(BSP_DS1302_HOUR_ADDR, HexToBCD(pTime->Hour));
bsp_DS1302_write_byte(BSP_DS1302_MIN_ADDR, HexToBCD(pTime->Minute));
bsp_DS1302_write_byte(BSP_DS1302_SEC_ADDR, HexToBCD(pTime->Second));
bsp_DS1302_write_byte(BSP_DS1302_CONTROL_ADDR, 0x80); //打开写保护
return USR_TRUE;
}
}
static void bsp_DS1302_Task(void)
{
u8 RegData;
RegData = bsp_DS1302_read_byte(BSP_DS1302_YEAR_ADDR);
pDS1302->Time.Year = (RegData / 16) * 10 + RegData % 16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_MONTH_ADDR);
pDS1302->Time.Month = (RegData / 16) * 10 + RegData % 16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_DATA_ADDR);
pDS1302->Time.Day = (RegData / 16) * 10 + RegData % 16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_HOUR_ADDR);
pDS1302->Time.Hour = (RegData / 16) * 10 + RegData % 16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_MIN_ADDR);
pDS1302->Time.Minute = (RegData / 16) * 10 + RegData % 16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_SEC_ADDR);
pDS1302->Time.Second = (RegData / 16) * 10 + RegData % 16;
}
static void bsp_DS1302Init(void)
{
RST_SET;
SCK_CLR;
bsp_DS1302_Task();
if ((pDS1302->Time.Year > 99) || (pDS1302->Time.Month > 12) || (pDS1302->Time.Day > 31) ||
(pDS1302->Time.Hour > 23) || (pDS1302->Time.Minute > 59) || (pDS1302->Time.Second > 59))
{
pDS1302->Time.Year = 25;
pDS1302->Time.Month = 1;
pDS1302->Time.Day = 1;
pDS1302->Time.Hour = 0;
pDS1302->Time.Minute = 0;
pDS1302->Time.Second = 0;
bsp_DS1302_Set(&pDS1302->Time);
}
}
+206
View File
@@ -0,0 +1,206 @@
#include "bsp_DS1302.h"
#define bsp_DS1302_DELAY() do{ \
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
__NOP();__NOP();__NOP();__NOP();\
}while(0)
#define RST_CLR HAL_GPIO_WritePin(DS1302_RST_GPIO_Port, DS1302_RST_Pin, GPIO_PIN_RESET )
#define RST_SET HAL_GPIO_WritePin(DS1302_RST_GPIO_Port, DS1302_RST_Pin, GPIO_PIN_SET )
#define IO_CLR HAL_GPIO_WritePin(DS1302_DIO_GPIO_Port, DS1302_DIO_Pin, GPIO_PIN_RESET )
#define IO_SET HAL_GPIO_WritePin(DS1302_DIO_GPIO_Port, DS1302_DIO_Pin, GPIO_PIN_SET )
#define IO_READ HAL_GPIO_ReadPin (DS1302_DIO_GPIO_Port, DS1302_DIO_Pin )
#define SCK_CLR HAL_GPIO_WritePin(DS1302_CLK_GPIO_Port, DS1302_CLK_Pin, GPIO_PIN_RESET )
#define SCK_SET HAL_GPIO_WritePin(DS1302_CLK_GPIO_Port, DS1302_CLK_Pin, GPIO_PIN_SET )
static void bsp_DS1302Init(void);
static void bsp_DS1302_Task(void);
static void bsp_DS1302_Set(bsp_DS1302_Time_t *pTime);
bsp_DS1302_t DS1302 =
{
.Init = bsp_DS1302Init,
.Task = bsp_DS1302_Task,
.Set = bsp_DS1302_Set,
};
bsp_DS1302_t *pDS1302 = &DS1302;
static void bsp_DS1302DataInput(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO结构体
GPIO_InitStruct.Pin = DS1302_DIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DS1302_DIO_GPIO_Port, &GPIO_InitStruct);
}
static void bsp_DS1302DataOutput(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO结构体
GPIO_InitStruct.Pin = DS1302_DIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DS1302_DIO_GPIO_Port, &GPIO_InitStruct);
}
/*向bsp_DS1302写入一字节数据*/
static void bsp_DS1302_write_byte(u8 Addr, u8 Data)
{
u8 i;
RST_SET; /*启动bsp_DS1302总线*/
bsp_DS1302_DELAY();
/*写入目标地址:addr*/
Addr = Addr & 0xFE;/*最低位置零*/
for(i=0; i<8; i++){
if(Addr&0x01) IO_SET;
else IO_CLR;
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
Addr = Addr >> 1;
}
/*写入数据:d*/
for(i=0; i<8; i++){
if(Data&0x01) IO_SET;
else IO_CLR;
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
Data = Data >> 1;
}
RST_CLR; /*停止bsp_DS1302总线*/
bsp_DS1302_DELAY();
}
/*从bsp_DS1302读出一字节数据*/
static u8 bsp_DS1302_read_byte(u8 Addr)
{
u8 i;
u8 temp;
RST_SET; /*启动bsp_DS1302总线*/
bsp_DS1302_DELAY();
/*写入目标地址:addr*/
Addr = Addr | 0x01;/*最低位置高*/
for(i=0; i<8; i++)
{
if(Addr&0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
Addr = Addr >> 1;
}
bsp_DS1302DataInput();
/*输出数据:temp*/
for(i=0; i<8; i++)
{
temp = temp>>1;
if(IO_READ) temp |= 0x80;
else temp&=0x7F;
bsp_DS1302_DELAY();
SCK_SET;
bsp_DS1302_DELAY();
SCK_CLR;
bsp_DS1302_DELAY();
}
RST_CLR; /*停止bsp_DS1302总线*/
bsp_DS1302_DELAY();
bsp_DS1302DataOutput();
return temp;
}
static u8 HexToBCD(u8 code)
{
u8 temp;
temp = ((code / 10)<<4)+(code % 10);
return temp;
}
static void bsp_DS1302_Set(bsp_DS1302_Time_t *pTime)
{
bsp_DS1302_write_byte(BSP_DS1302_CONTROL_ADDR,0x00); //关闭写保护
bsp_DS1302_write_byte(BSP_DS1302_SEC_ADDR,0x80); //暂停
bsp_DS1302_write_byte(BSP_DS1302_YEAR_ADDR, HexToBCD(pTime->Year));
bsp_DS1302_write_byte(BSP_DS1302_MONTH_ADDR, HexToBCD(pTime->Month));
bsp_DS1302_write_byte(BSP_DS1302_DATA_ADDR, HexToBCD(pTime->Day));
bsp_DS1302_write_byte(BSP_DS1302_HOUR_ADDR, HexToBCD(pTime->Hour));
bsp_DS1302_write_byte(BSP_DS1302_MIN_ADDR, HexToBCD(pTime->Minute));
bsp_DS1302_write_byte(BSP_DS1302_SEC_ADDR, HexToBCD(pTime->Second));
bsp_DS1302_write_byte(BSP_DS1302_CONTROL_ADDR,0x80); //打开写保护
}
static void bsp_DS1302_Task(void)
{
u8 RegData;
RegData = bsp_DS1302_read_byte(BSP_DS1302_YEAR_ADDR);
pDS1302->Time.Year = (RegData/16)*10 + RegData%16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_MONTH_ADDR);
pDS1302->Time.Month = (RegData/16)*10 + RegData%16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_DATA_ADDR);
pDS1302->Time.Day = (RegData/16)*10 + RegData%16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_HOUR_ADDR);
pDS1302->Time.Hour = (RegData/16)*10 + RegData%16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_MIN_ADDR);
pDS1302->Time.Minute = (RegData/16)*10 + RegData%16;
RegData = bsp_DS1302_read_byte(BSP_DS1302_SEC_ADDR);
pDS1302->Time.Second = (RegData/16)*10 + RegData%16;
}
static void bsp_DS1302Init(void)
{
RST_SET;
SCK_CLR;
bsp_DS1302_Task();
if((pDS1302->Time.Year>99)||(pDS1302->Time.Month>12)||(pDS1302->Time.Day>31)||
(pDS1302->Time.Hour>23)||(pDS1302->Time.Minute>59)||(pDS1302->Time.Second>59))
{
pDS1302->Time.Year = 25;
pDS1302->Time.Month = 1;
pDS1302->Time.Day = 1;
pDS1302->Time.Hour = 0;
pDS1302->Time.Minute = 0;
pDS1302->Time.Second = 0;
bsp_DS1302_Set(&pDS1302->Time);
}
}
+37
View File
@@ -0,0 +1,37 @@
#ifndef __BSP_DS1302_H__
#define __BSP_DS1302_H__
#include "main.h"
#define BSP_DS1302_SEC_ADDR 0x80 //秒数据地址
#define BSP_DS1302_MIN_ADDR 0x82 //分数据地址
#define BSP_DS1302_HOUR_ADDR 0x84 //时数据地址
#define BSP_DS1302_DATA_ADDR 0x86 //日数据地址
#define BSP_DS1302_MONTH_ADDR 0x88 //月数据地址
#define BSP_DS1302_DAY_ADDR 0x8a //星期数据地址
#define BSP_DS1302_YEAR_ADDR 0x8c //年数据地址
#define BSP_DS1302_CONTROL_ADDR 0x8e //控制数据地址
#define BSP_DS1302_CHARGER_ADDR 0x90
#define BSP_DS1302_CLKBURST_ADDR 0xbe
typedef struct
{
u16 Year;
u8 Month;
u8 Day;
u8 Hour;
u8 Minute;
u8 Second;
}bsp_DS1302_Time_t;
typedef struct
{
bsp_DS1302_Time_t Time;
void (*Init)(void);
u8 (*Set)(bsp_DS1302_Time_t *);
void (*Task)(void);
}bsp_DS1302_t;
extern bsp_DS1302_t DS1302;//系统时间
#endif
+1
View File
@@ -0,0 +1 @@
#include "bsp_Delay.h"
+6
View File
@@ -0,0 +1,6 @@
#ifndef _BSP_DELAY_H_
#define _BSP_DELAY_H_
#include "main.h"
#endif
+248
View File
@@ -0,0 +1,248 @@
#include "bsp_Flash.h"
#include "string.h"
#include "bsp_Wdg.h"
#include "bsp_W5500.h"
#include "proto_HSMS.h"
/* FLASH Memory Definitions */
#define BSP_FLASH_SIZE (0x10000UL)
#define BSP_FLASH_PAGE_SIZE (FLASH_PAGE_SIZE)
#define BSP_FLASH_PAGE_NUM (BSP_FLASH_SIZE/BSP_FLASH_PAGE_SIZE)
#define BSP_FLASH_ADDR_RW(n) ((uint32_t)(FLASH_BASE + (BSP_FLASH_PAGE_NUM - (n)) * BSP_FLASH_PAGE_SIZE))
#define BSP_FLASH_DATASAVE_ADDR BSP_FLASH_ADDR_RW(1)
static void bsp_Flash_Init(void);
static void bsp_FlashDataWrite(void);
static void bsp_FlashDataRead(void);
static void bsp_FlashReset(void);
bsp_Flash_t Usr_Flash =
{
.Init = bsp_Flash_Init,
.Write = bsp_FlashDataWrite,
.Read = bsp_FlashDataRead,
.Reset = bsp_FlashReset,
};
// 擦除指定页
static HAL_StatusTypeDef bsp_FLASH_ErasePage(uint32_t PageAddress)
{
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t PageError = 0;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = PageAddress;
EraseInitStruct.NbPages = 1;
return HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
}
// 读取数据 - 按32位读取
static void bsp_Flash_STMFLASH_Read(uint32_t ReadAddr, void *pBuffer, uint32_t size)
{
uint8_t *pBuf = (uint8_t*)pBuffer;
uint32_t *addr = (uint32_t*)ReadAddr;
uint32_t words = size / 4;
uint32_t bytes_remaining = size % 4;
// 读取完整的32位字
for(uint32_t i = 0; i < words; i++)
{
*((uint32_t*)pBuf) = addr[i];
pBuf += 4;
}
// 读取剩余的字节
if(bytes_remaining > 0)
{
uint32_t last_word = addr[words];
uint8_t *last_bytes = (uint8_t*)&last_word;
for(uint32_t i = 0; i < bytes_remaining; i++)
{
pBuf[i] = last_bytes[i];
}
}
}
// 写入数据 - 按32位写入
static HAL_StatusTypeDef bsp_Flash_STMFLASH_Write(uint32_t WriteAddr, void *pBuffer, uint32_t size)
{
HAL_StatusTypeDef status = HAL_OK;
uint8_t *pBuf = (uint8_t*)pBuffer;
uint32_t words = size / 4;
uint32_t bytes_remaining = size % 4;
uint32_t current_addr = WriteAddr;
HAL_FLASH_Unlock();
// 擦除目标页
status = bsp_FLASH_ErasePage(WriteAddr);
if(status != HAL_OK)
{
HAL_FLASH_Lock();
return status;
}
// 写入完整的32位字
for(uint32_t i = 0; i < words; i++)
{
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
current_addr,
*((uint32_t*)pBuf));
if(status != HAL_OK) break;
current_addr += 4;
pBuf += 4;
}
// 写入剩余的字节
if(status == HAL_OK && bytes_remaining > 0)
{
uint32_t last_word = 0xFFFFFFFF; // 默认填充0xFF
uint8_t *last_bytes = (uint8_t*)&last_word;
// 复制剩余数据
for(uint32_t i = 0; i < bytes_remaining; i++)
{
last_bytes[i] = pBuf[i];
}
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, current_addr, last_word);
}
HAL_FLASH_Lock();
return status;
}
static void bsp_FlashReset(void)
{
u16 port = 5000;
Usr_Flash.FlashData.IP_Addr[0] = 192;
Usr_Flash.FlashData.IP_Addr[1] = 168;
Usr_Flash.FlashData.IP_Addr[2] = 0;
Usr_Flash.FlashData.IP_Addr[3] = 100;
Usr_Flash.FlashData.Port[0] = port >> 8;
Usr_Flash.FlashData.Port[1] = port & 0x00ff;
Usr_Flash.FlashData.Sub_Mask[0] = 255;
Usr_Flash.FlashData.Sub_Mask[1] = 255;
Usr_Flash.FlashData.Sub_Mask[2] = 255;
Usr_Flash.FlashData.Sub_Mask[3] = 0;
Usr_Flash.FlashData.Gateway_IP[0] = 192;
Usr_Flash.FlashData.Gateway_IP[1] = 168;
Usr_Flash.FlashData.Gateway_IP[2] = 0;
Usr_Flash.FlashData.Gateway_IP[3] = 1;
Usr_Flash.FlashData.Devic_Id = 0;
// /*设备型号 - 'Atlas Abatement' */
// Usr_Flash.FlashData.Device_ID[0] = ('A' << 8) | 't'; // 'At'
// Usr_Flash.FlashData.Device_ID[1] = ('l' << 8) | 'a'; // 'la'
// Usr_Flash.FlashData.Device_ID[2] = ('s' << 8) | ' '; // 's '
// Usr_Flash.FlashData.Device_ID[3] = ('A' << 8) | 'b'; // 'Ab'
// Usr_Flash.FlashData.Device_ID[4] = ('a' << 8) | 't'; // 'at'
// Usr_Flash.FlashData.Device_ID[5] = ('e' << 8) | 'm'; // 'em'
// Usr_Flash.FlashData.Device_ID[6] = ('e' << 8) | 'n'; // 'en'
// Usr_Flash.FlashData.Device_ID[7] = ('t' << 8) | 0x00; // 't\0'
//
// /*设备标识 - 'AHTWA07CHAAC' */
// Usr_Flash.FlashData.Device_Model[0] = ('A' << 8) | 'H'; // 'AH'
// Usr_Flash.FlashData.Device_Model[1] = ('T' << 8) | 'W'; // 'TW'
// Usr_Flash.FlashData.Device_Model[2] = ('A' << 8) | '0'; // 'A0'
// Usr_Flash.FlashData.Device_Model[3] = ('7' << 8) | 'C'; // '7C'
// Usr_Flash.FlashData.Device_Model[4] = ('H' << 8) | 'A'; // 'HA'
// Usr_Flash.FlashData.Device_Model[5] = ('A' << 8) | 'C'; // 'AC'
//
// Usr_Flash.FlashData.Data_ID1 = 0;
// Usr_Flash.FlashData.Collection_event_ID1 = 111101; // 文档中的CEID
//// Usr_Flash.FlashData.Report_ID1 = 2329004; // 文档中的Report ID
// Usr_Flash.FlashData.Alarm_ID = 2320614; // 文档中的AlarmID
//
// /* 报警类型初始化 */
// const char *alarm_types[] = {"Major Warning", "Minor Warning", "Major Alarm", "Minor Alarm"};
// for(int i = 0; i < 4; i++) {
// const char *type = alarm_types[i];
// for(int j = 0; j < 13 && type[j]; j++) {
// if(j % 2 == 0) {
// Usr_Flash.FlashData.Alarm_Type[i*2 + j/2] = (type[j] << 8) | (type[j+1] ? type[j+1] : 0);
// }
// }
// }
bsp_FlashDataWrite();
}
static void bsp_Flash_Init(void)
{
u8 i;
bsp_FlashDataRead();
if( Usr_Flash.FlashData.IP_Addr[0] == 0xff
&& Usr_Flash.FlashData.IP_Addr[1] == 0xff
&& Usr_Flash.FlashData.IP_Addr[2] == 0xff
&& Usr_Flash.FlashData.IP_Addr[3] == 0xff
)
{
bsp_FlashReset();
}
memcpy(&Usr_Flash.TempFlashData, &Usr_Flash.FlashData, sizeof(bsp_FlashData_t));
W5500.IP_Addr[0] = Usr_Flash.FlashData.IP_Addr[0];
W5500.IP_Addr[1] = Usr_Flash.FlashData.IP_Addr[1];
W5500.IP_Addr[2] = Usr_Flash.FlashData.IP_Addr[2];
W5500.IP_Addr[3] = Usr_Flash.FlashData.IP_Addr[3];
W5500.Gateway_IP[0] =Usr_Flash.FlashData.Gateway_IP[0];
W5500.Gateway_IP[1]=Usr_Flash.FlashData.Gateway_IP[1];
W5500.Gateway_IP[2]=Usr_Flash.FlashData.Gateway_IP[2];
W5500.Gateway_IP[3]=Usr_Flash.FlashData.Gateway_IP[3];
W5500.W5500_Class[0].ConfigData.Port[0] = Usr_Flash.FlashData.Port[0];
W5500.W5500_Class[0].ConfigData.Port[1] = Usr_Flash.FlashData.Port[1];
W5500.Sub_Mask[0] = Usr_Flash.FlashData.Sub_Mask[0];
W5500.Sub_Mask[1] = Usr_Flash.FlashData.Sub_Mask[1];
W5500.Sub_Mask[2] = Usr_Flash.FlashData.Sub_Mask[2];
W5500.Sub_Mask[3] = Usr_Flash.FlashData.Sub_Mask[3];
HSMS.Flash_ConfigData.Device_Id = Usr_Flash.FlashData.Devic_Id;
}
static void bsp_FlashDataWrite(void)
{
/*防止重复擦写相同数据*/
if(memcmp(&Usr_Flash.TempFlashData, &Usr_Flash.FlashData, sizeof(bsp_FlashData_t)) != 0)
{
Wdg.Feed();
__disable_irq(); // 禁用全局中断
HAL_StatusTypeDef status = bsp_Flash_STMFLASH_Write(BSP_FLASH_DATASAVE_ADDR,&Usr_Flash.FlashData,sizeof(bsp_FlashData_t));
if(status == HAL_OK)
{
// 写入成功,更新临时数据
memcpy(&Usr_Flash.TempFlashData, &Usr_Flash.FlashData, sizeof(bsp_FlashData_t));
}
else
{
}
__enable_irq(); // 恢复中断
Wdg.Feed();
}
}
static void bsp_FlashDataRead(void)
{
Wdg.Feed();
bsp_Flash_STMFLASH_Read(BSP_FLASH_DATASAVE_ADDR,
&Usr_Flash.FlashData,
sizeof(bsp_FlashData_t));
Wdg.Feed();
}
+63
View File
@@ -0,0 +1,63 @@
#ifndef _BSP_FLASH_H_
#define _BSP_FLASH_H_
#include "main.h"
typedef struct
{
/*用于判断数据是否一致*/
u16 SN[5];
u8 IP_Addr[4];
u8 Gateway_IP[4];
u8 Port[2];
u8 Sub_Mask[4];
u16 Devic_Id;
u16 Device_ID[8]; // 'Atlas Abatement' - 15字符,设备型号(16字节)
u16 Device_Model[8]; // 'AHTWA07CHAAC' - 12字符,报警机台和位置(12字节)
u16 Device_SN[8]; //设备SN号
u16 Station_Name[8]; // 机台名称
u16 Chamber_Name[8]; // 腔体名称
u16 Manufacturer[8]; //厂商名称-10字符
u16 Version[8]; //机台软件版本号-10字符
u16 Station_Type[8]; //机台类型
u16 Alarm_info[20]; //使用PM100中的
u16 Data_ID1; //置空
u32 Collection_event_ID1; //CEID为固定值
u32 Report_ID1; //置空
u32 Alarm_ID; //使用函数内部的
u16 Alarm_Type[7]; // 使用函数内部
u16 Begin_Warning[7]; //函数内部固定为begin
u16 IDS[11]; //置空
u16 Over_Trigger[9];
u16 Equipment[5];
u16 E9[19];
u16 Device_Type; //置空
u16 Sensor;
u16 Alarm_value;
u16 Alarm_ubit;
u16 Start_Time[11]; //开始时间
u16 Alarm_Time[6]; //报警时长
u16 Alarm[6]; //报警类型 策略报警、机台报警
u16 Data_ID2;
u16 Collection_event_ID2;
u16 Report_ID2;
u16 Sub_Device_Type[2]; // 附属设备类型
u16 Sub_Device_State[2]; // 附属设备状态
u16 State_Change_Time[2]; // 状态切换时间格式
} bsp_FlashData_t;
typedef struct
{
bsp_FlashData_t TempFlashData;
bsp_FlashData_t FlashData;
void (*Init)(void);
void (*Write)(void);
void (*Read)(void);
void (*Reset)(void);
} bsp_Flash_t;
extern bsp_Flash_t Usr_Flash;
#endif
+39
View File
@@ -0,0 +1,39 @@
#include "bsp_Key.h"
#include "os_timer.h"
#include "bsp_Flash.h"
#define BSP_KEY_ENTER_NUM 500
static void bsp_key_init(void);
static void bsp_key_task(void);
bsp_key_t key =
{
.init = bsp_key_init,
.task = bsp_key_task,
};
static bsp_key_t *p_key = &key;
static void bsp_key_init(void)
{
}
static void bsp_key_task(void)
{
if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(SYS_RESET_GPIO_Port,SYS_RESET_Pin))
{
p_key->count++;
}
else
{
p_key->count = 0;
}
if(BSP_KEY_ENTER_NUM <= p_key->count)
{
/*ϵͳ¸´Î»*/
Usr_Flash.Reset();
HAL_NVIC_SystemReset();
}
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef _BSP_KEY_H_
#define _BSP_KEY_H_
#include "main.h"
typedef struct
{
u16 count;
void (*init)(void);
void (*task)(void);
}bsp_key_t;
extern bsp_key_t key;
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef _BSP_LED_H_
#define _BSP_LED_H_
#include "main.h"
typedef struct
{
void (*Init)(void);
void (*Flash)(void);
}bsp_Led_t;
extern bsp_Led_t Led;
#endif
+25
View File
@@ -0,0 +1,25 @@
#include "bsp_Led.h"
#include "os_timer.h"
static void bsp_Led_Init(void);
static void bsp_Led_Flash(void);
bsp_Led_t Led =
{
.Init = bsp_Led_Init,
.Flash = bsp_Led_Flash,
};
/*其他外设初始化后快速闪烁,提示初始化完成*/
static void bsp_Led_Init(void)
{
for(u8 i = 0;i < 20;i++)
{
Delay_ms(50);
HAL_GPIO_TogglePin(LED_RUN_GPIO_Port, LED_RUN_Pin);
}
}
static void bsp_Led_Flash(void)
{
HAL_GPIO_TogglePin(LED_RUN_GPIO_Port, LED_RUN_Pin);
}
+207
View File
@@ -0,0 +1,207 @@
#include "bsp_Uart.h"
#include "string.h"
#define RX_TEMP_BUFF_NUM (1100)
#define UART1_TX_LEN (32)
#define UART1_RX_LEN (1100)
#define UART2_TX_LEN (32)
#define UART2_RX_LEN (1100)
u8 Rx_Temp_Buff[RX_TEMP_BUFF_NUM];
/*发送使用DMA发送 接收*/
u8 Uart1_TX_Buff[UART1_TX_LEN];
u8 Uart1_Rx_Buff[UART1_RX_LEN];
u8 Uart2_TX_Buff[UART1_TX_LEN];
u8 Uart2_Rx_Buff[UART1_RX_LEN];
/*接收使用DMA+串口空闲+超时检测*/
static void bsp_Uart_Init(bsp_Uart_t *p_Uart);
static void bsp_Uart_Send(bsp_Uart_t *p_Uart,u8 *pData, u16 Len);
static void bsp_Uart_Tx_DMA_TCInt(bsp_Uart_t *p_Uart);
static void bsp_Uart_Rx_IdleInt(bsp_Uart_t *p_Uart);
static void bsp_Uart_Rx_TimeIncrement(bsp_Uart_t *p_Uart,u16 Time);
static void bsp_Uart_Rx_TimeStart(bsp_Uart_t *p_Uart);
static void bsp_Uart_Rx_TimeStop(bsp_Uart_t *p_Uart);
static void bsp_Uart_Rx_Task(bsp_Uart_t *p_Uart);
bsp_Uart_t COM_Uart1 =
{
.RxQueue = queue(u8,UART1_RX_LEN),
.Uart =USART1,
.Tx_DMA = DMA1,
.Rx_DMA = DMA1,
.Rx_DMA_CH = LL_DMA_CHANNEL_4,
.Tx_DMA_CH = LL_DMA_CHANNEL_5,
.Tx_DMA_Len = UART1_TX_LEN,
.Rx_DMA_Len = UART1_RX_LEN,
.Tx_Addr = &Uart1_TX_Buff[0],
.Rx_Addr = &Uart1_Rx_Buff[0],
.Tx_DMA_CompleteFlag = 1,
.Rx_TimeOver = 10, /*接收超时时间10ms 设置为0时为串口空闲中断触发 无超时检测*/
.Init = bsp_Uart_Init,
.Send = bsp_Uart_Send,
.Tx_DMA_TCInt = bsp_Uart_Tx_DMA_TCInt,
.Rx_IdleInt = bsp_Uart_Rx_IdleInt,
.Rx_TimeIncrementInt = bsp_Uart_Rx_TimeIncrement,
.Rx_DataAnalysis = NULL,
.Rx_Task = bsp_Uart_Rx_Task,
};
bsp_Uart_t COM_Uart2 =
{
.RxQueue = queue(u8,UART2_RX_LEN),
.Uart =USART2,
.Tx_DMA = DMA1,
.Rx_DMA = DMA1,
.Rx_DMA_CH = LL_DMA_CHANNEL_1,
.Tx_DMA_CH = LL_DMA_CHANNEL_2,
.Tx_DMA_Len = UART2_TX_LEN,
.Rx_DMA_Len = UART2_RX_LEN,
.Tx_Addr = &Uart2_TX_Buff[0],
.Rx_Addr = &Uart2_Rx_Buff[0],
.Tx_DMA_CompleteFlag = 1,
.Rx_TimeOver = 5, /*接收超时时间10ms设置为0时为串口空闲中断触发 无超时检测*/
.Init = bsp_Uart_Init,
.Send = bsp_Uart_Send,
.Tx_DMA_TCInt = bsp_Uart_Tx_DMA_TCInt,
.Rx_IdleInt = bsp_Uart_Rx_IdleInt,
.Rx_TimeIncrementInt = bsp_Uart_Rx_TimeIncrement,
.Rx_DataAnalysis = NULL,
.Rx_Task = bsp_Uart_Rx_Task,
};
static void bsp_Uart_Init(bsp_Uart_t *p_Uart)
{
/*配置数据解析函数*/
p_Uart->Rx_DataAnalysis = NULL;
/*RX*/
if(NULL == p_Uart->Uart)
return;
LL_USART_EnableIT_RXNE(p_Uart->Uart); //使能串口接收中断
if(NULL != p_Uart->Rx_DMA)
{
}
}
static void bsp_Uart2_DMASend(bsp_Uart_t *p_Uart,u8 *pData, u16 Len)
{
while (!p_Uart->Tx_DMA_CompleteFlag); /*等待传输完成标志*/
p_Uart->Tx_DMA_CompleteFlag = 0;
if(p_Uart->Tx_DMA_Len < Len)
Len = p_Uart->Tx_DMA_Len;
memcpy(p_Uart->Tx_Addr, pData, Len); /*拷贝数据到发送缓冲*/
}
/*空闲中断*/
static void bsp_Uart_Rx_IdleInt(bsp_Uart_t *p_Uart)
{
u8 rx_data;
rx_data = LL_USART_ReceiveData8(p_Uart->Uart);
queue_push_back(p_Uart->RxQueue,(void *)&rx_data);
/*开始计数*/
bsp_Uart_Rx_TimeStart(p_Uart);
}
/*大数据量发送*/
static void bsp_Uart_Send(bsp_Uart_t *p_Uart,u8 *pData, u16 Len)
{
u16 i;
for (i = 0; i < Len; i++)
{
while (!LL_USART_IsActiveFlag_TXE(p_Uart->Uart));
LL_USART_TransmitData8(p_Uart->Uart, pData[i]); // 发送一个字节的数据
}
}
static void bsp_Uart_Tx_DMA_TCInt(bsp_Uart_t *p_Uart)
{
p_Uart->Tx_DMA_CompleteFlag = 1;
}
/*中断计数*/
static void bsp_Uart_Rx_TimeIncrement(bsp_Uart_t *p_Uart,u16 Time)
{
/*开始计数*/
if(1 == p_Uart->Rx_StartFlag)
{
p_Uart->Rx_TimeCount += Time;
}
}
/*开始计数*/
static void bsp_Uart_Rx_TimeStart(bsp_Uart_t *p_Uart)
{
p_Uart->Rx_StartFlag = 1;
p_Uart->Rx_TimeCount = 0;
}
/*停止计数*/
static void bsp_Uart_Rx_TimeStop(bsp_Uart_t *p_Uart)
{
p_Uart->Rx_StartFlag = 0;
p_Uart->Rx_TimeCount = 0;
}
static void bsp_Uart_Rx_Task(bsp_Uart_t *p_Uart)
{
/*超时计数完成,接收到一帧数据*/
if(p_Uart->Rx_TimeOver < p_Uart->Rx_TimeCount)
{
p_Uart->Rx_Len = queue_size(p_Uart->RxQueue);
/*停止计数*/
bsp_Uart_Rx_TimeStop(p_Uart);
if(p_Uart->Rx_Len <= p_Uart->Rx_DMA_Len && (0 != p_Uart->Rx_Len))
{
if(RX_TEMP_BUFF_NUM < p_Uart->Rx_Len)
{
queue_clear(p_Uart->RxQueue);
}
else
{
for(u16 i = 0;i < p_Uart->Rx_Len;i++)
{
queue_pop(p_Uart->RxQueue,&Rx_Temp_Buff[i]);
}
if(NULL != p_Uart->Rx_DataAnalysis)
{
p_Uart->Rx_DataAnalysis(Rx_Temp_Buff,p_Uart->Rx_Len,p_Uart); /*解析数据*/
}
//p_Uart->Send(p_Uart,Rx_Buff,p_Uart->Rx_Len);
}
}
}
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef _BSP_UART_H_
#define _BSP_UART_H_
#include "main.h"
#include "algo_queue.h"
typedef struct bsp_Uart_t bsp_Uart_t;
struct bsp_Uart_t
{
queue RxQueue; /*数据接收队列*/
USART_TypeDef *Uart; /*串口*/
DMA_TypeDef *Tx_DMA; /*DMA*/
DMA_TypeDef *Rx_DMA;
u8 Tx_DMA_CH;
u8 Rx_DMA_CH;
vu8 Tx_DMA_CompleteFlag; /*DMA接受完成标志位*/
u8 *Tx_Addr; /*DMA搬运缓冲*/
u8 *Rx_Addr;
u16 Tx_DMA_Len;
u16 Rx_DMA_Len;
u16 Rx_Len; /*接收到的数据长度*/
u16 Rx_TimeCount; /*超时计数*/
u16 Rx_TimeOver; /*超时时间*/
u8 Rx_StartFlag; /*开始超时计数标志位*/
void (*Init)(bsp_Uart_t *); /*初始化*/
void (*Send)(bsp_Uart_t *,u8 *,u16); /*串口发送函数*/
void (*Tx_DMA_TCInt)(bsp_Uart_t *); /*DMA发送完成中断*/
void (*Rx_IdleInt)(bsp_Uart_t *); /*空闲中断*/
void (*Rx_TimeIncrementInt)(bsp_Uart_t *,u16); /*中断计数计数*/
void (*Rx_DataAnalysis)(u8 *,u16,void *); /*数据解析*/
void (*Rx_Task)(bsp_Uart_t *); /*串口接收任务*/
};
extern bsp_Uart_t COM_Uart1;
extern bsp_Uart_t COM_Uart2;
#endif
+852
View File
@@ -0,0 +1,852 @@
/**********************************************************************************
* 文件名 W5500.c
* 描述 :W5500 驱动函数库
* 库版本 ST_v3.5
* 作者 :泥人通信模块开发团队
* 博客 http://nirenelec.blog.163.com
* 淘宝 http://nirenelec.taobao.com
**********************************************************************************/
#include "stm32f1xx.h"
#include "stm32f1xx_hal_spi.h"
#include "bsp_W5500.h"
#include "usart.h"
#include "stdio.h"
#include "spi.h"
#include "bsp_print.h"
#define BSP_W5500_SPI_CS_LOW
/*Run_Mode 端口的运行模式*/
#define BSP_W5500_PORT_RUN_MODE_TCP_SERVER 0x00 /*TCP服务器模式*/
#define BSP_W5500_PORT_RUN_MODE_TCP_CLIENT 0x01 /*TCP客户端模式*/
#define BSP_W5500_PORT_RUN_MODE_UDP 0x02 /*UDP(广播)模式*/
/*Run_State 端口的运行状态 BIT位*/
#define BSP_W5500_PORT_RUN_STATE_INIT 0x01 /*端口完成初始化*/
#define BSP_W5500_PORT_RUN_STATE_CONN 0x02 /*端口完成连接,可以正常传输数据*/
/*TR_Data_State 端口的收发数据状态*/
#define BSP_W5500_PORT_DATA_RECEIVE 0x01 /*端口接收到一个数据包*/
#define BSP_W5500_PORT_DATA_TRANSMITOK 0x02 /*端口发送一个数据包完成*/
static void bsp_W5500_Interrupt_Process(void);
static void bsp_W5500_Init(void);
static void bsp_W5500_Task(void);
static void Write_SOCK_Data_Buffer(bsp_W5500_Class_t *pW5500_Class, u8 *dat_ptr, u16 size);
static void network_monitor_task(void);
void bsp_W5500_Socket_Set(bsp_W5500_Class_t *pW5500_Class);
static u8 last_link_status = 0; // 保存上一次链路状态
bsp_W5500_t W5500 =
{
.Gateway_IP = {192,168,1,1},
.Sub_Mask = {255,255,255,0},
.Phy_Addr = {0x0c,0x29,0xab,0x7c,0x00,0x01},
//.IP_Addr = {169,254,107,101},
.IP_Addr = {192,168,1,101},
.Monitor_task = network_monitor_task,
.Interrupt_Process = bsp_W5500_Interrupt_Process,
.Init = bsp_W5500_Init,
.Task = bsp_W5500_Task,
.Socket_Send = Write_SOCK_Data_Buffer,
.W5500_Class[0] =
{
.SocketPort = 0, /*使用端口0*/
.ConfigData.Port = {0x13,0x88},
// .ConfigData.DIP = {192,168,1,32},
// .ConfigData.DPort = {0x03,0x09},
.Run_Mode = BSP_W5500_PORT_RUN_MODE_TCP_SERVER,
// .Rx_DataAnalysis = proto_HSMS_Rx_DataAnalysis,
},
};
bsp_W5500_t *pW5500 = &W5500;
/*******************************************************************************
* 函数名 : SPI1_Send_Byte
* 描述 : SPI1发送1个字节数据
* 输入 : dat:待发送的数据
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void SPI1_Send_Byte(u8 dat)
{
// hspi1.Instance->DR=dat;
HAL_SPI_Transmit(&hspi1, &dat, 1, 0xff);
// while(__HAL_SPI_GET_FLAG(&hspi1,SPI_FLAG_TXE)==RESET);
// SPI_I2S_SendData(SPI1,dat);//写1个字节数据
// while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//等待数据寄存器空
}
/*******************************************************************************
* 函数名 : SPI1_Send_Short
* 描述 : SPI1发送2个字节数据(16位)
* 输入 : dat:待发送的16位数据
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void SPI1_Send_Short(u16 dat)
{
SPI1_Send_Byte(dat >> 8); // 写数据高位
SPI1_Send_Byte(dat); // 写数据低位
}
/*******************************************************************************
* 函数名 : Write_W5500_1Byte
* 描述 : 通过SPI1向指定地址寄存器写1个字节数据
* 输入 : reg:16位寄存器地址,dat:待写入的数据
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Write_W5500_1Byte(u16 reg, u8 dat)
{
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM1 | RWB_WRITE | COMMON_R); // 通过SPI1写控制字节,1个字节数据长度,写数据,选择通用寄存器
SPI1_Send_Byte(dat); // 写1个字节数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
}
/*******************************************************************************
* 函数名 : Write_W5500_2Byte
* 描述 : 通过SPI1向指定地址寄存器写2个字节数据
* 输入 : reg:16位寄存器地址,dat:16位待写入的数据(2个字节)
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Write_W5500_2Byte(u16 reg, u16 dat)
{
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM2 | RWB_WRITE | COMMON_R); // 通过SPI1写控制字节,2个字节数据长度,写数据,选择通用寄存器
SPI1_Send_Short(dat); // 写16位数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
}
/*******************************************************************************
* 函数名 : Write_W5500_nByte
* 描述 : 通过SPI1向指定地址寄存器写n个字节数据
* 输入 : reg:16位寄存器地址,*dat_ptr:待写入数据缓冲区指针,size:待写入的数据长度
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Write_W5500_nByte(u16 reg, u8 *dat_ptr, u16 size)
{
u16 i;
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(VDM | RWB_WRITE | COMMON_R); // 通过SPI1写控制字节,N个字节数据长度,写数据,选择通用寄存器
for (i = 0; i < size; i++) // 循环将缓冲区的size个字节数据写入W5500
{
SPI1_Send_Byte(*dat_ptr++); // 写一个字节数据
}
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
}
/*******************************************************************************
* 函数名 : Write_W5500_SOCK_1Byte
* 描述 : 通过SPI1向指定端口寄存器写1个字节数据
* 输入 : s:端口号,reg:16位寄存器地址,dat:待写入的数据
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Write_W5500_SOCK_1Byte(SOCKET s, u16 reg, u8 dat)
{
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM1 | RWB_WRITE | (s * 0x20 + 0x08)); // 通过SPI1写控制字节,1个字节数据长度,写数据,选择端口s的寄存器
SPI1_Send_Byte(dat); // 写1个字节数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
}
/*******************************************************************************
* 函数名 : Write_W5500_SOCK_2Byte
* 描述 : 通过SPI1向指定端口寄存器写2个字节数据
* 输入 : s:端口号,reg:16位寄存器地址,dat:16位待写入的数据(2个字节)
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Write_W5500_SOCK_2Byte(SOCKET s, u16 reg, u16 dat)
{
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM2 | RWB_WRITE | (s * 0x20 + 0x08)); // 通过SPI1写控制字节,2个字节数据长度,写数据,选择端口s的寄存器
SPI1_Send_Short(dat); // 写16位数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
}
/*******************************************************************************
* 函数名 : Write_W5500_SOCK_4Byte
* 描述 : 通过SPI1向指定端口寄存器写4个字节数据
* 输入 : s:端口号,reg:16位寄存器地址,*dat_ptr:待写入的4个字节缓冲区指针
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
void Write_W5500_SOCK_4Byte(SOCKET s, u16 reg, u8 *dat_ptr)
{
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM4 | RWB_WRITE | (s * 0x20 + 0x08)); // 通过SPI1写控制字节,4个字节数据长度,写数据,选择端口s的寄存器
SPI1_Send_Byte(*dat_ptr++); // 写第1个字节数据
SPI1_Send_Byte(*dat_ptr++); // 写第2个字节数据
SPI1_Send_Byte(*dat_ptr++); // 写第3个字节数据
SPI1_Send_Byte(*dat_ptr++); // 写第4个字节数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
}
/*******************************************************************************
* 函数名 : Read_W5500_1Byte
* 描述 : 读W5500指定地址寄存器的1个字节数据
* 输入 : reg:16位寄存器地址
* 输出 : 无
* 返回值 : 读取到寄存器的1个字节数据
* 说明 : 无
*******************************************************************************/
u8 Read_W5500_1Byte(u16 reg)
{
u8 i;
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM1 | RWB_READ | COMMON_R); // 通过SPI1写控制字节,1个字节数据长度,读数据,选择通用寄存器
i = hspi1.Instance->DR;
// HAL_SPI_Receive(&hspi1,&i,1,0xf);
// i=SPI_I2S_ReceiveData(SPI1);
SPI1_Send_Byte(0x00); // 发送一个哑数据
i = hspi1.Instance->DR;
// HAL_SPI_Receive(&hspi1,&i,1,0xf);
// i=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
return i; // 返回读取到的寄存器数据
}
/*******************************************************************************
* 函数名 : Read_W5500_SOCK_1Byte
* 描述 : 读W5500指定端口寄存器的1个字节数据
* 输入 : s:端口号,reg:16位寄存器地址
* 输出 : 无
* 返回值 : 读取到寄存器的1个字节数据
* 说明 : 无
*******************************************************************************/
u8 Read_W5500_SOCK_1Byte(SOCKET s, u16 reg)
{
u8 i;
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM1 | RWB_READ | (s * 0x20 + 0x08)); // 通过SPI1写控制字节,1个字节数据长度,读数据,选择端口s的寄存器
i = hspi1.Instance->DR;
// i=SPI_I2S_ReceiveData(SPI1);
SPI1_Send_Byte(0x00); // 发送一个哑数据
i = hspi1.Instance->DR;
// i=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
return i; // 返回读取到的寄存器数据
}
/*******************************************************************************
* 函数名 : Read_W5500_SOCK_2Byte
* 描述 : 读W5500指定端口寄存器的2个字节数据
* 输入 : s:端口号,reg:16位寄存器地址
* 输出 : 无
* 返回值 : 读取到寄存器的2个字节数据(16位)
* 说明 : 无
*******************************************************************************/
u16 Read_W5500_SOCK_2Byte(SOCKET s, u16 reg)
{
u16 i;
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(reg); // 通过SPI1写16位寄存器地址
SPI1_Send_Byte(FDM2 | RWB_READ | (s * 0x20 + 0x08)); // 通过SPI1写控制字节,2个字节数据长度,读数据,选择端口s的寄存器
i = hspi1.Instance->DR;
// i=SPI_I2S_ReceiveData(SPI1);
SPI1_Send_Byte(0x00); // 发送一个哑数据
i = hspi1.Instance->DR;
// i=SPI_I2S_ReceiveData(SPI1);//读取高位数据
SPI1_Send_Byte(0x00); // 发送一个哑数据
i *= 256;
i += hspi1.Instance->DR;
// i+=SPI_I2S_ReceiveData(SPI1);//读取低位数据
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
return i; // 返回读取到的寄存器数据
}
/*******************************************************************************
* 函数名 : Read_SOCK_Data_Buffer
* 描述 : 从W5500接收数据缓冲区中读取数据
* 输入 : s:端口号,*dat_ptr:数据保存缓冲区指针
* 输出 : 无
* 返回值 : 读取到的数据长度,rx_size个字节
* 说明 : 无
*******************************************************************************/
u16 Read_SOCK_Data_Buffer(SOCKET s, u8 *dat_ptr)
{
u16 rx_size;
u16 offset, offset1;
u16 i;
u8 j;
rx_size = Read_W5500_SOCK_2Byte(s, Sn_RX_RSR);
if (rx_size == 0)
return 0; // 没接收到数据则返回
if (rx_size > 1460)
rx_size = 1460;
offset = Read_W5500_SOCK_2Byte(s, Sn_RX_RD);
offset1 = offset;
offset &= (S_RX_SIZE - 1); // 计算实际的物理地址
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(offset); // 写16位地址
SPI1_Send_Byte(VDM | RWB_READ | (s * 0x20 + 0x18)); // 写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
j = hspi1.Instance->DR;
// j=SPI_I2S_ReceiveData(SPI1);
if ((offset + rx_size) < S_RX_SIZE) // 如果最大地址未超过W5500接收缓冲区寄存器的最大地址
{
for (i = 0; i < rx_size; i++) // 循环读取rx_size个字节数据
{
SPI1_Send_Byte(0x00); // 发送一个哑数据
j = hspi1.Instance->DR;
// j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
*dat_ptr = j; // 将读取到的数据保存到数据保存缓冲区
dat_ptr++; // 数据保存缓冲区指针地址自增1
}
}
else // 如果最大地址超过W5500接收缓冲区寄存器的最大地址
{
offset = S_RX_SIZE - offset;
for (i = 0; i < offset; i++) // 循环读取出前offset个字节数据
{
SPI1_Send_Byte(0x00); // 发送一个哑数据
j = hspi1.Instance->DR;
// j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
*dat_ptr = j; // 将读取到的数据保存到数据保存缓冲区
dat_ptr++; // 数据保存缓冲区指针地址自增1
}
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(0x00); // 写16位地址
SPI1_Send_Byte(VDM | RWB_READ | (s * 0x20 + 0x18)); // 写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
j = hspi1.Instance->DR;
// j=SPI_I2S_ReceiveData(SPI1);
for (; i < rx_size; i++) // 循环读取后rx_size-offset个字节数据
{
SPI1_Send_Byte(0x00); // 发送一个哑数据
j = hspi1.Instance->DR;
// j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
*dat_ptr = j; // 将读取到的数据保存到数据保存缓冲区
dat_ptr++; // 数据保存缓冲区指针地址自增1
}
}
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
offset1 += rx_size; // 更新实际物理地址,即下次读取接收到的数据的起始地址
Write_W5500_SOCK_2Byte(s, Sn_RX_RD, offset1);
Write_W5500_SOCK_1Byte(s, Sn_CR, RECV); // 发送启动接收命令
return rx_size; // 返回接收到数据的长度
}
/*******************************************************************************
* 函数名 : Write_SOCK_Data_Buffer
* 描述 : 将数据写入W5500的数据发送缓冲区
* 输入 : s:端口号,*dat_ptr:数据保存缓冲区指针,size:待写入数据的长度
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
static void Write_SOCK_Data_Buffer(bsp_W5500_Class_t *pW5500_Class, u8 *dat_ptr, u16 size)
{
u16 offset, offset1;
u16 i;
// 如果是UDP模式,可以在此设置目的主机的IP和端口号
if ((Read_W5500_SOCK_1Byte(pW5500_Class->SocketPort, Sn_MR) & 0x0f) != SOCK_UDP) // 如果Socket打开失败
{
Write_W5500_SOCK_4Byte(pW5500_Class->SocketPort, Sn_DIPR, pW5500_Class->ConfigData.UDP_DIPR); // 设置目的主机IP
Write_W5500_SOCK_2Byte(pW5500_Class->SocketPort, Sn_DPORTR, pW5500_Class->ConfigData.UDP_DPORT[0]<<8 | pW5500_Class->ConfigData.UDP_DPORT[1]); // 设置目的主机端口号
}
offset = Read_W5500_SOCK_2Byte(pW5500_Class->SocketPort, Sn_TX_WR);
offset1 = offset;
offset &= (S_TX_SIZE - 1); // 计算实际的物理地址
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(offset); // 写16位地址
SPI1_Send_Byte(VDM | RWB_WRITE | (pW5500_Class->SocketPort * 0x20 + 0x10)); // 写控制字节,N个字节数据长度,写数据,选择端口s的寄存器
if ((offset + size) < S_TX_SIZE) // 如果最大地址未超过W5500发送缓冲区寄存器的最大地址
{
for (i = 0; i < size; i++) // 循环写入size个字节数据
{
SPI1_Send_Byte(*dat_ptr++); // 写入一个字节的数据
}
}
else // 如果最大地址超过W5500发送缓冲区寄存器的最大地址
{
offset = S_TX_SIZE - offset;
for (i = 0; i < offset; i++) // 循环写入前offset个字节数据
{
SPI1_Send_Byte(*dat_ptr++); // 写入一个字节的数据
}
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_RESET); // 置W5500的SCS为低电平
SPI1_Send_Short(0x00); // 写16位地址
SPI1_Send_Byte(VDM | RWB_WRITE | (pW5500_Class->SocketPort * 0x20 + 0x10)); // 写控制字节,N个字节数据长度,写数据,选择端口s的寄存器
for (; i < size; i++) // 循环写入size-offset个字节数据
{
SPI1_Send_Byte(*dat_ptr++); // 写入一个字节的数据
}
}
HAL_GPIO_WritePin(W5500_SCS_PORT, W5500_SCS, GPIO_PIN_SET); // 置W5500的SCS为高电平
offset1 += size; // 更新实际物理地址,即下次写待发送数据到发送数据缓冲区的起始地址
Write_W5500_SOCK_2Byte(pW5500_Class->SocketPort, Sn_TX_WR, offset1);
Write_W5500_SOCK_1Byte(pW5500_Class->SocketPort, Sn_CR, SEND); // 发送启动发送命令
}
/*******************************************************************************
* 函数名 : W5500_Hardware_Reset
* 描述 : 硬件复位W5500
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : W5500的复位引脚保持低电平至少500us以上,才能重围W5500
*******************************************************************************/
void W5500_Hardware_Reset(void)
{
HAL_GPIO_WritePin(W5500_RST_PORT, W5500_RST, GPIO_PIN_RESET); // 复位引脚拉低
HAL_Delay(50);
HAL_GPIO_WritePin(W5500_RST_PORT, W5500_RST, GPIO_PIN_SET); // 复位引脚拉高
HAL_Delay(100);
// while((Read_W5500_1Byte(PHYCFGR)&LINK)==0);//等待以太网连接完成
}
/*******************************************************************************
* 函数名 : W5500_Init
* 描述 : 初始化W5500寄存器函数
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 在使用W5500之前,先对W5500初始化
*******************************************************************************/
void W5500_Init(void)
{
u16 i = 0;
Write_W5500_1Byte(MR, RST); // 软件复位W5500,置1有效,复位后自动清0
HAL_Delay(10); // 延时10ms,自己定义该函数
// 设置网关(Gateway)的IP地址,Gateway_IP为4字节u8数组,自己定义
// 使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入Internet
Write_W5500_nByte(GAR, pW5500->Gateway_IP, 4);
// 设置子网掩码(MASK)值,SUB_MASK为4字节u8数组,自己定义
// 子网掩码用于子网运算
Write_W5500_nByte(SUBR, pW5500->Sub_Mask, 4);
// 设置物理地址,PHY_ADDR为6字节u8数组,自己定义,用于唯一标识网络设备的物理地址值
// 该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号
// 如果自己定义物理地址,注意第一个字节必须为偶数
Write_W5500_nByte(SHAR, pW5500->Phy_Addr, 6);
// 设置本机的IP地址,IP_ADDR为4字节u8数组,自己定义
// 注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关
Write_W5500_nByte(SIPR, pW5500->IP_Addr, 4);
// 设置发送缓冲区和接收缓冲区的大小,参考W5500数据手册
for (i = 0; i < 8; i++)
{
Write_W5500_SOCK_1Byte(i, Sn_RXBUF_SIZE, 0x02); // Socket Rx memory size=2k
Write_W5500_SOCK_1Byte(i, Sn_TXBUF_SIZE, 0x02); // Socket Tx mempry size=2k
}
// 设置重试时间,默认为2000(200ms)
// 每一单位数值为100微秒,初始化时值设为2000(0x07D0),等于200毫秒
Write_W5500_2Byte(RTR, 0x07d0);
// 设置重试次数,默认为8次
// 如果重发的次数超过设定值,则产生超时中断(相关的端口中断寄存器中的Sn_IR 超时位(TIMEOUT)置“1”)
Write_W5500_1Byte(RCR, 8);
}
/*******************************************************************************
* 函数名 : Detect_Gateway
* 描述 : 检查网关服务器
* 输入 : 无
* 输出 : 无
* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
* 说明 : 无
*******************************************************************************/
u8 Detect_Gateway(void)
{
u8 ip_adde[4];
ip_adde[0] = pW5500->IP_Addr[0] + 1;
ip_adde[1] = pW5500->IP_Addr[1] + 1;
ip_adde[2] = pW5500->IP_Addr[2] + 1;
ip_adde[3] = pW5500->IP_Addr[3] + 1;
// 检查网关及获取网关的物理地址
Write_W5500_SOCK_4Byte(0, Sn_DIPR, ip_adde); // 向目的地址寄存器写入与本机IP不同的IP值
Write_W5500_SOCK_1Byte(0, Sn_MR, MR_TCP); // 设置socket为TCP模式
Write_W5500_SOCK_1Byte(0, Sn_CR, OPEN); // 打开Socket
HAL_Delay(5); // 延时5ms
if (Read_W5500_SOCK_1Byte(0, Sn_SR) != SOCK_INIT) // 如果socket打开失败
{
Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE); // 打开不成功,关闭Socket
return FALSE; // 返回FALSE(0x00)
}
Write_W5500_SOCK_1Byte(0, Sn_CR, CONNECT); // 设置Socket为Connect模式
do
{
u16 j = 0;
j = Read_W5500_SOCK_1Byte(0, Sn_IR); // 读取Socket0中断标志寄存器
if (j != 0)
Write_W5500_SOCK_1Byte(0, Sn_IR, j);
HAL_Delay(5); // 延时5ms
if ((j & IR_TIMEOUT) == IR_TIMEOUT)
{
return FALSE;
}
else if (Read_W5500_SOCK_1Byte(0, Sn_DHAR) != 0xff)
{
Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE); // 关闭Socket
return TRUE;
}
} while (1);
}
/*******************************************************************************
* 函数名 : Socket_Init
* 描述 : 指定Socket(0~7)初始化
* 输入 : s:待初始化的端口
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
static void bsp_W5500_Socket_Init(bsp_W5500_Class_t *pW5500_Class)
{
Write_W5500_SOCK_2Byte(pW5500_Class->SocketPort, Sn_MSSR, 1460); // 最大分片字节数=1460(0x5b4)
Write_W5500_SOCK_2Byte(pW5500_Class->SocketPort, Sn_PORT, pW5500_Class->ConfigData.Port[0]<<8 | pW5500_Class->ConfigData.Port[1]);
// 设置端口0目的(远程)端口号
Write_W5500_SOCK_2Byte(pW5500_Class->SocketPort, Sn_DPORTR, pW5500_Class->ConfigData.DPort[0]<<8 | pW5500_Class->ConfigData.DPort[1]);
// 设置端口0目的(远程)IP地址
Write_W5500_SOCK_4Byte(pW5500_Class->SocketPort, Sn_DIPR, pW5500_Class->ConfigData.DIP);
}
/*******************************************************************************
* 函数名 : Socket_Connect
* 描述 : 设置指定Socket(0~7)为客户端与远程服务器连接
* 输入 : s:待设定的端口
* 输出 : 无
* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
* 说明 : 当本机Socket工作在客户端模式时,引用该程序,与远程服务器建立连接
* 如果启动连接后出现超时中断,则与服务器连接失败,需要重新调用该程序连接
* 该程序每调用一次,就与服务器产生一次连接
*******************************************************************************/
u8 Socket_Connect(SOCKET s)
{
Write_W5500_SOCK_1Byte(s, Sn_MR, MR_TCP); // 设置socket为TCP模式
Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); // 打开Socket
HAL_Delay(5); // 延时5ms
if (Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_INIT) // 如果socket打开失败
{
Write_W5500_SOCK_1Byte(s, Sn_CR, CLOSE); // 打开不成功,关闭Socket
return FALSE; // 返回FALSE(0x00)
}
Write_W5500_SOCK_1Byte(s, Sn_CR, CONNECT); // 设置Socket为Connect模式
return TRUE; // 返回TRUE,设置成功
}
/*******************************************************************************
* 函数名 : Socket_Listen
* 描述 : 设置指定Socket(0~7)作为服务器等待远程主机的连接
* 输入 : s:待设定的端口
* 输出 : 无
* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
* 说明 : 当本机Socket工作在服务器模式时,引用该程序,等等远程主机的连接
* 该程序只调用一次,就使W5500设置为服务器模式
*******************************************************************************/
u8 Socket_Listen(SOCKET s)
{
Write_W5500_SOCK_1Byte(s, Sn_MR, MR_TCP); // 设置socket为TCP模式
Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); // 打开Socket
HAL_Delay(5); // 延时5ms
if (Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_INIT) // 如果socket打开失败
{
Write_W5500_SOCK_1Byte(s, Sn_CR, CLOSE); // 打开不成功,关闭Socket
return FALSE; // 返回FALSE(0x00)
}
Write_W5500_SOCK_1Byte(s, Sn_CR, LISTEN); // 设置Socket为侦听模式
HAL_Delay(5); // 延时5ms
if (Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_LISTEN) // 如果socket设置失败
{
Write_W5500_SOCK_1Byte(s, Sn_CR, CLOSE); // 设置不成功,关闭Socket
return FALSE; // 返回FALSE(0x00)
}
return TRUE;
// 至此完成了Socket的打开和设置侦听工作,至于远程客户端是否与它建立连接,则需要等待Socket中断,
// 以判断Socket的连接是否成功。参考W5500数据手册的Socket中断状态
// 在服务器侦听模式不需要设置目的IP和目的端口号
}
/*******************************************************************************
* 函数名 : Socket_UDP
* 描述 : 设置指定Socket(0~7)为UDP模式
* 输入 : s:待设定的端口
* 输出 : 无
* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
* 说明 : 如果Socket工作在UDP模式,引用该程序,在UDP模式下,Socket通信不需要建立连接
* 该程序只调用一次,就使W5500设置为UDP模式
*******************************************************************************/
u8 Socket_UDP(SOCKET s)
{
Write_W5500_SOCK_1Byte(s, Sn_MR, MR_UDP); // 设置Socket为UDP模式*/
Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); // 打开Socket*/
HAL_Delay(5); // 延时5ms
if (Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_UDP) // 如果Socket打开失败
{
Write_W5500_SOCK_1Byte(s, Sn_CR, CLOSE); // 打开不成功,关闭Socket
return FALSE; // 返回FALSE(0x00)
}
else
return TRUE;
// 至此完成了Socket的打开和UDP模式设置,在这种模式下它不需要与远程主机建立连接
// 因为Socket不需要建立连接,所以在发送数据前都可以设置目的主机IP和目的Socket的端口号
// 如果目的主机IP和目的Socket的端口号是固定的,在运行过程中没有改变,那么也可以在这里设置
}
/*******************************************************************************
* 函数名 : W5500_Interrupt_Process
* 描述 : W5500中断处理程序框架
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
static void bsp_W5500_Interrupt_Process(void)
{
u8 i, j;
u8 Int_Flag,Socket_Flag;
IntDispose:
Int_Flag = Read_W5500_1Byte(SIR); // 读取端口中断标志寄存器
HAL_Delay(10);
for(i=0;i<BSP_W5500_PORT_NUM;i++)
{
if(Int_Flag & (0x01 << i))
{
Socket_Flag = Read_W5500_SOCK_1Byte(pW5500->W5500_Class[i].SocketPort, Sn_IR); // 读取Socket0中断标志寄存器
Write_W5500_SOCK_1Byte(pW5500->W5500_Class[i].SocketPort, Sn_IR, Socket_Flag);
if (Socket_Flag & IR_CON) // 在TCP模式下,Socket0成功连接
{
pW5500->W5500_Class[i].Run_State |= BSP_W5500_PORT_RUN_STATE_CONN; // 网络连接状态0x02,端口完成连接,可以正常传输数据
}
if (Socket_Flag & IR_DISCON) // 在TCP模式下Socket断开连接处理
{
Write_W5500_SOCK_1Byte(pW5500->W5500_Class[i].SocketPort, Sn_CR, CLOSE); // 关闭端口,等待重新打开连接
bsp_W5500_Socket_Init(&pW5500->W5500_Class[i]); // 指定Socket(0~7)初始化,初始化端口0
pW5500->W5500_Class[i].Run_State = 0; // 网络连接状态0x00,端口连接失败
}
if (Socket_Flag & IR_SEND_OK) // Socket0数据发送完成,可以再次启动S_tx_process()函数发送数据
{
pW5500->W5500_Class[i].TR_Data_State |= BSP_W5500_PORT_DATA_TRANSMITOK; // 端口发送一个数据包完成
}
if (Socket_Flag & IR_RECV) // Socket接收到数据,可以启动S_rx_process()函数
{
pW5500->W5500_Class[i].TR_Data_State |= BSP_W5500_PORT_DATA_RECEIVE; // 端口接收到一个数据包
}
if (Socket_Flag & IR_TIMEOUT) {
// 1. 清除超时中断标志位 (你的代码已有)
Write_W5500_SOCK_1Byte(pW5500->W5500_Class[i].SocketPort, Sn_IR, Socket_Flag);
// 2. 强制关闭Socket,确保其状态机复位
Write_W5500_SOCK_1Byte(pW5500->W5500_Class[i].SocketPort, Sn_CR, CLOSE);
// 3. (强烈推荐) 增加一小段延时,等待硬件完成关闭操作
HAL_Delay(10);
// 4. 关键修复:重新打开Socket并进入监听模式
// bsp_W5500_Socket_Init 函数用于配置Socket参数
bsp_W5500_Socket_Init(&pW5500->W5500_Class[i]);
// bsp_W5500_Socket_Set 函数会根据配置的模式(TCP Server)调用 Socket_Listen
bsp_W5500_Socket_Set(&pW5500->W5500_Class[i]);
// 5. 清理相关的状态标志位
pW5500->W5500_Class[i].Run_State = 0;
pW5500->W5500_Class[i].TR_Data_State = 0;
}
}
}
if (Read_W5500_1Byte(SIR) != 0)
goto IntDispose;
}
/**
* @brief 设置指定Socket的Keep-Alive间隔
* @param s: Socket端口号 (0~7)
* @param interval_5s: 间隔时间,单位5秒,例如2表示10秒。0表示禁用。
*/
void w5500_set_keepalive(SOCKET s, uint8_t interval_5s)
{
Write_W5500_SOCK_1Byte(s, Sn_KPALVTR, interval_5s);
}
void bsp_W5500_Socket_Set(bsp_W5500_Class_t *pW5500_Class)
{
if (0 == pW5500_Class->Run_State)
{
switch(pW5500_Class->Run_Mode)
{
/*TCP服务器模式*/
case BSP_W5500_PORT_RUN_MODE_TCP_SERVER:
{
if (Socket_Listen(pW5500_Class->SocketPort) == TRUE)
{
pW5500_Class->Run_State = BSP_W5500_PORT_RUN_STATE_INIT;
w5500_set_keepalive(pW5500_Class->SocketPort, 2);
}
else
pW5500_Class->Run_State = 0;
}break;
/*TCP客户端模式*/
case BSP_W5500_PORT_RUN_MODE_TCP_CLIENT:
{
if(Socket_Connect(pW5500_Class->SocketPort)==TRUE)
pW5500_Class->Run_State = BSP_W5500_PORT_RUN_STATE_INIT;
else
pW5500_Class->Run_State = 0;
}break;
/*UDP模式*/
case BSP_W5500_PORT_RUN_MODE_UDP:
{
if(Socket_UDP(pW5500_Class->SocketPort)==TRUE)
pW5500_Class->Run_State = BSP_W5500_PORT_RUN_STATE_INIT | BSP_W5500_PORT_RUN_STATE_CONN;
else
pW5500_Class->Run_State = 0;
}break;
default:break;
}
}
}
static void bsp_W5500_Init()
{
u8 i;
W5500_Hardware_Reset(); /*硬件复位W5500*/
W5500_Init(); /*初始化W5500寄存器函数*/
Detect_Gateway(); /*检查网关服务器*/
for(i=0;i<BSP_W5500_PORT_NUM;i++)
{
bsp_W5500_Socket_Init(&pW5500->W5500_Class[i]);
pW5500->W5500_Class[i].Run_State = 0; /*复位状态*/
//bsp_W5500_Socket_Set(&pW5500->W5500_Class[i]); /*W5500端口初始化配置*/
}
}
static void bsp_W5500_Task(void)
{
u8 i;
for(i=0;i<BSP_W5500_PORT_NUM;i++)
{
bsp_W5500_Socket_Set(&pW5500->W5500_Class[i]); /*W5500端口初始化配置*/
}
bsp_W5500_Interrupt_Process(); // W5500中断处理程序框架
for(i=0;i<BSP_W5500_PORT_NUM;i++)
{
if ((pW5500->W5500_Class[i].TR_Data_State & BSP_W5500_PORT_DATA_RECEIVE) == BSP_W5500_PORT_DATA_RECEIVE) // 如果Socket0接收到数据
{
pW5500->W5500_Class[i].TR_Data_State &= ~BSP_W5500_PORT_DATA_RECEIVE;
u16 Len = Read_SOCK_Data_Buffer(0, pW5500->W5500_Class[i].Rx_Buffer);
// Write_SOCK_Data_Buffer(&pW5500->W5500_Class[i], pW5500->W5500_Class[i].Rx_Buffer, Len);
// printf("RX");
// Debug_UartSend(pW5500->W5500_Class[i].Rx_Buffer, Len);
if(pW5500->W5500_Class[i].Rx_DataAnalysis != NULL)
{
pW5500->W5500_Class[i].Rx_DataAnalysis(&pW5500->W5500_Class[i],pW5500->W5500_Class[i].Rx_Buffer,Len);/*数据解析*/
}
}
}
}
/**
* @brief 获取 W5500 物理链路状态
* @return 1: 链路连接, 0: 链路断开
*/
static u8 w5500_get_link_status(void)
{
u8 phycfgr = Read_W5500_1Byte(PHYCFGR); // 读取 PHYCFGR 寄存器
return (phycfgr & LINK) ? 1 : 0; // 返回 LINK 位
}
static void network_monitor_task(void)
{
u8 current_link = w5500_get_link_status();
if (last_link_status == 0 && current_link == 1) {
/*链路从断开变为连接,执行恢复操作*/
W5500.Init();
}
last_link_status = current_link;
}
+270
View File
@@ -0,0 +1,270 @@
#ifndef _W5500_H_
#define _W5500_H_
#include "main.h"
/***************** Common Register *****************/
#define MR 0x0000
#define RST 0x80
#define WOL 0x20
#define PB 0x10
#define PPP 0x08
#define FARP 0x02
#define GAR 0x0001
#define SUBR 0x0005
#define SHAR 0x0009
#define SIPR 0x000f
#define INTLEVEL 0x0013
#define IR 0x0015
#define CONFLICT 0x80
#define UNREACH 0x40
#define PPPOE 0x20
#define MP 0x10
#define IMR 0x0016
#define IM_IR7 0x80
#define IM_IR6 0x40
#define IM_IR5 0x20
#define IM_IR4 0x10
#define SIR 0x0017
#define S7_INT 0x80
#define S6_INT 0x40
#define S5_INT 0x20
#define S4_INT 0x10
#define S3_INT 0x08
#define S2_INT 0x04
#define S1_INT 0x02
#define S0_INT 0x01
#define SIMR 0x0018
#define S7_IMR 0x80
#define S6_IMR 0x40
#define S5_IMR 0x20
#define S4_IMR 0x10
#define S3_IMR 0x08
#define S2_IMR 0x04
#define S1_IMR 0x02
#define S0_IMR 0x01
#define RTR 0x0019
#define RCR 0x001b
#define PTIMER 0x001c
#define PMAGIC 0x001d
#define PHA 0x001e
#define PSID 0x0024
#define PMRU 0x0026
#define UIPR 0x0028
#define UPORT 0x002c
#define PHYCFGR 0x002e
#define RST_PHY 0x80
#define OPMODE 0x40
#define DPX 0x04
#define SPD 0x02
#define LINK 0x01
#define VERR 0x0039
/********************* Socket Register *******************/
#define Sn_MR 0x0000
#define MULTI_MFEN 0x80
#define BCASTB 0x40
#define ND_MC_MMB 0x20
#define UCASTB_MIP6B 0x10
#define MR_CLOSE 0x00
#define MR_TCP 0x01
#define MR_UDP 0x02
#define MR_MACRAW 0x04
#define Sn_CR 0x0001
#define OPEN 0x01
#define LISTEN 0x02
#define CONNECT 0x04
#define DISCON 0x08
#define CLOSE 0x10
#define SEND 0x20
#define SEND_MAC 0x21
#define SEND_KEEP 0x22
#define RECV 0x40
#define Sn_IR 0x0002
#define IR_SEND_OK 0x10
#define IR_TIMEOUT 0x08
#define IR_RECV 0x04
#define IR_DISCON 0x02
#define IR_CON 0x01
#define Sn_SR 0x0003
#define SOCK_CLOSED 0x00
#define SOCK_INIT 0x13
#define SOCK_LISTEN 0x14
#define SOCK_ESTABLISHED 0x17
#define SOCK_CLOSE_WAIT 0x1c
#define SOCK_UDP 0x22
#define SOCK_MACRAW 0x02
#define SOCK_SYNSEND 0x15
#define SOCK_SYNRECV 0x16
#define SOCK_FIN_WAI 0x18
#define SOCK_CLOSING 0x1a
#define SOCK_TIME_WAIT 0x1b
#define SOCK_LAST_ACK 0x1d
#define Sn_PORT 0x0004
#define Sn_DHAR 0x0006
#define Sn_DIPR 0x000c
#define Sn_DPORTR 0x0010
#define Sn_MSSR 0x0012
#define Sn_TOS 0x0015
#define Sn_TTL 0x0016
#define Sn_RXBUF_SIZE 0x001e
#define Sn_TXBUF_SIZE 0x001f
#define Sn_TX_FSR 0x0020
#define Sn_TX_RD 0x0022
#define Sn_TX_WR 0x0024
#define Sn_RX_RSR 0x0026
#define Sn_RX_RD 0x0028
#define Sn_RX_WR 0x002a
#define Sn_IMR 0x002c
#define IMR_SENDOK 0x10
#define IMR_TIMEOUT 0x08
#define IMR_RECV 0x04
#define IMR_DISCON 0x02
#define IMR_CON 0x01
#define Sn_FRAG 0x002d
#define Sn_KPALVTR 0x002f
/*******************************************************************/
/************************ SPI Control Byte *************************/
/*******************************************************************/
/* Operation mode bits */
#define VDM 0x00
#define FDM1 0x01
#define FDM2 0x02
#define FDM4 0x03
/* Read_Write control bit */
#define RWB_READ 0x00
#define RWB_WRITE 0x04
/* Block select bits */
#define COMMON_R 0x00
/* Socket 0 */
#define S0_REG 0x08
#define S0_TX_BUF 0x10
#define S0_RX_BUF 0x18
/* Socket 1 */
#define S1_REG 0x28
#define S1_TX_BUF 0x30
#define S1_RX_BUF 0x38
/* Socket 2 */
#define S2_REG 0x48
#define S2_TX_BUF 0x50
#define S2_RX_BUF 0x58
/* Socket 3 */
#define S3_REG 0x68
#define S3_TX_BUF 0x70
#define S3_RX_BUF 0x78
/* Socket 4 */
#define S4_REG 0x88
#define S4_TX_BUF 0x90
/* Socket 5 */
#define S5_REG 0xa8
#define S5_TX_BUF 0xb0
#define S5_RX_BUF 0xb8
/* Socket 6 */
#define S6_REG 0xc8
#define S6_TX_BUF 0xd0
#define S6_RX_BUF 0xd8
/* Socket 7 */
#define S7_REG 0xe8
#define S7_TX_BUF 0xf0
#define S7_RX_BUF 0xf8
#define TRUE 0xff
#define FALSE 0x00
#define S_RX_SIZE 2048 /*定义Socket接收缓冲区的大小,可以根据W5500_RMSR的设置修改 */
#define S_TX_SIZE 2048 /*定义Socket发送缓冲区的大小,可以根据W5500_TMSR的设置修改 */
/***************----- W5500 GPIO定义 -----***************/
#define W5500_SCS GPIO_PIN_0 // 定义W5500的CS引脚
#define W5500_SCS_PORT GPIOB
#define W5500_RST GPIO_PIN_4 // 定义W5500的RST引脚
#define W5500_RST_PORT GPIOA
#define W5500_INT GPIO_PIN_1 // 定义W5500的INT引脚
#define W5500_INT_PORT GPIOA
typedef u8 SOCKET; // 自定义端口号数据类型
#define BSP_W5500_PORT_NUM 1
#define BSP_W5500_TX_DATA_LEN 2048
#define BSP_W5500_RX_DATA_LEN 256
typedef struct bsp_W5500_Class_t bsp_W5500_Class_t;
struct bsp_W5500_Class_t
{
SOCKET SocketPort;
struct
{
/***************----- 网络参数变量定义 -----***************/
u8 Port[2]; /*端口0的端口号(5000) */
u8 DIP[4]; /*端口0目的IP地址*/
u8 DPort[2]; /*端口0目的端口号(6000)*/
u8 UDP_DIPR[4]; /*UDP(广播)模式,目的主机IP地址*/
u8 UDP_DPORT[2]; /*UDP(广播)模式,目的主机端口号*/
}ConfigData;
/***************----- 端口的运行模式 -----***************/
u8 Run_Mode;
/***************----- 端口的运行状态 -----***************/
u8 Run_State;
/***************----- 端口收发数据的状态 -----***********/
u8 TR_Data_State;
/***************----- 端口数据缓冲区 -----***************/
u8 Rx_Buffer[BSP_W5500_RX_DATA_LEN]; // 端口接收数据缓冲区
u8 Tx_Buffer[BSP_W5500_TX_DATA_LEN]; // 端口发送数据缓冲区
u8 Interrupt; // W5500中断标志(0:无中断,1:有中断)
void (*Rx_DataAnalysis)(bsp_W5500_Class_t *,u8 *,u16 );
};
typedef struct
{
u8 Gateway_IP[4]; /*网关IP地址*/
u8 Sub_Mask[4]; /*子网掩码*/
u8 Phy_Addr[6]; /*物理地址(MAC)*/
u8 IP_Addr[4]; /*本机IP地址*/
bsp_W5500_Class_t W5500_Class[BSP_W5500_PORT_NUM]; /*端口成员*/
void (*Interrupt_Process)(void); /*处理进程*/
void (*Init)(void); /*初始化*/
void (*Task)(void); /*任务*/
void (*Monitor_task)(void); /*重连检测*/
void (*Socket_Send)(bsp_W5500_Class_t *, u8 *, u16 ); /*端口发送数据*/
}bsp_W5500_t;
extern bsp_W5500_t W5500;
#endif
+25
View File
@@ -0,0 +1,25 @@
#include "bsp_Wdg.h"
#include "iwdg.h"
static void bsp_Wdg_Init(void);
static void bsp_Wdg_Feed(void);
bsp_Wdg_t Wdg =
{
.Init = bsp_Wdg_Init,
.Feed = bsp_Wdg_Feed,
};
bsp_Wdg_t *pWdg = &Wdg;
static void bsp_Wdg_Init(void)
{
__HAL_DBGMCU_FREEZE_IWDG(); //调试模式下,冻结看门狗计数器时钟
}
static void bsp_Wdg_Feed(void)
{
HAL_IWDG_Refresh(&hiwdg);
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef _BSP_WDG_H_
#define _BSP_WDG_H_
#include "main.h"
typedef struct
{
void (*Init)(void);
void (*Feed)(void);
}bsp_Wdg_t;
extern bsp_Wdg_t Wdg;
#endif
+455
View File
@@ -0,0 +1,455 @@
#include "bsp_iap.h"
#include <stdio.h>
#include <string.h>
#include "app.h"
#include "bsp_uart.h"
#include "usr_config.h"
#include "os_timer.h"
/* IAP 状态定义 */
#define BSP_IAP_STATE_NOMORAL (0) /* 正常模式,等待跳转 */
#define BSP_IAP_STATE_UPDATEING (1) /* 正在升级 */
#define BSP_IAP_STATE_SUCCEED (2) /* 升级完成,准备跳转 */
/* IAP 协议接收帧头 */
#define BSP_IAP_PROTO_RX_HEADER (0x5A)
/* IAP 协议接收命令码 */
#define BSP_IAP_PROTO_RX_CMD_GET_SV (0x01) /* 读取版本号 */
#define BSP_IAP_PROTO_RX_CMD_CODE_SIZE (0x02) /* 获取代码大小并擦除扇区 */
#define BSP_IAP_PROTO_RX_CMD_WRITE_DATA (0x03) /* 写入数据 */
#define BSP_IAP_PROTO_RX_CMD_UNKNOW_1 (0x04) /* 未知命令1 */
#define BSP_IAP_PROTO_RX_CMD_UNKNOW_2 (0x05) /* 未知命令2 */
#define BSP_IAP_PROTO_RX_CMD_UNKNOW_3 (0x06) /* 未知命令3 */
/* IAP 协议发送帧头 */
#define BSP_IAP_PROTO_TX_HEADER (0xA5)
/* IAP 协议错误码 */
#define BSP_IAP_PROTO_ERROR_CODE_SUCCEED (0) /* 解析成功 */
#define BSP_IAP_PROTO_ERROR_CODE_CHECK (1) /* 校验错误 */
#define BSP_IAP_PROTO_ERROR_CODE_CMD (2) /* 命令错误 */
#define BSP_IAP_PROTO_ERROR_CODE_LENGTH (3) /* 长度错误 */
/* 发送缓冲区大小 */
#define BSP_IAP_TX_LEN (32)
/* 静态变量 */
static u16 bsp_app_time_start; /* 等待跳转的起始时间(毫秒) */
static u8 bsp_iap_tx_buf[BSP_IAP_TX_LEN]; /* 发送缓冲区 */
/* 函数声明 */
static void app_jump(void);
static void flash_page_erase(u16 page_num);
static void flash_write_u32(u32 write_addr, u32 *p_buffer, u16 num_write);
static void flash_write_u8(u32 write_addr, u8 *p_buffer, u16 num_write);
static void bsp_iap_send(u8 *p_data, u16 len);
static void bsp_iap_rx_task(u8 *p_data, u16 len, void *other_data);
static void bsp_iap_init(void);
static void bsp_iap_task(void);
static u8 sum_check(u8 *p_data, u16 len);
/******************************************
* 结构体: bsp_iap
* 功能: IAP 控制实例
* 描述: 定义 IAP 的具体配置和回调函数
*******************************************/
bsp_iap_t iap =
{
.init = bsp_iap_init,
.task = bsp_iap_task,
};
/* 全局指针,指向 IAP 结构体 */
bsp_iap_t *p_iap = &iap;
bsp_Uart_t *p_rx_uart;
/* 应用程序起始地址 */
#define APP_START_ADDR 0x08002800
/* 扇区大小(字节) */
#define SECTOR_SIZE FLASH_PAGE_SIZE
/******************************************
* 函数: app_jump
* 功能: 跳转到应用程序
* 参数: 无
* 返回: 无
* 描述: 关闭所有外设和中断,设置堆栈指针,跳转到用户程序
*******************************************/
static void app_jump(void)
{
u32 app_addr = APP_START_ADDR;
/* 检查应用程序是否存在(堆栈指针有效) */
if (((*(u32*)app_addr) & 0x2FFE0000) == 0x20000000)
{
typedef void (*iapfun)(void);
iapfun jump_to_app;
/* 关闭所有中断 */
__disable_irq();
/* 设置所有时钟到默认状态,使用HSI时钟 */
HAL_RCC_DeInit();
// LL_USART_Disable(USART1);
// LL_USART_Disable(USART2);
//
// LL_USART_DisableIT_RXNE_RXFNE(USART1);
// LL_USART_DisableIT_RXNE_RXFNE(USART2);
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/* 关闭所有中断,清除所有中断挂起标志 */
for (u8 i = 0; i < 8; i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
/* 跳转到应用程序 */
jump_to_app = (iapfun)*(u32*)(app_addr + 4); /* 复位向量地址 */
__set_MSP(*(u32*)app_addr); /* 设置主堆栈指针 */
__enable_irq();
jump_to_app(); /* 跳转 */
while(1);
}
}
static void bsp_Flash_FLASH_ErasePage(uint32_t Address)
{
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t PageError = 0;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = Address;
EraseInitStruct.NbPages = 1;
HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
}
/******************************************
* 函数: flash_page_erase
* 功能: 擦除指定数量的 Flash 扇区
* 参数: page_num - 要擦除的扇区数量
* 返回: 无
* 描述: 从 APP_START_ADDR 开始擦除连续 page_num 个扇区
*******************************************/
static void flash_page_erase(u16 page_num)
{
u16 i;
HAL_FLASH_Unlock();//解锁
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR );
for (i = 0; i < page_num; i++)
{
bsp_Flash_FLASH_ErasePage(i * SECTOR_SIZE+APP_START_ADDR);
}
HAL_FLASH_Lock();//上锁
}
#include <string.h> // 使用 memcpy
/**
* @brief 将数据缓冲区写入 Flash(半字编程)
* @param write_addr Flash 目标地址(必须是 8 字节对齐)
* @param code_buffer 源数据缓冲区(可以为任意对齐)
* @param size 要写入的字节数
*/
static void flash_code_write(uint32_t write_addr, uint8_t *code_buffer, uint16_t size)
{
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR);
// 按半字(2字节)写入
for (uint16_t i = 0; i < size; i += 2)
{
uint16_t data;
if (i + 1 < size)
data = ((uint16_t)code_buffer[i+1] << 8) | code_buffer[i];
else
data = (uint16_t)code_buffer[i]; // 最后一个字节,高8位补0
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, write_addr + i, data);
}
HAL_FLASH_Lock();
}
/******************************************
* 函数: bsp_iap_send
* 功能: 通过 UART1 发送数据
* 参数: p_data - 数据缓冲区指针
* len - 数据长度
* 返回: 无
* 描述: 调用 UART1 的发送接口
*******************************************/
static void bsp_iap_send(u8 *p_data, u16 len)
{
if(p_rx_uart != NULL)
{
p_rx_uart->Send(p_rx_uart, p_data, len);
}
}
/******************************************
* 函数: bsp_iap_init
* 功能: IAP 初始化
* 参数: 无
* 返回: 无
* 描述: 设置初始状态,并注册接收处理函数
*******************************************/
static void bsp_iap_init(void)
{
p_iap->state = BSP_IAP_STATE_NOMORAL;
//COM_Uart1.Rx_DataAnalysis = bsp_iap_rx_task;
COM_Uart2.Rx_DataAnalysis = bsp_iap_rx_task;
}
/******************************************
* 函数: bsp_iap_task
* 功能: IAP 任务(主循环中调用)
* 参数: 无
* 返回: 无
* 描述: 根据当前状态执行相应操作
*******************************************/
static void bsp_iap_task(void)
{
switch (p_iap->state)
{
case BSP_IAP_STATE_NOMORAL: /* 正常模式,2 秒后跳转 APP */
{
if (TIME_TRUE == OsTimer_CheckTimeOut(bsp_app_time_start, osTime_MSecTick, 1000))
{
app_jump();
}
} break;
case BSP_IAP_STATE_UPDATEING: /* 升级中 */
{
/* 预留,可能处理超时等 */
} break;
case BSP_IAP_STATE_SUCCEED: /* 升级完成,立即跳转 */
{
app_jump();
} break;
default:
break;
}
}
/******************************************
* 函数: sum_check
* 功能: 计算校验和(累加和取反)
* 参数: p_data - 数据指针
* len - 数据长度
* 返回: 校验和字节
* 描述: 对数据进行累加求和,然后取反(补码)
*******************************************/
static u8 sum_check(u8 *p_data, u16 len)
{
u16 i;
u8 sum = 0;
for (i = 0; i < len; i++)
{
sum += p_data[i];
}
return (-sum);
}
/******************************************
* 函数: bsp_iap_rx_task
* 功能: IAP 协议接收处理函数
* 参数: p_data - 接收数据缓冲区
* len - 数据长度
* other_data - 附加数据(未使用)
* 返回: 无
* 描述: 解析 IAP 协议帧,执行相应命令并回复
*******************************************/
static void bsp_iap_rx_task(u8 *p_data, u16 len, void *other_data)
{
u16 i, cmd, data_len, tx_len = 0;
u8 check_data, error_code = BSP_IAP_PROTO_ERROR_CODE_SUCCEED;
u8 *p_data_offset;
if(BSP_IAP_STATE_SUCCEED == p_iap->state)/*升级成功后,不再进行检测*/
{
return;
}
/* 帧头检测和长度检查 */
if (p_data[0] != BSP_IAP_PROTO_RX_HEADER || len < 4)
{
return;
}
data_len = p_data[1] << 8 | p_data[2];
if (len - 4 != data_len) /* 长度错误 */
{
error_code = BSP_IAP_PROTO_ERROR_CODE_LENGTH;
}
else
{
check_data = sum_check(p_data, len - 1);
if (check_data != p_data[len - 1]) /* 校验错误 */
{
error_code = BSP_IAP_PROTO_ERROR_CODE_CHECK;
}
}
p_rx_uart = (bsp_Uart_t*)(other_data);
cmd = p_data[3];
p_data_offset = &p_data[4];
/* 根据命令处理 */
switch (cmd)
{
case BSP_IAP_PROTO_RX_CMD_GET_SV: /* 获取软件版本号 */
{
u8 str_len, tx_data_len;
p_iap->state = BSP_IAP_STATE_UPDATEING; /* 进入升级状态 */
str_len = strlen(SwVersion) + 1;
memcpy(&bsp_iap_tx_buf[3], SwVersion, str_len);
tx_data_len = str_len;
bsp_iap_tx_buf[0] = BSP_IAP_PROTO_TX_HEADER;
bsp_iap_tx_buf[1] = tx_data_len + 1;
bsp_iap_tx_buf[2] = cmd;
bsp_iap_tx_buf[tx_data_len + 3] = sum_check(bsp_iap_tx_buf, bsp_iap_tx_buf[1] + 2);
tx_len = bsp_iap_tx_buf[1] + 3;
} break;
case BSP_IAP_PROTO_RX_CMD_CODE_SIZE: /* 获取代码大小并擦除扇区 */
{
u8 tx_data_len;
u16 erase_size, erase_page, page_size;
erase_page = p_data_offset[0] << 8 | p_data_offset[1];
page_size = p_data_offset[2] << 8 | p_data_offset[3];
p_iap->page_size = page_size;
/* 计算需要擦除的扇区数 */
erase_page /= ((float)SECTOR_SIZE / (float)page_size);
flash_page_erase(erase_page);
tx_data_len = 0;
bsp_iap_tx_buf[0] = BSP_IAP_PROTO_TX_HEADER;
bsp_iap_tx_buf[1] = tx_data_len + 1;
bsp_iap_tx_buf[2] = cmd;
bsp_iap_tx_buf[tx_data_len + 3] = sum_check(bsp_iap_tx_buf, bsp_iap_tx_buf[1] + 2);
tx_len = bsp_iap_tx_buf[1] + 3;
} break;
case BSP_IAP_PROTO_RX_CMD_WRITE_DATA: /* 写入数据 */
{
u8 tx_data_len;
u16 index, code_size, addr_offset, i;
u32 addr;
u8 *p_code_data;
index = p_data_offset[0] << 8 | p_data_offset[1];
code_size = data_len - 3;
addr = index * p_iap->page_size;
p_code_data = &p_data_offset[2];
flash_code_write(APP_START_ADDR+addr, p_code_data, code_size);
/* 构造应答帧,返回当前索引 */
bsp_iap_tx_buf[3] = index >> 8;
bsp_iap_tx_buf[4] = index & 0x00ff;
tx_data_len = 2;
bsp_iap_tx_buf[0] = BSP_IAP_PROTO_TX_HEADER;
bsp_iap_tx_buf[1] = tx_data_len + 1;
bsp_iap_tx_buf[2] = cmd;
bsp_iap_tx_buf[tx_data_len + 3] = sum_check(bsp_iap_tx_buf, bsp_iap_tx_buf[1] + 2);
tx_len = bsp_iap_tx_buf[1] + 3;
} break;
case BSP_IAP_PROTO_RX_CMD_UNKNOW_1: /* 未知命令1(升级完成) */
{
u8 tx_data_len;
tx_data_len = 0;
p_iap->state = BSP_IAP_STATE_SUCCEED; /* 升级完成 */
bsp_iap_tx_buf[0] = BSP_IAP_PROTO_TX_HEADER;
bsp_iap_tx_buf[1] = tx_data_len + 1;
bsp_iap_tx_buf[2] = cmd;
bsp_iap_tx_buf[tx_data_len + 3] = sum_check(bsp_iap_tx_buf, bsp_iap_tx_buf[1] + 2);
tx_len = bsp_iap_tx_buf[1] + 3;
} break;
case BSP_IAP_PROTO_RX_CMD_UNKNOW_3: /* 未知命令3(回传两个字节) */
{
u8 tx_data_len;
tx_data_len = 2;
bsp_iap_tx_buf[3] = p_data_offset[0];
bsp_iap_tx_buf[4] = p_data_offset[1];
bsp_iap_tx_buf[0] = BSP_IAP_PROTO_TX_HEADER;
bsp_iap_tx_buf[1] = tx_data_len + 1;
bsp_iap_tx_buf[2] = cmd;
bsp_iap_tx_buf[tx_data_len + 3] = sum_check(bsp_iap_tx_buf, bsp_iap_tx_buf[1] + 2);
tx_len = bsp_iap_tx_buf[1] + 3;
} break;
case BSP_IAP_PROTO_RX_CMD_UNKNOW_2: /* 未知命令2(简单应答) */
{
u8 tx_data_len;
tx_data_len = 0;
bsp_iap_tx_buf[0] = BSP_IAP_PROTO_TX_HEADER;
bsp_iap_tx_buf[1] = tx_data_len + 1;
bsp_iap_tx_buf[2] = cmd;
bsp_iap_tx_buf[tx_data_len + 3] = sum_check(bsp_iap_tx_buf, bsp_iap_tx_buf[1] + 2);
tx_len = bsp_iap_tx_buf[1] + 3;
} break;
default:
{
error_code = BSP_IAP_PROTO_ERROR_CODE_CMD;
} break;
}
/* 错误处理 */
switch (error_code)
{
case BSP_IAP_PROTO_ERROR_CODE_SUCCEED:
{
bsp_iap_send(bsp_iap_tx_buf, tx_len);
} break;
case BSP_IAP_PROTO_ERROR_CODE_CHECK:
case BSP_IAP_PROTO_ERROR_CODE_CMD:
case BSP_IAP_PROTO_ERROR_CODE_LENGTH:
{
bsp_iap_tx_buf[0] = BSP_IAP_PROTO_TX_HEADER;
bsp_iap_tx_buf[1] = 0x01;
bsp_iap_tx_buf[2] = cmd;
bsp_iap_tx_buf[3] = error_code;
bsp_iap_tx_buf[4] = sum_check(bsp_iap_tx_buf, 4);
bsp_iap_send(bsp_iap_tx_buf, 5);
} break;
default:
break;
}
}
+32
View File
@@ -0,0 +1,32 @@
#ifndef _BSP_IAP_H_
#define _BSP_IAP_H_
#include "main.h"
typedef union
{
struct
{
u8 u8_Data[4];
};
uint32_t u64_Data;
}u64_Temp_n;
/******************************************
* 结构体: bsp_iap_t
* 功能: IAP 控制结构体
* 描述: 存储 IAP 状态和函数指针
*******************************************/
typedef struct
{
u8 state; /* IAP 状态 */
u16 page_size; /* 页面大小(字节) */
void (*init)(void); /* 初始化函数指针 */
void (*task)(void); /* 任务函数指针 */
} bsp_iap_t;
/* 声明外部变量 */
extern bsp_iap_t iap;
#endif /* _BSP_IAP_H_ */
+27
View File
@@ -0,0 +1,27 @@
#include "bsp_print.h"
#include "bsp_Uart.h"
#include "stdio.h"
//#include "wk_usart.h"
/*ÖØ¶¨Òåfputcº¯Êý*/
int fputc(int ch, FILE *f)
{
u8 Data = ch;
COM_Uart1.Send(&COM_Uart1,&Data,1);
}
void Debug_UartSend(u8 *pData,u16 Len)
{
//COM_Uart1.Send(&COM_Uart1,pData,Len);
}
void UartSend(u8 ch)
{
COM_Uart1.Send(&COM_Uart1,&ch,1);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef _BSP_PRINT_H_
#define _BSP_PRINT_H_
#include "main.h"
void Debug_UartSend(u8 *pData,u16 Len);
#endif
+106
View File
@@ -0,0 +1,106 @@
#ifndef _SYS_H_
#define _SYS_H_
#include "stm32f1xx.h"
//定义一些常用的数据类型短关键字
typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
typedef const int32_t sc32;
typedef const int16_t sc16;
typedef const int8_t sc8;
typedef __IO int32_t vs32;
typedef __IO int16_t vs16;
typedef __IO int8_t vs8;
typedef __I int32_t vsc32;
typedef __I int16_t vsc16;
typedef __I int8_t vsc8;
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef const uint32_t uc32;
typedef const uint16_t uc16;
typedef const uint8_t uc8;
typedef __IO uint32_t vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t vu8;
typedef __I uint32_t vuc32;
typedef __I uint16_t vuc16;
typedef __I uint8_t vuc8;
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
/////////////////////////////////////////////////////////////////
//Ex_NVIC_Config专用定义
#define GPIO_A 0
#define GPIO_B 1
#define GPIO_C 2
#define GPIO_D 3
#define GPIO_E 4
#define GPIO_F 5
#define GPIO_G 6
#define FTIR 1 //下降沿触发
#define RTIR 2 //上升沿触发
#endif
+274
View File
@@ -0,0 +1,274 @@
#include "proto_CS200.h"
#include "proto_Modbus.h"
#include "stdio.h"
#include "string.h"
#include "bsp_Uart.h"
/*CS200量程*/
#define CS200_RANGE (2.0)
#define CS200_RANGE_START (0x4000)
#define CS200_RANGE_END (0xC000)
#define CS200_MODBUS_ADDR_GetCurrentData (0x00)
#define CS200_MODBUS_ADDR_SetFlow (0x02)
static void proto_CS200_Init(void);
static void proto_CS200_Tx_Task(void);
static void proto_CS200_Rx_Task(u8 *pData,u16 Len);
static void proto_SetFlow_1(float Value);
static void proto_SetFlow_2(float Value);
proto_CS200_t CS200 =
{
.ID_1 = 32,
.ID_2 = 33,
.Init = proto_CS200_Init,
.Tx_Task = proto_CS200_Tx_Task,
.Rx_Task = proto_CS200_Rx_Task,
.SetFlow_1 = proto_SetFlow_1,
.SetFlow_2 = proto_SetFlow_2,
};
static proto_CS200_t *pCS200 = &CS200;
static void proto_CS200_Init(void)
{
COM_Uart1.Rx_DataAnalysis = pCS200 ->Rx_Task;
}
static void proto_CS200_Send(u8 *pData,u16 Len)
{
COM_Uart1.Send(&COM_Uart1,pData,Len);
}
/*设置*/
static void proto_SetFlow_1(float Value)
{
float FlowRange;
if(0 == pCS200->CurrentData[0].Range_u16)
{
FlowRange = CS200_RANGE;
}
else
{
FlowRange = pCS200->CurrentData[0].Range_u16 / 1000.0;
}
pCS200->SetFlowValue_1 = CS200_RANGE_START + (float)(CS200_RANGE_END - CS200_RANGE_START) * Value / FlowRange;
}
static void proto_SetFlow_2(float Value)
{
float FlowRange;
if(0 == pCS200->CurrentData[1].Range_u16)
{
FlowRange = CS200_RANGE;
}
else
{
FlowRange = pCS200->CurrentData[1].Range_u16 / 1000.0;
}
pCS200->SetFlowValue_2 = CS200_RANGE_START + (float)(CS200_RANGE_END - CS200_RANGE_START) * Value / FlowRange;
}
/*发送指令*/
static void proto_CS200_Tx_GetCurrentData(u8 ID)
{
u16 Addr = CS200_MODBUS_ADDR_GetCurrentData;
u8 Len = 14;
ModbusReadData(ID,Addr,Len,proto_CS200_Send);
}
static void proto_CS200_Tx_SetFlow_1(void)
{
u16 Addr = CS200_MODBUS_ADDR_SetFlow;
u8 Len = 1;
u16 Data[1]= {pCS200->SetFlowValue_1};
ModbusyWriteOnlData(pCS200->ID_1,Addr,*Data,proto_CS200_Send);
}
static void proto_CS200_Tx_SetFlow_2(void)
{
u16 Addr = CS200_MODBUS_ADDR_SetFlow;
u8 Len = 1;
u16 Data[1]= {pCS200->SetFlowValue_2};
ModbusyWriteOnlData(pCS200->ID_2,Addr,*Data,proto_CS200_Send);
}
static void proto_CS200_Rx_Task(u8 *pData,u16 Len)
{
u8 SendTimeFlag = 0;
u8 ModbusID,CMD;
u16 CheckCRC16,ModbusCrc;
u16 Addr,Data;
u32 u32Temp;
float FlowTemp;
proto_CS2000_CurrentData_t *pCurrentData;
ModbusID = *pData;
CMD = *(pData+1);
CheckCRC16 = pData[Len-2] << 8 | pData[Len-1];
if(ModbusID == pCS200->ID_1)
{
pCurrentData = &pCS200->CurrentData[0];
}
else if(ModbusID == pCS200->ID_2)
{
pCurrentData = &pCS200->CurrentData[1];
}
else
{
return;
}
pCS200->TimeCount = 0;
if(CMD != 0x03 &&CMD != 0x04 && CMD != 0x06 && CMD != 0x10) return ;
ModbusCrc = ModbusCrc16(pData,Len-2);
ModbusCrc = (ModbusCrc >> 8) | (ModbusCrc << 8);
if(CheckCRC16 != ModbusCrc) return ;
switch(pCS200->State)
{
case CS200_STATE_Init:
{
pCS200->State = CS200_STATE_GetCurrentData;
}break;
case CS200_STATE_GetCurrentData:
{
pCurrentData->ID = pData[3 ] << 8 | pData[4 ];
pCurrentData->BaudRate = pData[5 ] << 8 | pData[6 ];
pCurrentData->SetFlow = pData[7 ] << 8 | pData[8 ];
pCurrentData->Flow = pData[9] << 8 | pData[10];
pCurrentData->Range_u16 = pData[11] << 8 | pData[12]; //单位ml
pCurrentData->ValveCmd = pData[13] << 8 | pData[14];
u32Temp = pData[15] << 24 | pData[16] << 16 | pData[17] << 8 | pData[18] << 8;
pCurrentData->SumFlow = *((float *)&u32Temp);
pCurrentData->SumFlow_Mode = pData[19] << 8 | pData[20];
pCurrentData->Parity = pData[21] << 8 | pData[22];
pCurrentData->Valve_U = pData[23] << 8 | pData[24];
u32Temp = pData[25] << 24 | pData[26] << 16 | pData[27] << 8 | pData[28] << 8;
pCurrentData->Range_Float = *((float *)&u32Temp);
pCurrentData->SoftStartValue = pData[29] << 8 | pData[30];
FlowTemp = pCurrentData->Flow;
pCurrentData->RealFlow = pCurrentData->Range_u16 / 1000.0 * (FlowTemp - CS200_RANGE_START) / ((float)(CS200_RANGE_END - CS200_RANGE_START));
if(pCS200->SetFlowValue_1 != pCS200->CurrentData[0].SetFlow)
{
pCS200->State = CS200_STATE_SetFlow_1;
pCS200->ReadState = CS200_READ_STATE_ID_1;
}
else if(pCS200->SetFlowValue_2 != pCS200->CurrentData[1].SetFlow)
{
pCS200->State = CS200_STATE_SetFlow_2;
pCS200->ReadState = CS200_READ_STATE_ID_2;
}
SendTimeFlag = 1;
}break;
case CS200_STATE_SetFlow_1:
{
pCS200->State = CS200_STATE_GetCurrentData;
}break;
case CS200_STATE_SetFlow_2:
{
pCS200->State = CS200_STATE_GetCurrentData;
}break;
}
if(SendTimeFlag)
{
return;
}
else
{
pCS200->ErrorFlag &= (~(0x00000001 << pCS200->State));/*消除异常状态*/
pCS200->SendTime = 0;
return;
}
}
static void proto_CS200_Tx_Task(void)
{
u8 SendTimeFlag = 0;
if(++pCS200->TimeCount > 50)/*通讯超时*/
{
memset(&pCS200->CurrentData,0,sizeof(pCS200->CurrentData));
}
switch(pCS200->State)
{
case CS200_STATE_Init:
{
}break;
case CS200_STATE_GetCurrentData:
{
switch(pCS200->ReadState)
{
case CS200_READ_STATE_ID_1:
{
proto_CS200_Tx_GetCurrentData(pCS200->ID_1);
pCS200->ReadState = CS200_READ_STATE_ID_2;
}break;
case CS200_READ_STATE_ID_2:
{
proto_CS200_Tx_GetCurrentData(pCS200->ID_2);
pCS200->ReadState = CS200_READ_STATE_ID_1;
}break;
default:
{
proto_CS200_Tx_GetCurrentData(pCS200->ID_1);
pCS200->ReadState = CS200_READ_STATE_ID_2;
}break;
}
SendTimeFlag = 1;
}break;
case CS200_STATE_SetFlow_1:
{
proto_CS200_Tx_SetFlow_1();
}break;
case CS200_STATE_SetFlow_2:
{
proto_CS200_Tx_SetFlow_2();
}break;
default:
{
}break;
}
if(SendTimeFlag)
{
return ;
}
else
{
pCS200->SendTime++;
if(pCS200->SendTime >= 3)
{
pCS200->ErrorFlag |= (0x00000001 << pCS200->State);/*记录异常状态*/
pCS200->SendTime = 0;
pCS200->State = CS200_STATE_GetCurrentData;
}
}
}
+58
View File
@@ -0,0 +1,58 @@
#ifndef _PROTO_CS200_H_
#define _PROTO_CS200_H_
#include "main.h"
#include "proto_Modbus.h"
#define CS200_STATE_Init 0
#define CS200_STATE_GetCurrentData 1
#define CS200_STATE_SetFlow_1 2
#define CS200_STATE_SetFlow_2 3
#define CS200_READ_STATE_ID_1 0
#define CS200_READ_STATE_ID_2 1
typedef struct
{
u8 ID;
u16 BaudRate;
u16 SetFlow;
u16 Flow;
u16 Range_u16;
u8 ValveCmd;
float SumFlow; //累计流量
u8 SumFlow_Mode; //累计流量模式
u8 Parity; //校验位
u16 Valve_U; //阀电压
float Range_Float;
float SoftStartValue; //软启动值
float RealFlow; //实机流量值
}proto_CS2000_CurrentData_t;
typedef struct
{
proto_CS2000_CurrentData_t CurrentData[2];
u16 ErrorFlag;
u8 SendTime;
u8 TimeCount;
u8 ID_1,ID_2;
u8 State;
u8 ReadState;
u16 SetFlowValue_1;
u16 SetFlowValue_2;
void (*Init)(void);
void (*Tx_Task)(void);
void (*Rx_Task)(u8 *,u16);
void (*SetFlow_1)(float);
void (*SetFlow_2)(float);
}proto_CS200_t;
extern proto_CS200_t CS200;
#endif
+169
View File
@@ -0,0 +1,169 @@
#include "proto_HSMS.h"
#include "string.h"
#include "stdio.h"
#include "bsp_print.h"
#include "bsp_W5500.h"
#include "proto_SECS2.h"
static void proto_HSMS_Init(void);
static void proto_W5500_DataAnalysis(bsp_W5500_Class_t *pW5500_Class,u8 *pData,u16 Len);
static void proto_HSMS_Rx_DataAnalysis(u8 *pData,u16 Len);
static void proto_HSMS_Tx_Rsq(proto_HSMS_Header_Data_t *pHeader_Data,u8 *Tx_Data,u16 Tx_Data_Len,void *OtherData);
u8 proto_HSMS_Tx_Buffer[1024];
proto_HSMS_t HSMS =
{
.Init = proto_HSMS_Init,
.Tx_RsqData = proto_HSMS_Tx_Rsq,
};
proto_HSMS_t *pHSMS = &HSMS;
static void proto_HSMS_Init(void)
{
W5500.W5500_Class[0].Rx_DataAnalysis = proto_W5500_DataAnalysis;
}
static void proto_HSMS_Send(u8 *pData,u16 Len)
{
Debug_UartSend(pData, Len);
W5500.Socket_Send(&W5500.W5500_Class[0],pData,Len);
}
static void proto_W5500_DataAnalysis(bsp_W5500_Class_t *pW5500_Class,u8 *pData,u16 Len)
{
proto_HSMS_Rx_DataAnalysis(pData,Len);
}
/*响应请求*/
static void proto_HSMS_Tx_Rsq(proto_HSMS_Header_Data_t *pHeader_Data,u8 *Tx_Data,u16 Tx_Data_Len,void *OtherData)
{
u8 *Tx = proto_HSMS_Tx_Buffer;
u16 Len;
pHeader_Data->Data_Len = 10 + Tx_Data_Len;
u32TOu8(pHeader_Data->Data_Len,Tx,PROTO_HSMS_ENDIAN);
u16TOu8(pHeader_Data->Device_Id,&Tx[4],PROTO_HSMS_ENDIAN);
Tx[6] = pHeader_Data->Header_Byte2.ALL_Data;
Tx[7] = pHeader_Data->Header_Byte3;
Tx[8] = pHeader_Data->PType;
Tx[9] = pHeader_Data->SType;
u32TOu8(pHeader_Data->Sys_Byte,&Tx[10],PROTO_HSMS_ENDIAN);
Len = 14;
if(NULL != Tx_Data && 0 != Tx_Data_Len)
{
memcpy(&Tx[Len],Tx_Data,Tx_Data_Len);
Len += Tx_Data_Len;
}
proto_HSMS_Send(Tx,Len);
Debug_UartSend(Tx,Len);
}
void proto_HSMS_Header_DataAnalysis(proto_HSMS_Header_Data_t *pHeader_Data,u8 *pData)
{
/*拷贝数据进行解析*/
pHeader_Data->Data_Len = u8TOu32(&pData[0],PROTO_HSMS_ENDIAN);
pHeader_Data->Device_Id = u8TOu16(&pData[4],PROTO_HSMS_ENDIAN);
pHeader_Data->Header_Byte2.ALL_Data = pData[6];
pHeader_Data->Header_Byte3 = pData[7];
pHeader_Data->PType = pData[8];
pHeader_Data->SType = pData[9];
pHeader_Data->Sys_Byte = u8TOu32(&pData[10],PROTO_HSMS_ENDIAN);
}
void proto_HSMS_Rx_DataAnalysis(u8 *pData,u16 Len)
{
if(Len < 14)/*不满足最低长度*/
return ;
proto_HSMS_Header_DataAnalysis(&pHSMS->Rx_Header_Data,pData);
/*长度判断*/
if((pHSMS->Rx_Header_Data.Data_Len + 4) != Len)
{
return ;
}
/*不是SECS2编码格式*/
if(proto_HSMS_PTYPE_SECS2 != pHSMS->Rx_Header_Data.PType)
{
return ;
}
switch(pHSMS->Rx_Header_Data.SType)
{
/*数据消息*/
case PROTO_HSMS_STYPE_Data_Message :
{
/*匹配设备ID*/
if(pHSMS->Flash_ConfigData.Device_Id != pHSMS->Rx_Header_Data.Device_Id)
{
return;
}
memcpy(&pHSMS->Tx_Header_Data,&pHSMS->Rx_Header_Data,sizeof(proto_HSMS_Header_Data_t));
/*去除HSMS头部数据*/
SECS2.Rx_DataAnalysis(&pHSMS->Tx_Header_Data,&pData[14],Len-14);
}break;
/*选择请求*/
case PROTO_HSMS_STYPE_Select_Req :
{
memcpy(&pHSMS->Tx_Header_Data,&pHSMS->Rx_Header_Data,sizeof(proto_HSMS_Header_Data_t));
pHSMS->Tx_Header_Data.SType = PROTO_HSMS_STYPE_Select_Rsq;
proto_HSMS_Tx_Rsq(&pHSMS->Tx_Header_Data,NULL,0,NULL);
}break;
/*选择响应*/
case PROTO_HSMS_STYPE_Select_Rsq :
{
}break;
/*取消选择请求*/
case PROTO_HSMS_STYPE_Deselect_Req :
{
memcpy(&pHSMS->Tx_Header_Data,&pHSMS->Rx_Header_Data,sizeof(proto_HSMS_Header_Data_t));
pHSMS->Tx_Header_Data.SType = PROTO_HSMS_STYPE_Deselect_Rsq;
proto_HSMS_Tx_Rsq(&pHSMS->Tx_Header_Data,NULL,0,NULL);
}break;
/*取消选择响应*/
case PROTO_HSMS_STYPE_Deselect_Rsq :
{
}break;
/*连接测试请求*/
case PROTO_HSMS_STYPE_Linktest_Req :
{
memcpy(&pHSMS->Tx_Header_Data,&pHSMS->Rx_Header_Data,sizeof(proto_HSMS_Header_Data_t));
pHSMS->Tx_Header_Data.SType = PROTO_HSMS_STYPE_Linktest_Rsp;
proto_HSMS_Tx_Rsq(&pHSMS->Tx_Header_Data,NULL,0,NULL);
}break;
/*连接测试响应*/
case PROTO_HSMS_STYPE_Linktest_Rsp :
{
}break;
/*拒绝请求*/
case PROTO_HSMS_STYPE_Reject_Req :
{
}break;
/*断开请求*/
case PROTO_HSMS_STYPE_Separate_Req :
{
}break;
default: break;
}
}
+63
View File
@@ -0,0 +1,63 @@
#ifndef _PROTO_HSMS_H_
#define _PROTO_HSMS_H_
#include "main.h"
#include "proto_Modbus.h"
#define PROTO_HSMS_ENDIAN BIG_ENDIAN
/*表示类型 PType*/
#define proto_HSMS_PTYPE_SECS2 0 /*SECS-II 编码格式*/
/*会话类型 SType*/
#define PROTO_HSMS_STYPE_Data_Message 0 /*数据消息*/
#define PROTO_HSMS_STYPE_Select_Req 1 /*选择请求*/
#define PROTO_HSMS_STYPE_Select_Rsq 2 /*选择响应*/
#define PROTO_HSMS_STYPE_Deselect_Req 3 /*取消选择请求*/
#define PROTO_HSMS_STYPE_Deselect_Rsq 4 /*取消选择响应*/
#define PROTO_HSMS_STYPE_Linktest_Req 5 /*连接测试请求*/
#define PROTO_HSMS_STYPE_Linktest_Rsp 6 /*连接测试响应*/
#define PROTO_HSMS_STYPE_Reject_Req 7 /*拒绝请求*/
#define PROTO_HSMS_STYPE_Separate_Req 9 /*断开请求*/
typedef struct
{
u32 Data_Len; /*字节长度*/
u16 Device_Id; /*会话/设备标识*/
union
{
struct
{
u8 Stream: 7;
u8 Wait: 1; /*指令是否需要回复*/
}Analysis_Data;
u8 ALL_Data;
}Header_Byte2;
u8 Header_Byte3; /*头部字节3*/
u8 PType; /*表示类型*/
u8 SType; /*会话类型*/
u32 Sys_Byte; /*系统字节:标记这次指令的ID,通常用于超时判断(响应时依据发送者指令的最后4字节作为回复,发送时生成不重复的4个字节)*/
}proto_HSMS_Header_Data_t;
typedef struct
{
u16 Device_Id; /*会话/设备标识*/
}proto_HSMS_Flash_Data_t;
typedef struct
{
proto_HSMS_Header_Data_t Rx_Header_Data; /*接收解析的头部数据*/
proto_HSMS_Header_Data_t Tx_Header_Data; /*发送时的头部数据*/
proto_HSMS_Flash_Data_t Flash_ConfigData; /*存入Flash的配置参数*/
void (*Init)(void);
void (*Tx_RsqData)(proto_HSMS_Header_Data_t *,u8 *,u16 ,void *);
}proto_HSMS_t;
extern proto_HSMS_t HSMS;
#endif
+294
View File
@@ -0,0 +1,294 @@
#include "proto_Modbus.h"
#include "stdio.h"
#include "string.h"
#include "bsp_Uart.h"
u16 ModbusCrc16(u8 *pData, u16 Len)
{
u16 CRC_16 = 0xffff;
u16 i;
while(Len--)
{
CRC_16 = CRC_16^(*pData++);
for(i=0; i++<8; )
{
if(CRC_16&0x0001)
{
CRC_16 = (CRC_16>>1)^0xa001;
}
else
{
CRC_16>>=1;
}
}
}
return CRC_16;
}
/******************************************
* 函数: Float2u16
* 功能: 提取浮点数的高16或低16位
* 参数: FloatData : 要转换的浮点数
HorL : 返回高16位还是低16位
* 返回: 返回对应的高16位还是低16位
* 描述: 无
******************************************/
u16 FloatTOu16(float FloatData,u8 HorL)
{
u16 Temp = 0XFFFF;
if(HorL == U16_DATA_L)
{
Temp = *((u32 *)&FloatData) & 0x0000ffff;
}
else if(HorL == U16_DATA_H)
{
Temp = ((*((u32 *)&FloatData)) >> 16) & 0x0000ffff;
}
return Temp;
}
/******************************************
* 函数: u32TOu16
* 功能: 提取u32的高16或低16位
* 参数: u32Data : 要转换的u32
HorL : 返回高16位还是低16位
* 返回: 返回对应的高16位还是低16位
* 描述: 无
******************************************/
u16 u32TOu16(u32 u32Data,u8 HorL)
{
u16 Temp = 0XFFFF;
if(HorL == U16_DATA_L)
{
Temp = u32Data & 0x0000ffff;
}
else if(HorL == U16_DATA_H)
{
Temp = (u32Data >> 16) & 0x0000ffff;
}
return Temp;
}
void u32TOu8(u32 u32Data,u8 *pData,u8 Endian)
{
if(BIG_ENDIAN == Endian)
{
for(u8 i = 0;i < 4;i++)
{
pData[i] = (u32Data >> (8 * (3 - i))) & 0xff;
}
}
else if(LITTLE_ENDIAN == Endian)
{
for(u8 i = 0;i < 4;i++)
{
pData[i] = (u32Data >> (8 * i)) & 0xff;
}
}
}
void u16TOu8(u16 u16Data,u8 *pData,u8 Endian)
{
if(BIG_ENDIAN == Endian)
{
for(u8 i = 0;i < 2;i++)
{
pData[i] = (u16Data >> (8 * (1 - i))) & 0xff;
}
}
else if(LITTLE_ENDIAN == Endian)
{
for(u8 i = 0;i < 2;i++)
{
pData[i] = (u16Data >> (8 * i)) & 0xff;
}
}
}
float u32TOFloat(u32 u32Data,u8 HorL)
{
float Temp = 0;
Temp = *((float *)&u32Data);
return Temp;
}
/*将u8Endian端序的p_u8Data转换为单片机对应的小端序*/
u32 u8TOu32(u8 *p_u8Data,u8 u8Endian)
{
u32 Temp = 0;
if(BIG_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 4;i++)
{
Temp |= p_u8Data[i] << ((3 - i) * 8);
}
}
else if(LITTLE_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 4;i++)
{
Temp |= p_u8Data[i] << (i * 8);
}
}
return Temp;
}
/*将u8Endian端序的p_u8Data转换为单片机对应的小端序*/
u16 u8TOu16(u8 *p_u8Data,u8 u8Endian)
{
u32 Temp = 0;
if(BIG_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 2;i++)
{
Temp |= p_u8Data[i] << ((1 - i) * 8);
}
}
else if(LITTLE_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 2;i++)
{
Temp |= p_u8Data[i] << (i * 8);
}
}
return Temp;
}
/*字节端序转换*/
u32 u32_EndianConv(u32 Data)
{
u32 TempData = 0;
TempData = (((Data >> 0 ) & 0xff) << 24)
| (((Data >> 8 ) & 0xff) << 16)
| (((Data >> 16) & 0xff) << 8 )
| (((Data >> 24) & 0xff) << 0 );
return TempData;
}
/*字节端序转换*/
u16 u16_EndianConv(u16 Data)
{
u16 TempData = 0;
TempData = (((Data >> 0) & 0xff) << 8)
| (((Data >> 8) & 0xff) << 0);
return TempData;
}
/******************************************
* 函数: ModbusReadData
* 功能: MODBUS读数据
* 参数: Id :MODBUS从机地址
* Addr :写数据的起始地址
* Num :写的寄存器数量
* UsartSendBuffer :串口发送函数
* 返回: 无
* 描述: 无
******************************************/
void ModbusReadData(u8 Id,u16 Addr,u16 Num,void (*UsartSendBuffer)(u8 *,u16 ))
{
u8 Tx[8];
u16 CRC16;
Tx[0] = Id;
Tx[1] = 0x03;
Tx[2] = (Addr >> 8) & 0xff;
Tx[3] = Addr & 0xff;
Tx[4] = (Num >> 8) & 0xff;
Tx[5] = Num & 0xff;
CRC16 = ModbusCrc16(Tx,6);
Tx[6] = CRC16 & 0xff;
Tx[7] = (CRC16 >> 8) & 0xff;
UsartSendBuffer(Tx,8);
}
/******************************************
* 函数: ModbusWriteMultipleData
* 功能: MODBUS写数据
* 参数: Id :MODBUS从机地址
* Addr :写数据的起始地址
* Num :写的寄存器数量
* Data :写的数据
* UsartSendBuffer :串口发送函数
* 返回: 无
* 描述: 无
******************************************/
void ModbusWriteMultipleData(u8 ID,u16 Addr,u16 Num,u16 *Data,void (*UsartSendBuffer)(u8 *,u16 ))
{
u8 Tx[50],i;
u16 CRC16;
Tx[0] = ID;
Tx[1] = 0x10;
Tx[2] = (Addr >> 8) & 0xff;
Tx[3] = Addr & 0xff;
Tx[4] = (Num >> 8) & 0xff;
Tx[5] = Num & 0xff;
Tx[6] = Num * 2;
for(i = 0;i < Tx[6]/2;i++)
{
Tx[7 + 2 * i] = (Data[i] >> 8) & 0xff;
Tx[8 + 2 * i] = Data[i] & 0xff;
}
CRC16 = ModbusCrc16(Tx,7 + 2 * i);
Tx[7 + 2 * i] = CRC16 & 0xff;
Tx[8 + 2 * i] = (CRC16 >> 8) & 0xff;
UsartSendBuffer(Tx,9 + 2 * i);
}
void ModbusyWriteOnlData(u8 ID,u16 Addr,u16 Value,void (*UsartSendBuffer)(u8 *,u16 ))
{
u8 Tx[8];
u16 CRC16;
Tx[0] = ID;
Tx[1] = 0x06;
Tx[2] = (Addr >> 8) & 0xff;
Tx[3] = Addr & 0xff;
Tx[4] = (Value >> 8) & 0xff;
Tx[5] = Value & 0xff;
CRC16 = ModbusCrc16(Tx,6);
Tx[6] = CRC16 & 0xff;
Tx[7] = (CRC16 >> 8) & 0xff;
UsartSendBuffer(Tx,8);
}
//01 10 00 02 00 01 02 12 34 CRC
//ID Func StartAddress RegNumber wDataAddress
u8 ModbusAnalysis(ModbusAnalysisData_t *pModbus, u8 *pData, u16 len)
{
u16 CRC_16;
u16 TempU16;
if(NULL == pModbus) return 0;
if(len < 8) return 0;
CRC_16 = ModbusCrc16(pData, len-2);
TempU16 = *(pData+len-1);
TempU16 <<= 8;
TempU16 |= *(pData+len-2);
if(TempU16 != CRC_16) return 0;
pModbus->ID = *pData;
pModbus->Func = *(pData+1);
pModbus->StartAddress = (*(pData+2))<<8;
pModbus->StartAddress |= *(pData+3);
/*单独写一个寄存器*/
if(0x06 == pModbus->Func)
{
pModbus->wDataAddress = pData+4;
}
else if(0x10 == pModbus->Func) /*写多个寄存器*/
{
pModbus->RegNumber = (*(pData+4))<<8;
pModbus->RegNumber |= *(pData+5);
pModbus->wDataAddress = pData+7;
}
else
{
pModbus->RegNumber = (*(pData+4))<<8;
pModbus->RegNumber |= *(pData+5);
}
return 1;
}
+66
View File
@@ -0,0 +1,66 @@
#ifndef _PROTO_MODBUS_H_
#define _PROTO_MODBUS_H_
#include "main.h"
#define MODBUS_DEFAULT_ID (0x01)
#define MODBUS_SENDBUF_LEN (512U)
#define U16_DATA_L (0)//低16位
#define U16_DATA_H (1)//高16位
#define BIG_ENDIAN (0)//大端序
#define LITTLE_ENDIAN (1)//小端序
typedef struct _ModbusCommunicationSendBuf{
u8 SendBuffer[MODBUS_SENDBUF_LEN];
u16 Len;
}ModbusCommunicationSendBuf_t;
typedef struct _ModbusAnalysisData
{
u8 ID; /*ModbusID*/
u8 Func; /*功能号*/
u16 StartAddress; /*起始地址*/
u16 RegNumber; /*寄存器数量*/
u8 *wDataAddress; /*写入寄存器数据地址*/
}ModbusAnalysisData_t;
typedef enum _ModbusErrorCode
{
ModbusErrorCode_Success = 0x00,
ModbusErrorCode_IllegalFunction = 0x01,
ModbusErrorCode_IllegalAddr = 0x02,
ModbusErrorCode_IllegalData = 0x03,
ModbusErrorCode_DeviceBusy = 0x06
}ModbusErrorCode_e;
typedef struct proto_Modbus_t proto_Modbus_t;
struct proto_Modbus_t
{
u8 ID;
u16 (*DataRead)(u16); /*Modbus读数据*/
ModbusErrorCode_e (*DataWrite)(u16,u16); /*Modbus写数据*/
void (*Init)(void); /*初始化函数*/
void (*Task)(void); /*任务函数*/
void (*DataAnalysis)(u8 *,u16,void *); /*数据解析*/
};
u16 ModbusCrc16(u8 *pData, u16 Len);
u16 FloatTOu16(float FloatData,unsigned char HorL);
u16 u32TOu16(u32 u32Data,unsigned char HorL);
u32 u8TOu32(u8 *p_u8Data,unsigned char u8Endian);
u16 u8TOu16(u8 *p_u8Data,unsigned char u8Endian);
void u32TOu8(u32 u32Data,u8 *pData,u8 Endian);
void u16TOu8(u16 u16Data,u8 *pData,u8 Endian);
u32 u32_EndianConv(u32 Data);
u16 u16_EndianConv(u16 Data);
void ModbusReadData(u8 Id,u16 Addr,u16 Num,void (*UsartSendBuffer)(u8 *,u16 ));
void ModbusWriteMultipleData(u8 ID,u16 Addr,u16 Num,u16 *Data,void (*UsartSendBuffer)(u8 *,u16 ));
void ModbusyWriteOnlData(u8 ID,u16 Addr,u16 Value,void (*UsartSendBuffer)(u8 *,u16 ));
u8 ModbusAnalysis(ModbusAnalysisData_t *pModbus, u8 *pData, u16 len);
#endif
+741
View File
@@ -0,0 +1,741 @@
#include "proto_PM100.h"
#include "proto_Modbus.h"
#include "stdio.h"
#include "string.h"
#include "bsp_Uart.h"
#include "os_timer.h"
char *proto_PM100_Str_WarmingCode[32] =
{
"Water flow low" ,
"" ,
"Dil.N2 flow low" ,
"BP Drooping" ,
"MP Drooping" ,
"Casing temp. high" ,
"BP-G oil level low" ,
"BP-M oil level low" ,
"MP-G oil level low" ,
"MP-M oil level low" ,
"Drv brg temp. high" ,
"Drvn brg temp. high" ,
"Oil level low" ,
"BOX temp.high" ,
"N2 valve open" ,
"Cooler 1 temp. high" ,
"Cooler 2 temp. high" ,
"Cooler 3 temp. high" ,
"Pump N2 flow low" ,
"Exh. N2 flow low" ,
"Exh. trap temp. high" ,
"Back press. high" ,
"Heater error" ,
"BP motor temp. high" ,
"MP motor temp. high" ,
"Driver temp. high" ,
"Communication error" ,
"Valve error" ,
"" ,
"" ,
"" ,
"Other warnings"
};
char *proto_PM100_Str_AlarmCode[32] =
{
"Casing temp. HH" ,
"BP motor temp. high" ,
"MP motor temp. high" ,
"Water leakage" ,
"BP thermal" ,
"MP thermal" ,
"" ,
"" ,
"" ,
"Emergency stop(EMS)" ,
"MP no current" ,
"BP no current" ,
"" ,
"Back press. high" ,
"Power failure" ,
"MP driver protection active",
"BP driver protection active",
"BP overload 2" ,
"MP overload 2" ,
"BP step out" ,
"MP step out" ,
"Emergency off(EMO)" ,
"Exh. N2 flow low" ,
"Water flow low continued" ,
"External interlock" ,
"" ,
"" ,
"" ,
"" ,
"" ,
"" ,
"Other alarms"
};
static void proto_PM100_Init(void);
static void proto_PM100_Tx_Task(void);
static void proto_PM100_Rx_Task(u8 *pData,u16 Len,void *other_data);
static void proto_PM100_Control_Start(u8 Dev);
static void proto_PM100_Control_Stop(u8 Dev);
static void proto_PM100_Control_Reset(void);
static void proto_PM100_Control_Set_Mode(u8 Mode);
static void proto_PM100_Control_Set_Mode_Speed(u8 Dev,u8 Mode,u16 Speed);
static void proto_PM100_Alarm_Control_Reset(void);
static void proto_PM100_Dev_Status_Control_Reset(void);
proto_PM100_t PM100 =
{
.Sys_StateQueue = queue(proto_PM100_Set_Data_t,10),
.Sys_State = PROTO_PM100_CMD_GET_STATE_ALARM,
.Init = proto_PM100_Init,
.Tx_Task = proto_PM100_Tx_Task,
.Rx_Task = proto_PM100_Rx_Task,
.Set_Data.Analog_Code = PROTO_PM100_GET_DATA_CODE,
.Alarm_Control.Reset = proto_PM100_Alarm_Control_Reset,
.Dev_Status_Control.Reset = proto_PM100_Dev_Status_Control_Reset,
.Control.Start = proto_PM100_Control_Start,
.Control.Stop = proto_PM100_Control_Stop,
.Control.Reset = proto_PM100_Control_Reset,
.Control.Set_Mode = proto_PM100_Control_Set_Mode,
.Control.Set_Speed = proto_PM100_Control_Set_Mode_Speed,
};
static proto_PM100_t *pPM100 = &PM100;
static void proto_PM100_Init(void)
{
/*让两个主动上发的信息有时间间隔*/
pPM100->Alarm_Control.StartTime = osTime_MSecTick;
pPM100->Dev_Status_Control.StartTime = osTime_MSecTick + 500;
COM_Uart3.Rx_DataAnalysis = proto_PM100_Rx_Task;
/*清空时间和报警时长数组*/
for (int i = 0; i < 32; i++)
{
PM100.Opera_Status.alarm_start_str[i][0] = '\0';
PM100.Opera_Status.warning_start_str[i][0] = '\0';
PM100.Opera_Status.alarm_start_sec[i] = 0;
PM100.Opera_Status.warning_start_sec[i] = 0;
}
}
static void proto_PM100_Send(u8 *pData,u16 Len)
{
COM_Uart3.Send(&COM_Uart3,pData,Len);
}
static u8 proto_PM100_SysState_Switch(void)
{
proto_PM100_Set_Data_t Set_Data;
if(0 == queue_pop(pPM100->Sys_StateQueue,&Set_Data))
{
pPM100->Sys_State = PROTO_PM100_CMD_GET_STATE_ALARM;
return 0;
}
else
{
pPM100->Sys_State = Set_Data.Sys_State;
memcpy(&pPM100->Set_Data,&Set_Data,sizeof(proto_PM100_Set_Data_t));
return 1;
}
}
static void proto_PM100_Alarm_Control_Reset(void)
{
pPM100->Alarm_Control.Code_Last = ((u64)pPM100->Opera_Status.Warming_Code << 32) | (u64)pPM100->Opera_Status.Alarm_Code;
}
static void proto_PM100_Dev_Status_Control_Reset(void)
{
memcpy(&pPM100->Dev_Status_Control.Opera_Status_Last,&pPM100->Opera_Status,sizeof(proto_PM100_Set_Data_t));
}
static void proto_PM100_Control_Start(u8 Dev)
{
proto_PM100_Set_Data_t Set_Data;
Set_Data.Sys_State = PROTO_PM100_CMD_START;
Set_Data.Dev = Dev;
queue_push_back(pPM100->Sys_StateQueue,(void *)&Set_Data);
}
static void proto_PM100_Control_Stop(u8 Dev)
{
proto_PM100_Set_Data_t Set_Data;
Set_Data.Sys_State = PROTO_PM100_CMD_STOP;
Set_Data.Dev = Dev;
queue_push_back(pPM100->Sys_StateQueue,(void *)&Set_Data);
}
static void proto_PM100_Control_Reset(void)
{
proto_PM100_Set_Data_t Set_Data;
Set_Data.Sys_State = PROTO_PM100_CMD_RESET;
queue_push_back(pPM100->Sys_StateQueue,(void *)&Set_Data);
}
static void proto_PM100_Control_Set_Mode(u8 Mode)
{
proto_PM100_Set_Data_t Set_Data;
Set_Data.Sys_State = PROTO_PM100_CMD_SET_MODE;
Set_Data.Mode = Mode;
queue_push_back(pPM100->Sys_StateQueue,(void *)&Set_Data);
}
static void proto_PM100_Control_Set_Mode_Speed(u8 Dev,u8 Mode,u16 Speed)
{
proto_PM100_Set_Data_t Set_Data;
Set_Data.Sys_State = PROTO_PM100_CMD_SET_SPEED;
Set_Data.Dev = Dev;
Set_Data.Mode = Mode;
Set_Data.Speed = Speed;
queue_push_back(pPM100->Sys_StateQueue,(void *)&Set_Data);
}
/*数据校验*/
static u8 proto_PM100_CheckSum(u8 *pData,u16 len)
{
u16 i;
u8 Sum=0;
for(i=0;i<len;i++)
{
Sum += pData[i];
}
return Sum;
}
/*启动设备*/
static void proto_PM100_Tx_Start(u8 Dev)
{
char Tx[20];
u16 Len;
Tx[0] = PROTO_PM100_FRAME_STRUCT_STX;
sprintf(&Tx[1],"%s",PROTO_PM100_CMD_STR_START);
if(PROTO_PM100_DEV_MP == Dev)
{
Tx[4] = PROTO_PM100_DEV_CHAR_MP;
}
else if(PROTO_PM100_DEV_BP == Dev)
{
Tx[4] = PROTO_PM100_DEV_CHAR_BP;
}
else/*异常*/
{
return ;
}
Tx[5] = PROTO_PM100_FRAME_STRUCT_ETX;
sprintf(&Tx[6],"%02X",proto_PM100_CheckSum((u8 *)Tx,6));
Tx[8] = PROTO_PM100_FRAME_STRUCT_CR;
Len = 9;
proto_PM100_Send((u8*)Tx,Len);
}
/*停止设备*/
static void proto_PM100_Tx_Stop(u8 Dev)
{
char Tx[20];
u16 Len;
Tx[0] = PROTO_PM100_FRAME_STRUCT_STX;
sprintf(&Tx[1],"%s",PROTO_PM100_CMD_STR_STOP);
if(PROTO_PM100_DEV_MP == Dev)
{
Tx[4] = PROTO_PM100_DEV_CHAR_MP;
}
else if(PROTO_PM100_DEV_BP == Dev)
{
Tx[4] = PROTO_PM100_DEV_CHAR_BP;
}
else/*异常*/
{
return ;
}
Tx[5] = PROTO_PM100_FRAME_STRUCT_ETX;
sprintf(&Tx[6],"%02X",proto_PM100_CheckSum((u8 *)Tx,6));
Tx[8] = PROTO_PM100_FRAME_STRUCT_CR;
Len = 9;
proto_PM100_Send((u8*)Tx,Len);
}
/*复位设备*/
static void proto_PM100_Tx_Reset(void)
{
char Tx[20];
u16 Len;
Tx[0] = PROTO_PM100_FRAME_STRUCT_STX;
sprintf(&Tx[1],"%s",PROTO_PM100_CMD_STR_RESET);
Tx[4] = PROTO_PM100_FRAME_STRUCT_ETX;
sprintf(&Tx[5],"%02X",proto_PM100_CheckSum((u8 *)Tx,5));
Tx[7] = PROTO_PM100_FRAME_STRUCT_CR;
Len = 8;
proto_PM100_Send((u8*)Tx,Len);
}
/*设置模式*/
static void proto_PM100_Tx_Set_Mode(u8 Mode)
{
char Tx[20];
u16 Len;
Tx[0] = PROTO_PM100_FRAME_STRUCT_STX;
sprintf(&Tx[1],"%s",PROTO_PM100_CMD_STR_SET_MODE);
if(PROTO_PM100_MODE_NORMAL == Mode)
{
Tx[4] = PROTO_PM100_MODE_CHAR_NORMAL;
}
else if(PROTO_PM100_MODE_POWER_SAVING == Mode)
{
Tx[4] = PROTO_PM100_MODE_CHAR_POWER_SAVING;
}
else/*异常*/
{
return ;
}
Tx[5] = PROTO_PM100_FRAME_STRUCT_ETX;
sprintf(&Tx[6],"%02X",proto_PM100_CheckSum((u8 *)Tx,6));
Tx[8] = PROTO_PM100_FRAME_STRUCT_CR;
Len = 9;
proto_PM100_Send((u8*)Tx,Len);
}
/*设置模式和转速*/
static void proto_PM100_Tx_Set_Mode_Speed(u8 Dev,u8 Mode,u16 Speed)
{
char Tx[20];
u16 Len;
Tx[0] = PROTO_PM100_FRAME_STRUCT_STX;
sprintf(&Tx[1],"%s",PROTO_PM100_CMD_STR_SET_SPEED);
if(PROTO_PM100_DEV_MP == Dev)
{
Tx[4] = PROTO_PM100_DEV_CHAR_MP;
}
else if(PROTO_PM100_DEV_BP == Dev)
{
Tx[4] = PROTO_PM100_DEV_CHAR_BP;
}
else/*异常*/
{
return ;
}
if(PROTO_PM100_MODE_NORMAL == Mode)
{
Tx[5] = PROTO_PM100_MODE_CHAR_NORMAL;
}
else if(PROTO_PM100_MODE_POWER_SAVING == Mode)
{
Tx[5] = PROTO_PM100_MODE_CHAR_POWER_SAVING;
}
else/*异常*/
{
return ;
}
if(Speed > 9900)
{
Speed = 99;
}
sprintf(&Tx[6],"%d",Speed);
Tx[8] = PROTO_PM100_FRAME_STRUCT_ETX;
sprintf(&Tx[9],"%02X",proto_PM100_CheckSum((u8 *)Tx,9));
Tx[11] = PROTO_PM100_FRAME_STRUCT_CR;
Len = 12;
proto_PM100_Send((u8*)Tx,Len);
}
/*获取模拟量参数*/
static void proto_PM100_Tx_Get_Data(u32 Analog_Code)
{
char Tx[20];
u16 Len;
u8 i,AD[8];
Analog_Code = PROTO_PM100_GET_DATA_CODE;
Tx[0] = PROTO_PM100_FRAME_STRUCT_STX;
sprintf(&Tx[1],"%s",PROTO_PM100_CMD_STR_GET_DATA);
for(i=0;i<8;i++)
{
AD[i] = (Analog_Code >> (4 * (7 - i))) & 0x0000000f;
sprintf(&Tx[4 + i],"%X",AD[i]);
}
Tx[12] = PROTO_PM100_FRAME_STRUCT_ETX;
sprintf(&Tx[13],"%02X",proto_PM100_CheckSum((u8 *)Tx,13));
Tx[15] = PROTO_PM100_FRAME_STRUCT_CR;
Len = 16;
proto_PM100_Send((u8*)Tx,Len);
}
/*获取状态和报警*/
static void proto_PM100_Tx_Get_State_Alarm(void)
{
char Tx[20];
u16 Len;
Tx[0] = PROTO_PM100_FRAME_STRUCT_STX;
sprintf(&Tx[1],"%s",PROTO_PM100_CMD_STR_GET_STATE_ALARM);
Tx[4] = PROTO_PM100_FRAME_STRUCT_ETX;
sprintf(&Tx[5],"%02X",proto_PM100_CheckSum((u8 *)Tx,5));
Tx[7] = PROTO_PM100_FRAME_STRUCT_CR;
Len = 8;
proto_PM100_Send((u8*)Tx,Len);
}
static void proto_PM100_Tx_Task(void)
{
u8 SendTimeFlag = 0;
if(0 == (pPM100->error_code & PROTO_PM100_ERROR_CODE_TIMEOUT))
{
pPM100->time_out_count++;
if(pPM100->time_out_count > 10)
{
pPM100->error_code |= PROTO_PM100_ERROR_CODE_TIMEOUT;
}
}
if( 1 == pPM100->AnalogData_Control.FirstFlag
&& 1 != pPM100->AnalogData_Control.EndFlag
)
{
pPM100->AnalogData_Control.CountTime++;
if(pPM100->AnalogData_Control.CountTime >= 3) /*连续3次没接收到数据*/
{
pPM100->AnalogData_Control.FirstFlag = 0;
pPM100->AnalogData_Control.EndFlag = 0;
pPM100->AnalogData_Control.CountTime = 0;
pPM100->Sys_State = PROTO_PM100_CMD_GET_STATE_ALARM;
}
return;
}
switch(pPM100->Sys_State)
{
case PROTO_PM100_CMD_START :
{
proto_PM100_Tx_Start(pPM100->Set_Data.Dev);
}break;
case PROTO_PM100_CMD_STOP :
{
proto_PM100_Tx_Stop(pPM100->Set_Data.Dev);
}break;
case PROTO_PM100_CMD_RESET :
{
proto_PM100_Tx_Reset();
}break;
case PROTO_PM100_CMD_SET_MODE :
{
proto_PM100_Tx_Set_Mode(pPM100->Set_Data.Mode);
}break;
case PROTO_PM100_CMD_SET_SPEED :
{
proto_PM100_Tx_Set_Mode_Speed(pPM100->Set_Data.Dev,pPM100->Set_Data.Mode,pPM100->Set_Data.Speed);
}break;
case PROTO_PM100_CMD_GET_DATA :
{
proto_PM100_Tx_Get_Data(pPM100->Set_Data.Analog_Code);
pPM100->AnalogData_Control.FirstFlag = 1;
SendTimeFlag = 1;
}break;
case PROTO_PM100_CMD_GET_STATE_ALARM :
{
proto_PM100_Tx_Get_State_Alarm();
SendTimeFlag = 1;
}break;
default:
{
}break;
}
if(SendTimeFlag)
{
return ;
}
else
{
pPM100->SendTime++;
if(pPM100->SendTime >= 3)
{
pPM100->SendTime = 0;
pPM100->Sys_State = PROTO_PM100_CMD_GET_STATE_ALARM;
}
}
}
/*接收数据解析*/
static void proto_PM100_Rx_Task(u8 *pData,u16 Len,void *other_data)
{
u8 SumCheck[2],SuccessFlag;
u8 *pTextData;
char TextData[10];
/*帧头判断*/
if(PROTO_PM100_FRAME_STRUCT_STX != pData[0])
{
return;
}
/*帧尾判断*/
if( PROTO_PM100_FRAME_STRUCT_ETX != pData[Len-4]
|| PROTO_PM100_FRAME_STRUCT_CR != pData[Len-1]
)
{
return;
}
if(PROTO_PM100_CMD_GET_DATA == pPM100->Sys_State)/*实时模拟量数据不进行校验判断,已经粘包了*/
{
}
else
{
/*校验和判断*/
sprintf((char*)SumCheck,"%02X",proto_PM100_CheckSum(pData,Len - 3));
if(SumCheck[0] != pData[Len - 3] || SumCheck[1] != pData[Len - 2])
{
return ;
}
}
/*清除超时计数*/
pPM100->error_code &= (~PROTO_PM100_ERROR_CODE_TIMEOUT);
pPM100->time_out_count = 0;
SuccessFlag = 0;
pTextData = &pData[1];
switch(pPM100->Sys_State)
{
case PROTO_PM100_CMD_START :
case PROTO_PM100_CMD_STOP :
case PROTO_PM100_CMD_RESET :
case PROTO_PM100_CMD_SET_MODE :
case PROTO_PM100_CMD_SET_SPEED :
{
if(0 == strncmp((char *)pTextData,PROTO_PM100_CMD_STR_SET_OK,strlen(PROTO_PM100_CMD_STR_SET_OK)))
{
SuccessFlag = 1;
proto_PM100_SysState_Switch();
}
else
{
SuccessFlag = 0;
}
}break;
case PROTO_PM100_CMD_GET_DATA :
{
u16 Len_Index = 0;
u8 *pData_u8 = pData;
int DataIndex;
float Data;
float *pData_float = (float *)&pPM100->AnalogData;
while(Len_Index < Len)
{
pData_u8 = &pData[Len_Index + 1];
snprintf(TextData,3,"%s",pData_u8);
sscanf((char*)TextData,"%d",&DataIndex);
if(DataIndex > 22)
{
Len_Index += 14;
continue ;
}
snprintf(TextData,8,"%s",&pData_u8[3]);
sscanf((char*)TextData,"%f",&Data);
pData_float[DataIndex] = Data;
Len_Index += 14;
}
Len_Index -=14;
pData_u8 = &pData[Len_Index + 1];
if(0 == strncmp((char *)pData_u8,PROTO_PM100_CMD_STR_SET_END,strlen(PROTO_PM100_CMD_STR_SET_END)))
{
SuccessFlag = 1;
pPM100->AnalogData_Control.EndFlag = 1;
}
else
{
SuccessFlag = 0;
}
/*
if(Len > 8)
{
int DataIndex;
float Data;
float *pData = (float *)&pPM100->AnalogData;
snprintf(TextData,3,"%s",pTextData);
sscanf((char*)TextData,"%d",&DataIndex);
if(DataIndex >= 32)
{
return ;
}
snprintf(TextData,8,"%s",&pTextData[3]);
sscanf((char*)TextData,"%f",&Data);
pData[DataIndex] = Data;
SuccessFlag = 1;
}
else
{
if(0 == strncmp((char *)pTextData,PROTO_PM100_CMD_STR_SET_END,strlen(PROTO_PM100_CMD_STR_SET_END)))
{
SuccessFlag = 1;
pPM100->AnalogData_Control.EndFlag = 1;
}
else
{
SuccessFlag = 0;
}
} */
}break;
case PROTO_PM100_CMD_GET_STATE_ALARM :
{
u32 Data,i;
if(0 != strncmp((char *)pTextData,PROTO_PM100_CMD_STR_GET_STATE_ALARM,strlen(PROTO_PM100_CMD_STR_GET_STATE_ALARM)))
{
SuccessFlag = 0;
break;
}
if(PROTO_PM100_MODE_CHAR_NORMAL == pTextData[3])
{
pPM100->Opera_Status.Run_Status = PROTO_PM100_MODE_NORMAL;
}
else if(PROTO_PM100_MODE_CHAR_POWER_SAVING == pTextData[3])
{
pPM100->Opera_Status.Run_Status = PROTO_PM100_MODE_POWER_SAVING;
}
else/*异常*/
{
SuccessFlag = 0;
break;
}
if(PROTO_PM100_MODE_CHAR_RUNING == pTextData[4])
{
pPM100->Opera_Status.MP_Status = PROTO_PM100_MODE_RUNING;
}
else if(PROTO_PM100_MODE_CHAR_STOP == pTextData[4])
{
pPM100->Opera_Status.MP_Status = PROTO_PM100_MODE_STOP;
}
else/*异常*/
{
SuccessFlag = 0;
break;
}
if(PROTO_PM100_MODE_CHAR_RUNING == pTextData[5])
{
pPM100->Opera_Status.BP_Status = PROTO_PM100_MODE_RUNING;
}
else if(PROTO_PM100_MODE_CHAR_STOP == pTextData[5])
{
pPM100->Opera_Status.BP_Status = PROTO_PM100_MODE_STOP;
}
else/*异常*/
{
SuccessFlag = 0;
break;
}
pPM100->Opera_Status.Warming_Code = 0;
pPM100->Opera_Status.Alarm_Code = 0;
// for(i=0;i<8;i++)
// {
// snprintf(TextData,8,"%s",&pTextData[6]);
// sscanf((char*)TextData,"%x",&Data);
// pPM100->Opera_Status.Warming_Code |= (Data & 0x0000000f);
//
// snprintf(TextData,8,"%s",&pTextData[14]);
// sscanf((char*)TextData,"%x",&Data);
// pPM100->Opera_Status.Alarm_Code |= Data & 0x0000000f;
// }
sscanf((const char *)&pTextData[6], "%8x", &pPM100->Opera_Status.Warming_Code);
sscanf((const char *)&pTextData[14], "%8x", &pPM100->Opera_Status.Alarm_Code);
if(0 == proto_PM100_SysState_Switch())
{
pPM100->Sys_State = PROTO_PM100_CMD_GET_DATA; /*如果队列没有数据,就获取数据*/
}
SuccessFlag = 1;
}break;
default:
{
}break;
}
/*实时数据是分包获取的,需特殊处理*/
if(PROTO_PM100_CMD_GET_DATA == pPM100->Sys_State)
{
if(1 == pPM100->AnalogData_Control.FirstFlag)
{
/*分包数据接收完成*/
if(1 == pPM100->AnalogData_Control.EndFlag)
{
pPM100->AnalogData_Control.FirstFlag = 0;
pPM100->AnalogData_Control.EndFlag = 0;
pPM100->AnalogData_Control.CountTime = 0;
proto_PM100_SysState_Switch();
}
else if(0 == SuccessFlag)
{
}
else
{
pPM100->AnalogData_Control.CountTime = 0;
}
}
}
else
{
if(0 == SuccessFlag)
{
}
else
{
pPM100->SendTime = 0;
return;
}
}
}
+189
View File
@@ -0,0 +1,189 @@
#ifndef _PROTO_PM100_H_
#define _PROTO_PM100_H_
#include "main.h"
#include "algo_queue.h"
/*数据帧格式 STX TEXT ETX SUM CR*/
#define PROTO_PM100_FRAME_STRUCT_STX (0x02)
#define PROTO_PM100_FRAME_STRUCT_ETX (0x03)
#define PROTO_PM100_FRAME_STRUCT_CR (0x0D)
/*设备*/
#define PROTO_PM100_DEV_MP 0 /*主泵*/
#define PROTO_PM100_DEV_BP 1 /*增加泵*/
#define PROTO_PM100_MODE_NORMAL 0 /*NORMAL 正常*/
#define PROTO_PM100_MODE_POWER_SAVING 1 /*POWER-SAVING 节能*/
#define PROTO_PM100_MODE_RUN 0 /*设备运行*/
#define PROTO_PM100_MODE_ALARM 1 /*设备报警*/
#define PROTO_PM100_MODE_PE 2
#define PROTO_PM100_MODE_IDIE 3 /*设备空闲/停止*/
#define PROTO_PM100_MODE_OFFLINE 4 /*设备离线*/
#define PROTO_PM100_MODE_ONLINE 5 /*设备在线*/
#define PROTO_PM100_MODE_RUNING 0 /*运行*/
#define PROTO_PM100_MODE_STOP 1 /*停止*/
#define PROTO_PM100_DEV_CHAR_MP ('M') /*主泵*/
#define PROTO_PM100_DEV_CHAR_BP ('B') /*增加泵*/
#define PROTO_PM100_MODE_CHAR_NORMAL ('N') /*NORMAL 正常*/
#define PROTO_PM100_MODE_CHAR_POWER_SAVING ('S') /*POWER-SAVING 节能*/
#define PROTO_PM100_MODE_CHAR_RUNING ('R') /*运行*/
#define PROTO_PM100_MODE_CHAR_STOP ('S') /*停止*/
/*指令*/
/*字符串*/
#define PROTO_PM100_CMD_STR_START ("S20") /*启动*/
#define PROTO_PM100_CMD_STR_STOP ("S21") /*停止*/
#define PROTO_PM100_CMD_STR_RESET ("S22") /*复位*/
#define PROTO_PM100_CMD_STR_SET_MODE ("S23") /*设置泵模式:NORMAL/POWER-SAVING 正常/节能*/
#define PROTO_PM100_CMD_STR_SET_SPEED ("S24") /*设置转速模式:NORMAL/POWER-SAVING 正常/节能*/
#define PROTO_PM100_CMD_STR_GET_DATA ("M20") /*读取用户选择的模拟量*/
#define PROTO_PM100_CMD_STR_GET_STATE_ALARM ("M21") /*读取运行状态与报警*/
#define PROTO_PM100_CMD_STR_SET_OK ("OK") /*设置成功*/
#define PROTO_PM100_CMD_STR_SET_NG ("NG") /*设置失败*/
#define PROTO_PM100_CMD_STR_SET_END ("END") /*发送结束*/
/*CMD*/
#define PROTO_PM100_CMD_START 0 /*启动*/
#define PROTO_PM100_CMD_STOP 2 /*停止*/
#define PROTO_PM100_CMD_RESET 3 /*复位*/
#define PROTO_PM100_CMD_SET_MODE 4 /*设置泵模式:NORMAL/POWER-SAVING 正常/节能*/
#define PROTO_PM100_CMD_SET_SPEED 5 /*设置转速模式:NORMAL/POWER-SAVING 正常/节能*/
#define PROTO_PM100_CMD_GET_DATA 6 /*读取用户选择的模拟量*/
#define PROTO_PM100_CMD_GET_STATE_ALARM 7 /*读取运行状态与报警*/
#define BP_ON ("BPON") /*bp启动*/
#define MP_ON ("MPON") /*mp启动*/
#define ALL_RESET ("ALLRESET") /*重置*/
#define BP_STOP ("BPSTOP") /*bp停止*/
#define MP_STOP ("MPSTOP") /*mp停止*/
#define NORMAL ("N") /*正常模式*/
#define POWER_SAVE ("S") /*节能模式*/
#define MP_NORMAL_SPEED ("MN") /*mp正常模式转速*/
#define MP_SAVE_SPEED ("MS") /*mp节能模式转速*/
#define BP_NORMAL_SPEED ("BN") /*bp正常模式转速*/
#define BP_SAVE_SPEED ("BS") /*bp节能模式转速*/
#define PROTO_PM100_GET_DATA_CODE (0x007FD9FF)/*获取哪些实数数据*/
#define PROTO_PM100_ERROR_CODE_TIMEOUT (0x0001)/*通讯超时*/
/*PM100模拟量数据*/
typedef struct
{
float Total_running_time; /*H*/
float BP_power ; /*KW*/
float MP_power ; /*KW*/
float BP_motor_speed ; /*K/min*/
float MP_motor_speed ; /*K/min*/
float BP_current ; /*A*/
float MP_current ; /*A*/
float BP_casing_temp ; /*℃*/
float MP_casing_temp ; /*℃*/
float Reserved_1[2] ; /* */
float Cooling_water_flow; /*L/min*/
float Pump_N2_flow ; /*Pam3/s*/
float Reserved ; /* */
float Back_pressure_1 ; /*KPa*/
float Heater1 ; /*℃*/
float Heater2 ; /*℃*/
float Heater3 ; /*℃*/
float Heater4 ; /*℃*/
float Vacuum_pressure ; /*KPa*/
float Cooler_1 ; /*℃*/
float Cooler_2 ; /*℃*/
float Cooler_3 ; /*℃*/
float Reserved_2[9] ; /*H*/
}proto_PM100_AnalogData_t;
typedef struct
{
u8 Sys_State;
u8 Dev;
u8 Mode;
u16 Speed;
u32 Analog_Code; /*获取哪些模拟量数据*/
}proto_PM100_Set_Data_t;
typedef struct
{
u8 Run_Status;
u8 MP_Status;
u8 BP_Status;
u32 Warming_Code; /*设备状态码*/
u32 Alarm_Code; /*报警状态码*/
char alarm_start_str[32][15]; // 报警开始时间字符串 YYYYMMDDHHMMSS
char warning_start_str[32][15]; // 警告开始时间字符串
u32 alarm_start_sec[32]; // 报警开始秒数(基准2000-01-01
u32 warning_start_sec[32]; // 警告开始秒数
}proto_Opera_Status_t;
typedef struct
{
queue Sys_StateQueue; /*状态队列*/
u8 Sys_State; /*协议程序运行状态*/
u8 SendTime; /*指令发送次数*/
proto_PM100_AnalogData_t AnalogData;
u16 time_out_count; /*超时计数*/
u32 error_code; /*设备状态*/
struct
{
u8 FirstFlag;
u8 EndFlag;
u16 CountTime;
}AnalogData_Control; /*读取模拟数据相关的控制参数*/
struct
{
u64 Code_Last; /*上一次的报警值*/
u16 StartTime; /*计时*/
void (*Reset)(void); /*复位报警,不再上发*/
}Alarm_Control; /*报警上发的相关数据*/
proto_PM100_Set_Data_t Set_Data; /*设置的参数*/
proto_Opera_Status_t Opera_Status;
struct
{
proto_Opera_Status_t Opera_Status_Last; /*上一次的设备状态*/
u16 StartTime; /*计时*/
void (*Reset)(void); /*更新状态,不再上发*/
}Dev_Status_Control; /*设备状态控制*/
struct
{
void (*Start)(u8); /*启动*/
void (*Stop)(u8); /*停止*/
void (*Reset)(void); /*复位*/
void (*Set_Mode)(u8); /*设置泵模式:NORMAL/POWER-SAVING 正常/节能*/
void (*Set_Speed)(u8,u8,u16); /*设置转速模式:NORMAL/POWER-SAVING 正常/节能*/
}Control;
void (*Init)(void);
void (*Rx_Task)(u8 *,u16,void *);
void (*Tx_Task)(void);
}proto_PM100_t;
extern proto_PM100_t PM100;
extern char *proto_PM100_Str_WarmingCode[32];
extern char *proto_PM100_Str_AlarmCode[32];
#endif
+745
View File
@@ -0,0 +1,745 @@
#include "proto_Para_Modbus.h"
#include "string.h"
#include "bsp_Uart.h"
#include "os_timer.h"
#include "stdio.h"
#include "app.h"
#include "bsp_W5500.h"
#include "proto_HSMS.h"
#include "bsp_Flash.h"
#include "bsp_Wdg.h"
static ModbusAnalysisData_t ModbusAnalysisData;//指令解析结构体
static ModbusCommunicationSendBuf_t SendStruct;//发送结构体
static void ModbusCommunicationDataReceive(u8 *pData, u16 len,void *other_data);
static void ModbusCommunicationDataSend(u8 *pData, u16 len);
static void proto_Modbus_Init(void);
static void proto_Modbus_Task(void);
static ModbusErrorCode_e ModbusCommunicationDataWrite(u16 Addr, u16 Value);
static u16 ModbusCommunicationDataRead(u16 Addr);
proto_Modbus_t Para_Modbus=
{
.ID = 0x01,
.DataRead = ModbusCommunicationDataRead,
.DataWrite = ModbusCommunicationDataWrite,
.DataAnalysis = ModbusCommunicationDataReceive,
.Init = proto_Modbus_Init,
.Task = proto_Modbus_Task,
};
static proto_Modbus_t *pModbus = &Para_Modbus;
static bsp_Uart_t *rx_uart = NULL;
static void ModbusCommunicationDataSend(u8 *pData, u16 Len)
{
if(&COM_Uart1 == rx_uart)
{
COM_Uart1.Send(&COM_Uart1,pData,Len);
}
else if(&COM_Uart2 == rx_uart)
{
COM_Uart2.Send(&COM_Uart2,pData,Len);
}
}
static void proto_Modbus_Init(void)
{
COM_Uart1.Rx_DataAnalysis = ModbusCommunicationDataReceive;
COM_Uart2.Rx_DataAnalysis = ModbusCommunicationDataReceive;
}
static void proto_Modbus_Task(void)
{
}
static void ModbusCommunicationDataReceive(u8 *pData, u16 len,void *other_data)
{
ModbusErrorCode_e ErrorCode;
u8 inx;
u16 TempAddr, TempData, Crc16;
if (0 == ModbusAnalysis(&ModbusAnalysisData, pData, len))//检查数据长度 校验是否正确
return;
if (pModbus->ID != ModbusAnalysisData.ID)//判断ID是否正确
return;
ErrorCode = ModbusErrorCode_Success;
rx_uart = (bsp_Uart_t *)other_data;
/* //检查地址是否超出范围
if ((ModbusAnalysisData.StartAddress >= MODBUS_REG_LEN) || (ModbusAnalysisData.RegNumber >= MODBUS_REG_LEN) ||
(ModbusAnalysisData.StartAddress + ModbusAnalysisData.RegNumber >= MODBUS_REG_LEN))
{
ErrorCode = ModbusErrorCode_IllegalAddr;
goto Error;
}
*/
switch (ModbusAnalysisData.Func)
{
case 0x03:
case 0x04:
{
TempAddr = ModbusAnalysisData.StartAddress;
SendStruct.SendBuffer[0] = ModbusAnalysisData.ID;
SendStruct.SendBuffer[1] = ModbusAnalysisData.Func;
SendStruct.SendBuffer[2] = 2 * ModbusAnalysisData.RegNumber;
for (inx = 0; inx < ModbusAnalysisData.RegNumber; inx++)
{
TempData = ModbusCommunicationDataRead(TempAddr);
SendStruct.SendBuffer[3 + 2 * inx] = (TempData >> 8) & 0xff;
SendStruct.SendBuffer[4 + 2 * inx] = TempData & 0xff;
TempAddr++;
}
Crc16 = ModbusCrc16(SendStruct.SendBuffer, 3 + SendStruct.SendBuffer[2]);
SendStruct.SendBuffer[3 + SendStruct.SendBuffer[2]] = Crc16 & 0xff;
SendStruct.SendBuffer[4 + SendStruct.SendBuffer[2]] = (Crc16 >> 8) & 0xff;
SendStruct.Len = 5 + SendStruct.SendBuffer[2];
}goto Success;
/*特殊协议*/
case 0x41:
{
TempAddr = ModbusAnalysisData.StartAddress;
SendStruct.SendBuffer[0] = ModbusAnalysisData.ID;
SendStruct.SendBuffer[1] = ModbusAnalysisData.Func;
SendStruct.SendBuffer[2] = ModbusAnalysisData.StartAddress >> 8;
SendStruct.SendBuffer[3] = ModbusAnalysisData.StartAddress & 0xff;
SendStruct.SendBuffer[4] = (2 * ModbusAnalysisData.RegNumber) >> 8;
SendStruct.SendBuffer[5] = (2 * ModbusAnalysisData.RegNumber) & 0xff;
for (inx = 0; inx < ModbusAnalysisData.RegNumber; inx++)
{
TempData = ModbusCommunicationDataRead(TempAddr);
SendStruct.SendBuffer[6 + 2 * inx] = (TempData >> 8) & 0xff;
SendStruct.SendBuffer[7 + 2 * inx] = TempData & 0xff;
TempAddr++;
}
Crc16 = ModbusCrc16(SendStruct.SendBuffer, 6 + 2 * ModbusAnalysisData.RegNumber);
SendStruct.SendBuffer[6 + 2 * ModbusAnalysisData.RegNumber] = Crc16 & 0xff;
SendStruct.SendBuffer[7 + 2 * ModbusAnalysisData.RegNumber] = (Crc16 >> 8) & 0xff;
SendStruct.Len = 8 + 2 * ModbusAnalysisData.RegNumber;
}goto Success;
case 0x06:
{
TempAddr = ModbusAnalysisData.StartAddress;
TempData = (ModbusAnalysisData.wDataAddress[0] << 8) | ModbusAnalysisData.wDataAddress[1];
ErrorCode = ModbusCommunicationDataWrite(TempAddr, TempData);
if (ErrorCode)
{
goto Error;
}
SendStruct.Len = 8;
SendStruct.SendBuffer[0] = ModbusAnalysisData.ID;
SendStruct.SendBuffer[1] = ModbusAnalysisData.Func;
SendStruct.SendBuffer[2] = ModbusAnalysisData.StartAddress >> 8;
SendStruct.SendBuffer[3] = ModbusAnalysisData.StartAddress & 0xff;
SendStruct.SendBuffer[4] = ModbusAnalysisData.wDataAddress[0];
SendStruct.SendBuffer[5] = ModbusAnalysisData.wDataAddress[1];
Crc16 = ModbusCrc16(SendStruct.SendBuffer, 6);
SendStruct.SendBuffer[6] = Crc16 & 0xff;
SendStruct.SendBuffer[7] = (Crc16 >> 8) & 0xff;
}break;
case 0x10:
{
TempAddr = ModbusAnalysisData.StartAddress;
for (inx = 0; inx < ModbusAnalysisData.RegNumber; inx++)
{
TempData = ModbusAnalysisData.wDataAddress[2 * inx];
TempData = (TempData << 8) | ModbusAnalysisData.wDataAddress[2 * inx + 1];
ErrorCode = ModbusCommunicationDataWrite(TempAddr, TempData);
TempAddr++;
if (ErrorCode)
{
goto Error;
}
}
SendStruct.Len = 8;
SendStruct.SendBuffer[0] = ModbusAnalysisData.ID;
SendStruct.SendBuffer[1] = ModbusAnalysisData.Func;
SendStruct.SendBuffer[2] = ModbusAnalysisData.StartAddress >> 8;
SendStruct.SendBuffer[3] = ModbusAnalysisData.StartAddress & 0xff;
SendStruct.SendBuffer[4] = ModbusAnalysisData.RegNumber >> 8;
SendStruct.SendBuffer[5] = ModbusAnalysisData.RegNumber & 0xff;
Crc16 = ModbusCrc16(SendStruct.SendBuffer, 6);
SendStruct.SendBuffer[6] = Crc16 & 0xff;
SendStruct.SendBuffer[7] = (Crc16 >> 8) & 0xff;
}
break;
default:
{
ErrorCode = ModbusErrorCode_IllegalFunction;
}
goto Error;
}
Success:
ModbusCommunicationDataSend(SendStruct.SendBuffer, SendStruct.Len);
return;
Error:
SendStruct.Len = 5;
SendStruct.SendBuffer[0] = ModbusAnalysisData.ID;
SendStruct.SendBuffer[1] = ModbusAnalysisData.Func | 0x80;
SendStruct.SendBuffer[2] = ErrorCode;
Crc16 = ModbusCrc16(SendStruct.SendBuffer, 3);
SendStruct.SendBuffer[3] = Crc16 & 0xff;
SendStruct.SendBuffer[4] = (Crc16 >> 8) & 0xff;
ModbusCommunicationDataSend(SendStruct.SendBuffer, SendStruct.Len);
}
/*modbus接收到的u16转换为ascii的u16 实际为对调高低字节*/
static u16 modbus_u16_to_ascii_u16(u16 modbus_u16)
{
return (modbus_u16 << 8) | (modbus_u16 >> 8);
}
/*ascii的u16 转换为modbus u16发送 实际为对调高低字节*/
static u16 ascii_u16_to_modbus_u16(u16 modbus_u16)
{
return (modbus_u16 << 8) | (modbus_u16 >> 8);
}
/******************************************
* 函数: ModbusCommunicationDataWrite
* 功能: Modbus写寄存器
* 参数: Addr: 地址
Value:数据
* 返回: 无
* 描述: 无
******************************************/
static ModbusErrorCode_e ModbusCommunicationDataWrite(u16 Addr, u16 Value)
{
ModbusErrorCode_e ErrorCode;
ErrorCode = ModbusErrorCode_Success;
switch(Addr)
{
/*SN*/
case 12 ... 16:
{
Usr_Flash.FlashData.SN[Addr - 12] = Value;
Usr_Flash.Write();
}break;
/*IP地址*/
case 17 ... 20:
{
W5500.IP_Addr[Addr - 17] = Value;
Usr_Flash.FlashData.IP_Addr[Addr - 17] = Value;
}break;
/*端口号*/
case 21:
{
W5500.W5500_Class[0].ConfigData.Port[0] = Value >> 8;
W5500.W5500_Class[0].ConfigData.Port[1] = Value & 0x00ff;
Usr_Flash.FlashData.Port[0] = Value >> 8;
Usr_Flash.FlashData.Port[1] = Value & 0x00ff;
}break;
/*子网掩码*/
case 22 ... 25:
{
W5500.Sub_Mask[Addr - 22] = Value;
Usr_Flash.FlashData.Sub_Mask[Addr - 22] = Value;
}break;
case 26:
{
HSMS.Flash_ConfigData.Device_Id = Value;
Usr_Flash.FlashData.Devic_Id = Value;
Wdg.Feed();
W5500.Init();
Wdg.Feed();
Usr_Flash.Write();
}break;
/* 网关设置*/
case 27 ... 30:
{
W5500.Gateway_IP[Addr - 27] = Value;
Usr_Flash.FlashData.Gateway_IP[Addr - 27] = Value;
W5500.Init();
Usr_Flash.Write();
} break;
/* 设备 SN */
case 100 ... 107:
{
Usr_Flash.FlashData.Device_SN[Addr - 100] = modbus_u16_to_ascii_u16(Value);
} break;
/* 报警机台和位置 */
case 108 ... 115:
{
Usr_Flash.FlashData.Device_Model[Addr - 108] = modbus_u16_to_ascii_u16(Value);
} break;
/* 设备型号 */
case 116 ... 123:
{
Usr_Flash.FlashData.Device_ID[Addr - 116] = modbus_u16_to_ascii_u16(Value);
} break;
/* 机台软件版本号 */
case 124 ... 131:
{
Usr_Flash.FlashData.Version[Addr - 124] = modbus_u16_to_ascii_u16(Value);
} break;
/* 厂商名称 */
case 132 ... 139:
{
Usr_Flash.FlashData.Manufacturer[Addr - 132] = modbus_u16_to_ascii_u16(Value);
} break;
/* 机台名称 */
case 140 ... 147:
{
Usr_Flash.FlashData.Station_Name[Addr - 140] = modbus_u16_to_ascii_u16(Value);
} break;
/* 腔体名称 */
case 148 ... 155:
{
Usr_Flash.FlashData.Chamber_Name[Addr - 148] = modbus_u16_to_ascii_u16(Value);
} break;
/* 机台类型 */
case 156 ... 163:
{
Usr_Flash.FlashData.Station_Type[Addr - 156] = modbus_u16_to_ascii_u16(Value);
Usr_Flash.Write();
} break;
/* 预留 Alarm_info */
case 164 ... 183:
{
Usr_Flash.FlashData.Alarm_info[Addr - 164] = Value;
Usr_Flash.Write();
} break;
/* 预留 Data_ID1 */
case 184:
{
Usr_Flash.FlashData.Data_ID1 = Value;
Usr_Flash.Write();
} break;
/* 预留 Collection_event_ID1 */
case 185:
{
Usr_Flash.FlashData.Collection_event_ID1 = Value;
Usr_Flash.Write();
} break;
/* 预留 Report_ID1 */
case 186:
{
Usr_Flash.FlashData.Report_ID1 = Value;
Usr_Flash.Write();
} break;
/* 预留 Alarm_ID */
case 187:
{
Usr_Flash.FlashData.Alarm_ID = Value;
Usr_Flash.Write();
} break;
/* 预留 Alarm_Type */
case 188 ... 194:
{
Usr_Flash.FlashData.Alarm_Type[Addr - 188] = Value;
Usr_Flash.Write();
} break;
/* 预留 Begin_Warning */
case 195 ... 201:
{
Usr_Flash.FlashData.Begin_Warning[Addr - 195] = Value;
Usr_Flash.Write();
} break;
/* 预留 IDS */
case 202 ... 212:
{
Usr_Flash.FlashData.IDS[Addr - 202] = Value;
Usr_Flash.Write();
} break;
/* 预留 Over_Trigger */
case 213 ... 221:
{
Usr_Flash.FlashData.Over_Trigger[Addr - 213] = Value;
Usr_Flash.Write();
} break;
/* 预留 Equipment */
case 222 ... 226:
{
Usr_Flash.FlashData.Equipment[Addr - 222] = Value;
Usr_Flash.Write();
} break;
/* 预留 E9 */
case 227 ... 245:
{
Usr_Flash.FlashData.E9[Addr - 227] = Value;
Usr_Flash.Write();
} break;
/* 预留 Device_Type */
case 246:
{
Usr_Flash.FlashData.Device_Type = Value;
Usr_Flash.Write();
} break;
/* 预留 Sensor */
case 247:
{
Usr_Flash.FlashData.Sensor = Value;
Usr_Flash.Write();
} break;
/* 预留 Alarm_value */
case 248:
{
Usr_Flash.FlashData.Alarm_value = Value;
Usr_Flash.Write();
} break;
/* 预留 Alarm_ubit */
case 249:
{
Usr_Flash.FlashData.Alarm_ubit = Value;
Usr_Flash.Write();
} break;
/* 预留 Start_Time */
case 250 ... 260:
{
Usr_Flash.FlashData.Start_Time[Addr - 250] = Value;
Usr_Flash.Write();
} break;
/* 预留 Alarm_Time */
case 261 ... 266:
{
Usr_Flash.FlashData.Alarm_Time[Addr - 261] = Value;
Usr_Flash.Write();
} break;
/* 预留 Alarm */
case 267 ... 272:
{
Usr_Flash.FlashData.Alarm[Addr - 267] = Value;
Usr_Flash.Write();
} break;
/* 预留 Data_ID2 */
case 273:
{
Usr_Flash.FlashData.Data_ID2 = Value;
Usr_Flash.Write();
} break;
/* 预留 Collection_event_ID2 */
case 274:
{
Usr_Flash.FlashData.Collection_event_ID2 = Value;
Usr_Flash.Write();
} break;
/* 预留 Report_ID2 */
case 275:
{
Usr_Flash.FlashData.Report_ID2 = Value;
Usr_Flash.Write();
} break;
/* 预留 Sub_Device_Type */
case 276 ... 277:
{
Usr_Flash.FlashData.Sub_Device_Type[Addr - 276] = Value;
Usr_Flash.Write();
} break;
/* 预留 Sub_Device_State */
case 278 ... 279:
{
Usr_Flash.FlashData.Sub_Device_State[Addr - 278] = Value;
Usr_Flash.Write();
} break;
/* 预留 State_Change_Time */
case 280 ... 281:
{
Usr_Flash.FlashData.State_Change_Time[Addr - 280] = Value;
Usr_Flash.Write();
} break;
}
return ErrorCode;
}
/******************************************
* 函数: ModbusCommunicationDataRead
* 功能: Modbus读寄存器数据
* 参数: Addr: 地址
* 返回: 地址对应的数据
* 描述: 无
******************************************/
static u16 ModbusCommunicationDataRead(u16 Addr)
{
u8 *p_u8Data;
u16 Data;
u16 *pData;
switch(Addr)
{
/*SV*/
case 0 ... 11:
{
p_u8Data = &SwVersion[Addr * 2];
Data = p_u8Data[1] | p_u8Data[0] << 8;
}break;
/*SN*/
case 12 ... 16:
{
Data = Usr_Flash.FlashData.SN[Addr - 12];
}break;
/*IP地址*/
case 17 ... 20:
{
Data = W5500.IP_Addr[Addr - 17];
}break;
/*端口号*/
case 21:
{
Data = W5500.W5500_Class[0].ConfigData.Port[0] << 8 | W5500.W5500_Class[0].ConfigData.Port[1];
}break;
/*子网掩码*/
case 22 ... 25:
{
Data = W5500.Sub_Mask[Addr - 22];
}break;
/*SECS2协议设备ID*/
case 26:
{
Data = HSMS.Flash_ConfigData.Device_Id;
}break;
/* 网关*/
case 27 ... 30:
{
Data = W5500.Gateway_IP[Addr - 27];
} break;
/* 设备 SN */
case 100 ... 107:
{
Data = Usr_Flash.FlashData.Device_SN[Addr - 100];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 报警机台和位置 */
case 108 ... 115:
{
Data = Usr_Flash.FlashData.Device_Model[Addr - 108];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 设备型号 */
case 116 ... 123:
{
Data = Usr_Flash.FlashData.Device_ID[Addr - 116];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 机台软件版本号 */
case 124 ... 131:
{
Data = Usr_Flash.FlashData.Version[Addr - 124];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 厂商名称 */
case 132 ... 139:
{
Data = Usr_Flash.FlashData.Manufacturer[Addr - 132];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 机台名称 */
case 140 ... 147:
{
Data = Usr_Flash.FlashData.Station_Name[Addr - 140];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 腔体名称 */
case 148 ... 155:
{
Data = Usr_Flash.FlashData.Chamber_Name[Addr - 148];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 机台类型 */
case 156 ... 163:
{
Data = Usr_Flash.FlashData.Station_Type[Addr - 156];
Data = ascii_u16_to_modbus_u16(Data);
} break;
/* 预留 Alarm_info */
case 164 ... 183:
{
Data = Usr_Flash.FlashData.Alarm_info[Addr - 164];
} break;
/* 预留 Data_ID1 */
case 184:
{
Data = Usr_Flash.FlashData.Data_ID1;
} break;
/* 预留 Collection_event_ID1 */
case 185:
{
Data = Usr_Flash.FlashData.Collection_event_ID1;
} break;
/* 预留 Report_ID1 */
case 186:
{
Data = Usr_Flash.FlashData.Report_ID1;
} break;
/* 预留 Alarm_ID */
case 187:
{
Data = Usr_Flash.FlashData.Alarm_ID;
} break;
/* 预留 Alarm_Type */
case 188 ... 194:
{
Data = Usr_Flash.FlashData.Alarm_Type[Addr - 188];
} break;
/* 预留 Begin_Warning */
case 195 ... 201:
{
Data = Usr_Flash.FlashData.Begin_Warning[Addr - 195];
} break;
/* 预留 IDS */
case 202 ... 212:
{
Data = Usr_Flash.FlashData.IDS[Addr - 202];
} break;
/* 预留 Over_Trigger */
case 213 ... 221:
{
Data = Usr_Flash.FlashData.Over_Trigger[Addr - 213];
} break;
/* 预留 Equipment */
case 222 ... 226:
{
Data = Usr_Flash.FlashData.Equipment[Addr - 222];
} break;
/* 预留 E9 */
case 227 ... 245:
{
Data = Usr_Flash.FlashData.E9[Addr - 227];
} break;
/* 预留 Device_Type */
case 246:
{
Data = Usr_Flash.FlashData.Device_Type;
} break;
/* 预留 Sensor */
case 247:
{
Data = Usr_Flash.FlashData.Sensor;
} break;
/* 预留 Alarm_value */
case 248:
{
Data = Usr_Flash.FlashData.Alarm_value;
} break;
/* 预留 Alarm_ubit */
case 249:
{
Data = Usr_Flash.FlashData.Alarm_ubit;
} break;
/* 预留 Start_Time */
case 250 ... 260:
{
Data = Usr_Flash.FlashData.Start_Time[Addr - 250];
} break;
/* 预留 Alarm_Time */
case 261 ... 266:
{
Data = Usr_Flash.FlashData.Alarm_Time[Addr - 261];
} break;
/* 预留 Alarm */
case 267 ... 272:
{
Data = Usr_Flash.FlashData.Alarm[Addr - 267];
} break;
/* 预留 Data_ID2 */
case 273:
{
Data = Usr_Flash.FlashData.Data_ID2;
} break;
/* 预留 Collection_event_ID2 */
case 274:
{
Data = Usr_Flash.FlashData.Collection_event_ID2;
} break;
/* 预留 Report_ID2 */
case 275:
{
Data = Usr_Flash.FlashData.Report_ID2;
} break;
/* 预留 Sub_Device_Type */
case 276 ... 277:
{
Data = Usr_Flash.FlashData.Sub_Device_Type[Addr - 276];
} break;
/* 预留 Sub_Device_State */
case 278 ... 279:
{
Data = Usr_Flash.FlashData.Sub_Device_State[Addr - 278];
} break;
/* 预留 State_Change_Time */
case 280 ... 281:
{
Data = Usr_Flash.FlashData.State_Change_Time[Addr - 280];
} break;
default:
Data = 0;
}
return Data;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef _PROTO_PARA_MODBUS_H_
#define _PROTO_PARA_MODBUS_H_
#include "main.h"
#include "proto_Modbus.h"
extern proto_Modbus_t Para_Modbus;
#endif
File diff suppressed because it is too large Load Diff
+59
View File
@@ -0,0 +1,59 @@
#ifndef _PROTO_SECS2_H_
#define _PROTO_SECS2_H_
#include "main.h"
#include "proto_HSMS.h"
#define PROTO_SECS2_S1F3 (0x0103) /*数据采集*/
#define PROTO_SECS2_S2F49 (0x0231) /*设备状态远程控制*/
#define PROTO_SECS2_S1F1 (0x0101) /*心跳*/
#define PROTO_SECS2_S6F11 (0x060B) /*设备主动报警*/
#define PROTO_SECS2_S6F12 (0x060C) /*确认报警*/
#define PROTO_SECS2_S1F13 (0x010D) /*建立连接*/
#define PROTO_SECS2_S2F31 (0x021F) /*时间设置*/
/*报警和状态哦改变是否需要响应*/
#define PROTO_ALARM_CHANGE_RX_WAIT (1)
#define PROTO_STATE_CHANGE_RX_WAIT (1)
/*数据类型*/
#define PROTO_SECS2_DATA_TYPE_List 000/*八进制*/
#define PROTO_SECS2_DATA_TYPE_Binary 010
#define PROTO_SECS2_DATA_TYPE_Bool 011
#define PROTO_SECS2_DATA_TYPE_ASCII 020
#define PROTO_SECS2_DATA_TYPE_JIS_8 021
#define PROTO_SECS2_DATA_TYPE_2Byte_char 022
#define PROTO_SECS2_DATA_TYPE_8Byte_int 030
#define PROTO_SECS2_DATA_TYPE_1Byte_int 031
#define PROTO_SECS2_DATA_TYPE_2Byte_int 032
#define PROTO_SECS2_DATA_TYPE_4Byte_int 034
#define PROTO_SECS2_DATA_TYPE_8Byte_float 040
#define PROTO_SECS2_DATA_TYPE_4Byte_float 044
#define PROTO_SECS2_DATA_TYPE_8Byte_uint 050
#define PROTO_SECS2_DATA_TYPE_1Byte_uint 051
#define PROTO_SECS2_DATA_TYPE_2Byte_uint 052
#define PROTO_SECS2_DATA_TYPE_4Byte_uint 054
/*解析出来的消息数据*/
typedef struct
{
void *pData; /*解析的数据首地址*/
u8 w_bit; /*是否需要响应*/
u8 DataType; /*数据类型*/
u8 ByteLen; /*字节长度*/
u8 DataNum; /*数据个数*/
}proto_SECS2_MessageData_t;
typedef struct
{
u32 sys_count;
void (*Rx_DataAnalysis)(proto_HSMS_Header_Data_t *,u8 *,u16);
void (*Tx_Alarm_Task)(void);
void (*Tx_Dev_State_Task)(void);
}proto_SECS2_t;
extern proto_SECS2_t SECS2;
#endif
+10
View File
@@ -0,0 +1,10 @@
#include "proto_Transform.h"
#include "proto_CS200.h"
#include "string.h"
void proto_Transform_Task(void)
{
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef _PROTO_TRANSFORM_H_
#define _PROTO_TRANSFORM_H_
#include "main.h"
u8 proto_AA55_to_Modbus_Unit(u8 AA55_Uint);
u8 proto_Modbus_to_AA55_Unit(u8 Modbus_Uint);
void proto_Transform_Task(void);
#endif