leakage
This commit is contained in:
@@ -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));
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "app.h"
|
||||
#include "os_timer.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "bsp_Uart.h"
|
||||
#include "bsp_Wdg.h"
|
||||
#include "bsp_Led.h"
|
||||
#include "bsp_74HC4067.h"
|
||||
#include "bsp_Flash.h"
|
||||
#include "tjc_usart_hmi.h"
|
||||
|
||||
#include "proto_modbus_master_tdlas.h"
|
||||
#include "proto_modbus_slave_ex.h"
|
||||
|
||||
const char *HwVersion = "V1.0";
|
||||
char SwVersion[24] = "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)
|
||||
{
|
||||
Usr_Flash.Init();
|
||||
|
||||
COM_Uart1.Init(&COM_Uart1);
|
||||
COM_Uart2.Init(&COM_Uart2);
|
||||
COM_Uart4.Init(&COM_Uart4);
|
||||
Led.Init();
|
||||
UartCH_Config.init();
|
||||
|
||||
|
||||
|
||||
tdlas.init();
|
||||
modbus_slave_ex.init();
|
||||
TJC_Init(&COM_Uart2);
|
||||
initRingBuffer();
|
||||
char init_msg[] = "系统初始化...\r\n";
|
||||
HAL_UART_Transmit(COM_Uart2.Uart, (uint8_t*)init_msg, strlen(init_msg), 100);
|
||||
//Wdg.Init();
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* 函数: App_Task
|
||||
* 功能: 分时复用
|
||||
* 参数: 无
|
||||
* 返回: 无
|
||||
* 描述: 主循环中调用
|
||||
******************************************/
|
||||
void App_Task(void)
|
||||
{
|
||||
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_10ms, osTime_MSecTick, 10))
|
||||
{
|
||||
OsTimeTick_10ms = osTime_MSecTick;
|
||||
Task_10ms();
|
||||
}
|
||||
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_50ms, osTime_MSecTick, 50))
|
||||
{
|
||||
OsTimeTick_50ms = osTime_MSecTick;
|
||||
Task_50ms();
|
||||
}
|
||||
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_100ms, osTime_MSecTick, 100))
|
||||
{
|
||||
OsTimeTick_100ms = osTime_MSecTick;
|
||||
Task_100ms();
|
||||
}
|
||||
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_200ms, osTime_MSecTick, 200))
|
||||
{
|
||||
OsTimeTick_200ms = osTime_MSecTick;
|
||||
Task_200ms();
|
||||
}
|
||||
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_500ms, osTime_MSecTick, 500))
|
||||
{
|
||||
OsTimeTick_500ms = osTime_MSecTick;
|
||||
Task_500ms();
|
||||
}
|
||||
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_1s, osTime_MSecTick, 1000))
|
||||
{
|
||||
OsTimeTick_1s = osTime_MSecTick;
|
||||
Task_1s();
|
||||
}
|
||||
if (TIME_TRUE == OsTimer_CheckTimeOut(OsTimeTick_2s, osTime_MSecTick, 2000))
|
||||
{
|
||||
OsTimeTick_2s = osTime_MSecTick;
|
||||
Task_2s();
|
||||
}
|
||||
TASK_Idle();
|
||||
}
|
||||
/*空闲执行的函数*/
|
||||
void TASK_Idle(void)
|
||||
{
|
||||
COM_Uart1.Rx_Task(&COM_Uart1);
|
||||
COM_Uart2.Rx_Task(&COM_Uart2);
|
||||
COM_Uart4.Rx_Task(&COM_Uart4);
|
||||
}
|
||||
|
||||
void Task_10ms(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Task_50ms(void)
|
||||
{
|
||||
// tdlas.tx_task();
|
||||
}
|
||||
|
||||
void Task_100ms(void)
|
||||
{
|
||||
// tdlas.tx_task();
|
||||
}
|
||||
|
||||
void Task_200ms(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Task_500ms(void)
|
||||
{
|
||||
// UartCH_Config.ch_set(ch);
|
||||
// tdlas.tx_task();
|
||||
Led.Flash();
|
||||
}
|
||||
|
||||
|
||||
void Task_1s(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Task_2s(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _APP_H_
|
||||
#define _APP_H_
|
||||
|
||||
extern const char *HwVersion;
|
||||
extern char SwVersion[24];
|
||||
|
||||
void App_Init(void);
|
||||
void App_Task(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "gas_data.h"
|
||||
|
||||
gas_data_t gas_data[SENSOR_NUM];
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef _GAS_DATA_H__
|
||||
#define _GAS_DATA_H__
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define SENSOR_NUM 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 ver[20]; /*软件版本号*/
|
||||
u8 sn[20]; /*SN号*/
|
||||
u16 range; /*量程*/
|
||||
s16 value; /*浓度*/
|
||||
u16 pp_ad; /*峰峰值*/
|
||||
u16 r_pp_ad; /*原始峰峰值*/
|
||||
u16 pp_pix; /*峰峰值坐标*/
|
||||
u16 light_ad; /*光功率*/
|
||||
u16 tec_set_value; /*tec设定值*/
|
||||
u16 tec_temp; /*tec温度*/
|
||||
s16 temp; /*环境温度*/
|
||||
u16 light_ad_max; /*波形最大值*/
|
||||
u16 light_ad_min; /*波形最小值*/
|
||||
u16 state_code; /*状态码*/
|
||||
u16 dc_offset; /*直流偏置*/
|
||||
//u16 ad_befor_multiple; /*AD前放大倍数*/
|
||||
u16 demod_multiple; /*锁相放大倍数*/
|
||||
//u16 mode; /*模式状态*/
|
||||
s16 calib_temp; /*标定时的温度*/
|
||||
u16 calib_press; /*标定时的压力*/
|
||||
u16 calib_humidity; /*标定时的湿度*/
|
||||
u16 fac_calib_code_h;
|
||||
u16 fac_calib_code_l; /*厂家标定时的状态码*/
|
||||
u16 reserve[1]; /*预留*/
|
||||
}gas_data_t;
|
||||
|
||||
extern gas_data_t gas_data[SENSOR_NUM];
|
||||
|
||||
#endif
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "bsp_74HC4067.h"
|
||||
#include "os_timer.h"
|
||||
|
||||
/*两片74HC4067,一片TX 一片RX 每片16通道*/
|
||||
|
||||
#define BSP_74HC4067_CH_MAX 16
|
||||
|
||||
/*TX*/
|
||||
#define TX_EN_ENABLE HAL_GPIO_WritePin (TX_EN_GPIO_Port, TX_EN_Pin, GPIO_PIN_RESET)
|
||||
#define TX_EN_DISENABLE HAL_GPIO_WritePin (TX_EN_GPIO_Port, TX_EN_Pin, GPIO_PIN_SET)
|
||||
|
||||
/*RX*/
|
||||
#define RX_EN_ENABLE HAL_GPIO_WritePin (RX_EN_GPIO_Port, RX_EN_Pin, GPIO_PIN_RESET)
|
||||
#define RX_EN_DISENABLE HAL_GPIO_WritePin (RX_EN_GPIO_Port, RX_EN_Pin, GPIO_PIN_SET)
|
||||
|
||||
|
||||
/*LED通道指示*/
|
||||
#define LED_CH0_ON HAL_GPIO_WritePin (RX_S3_GPIO_Port, RX_S3_Pin, GPIO_PIN_RESET)
|
||||
#define LED_CH0_OFF HAL_GPIO_WritePin (RX_S3_GPIO_Port, RX_S3_Pin, GPIO_PIN_SET)
|
||||
|
||||
#define BSP_LOW GPIO_PIN_RESET
|
||||
#define BSP_HIG GPIO_PIN_SET
|
||||
|
||||
#define BSP_LED_ON GPIO_PIN_RESET
|
||||
#define BSP_LED_OFF GPIO_PIN_SET
|
||||
|
||||
static GPIO_TypeDef* bsp_74HC4067_TX_SW_GPIO[4] = {TX_S0_GPIO_Port,TX_S1_GPIO_Port,TX_S2_GPIO_Port,TX_S3_GPIO_Port};
|
||||
static uint16_t bsp_74HC4067_TX_SW_Pin[4] = {TX_S0_Pin, TX_S1_Pin, TX_S2_Pin, TX_S3_Pin};
|
||||
|
||||
static GPIO_TypeDef* bsp_74HC4067_RX_SW_GPIO[4] = {RX_S0_GPIO_Port,RX_S1_GPIO_Port,RX_S2_GPIO_Port,RX_S3_GPIO_Port};
|
||||
static uint16_t bsp_74HC4067_RX_SW_Pin[4] = {RX_S0_Pin, RX_S1_Pin, RX_S2_Pin, RX_S3_Pin};
|
||||
|
||||
static GPIO_TypeDef* bsp_74HC4067_LED_CH_GPIO[BSP_74HC4067_CH_MAX] = {LED_CH1_GPIO_Port, LED_CH2_GPIO_Port, LED_CH3_GPIO_Port, LED_CH4_GPIO_Port, LED_CH5_GPIO_Port, LED_CH6_GPIO_Port, LED_CH7_GPIO_Port, LED_CH8_GPIO_Port, LED_CH9_GPIO_Port, LED_CH10_GPIO_Port, LED_CH11_GPIO_Port, LED_CH12_GPIO_Port, LED_CH13_GPIO_Port, LED_CH14_GPIO_Port, LED_CH15_GPIO_Port, LED_CH16_GPIO_Port};
|
||||
static uint16_t bsp_74HC4067_LED_CH_Pin[BSP_74HC4067_CH_MAX] = {LED_CH1_Pin, LED_CH2_Pin, LED_CH3_Pin, LED_CH4_Pin, LED_CH5_Pin, LED_CH6_Pin, LED_CH7_Pin, LED_CH8_Pin, LED_CH9_Pin, LED_CH10_Pin, LED_CH11_Pin, LED_CH12_Pin, LED_CH13_Pin, LED_CH14_Pin, LED_CH15_Pin, LED_CH16_Pin};
|
||||
|
||||
/*通道转换,硬件实际连接的通道与芯片定义通道不一致*/
|
||||
static u8 bsp_74HC4067_TX_CH_Conv[BSP_74HC4067_CH_MAX] = {13,14,15,12,11,10,9, 8, 7, 4, 3, 2, 1, 0, 6, 5};
|
||||
static u8 bsp_74HC4067_RX_CH_Conv[BSP_74HC4067_CH_MAX] = {13,14,15,8, 9, 10,11,12,0, 1, 2, 3, 4, 5, 6, 7};
|
||||
|
||||
|
||||
static void bsp_74HC4067_Init(void);
|
||||
static void bsp_74HC4067_Set_CH(u8 CH);
|
||||
static u8 bsp_74HC4067_Get_CH(void);
|
||||
|
||||
static u8 bsp_74HC4067_CH;
|
||||
|
||||
bsp_74HC4067_t UartCH_Config =
|
||||
{
|
||||
.init = bsp_74HC4067_Init,
|
||||
.ch_set = bsp_74HC4067_Set_CH,
|
||||
.ch_get = bsp_74HC4067_Get_CH,
|
||||
};
|
||||
/*其他外设初始化后快速闪烁,提示初始化完成*/
|
||||
static void bsp_74HC4067_Init(void)
|
||||
{
|
||||
bsp_74HC4067_CH = 0;
|
||||
TX_EN_ENABLE;
|
||||
RX_EN_ENABLE;
|
||||
bsp_74HC4067_Set_CH(0);
|
||||
}
|
||||
|
||||
|
||||
//static u8 CH;
|
||||
static void bsp_74HC4067_Set_CH(u8 CH1)
|
||||
{
|
||||
u8 CH = 0;
|
||||
if(CH >= BSP_74HC4067_CH_MAX)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
u8 i,TX_CH,RX_CH;
|
||||
bsp_74HC4067_CH = CH;
|
||||
TX_CH = bsp_74HC4067_TX_CH_Conv[CH];
|
||||
RX_CH = bsp_74HC4067_RX_CH_Conv[CH];
|
||||
/*选择对应的通道输出*/
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
if((TX_CH >> i) & 0x01)
|
||||
{
|
||||
HAL_GPIO_WritePin(bsp_74HC4067_TX_SW_GPIO[i],bsp_74HC4067_TX_SW_Pin[i],BSP_HIG);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(bsp_74HC4067_TX_SW_GPIO[i],bsp_74HC4067_TX_SW_Pin[i],BSP_LOW);
|
||||
}
|
||||
if((RX_CH >> i) & 0x01)
|
||||
{
|
||||
HAL_GPIO_WritePin(bsp_74HC4067_RX_SW_GPIO[i],bsp_74HC4067_RX_SW_Pin[i],BSP_HIG);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(bsp_74HC4067_RX_SW_GPIO[i],bsp_74HC4067_RX_SW_Pin[i],BSP_LOW);
|
||||
}
|
||||
}
|
||||
/*开启对应指示灯*/
|
||||
for(i=0;i<BSP_74HC4067_CH_MAX;i++)
|
||||
{
|
||||
if(i == CH)
|
||||
{
|
||||
HAL_GPIO_WritePin(bsp_74HC4067_LED_CH_GPIO[i],bsp_74HC4067_LED_CH_Pin[i],BSP_LED_ON);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_GPIO_WritePin(bsp_74HC4067_LED_CH_GPIO[i],bsp_74HC4067_LED_CH_Pin[i],BSP_LED_OFF);
|
||||
}
|
||||
}
|
||||
// HAL_Delay(20);
|
||||
}
|
||||
|
||||
static u8 bsp_74HC4067_Get_CH(void)
|
||||
{
|
||||
return bsp_74HC4067_CH;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _BSP_74HC4067_H_
|
||||
#define _BSP_74HC4067_H_
|
||||
|
||||
#include "main.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*init)(void);
|
||||
void (*ch_set)(u8);
|
||||
u8 (*ch_get)(void);
|
||||
}bsp_74HC4067_t;
|
||||
|
||||
extern bsp_74HC4067_t UartCH_Config;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
#include "bsp_Delay.h"
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef _BSP_DELAY_H_
|
||||
#define _BSP_DELAY_H_
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
#include "bsp_Flash.h"
|
||||
#include "string.h"
|
||||
#include "bsp_Wdg.h"
|
||||
#include "gas_data.h"
|
||||
/* FLASH Memory Definitions */
|
||||
//#define BSP_FLASH_SIZE (0x100000UL)
|
||||
//#define BSP_FLASH_PAGE_SIZE (PAGESIZE)
|
||||
//#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)
|
||||
|
||||
//FLASH地址
|
||||
#define BSP_FLASH_SECTION_0_ADDR ((u32)0x08000000) //16k
|
||||
#define BSP_FLASH_SECTION_1_ADDR ((u32)0x08004000) //16k
|
||||
#define BSP_FLASH_SECTION_2_ADDR ((u32)0x08008000) //16k
|
||||
#define BSP_FLASH_SECTION_3_ADDR ((u32)0x0800C000) //16k
|
||||
#define BSP_FLASH_SECTION_4_ADDR ((u32)0x08010000) //64k
|
||||
#define BSP_FLASH_SECTION_5_ADDR ((u32)0x08020000) //128k
|
||||
#define BSP_FLASH_SECTION_6_ADDR ((u32)0x08040000) //128k
|
||||
#define BSP_FLASH_SECTION_7_ADDR ((u32)0x08060000) //128k
|
||||
#define BSP_FLASH_SECTION_8_ADDR ((u32)0x08080000) //128k
|
||||
#define BSP_FLASH_SECTION_9_ADDR ((u32)0x080A0000) //128k
|
||||
#define BSP_FLASH_SECTION_10_ADDR ((u32)0x080C0000) //128k
|
||||
#define BSP_FLASH_SECTION_11_ADDR ((u32)0x080E0000) //128k
|
||||
|
||||
#define BSP_FLASH_DATASAVE_ADDR BSP_FLASH_SECTION_11_ADDR//最后一片扇区 128k
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
bsp_Flash_t *p_Usr_Flash = &Usr_Flash;
|
||||
|
||||
// 擦除指定页
|
||||
static HAL_StatusTypeDef bsp_FLASH_ErasePage(uint32_t PageAddress)
|
||||
{
|
||||
//初始化FLASH_EraseInitTypeDef
|
||||
FLASH_EraseInitTypeDef f;
|
||||
|
||||
f.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||
f.Sector = FLASH_SECTOR_11;
|
||||
f.NbSectors = 1;
|
||||
f.VoltageRange = VOLTAGE_RANGE_3;
|
||||
//设置PageError
|
||||
uint32_t PageError = 0;
|
||||
//调用擦除函数
|
||||
return HAL_FLASHEx_Erase(&f, &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)
|
||||
{
|
||||
|
||||
bsp_FlashDataWrite();
|
||||
}
|
||||
|
||||
static void bsp_Flash_Init(void)
|
||||
{
|
||||
|
||||
bsp_FlashDataRead();
|
||||
if(p_Usr_Flash->FlashData.modbus_read_reg_num > 1000)
|
||||
p_Usr_Flash->FlashData.modbus_read_reg_num = sizeof(gas_data_t)/2;
|
||||
if(p_Usr_Flash->FlashData.modbus_read_sensor_num > SENSOR_NUM)
|
||||
p_Usr_Flash->FlashData.modbus_read_sensor_num = SENSOR_NUM;
|
||||
memcpy(&Usr_Flash.TempFlashData, &Usr_Flash.FlashData, sizeof(bsp_FlashData_t));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef _BSP_FLASH_H_
|
||||
#define _BSP_FLASH_H_
|
||||
|
||||
#include "main.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*用于判断数据是否一致*/
|
||||
u16 sn[5];
|
||||
u8 modbus_id;
|
||||
u16 modbus_read_reg_num;
|
||||
u16 modbus_read_sensor_num;
|
||||
} 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
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "bsp_Led.h"
|
||||
#include "os_timer.h"
|
||||
|
||||
#define LED1_ON HAL_GPIO_WritePin (LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET)
|
||||
#define LED1_OFF HAL_GPIO_WritePin (LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET)
|
||||
#define LED1_TOGGLE HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin)
|
||||
|
||||
#define LED2_ON HAL_GPIO_WritePin (LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET)
|
||||
#define LED2_OFF HAL_GPIO_WritePin (LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET)
|
||||
#define LED2_TOGGLE HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin)
|
||||
|
||||
#define LED3_ON HAL_GPIO_WritePin (LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET)
|
||||
#define LED3_OFF HAL_GPIO_WritePin (LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET)
|
||||
#define LED3_TOGGLE HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin)
|
||||
|
||||
|
||||
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(LED1_GPIO_Port, LED1_Pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void bsp_Led_Flash(void)
|
||||
{
|
||||
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,396 @@
|
||||
#include "bsp_Uart.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
//#define RS485_RX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_RESET)
|
||||
#define RS485_RX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_SET)
|
||||
#define RS485_TX HAL_GPIO_WritePin(RS485_EN_GPIO_Port, RS485_EN_Pin, GPIO_PIN_SET)
|
||||
|
||||
/*缓冲收发区*/
|
||||
#define RX_TEMP_BUFF_NUM (3000U)
|
||||
u8 Rx_Temp_Buff[RX_TEMP_BUFF_NUM];
|
||||
|
||||
#define UART1_TX_LEN (3000U)
|
||||
#define UART1_RX_LEN (3000U)
|
||||
|
||||
#define UART2_TX_LEN (3000U)
|
||||
#define UART2_RX_LEN (3000U)
|
||||
|
||||
#define UART4_TX_LEN (3000U)
|
||||
#define UART4_RX_LEN (3000U)
|
||||
|
||||
u8 Uart1_TX_Buff[UART1_TX_LEN];
|
||||
u8 Uart1_Rx_Buff[UART1_RX_LEN];
|
||||
|
||||
u8 Uart2_TX_Buff[UART2_TX_LEN];
|
||||
u8 Uart2_Rx_Buff[UART2_RX_LEN];
|
||||
|
||||
u8 Uart4_TX_Buff[UART4_TX_LEN];
|
||||
u8 Uart4_Rx_Buff[UART4_RX_LEN];
|
||||
|
||||
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_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_Task(bsp_Uart_t *p_Uart);
|
||||
static void bsp_Uart_Rx_TimeStart(bsp_Uart_t *p_Uart);
|
||||
static void bsp_Uart_Tx_DMA_TCInt(bsp_Uart_t *p_Uart);
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
extern UART_HandleTypeDef huart2;
|
||||
extern UART_HandleTypeDef huart4;
|
||||
|
||||
extern DMA_HandleTypeDef hdma_usart1_rx;
|
||||
extern DMA_HandleTypeDef hdma_usart1_tx;
|
||||
extern DMA_HandleTypeDef hdma_usart2_rx;
|
||||
extern DMA_HandleTypeDef hdma_usart2_tx;
|
||||
extern DMA_HandleTypeDef hdma_uart4_rx;
|
||||
extern DMA_HandleTypeDef hdma_uart4_tx;
|
||||
|
||||
bsp_Uart_t COM_Uart1 =
|
||||
{
|
||||
.RxQueue = queue(u8,UART1_RX_LEN),
|
||||
.Uart =&huart1,
|
||||
|
||||
.Tx_DMA = &hdma_usart1_tx,
|
||||
.Rx_DMA = &hdma_usart1_rx,
|
||||
|
||||
.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 = 0,
|
||||
|
||||
.relay.uart = NULL,
|
||||
|
||||
.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 =&huart2,
|
||||
|
||||
.Tx_DMA = &hdma_usart2_tx,
|
||||
.Rx_DMA = &hdma_usart2_rx,
|
||||
|
||||
.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 = 0,
|
||||
|
||||
.relay.uart = &COM_Uart4,
|
||||
|
||||
.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_Uart4 =
|
||||
{
|
||||
.RxQueue = queue(u8,UART4_RX_LEN),
|
||||
.Uart =&huart4,
|
||||
|
||||
.Tx_DMA = &hdma_uart4_tx,
|
||||
.Rx_DMA = &hdma_uart4_rx,
|
||||
|
||||
.Tx_DMA_Len = UART4_TX_LEN,
|
||||
.Rx_DMA_Len = UART4_RX_LEN,
|
||||
|
||||
.Tx_Addr = &Uart4_TX_Buff[0],
|
||||
.Rx_Addr = &Uart4_Rx_Buff[0],
|
||||
|
||||
.Tx_DMA_CompleteFlag = 1,
|
||||
.Rx_TimeOver = 0,
|
||||
|
||||
.relay.uart = NULL,
|
||||
|
||||
.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;
|
||||
|
||||
/* 启用空闲中断 */
|
||||
__HAL_UART_ENABLE_IT(p_Uart->Uart, UART_IT_IDLE);
|
||||
|
||||
/* 启动DMA接收 */
|
||||
//HAL_UART_Receive_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
|
||||
/* 重新启动接收 */
|
||||
HAL_UARTEx_ReceiveToIdle_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
|
||||
}
|
||||
|
||||
|
||||
static void bsp_Uart_DMASend(bsp_Uart_t *p_Uart,u8 *pData, u16 Len)
|
||||
{
|
||||
u32 tickstart,tick;
|
||||
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); /*拷贝数据到发送缓冲*/
|
||||
|
||||
// /*阻塞式发送,非阻塞式发送,会导致收发数据时正好切换通道的情况*/
|
||||
// HAL_UART_Transmit(p_Uart->Uart,p_Uart->Tx_Addr,Len,500);
|
||||
|
||||
|
||||
HAL_UART_Transmit_DMA(p_Uart->Uart,p_Uart->Tx_Addr,Len);
|
||||
tickstart = HAL_GetTick();
|
||||
while( !p_Uart->Tx_DMA_CompleteFlag)
|
||||
{
|
||||
tick = HAL_GetTick();
|
||||
if((tick - tickstart) > 200) // 1000ms 超时
|
||||
{
|
||||
p_Uart->Tx_DMA_CompleteFlag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*大数据量发送*/
|
||||
static void bsp_Uart_Send(bsp_Uart_t *p_Uart,u8 *pData, u16 Len)
|
||||
{
|
||||
u16 i,SendNum;
|
||||
|
||||
if(p_Uart == &COM_Uart4)
|
||||
RS485_TX;
|
||||
SendNum = Len / p_Uart->Tx_DMA_Len;
|
||||
for(i=0;i<SendNum;i++)
|
||||
{
|
||||
bsp_Uart_DMASend(p_Uart,&pData[p_Uart->Tx_DMA_Len * i], p_Uart->Tx_DMA_Len);
|
||||
}
|
||||
|
||||
/*发送剩余数据*/
|
||||
Len -= p_Uart->Tx_DMA_Len * i;
|
||||
if(0 == Len)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
else
|
||||
{
|
||||
bsp_Uart_DMASend(p_Uart,&pData[p_Uart->Tx_DMA_Len * i],Len);
|
||||
}
|
||||
}
|
||||
|
||||
static void bsp_Uart_Tx_DMA_TCInt(bsp_Uart_t *p_Uart)
|
||||
{
|
||||
p_Uart->Tx_DMA_CompleteFlag = 1;
|
||||
}
|
||||
|
||||
/*空闲接收中断*/
|
||||
static void bsp_Uart_Rx_IdleInt(bsp_Uart_t *p_Uart)
|
||||
{
|
||||
u16 Rx_Length, i;
|
||||
/*停止接收*/
|
||||
HAL_UART_DMAStop(p_Uart->Uart);
|
||||
|
||||
/* 计算接收到的数据长度 */
|
||||
Rx_Length = p_Uart->Rx_DMA_Len - __HAL_DMA_GET_COUNTER(p_Uart->Rx_DMA);
|
||||
|
||||
/* 如果长度为0,直接返回 */
|
||||
if (Rx_Length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* 入队 */
|
||||
for (i = 0; i < Rx_Length; i++)
|
||||
{
|
||||
queue_push_back(p_Uart->RxQueue, (void *)&p_Uart->Rx_Addr[i]);
|
||||
}
|
||||
/* 开始计数 */
|
||||
bsp_Uart_Rx_TimeStart(p_Uart);
|
||||
// HAL_UART_Receive_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
|
||||
HAL_UARTEx_ReceiveToIdle_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*中断计数*/
|
||||
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_Temp_Buff,p_Uart->Rx_Len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 错误回调函数中处理ORE
|
||||
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
bsp_Uart_t *p_Uart = NULL;
|
||||
if (huart->Instance == USART1)
|
||||
{
|
||||
p_Uart = &COM_Uart1;
|
||||
}
|
||||
else if (huart->Instance == USART2)
|
||||
{
|
||||
p_Uart = &COM_Uart2;
|
||||
}
|
||||
else if (huart->Instance == UART4)
|
||||
{
|
||||
p_Uart = &COM_Uart4;
|
||||
}
|
||||
|
||||
// 检查具体错误类型
|
||||
if(huart->ErrorCode & HAL_UART_ERROR_NE)
|
||||
{
|
||||
// 处理噪声错误
|
||||
__HAL_UART_CLEAR_NEFLAG(huart);
|
||||
}
|
||||
if(huart->ErrorCode & HAL_UART_ERROR_FE)
|
||||
{
|
||||
// 处理帧错误
|
||||
__HAL_UART_CLEAR_FEFLAG(huart);
|
||||
}
|
||||
// 其他错误处理...
|
||||
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET)
|
||||
{
|
||||
__HAL_UART_CLEAR_OREFLAG(huart); // 清除ORE标志
|
||||
}
|
||||
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET)
|
||||
{
|
||||
__HAL_UART_CLEAR_FEFLAG(huart); // 清除ORE标志
|
||||
}
|
||||
|
||||
//
|
||||
if(p_Uart != NULL)
|
||||
{
|
||||
// HAL_UART_DeInit(huart);
|
||||
// HAL_UART_Init(huart);
|
||||
// HAL_UART_DMAStop(p_Uart->Uart);
|
||||
HAL_UARTEx_ReceiveToIdle_DMA(p_Uart->Uart, p_Uart->Rx_Addr, p_Uart->Rx_DMA_Len);
|
||||
}
|
||||
}
|
||||
|
||||
// 实现空闲中断回调
|
||||
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
|
||||
{
|
||||
if (huart->Instance == USART1)
|
||||
{
|
||||
bsp_Uart_Rx_IdleInt(&COM_Uart1);
|
||||
}
|
||||
else if (huart->Instance == USART2)
|
||||
{
|
||||
bsp_Uart_Rx_IdleInt(&COM_Uart2);
|
||||
}
|
||||
else if (huart->Instance == UART4)
|
||||
{
|
||||
bsp_Uart_Rx_IdleInt(&COM_Uart4);
|
||||
}
|
||||
}
|
||||
|
||||
/* 串口接收完成回调函数 - 处理空闲中断 */
|
||||
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
|
||||
// {
|
||||
// __HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
|
||||
// if (huart->Instance == USART1)
|
||||
// {
|
||||
// bsp_Uart_Rx_IdleInt(&COM_Uart1);
|
||||
// }
|
||||
// else if (huart->Instance == USART2)
|
||||
// {
|
||||
// bsp_Uart_Rx_IdleInt(&COM_Uart2);
|
||||
// }
|
||||
// else if (huart->Instance == UART4)
|
||||
// {
|
||||
// bsp_Uart_Rx_IdleInt(&COM_Uart4);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
if (huart->Instance == USART1)
|
||||
{
|
||||
COM_Uart1.Tx_DMA_TCInt(&COM_Uart1);
|
||||
}
|
||||
else if (huart->Instance == USART2)
|
||||
{
|
||||
COM_Uart2.Tx_DMA_TCInt(&COM_Uart2);
|
||||
}
|
||||
else if (huart->Instance == UART4)
|
||||
{
|
||||
RS485_RX;
|
||||
COM_Uart4.Tx_DMA_TCInt(&COM_Uart4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef _BSP_UART_H_
|
||||
#define _BSP_UART_H_
|
||||
|
||||
#include "main.h"
|
||||
#include "algo_Queue.h"
|
||||
|
||||
typedef struct bsp_Uart_t bsp_Uart_t;
|
||||
|
||||
|
||||
#define usart_type UART_HandleTypeDef
|
||||
#define dma_type DMA_HandleTypeDef
|
||||
|
||||
/*串口转发*/
|
||||
typedef struct
|
||||
{
|
||||
u8 flag; /*串口转发标志位*/
|
||||
bsp_Uart_t *uart; /*转发出去的串口*/
|
||||
u16 time_out; /*转发超时时间*/
|
||||
}bsp_uart_relay_t;
|
||||
|
||||
struct bsp_Uart_t
|
||||
{
|
||||
queue RxQueue; /*数据接收队列*/
|
||||
usart_type *Uart; /*串口*/
|
||||
|
||||
dma_type *Tx_DMA; /*DMA*/
|
||||
dma_type *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; /*开始超时计数标志位*/
|
||||
|
||||
|
||||
bsp_uart_relay_t relay; /*串口转发*/
|
||||
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;
|
||||
extern bsp_Uart_t COM_Uart4;
|
||||
#endif
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,104 @@
|
||||
#ifndef _SYS_H_
|
||||
#define _SYS_H_
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
|
||||
//定义一些常用的数据类型短关键字
|
||||
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 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
||||
#ifndef __TJCUSARTHMI_H_
|
||||
#define __TJCUSARTHMI_H_
|
||||
|
||||
#include "stm32f4xx.h"
|
||||
#include "main.h" // 包含 HAL 库头文件
|
||||
#include "bsp_Uart.h"
|
||||
#include "bsp_Flash.h" // 添加Flash操作支持
|
||||
|
||||
// 定义使用的串口句柄(在main.c中定义的huart2)
|
||||
extern UART_HandleTypeDef huart2;
|
||||
|
||||
// 定义串口屏使用的串口
|
||||
#define TJC_UART huart2
|
||||
|
||||
// 环形缓冲区长度
|
||||
#define RINGBUFF_LEN (500)
|
||||
|
||||
// 指令结束符(TJC串口屏协议)
|
||||
#define TJC_END_BYTES 0xFF
|
||||
|
||||
// 最大指令长度
|
||||
#define MAX_COMMAND_LEN 200 // 增加长度以适应设备信息
|
||||
|
||||
// 自定义指令定义
|
||||
#define CUSTOM_CMD_HEADER_0 0xAA
|
||||
#define CUSTOM_CMD_HEADER_1 0x55
|
||||
|
||||
// 指令类型
|
||||
#define CMD_DISPLAY_DATA 0x02 // 显示数据
|
||||
#define CMD_ALARM 0x03 // 报警
|
||||
#define CMD_DELETE_DEVICE 0x04 // 删除设备
|
||||
|
||||
// 显示数据子命令
|
||||
#define SUB_CMD_SHOW_DEVICES 0x01 // 显示已添加的设备
|
||||
#define SUB_CMD_REGION_STATS 0x02 // 主界面区域显示
|
||||
#define SUB_CMD_REGION1_DEVICES 0x03 // 第一个区域设备
|
||||
#define SUB_CMD_REGION2_DEVICES 0x04 // 第二个区域设备
|
||||
#define SUB_CMD_REGION3_DEVICES 0x05 // 第三个区域设备
|
||||
#define SUB_CMD_REGION4_DEVICES 0x06 // 第四个区域设备
|
||||
|
||||
// 报警子命令
|
||||
#define SUB_CMD_HISTORY_ALARM 0x01 // 历史报警
|
||||
#define SUB_CMD_REALTIME_ALARM 0x02 // 实时报警
|
||||
|
||||
// 添加设备指令识别
|
||||
#define ADD_DEVICE_CMD_BYTE 0x43 // 'C'的ASCII码
|
||||
|
||||
// 分隔符
|
||||
#define DATA_SEPARATOR 0xAA
|
||||
|
||||
// 通信状态枚举
|
||||
typedef enum {
|
||||
COMM_STATUS_NORMAL = 0, // 正常
|
||||
COMM_STATUS_ABNORMAL // 异常
|
||||
} CommStatus;
|
||||
|
||||
// 漏液状态枚举
|
||||
typedef enum {
|
||||
LEAK_NORMAL = 0, // 正常
|
||||
LEAK_ABNORMAL // 漏液
|
||||
} LeakStatus;
|
||||
|
||||
// 断带状态枚举
|
||||
typedef enum {
|
||||
BREAK_NORMAL = 0, // 正常
|
||||
BREAK_ABNORMAL // 断带
|
||||
} BreakStatus;
|
||||
|
||||
// 通道状态结构体
|
||||
typedef struct {
|
||||
LeakStatus leak_status; // 漏液状态
|
||||
BreakStatus break_status; // 断带状态
|
||||
int leak_meter; // 漏液米数(如果漏液状态为漏液,则显示具体米数,否则显示0)
|
||||
} ChannelStatus;
|
||||
|
||||
// 报警类型枚举
|
||||
typedef enum {
|
||||
ALARM_LEAK = 0, // 漏液
|
||||
ALARM_BREAK, // 断带
|
||||
ALARM_COMM // 通信异常
|
||||
} AlarmType;
|
||||
|
||||
// 设备信息结构体
|
||||
typedef struct {
|
||||
uint8_t port; // 端口号
|
||||
char region[20]; // 区域名(英文)
|
||||
uint8_t device_id; // 设备ID (1-254)
|
||||
char device_name[20]; // 设备名(英文)
|
||||
LeakStatus leak_status; // 漏液状态
|
||||
BreakStatus break_status; // 断带状态
|
||||
CommStatus comm_status; // 通信状态
|
||||
ChannelStatus channels[4]; // 四个通道的状态
|
||||
} DeviceInfo;
|
||||
|
||||
// 报警信息结构体
|
||||
typedef struct {
|
||||
char region[20]; // 设备区域
|
||||
uint8_t device_id; // 设备ID
|
||||
char device_name[20]; // 设备名称
|
||||
AlarmType alarm_type; // 报警类型
|
||||
char start_time[20]; // 开始时间
|
||||
char end_time[20]; // 结束时间
|
||||
} AlarmInfo;
|
||||
|
||||
// 区域统计结构体
|
||||
typedef struct {
|
||||
char region_name[20]; // 区域名
|
||||
uint8_t total_devices; // 总设备数量
|
||||
uint8_t leak_devices; // 漏液设备数量
|
||||
uint8_t break_devices; // 断带设备数量
|
||||
uint8_t comm_devices; // 通信异常设备数量
|
||||
} RegionStats;
|
||||
|
||||
// 外部可调用函数的声明
|
||||
void TJC_Init(bsp_Uart_t *pUart);
|
||||
void TJC_SendData(uint8_t *data, uint16_t len);
|
||||
void TJCPrintf(const char *cmd, ...);
|
||||
|
||||
// 环形缓冲区相关函数
|
||||
uint16_t TJC_CleanBufferFromInvalidPatterns(void);
|
||||
void initRingBuffer(void);
|
||||
void writeRingBuff(uint8_t data);
|
||||
void deleteRingBuff(uint16_t size);
|
||||
uint16_t getRingBuffLength(void);
|
||||
uint8_t read1BFromRingBuff(uint16_t position);
|
||||
uint8_t isRingBuffOverflow(void);
|
||||
|
||||
// 指令处理相关函数
|
||||
void TJC_ProcessCommand(uint8_t *cmd, uint16_t len);
|
||||
uint8_t TJC_CheckEndBytes(uint8_t *data, uint16_t len, uint16_t *end_pos);
|
||||
void TJC_SendResponse(const char *response);
|
||||
void TJC_ProcessSerialData(u8 *data, u16 len, void *p_arg);
|
||||
void TJC_DeleteDevices(uint8_t *delete_flags, uint8_t flag_count);
|
||||
void TJC_ProcessDeleteCommand(uint8_t *cmd, uint16_t len);
|
||||
|
||||
/*测试发送历史报警数据*/
|
||||
void TJC_SendInitCommands(void);
|
||||
|
||||
// 新增函数声明
|
||||
uint16_t CalculateCRC16(uint8_t *data, uint16_t length);
|
||||
void TJC_ProcessCustomCommand(uint8_t *cmd, uint16_t len);
|
||||
void TJC_SendAlarmHistory(void);
|
||||
void TJC_SendRealtimeAlarms(void);
|
||||
void TJC_SendDeviceList(void);
|
||||
uint8_t TJC_AddDeviceToFlash(uint8_t *data, uint16_t len);
|
||||
void TJC_SendRegionStats(void); // 新增:发送区域统计
|
||||
void TJC_SendRegionDeviceDetails(uint8_t region_index);
|
||||
|
||||
// 宏定义简化
|
||||
#define usize getRingBuffLength()
|
||||
#define code_c() initRingBuffer()
|
||||
#define udelete(x) deleteRingBuff(x)
|
||||
#define u(x) read1BFromRingBuff(x)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,300 @@
|
||||
#include "proto_modbus_lib.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "bsp_Uart.h"
|
||||
|
||||
/**************************************************
|
||||
*名称: modbus_lib_crc16
|
||||
*功能: modbus crc16校验
|
||||
*参数: p_data -- 校验数据指针
|
||||
* len -- 数据长度
|
||||
*返回: 校验结果(小端序)
|
||||
**************************************************/
|
||||
u16 modbus_lib_crc16(u8 *p_data, u16 len)
|
||||
{
|
||||
u16 crc16 = 0xffff;
|
||||
u16 i;
|
||||
while(len--)
|
||||
{
|
||||
crc16 = crc16^(*p_data++);
|
||||
for(i=0; i++<8; )
|
||||
{
|
||||
if(crc16&0x0001)
|
||||
{
|
||||
crc16 = (crc16>>1)^0xa001;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc16>>=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc16;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* 函数: Float2u16
|
||||
* 功能: 提取浮点数的高16或低16位
|
||||
* 参数: float_data : 要转换的浮点数
|
||||
h_l : 返回高16位还是低16位
|
||||
* 返回: 返回对应的高16位还是低16位
|
||||
* 描述: 无
|
||||
******************************************/
|
||||
u16 float_to_u16(float float_data,unsigned char h_l)
|
||||
{
|
||||
u16 temp = 0XFFFF;
|
||||
if(h_l == U16_DATA_L)
|
||||
{
|
||||
temp = *((u32 *)&float_data) & 0x0000ffff;
|
||||
}
|
||||
else if(h_l == U16_DATA_H)
|
||||
{
|
||||
temp = ((*((u32 *)&float_data)) >> 16) & 0x0000ffff;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* 函数: u32TOu16
|
||||
* 功能: 提取u32的高16或低16位
|
||||
* 参数: u32_data : 要转换的u32
|
||||
h_l : 返回高16位还是低16位
|
||||
* 返回: 返回对应的高16位还是低16位
|
||||
* 描述: 无
|
||||
******************************************/
|
||||
u16 u32_to_u16(u32 u32_data,unsigned char h_l)
|
||||
{
|
||||
u16 temp = 0XFFFF;
|
||||
if(h_l == U16_DATA_L)
|
||||
{
|
||||
temp = u32_data & 0x0000ffff;
|
||||
}
|
||||
else if(h_l == U16_DATA_H)
|
||||
{
|
||||
temp = (u32_data >> 16) & 0x0000ffff;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
void u32_to_u8(u32 u32_data,u8 *p_data,u8 endian)
|
||||
{
|
||||
if(BIG_ENDIAN == endian)
|
||||
{
|
||||
for(u8 i = 0;i < 4;i++)
|
||||
{
|
||||
p_data[i] = (u32_data >> (8 * (3 - i))) & 0xff;
|
||||
}
|
||||
}
|
||||
else if(LITTLE_ENDIAN == endian)
|
||||
{
|
||||
for(u8 i = 0;i < 4;i++)
|
||||
{
|
||||
p_data[i] = (u32_data >> (8 * i)) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void u16_to_u8(u16 u16_data,u8 *p_data,u8 endian)
|
||||
{
|
||||
if(BIG_ENDIAN == endian)
|
||||
{
|
||||
for(u8 i = 0;i < 2;i++)
|
||||
{
|
||||
p_data[i] = (u16_data >> (8 * (1 - i))) & 0xff;
|
||||
}
|
||||
}
|
||||
else if(LITTLE_ENDIAN == endian)
|
||||
{
|
||||
for(u8 i = 0;i < 2;i++)
|
||||
{
|
||||
p_data[i] = (u16_data >> (8 * i)) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float u32_to_float(u32 u32_data,unsigned char h_l)
|
||||
{
|
||||
float temp = 0;
|
||||
temp = *((float *)&u32_data);
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*将u8_endian端序的p_u8data转换为单片机对应的小端序*/
|
||||
u32 u8_to_u32(u8 *p_u8data,unsigned char u8_endian)
|
||||
{
|
||||
u32 temp = 0;
|
||||
if(BIG_ENDIAN == u8_endian)
|
||||
{
|
||||
for(u8 i = 0;i < 4;i++)
|
||||
{
|
||||
temp |= p_u8data[i] << ((3 - i) * 8);
|
||||
}
|
||||
}
|
||||
else if(LITTLE_ENDIAN == u8_endian)
|
||||
{
|
||||
for(u8 i = 0;i < 4;i++)
|
||||
{
|
||||
temp |= p_u8data[i] << (i * 8);
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*将u8_endian端序的p_u8data转换为单片机对应的小端序*/
|
||||
u16 u8_to_u16(u8 *p_u8data,unsigned char u8_endian)
|
||||
{
|
||||
u32 temp = 0;
|
||||
if(BIG_ENDIAN == u8_endian)
|
||||
{
|
||||
for(u8 i = 0;i < 2;i++)
|
||||
{
|
||||
temp |= p_u8data[i] << ((1 - i) * 8);
|
||||
}
|
||||
}
|
||||
else if(LITTLE_ENDIAN == u8_endian)
|
||||
{
|
||||
for(u8 i = 0;i < 2;i++)
|
||||
{
|
||||
temp |= p_u8data[i] << (i * 8);
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*字节端序转换*/
|
||||
u32 u32_endian_conv(u32 data)
|
||||
{
|
||||
u32 temp = 0;
|
||||
temp = (((data >> 0 ) & 0xff) << 24)
|
||||
| (((data >> 8 ) & 0xff) << 16)
|
||||
| (((data >> 16) & 0xff) << 8 )
|
||||
| (((data >> 24) & 0xff) << 0 );
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*字节端序转换*/
|
||||
u16 u16_endian_conv(u16 data)
|
||||
{
|
||||
u16 temp = 0;
|
||||
temp = (((data >> 0) & 0xff) << 8)
|
||||
| (((data >> 8) & 0xff) << 0);
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
/******************************************
|
||||
* 函数: ModbusReaddata
|
||||
* 功能: MODBUS读数据
|
||||
* 参数: Id :MODBUS从机地址
|
||||
* addr :写数据的起始地址
|
||||
* Num :写的寄存器数量
|
||||
* send :串口发送函数
|
||||
* 返回: 无
|
||||
* 描述: 无
|
||||
******************************************/
|
||||
void modbus_lib_data_read(u8 id,u16 addr,u16 num,void (*send)(u8 *,u16 ))
|
||||
{
|
||||
u8 tx[8];
|
||||
u16 crc16;
|
||||
tx[0] = id;
|
||||
tx[1] = 0x41;//0x03;
|
||||
tx[2] = (addr >> 8) & 0xff;
|
||||
tx[3] = addr & 0xff;
|
||||
tx[4] = (num >> 8) & 0xff;
|
||||
tx[5] = num & 0xff;
|
||||
crc16 = modbus_lib_crc16(tx,6);
|
||||
tx[6] = crc16 & 0xff;
|
||||
tx[7] = (crc16 >> 8) & 0xff;
|
||||
send(tx,8);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* 函数: modbus_multiple_data_write
|
||||
* 功能: MODBUS写数据
|
||||
* 参数: Id :MODBUS从机地址
|
||||
* addr :写数据的起始地址
|
||||
* Num :写的寄存器数量
|
||||
* data :写的数据
|
||||
* send :串口发送函数
|
||||
* 返回: 无
|
||||
* 描述: 无
|
||||
******************************************/
|
||||
void modbus_lib_multiple_data_write(u8 id,u16 addr,u16 Num,u16 *data,void (*send)(u8 *,u16 ))
|
||||
{
|
||||
u8 tx[50];
|
||||
u16 crc16,i;
|
||||
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 = modbus_lib_crc16(tx,7 + 2 * i);
|
||||
tx[7 + 2 * i] = crc16 & 0xff;
|
||||
tx[8 + 2 * i] = (crc16 >> 8) & 0xff;
|
||||
send(tx,9 + 2 * i);
|
||||
}
|
||||
|
||||
void modbus_lib_only_data_write(u8 id,u16 addr,u16 value,void (*send)(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 = modbus_lib_crc16(tx,6);
|
||||
tx[6] = crc16 & 0xff;
|
||||
tx[7] = (crc16 >> 8) & 0xff;
|
||||
send(tx,8);
|
||||
}
|
||||
|
||||
|
||||
//01 10 00 02 00 01 02 12 34 CRC
|
||||
//id Func Startaddress RegNumber wdataaddress
|
||||
u8 modbus_lib_analysis(modbus_analysis_data_t *p_modbus, u8 *p_data, u16 len)
|
||||
{
|
||||
u16 crc16;
|
||||
u16 u16_temp;
|
||||
|
||||
if(NULL == p_modbus) return 0;
|
||||
if(len < 8) return 0;
|
||||
|
||||
crc16 = modbus_lib_crc16(p_data, len-2);
|
||||
u16_temp = *(p_data+len-1);
|
||||
u16_temp <<= 8;
|
||||
u16_temp |= *(p_data+len-2);
|
||||
if(u16_temp != crc16) return 0;
|
||||
|
||||
p_modbus->id = *p_data;
|
||||
p_modbus->func = *(p_data+1);
|
||||
|
||||
p_modbus->start_addr = (*(p_data+2))<<8;
|
||||
p_modbus->start_addr |= *(p_data+3);
|
||||
|
||||
/*单独写一个寄存器*/
|
||||
if(0x06 == p_modbus->func)
|
||||
{
|
||||
p_modbus->write_data_addr = p_data+4;
|
||||
}
|
||||
else if(0x10 == p_modbus->func) /*写多个寄存器*/
|
||||
{
|
||||
p_modbus->reg_number = (*(p_data+4))<<8;
|
||||
p_modbus->reg_number |= *(p_data+5);
|
||||
p_modbus->write_data_addr = p_data+7;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_modbus->reg_number = (*(p_data+4))<<8;
|
||||
p_modbus->reg_number |= *(p_data+5);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef _PROTO_MODBUS_LIB_H_
|
||||
#define _PROTO_MODBUS_LIB_H_
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define MODBUS_DEFAULT_ID (0x01)
|
||||
#define MODBUS_SENDBUF_LEN (2048U)
|
||||
|
||||
#define U16_DATA_L (0)//低16位
|
||||
#define U16_DATA_H (1)//高16位
|
||||
|
||||
#define BIG_ENDIAN (0)//大端序
|
||||
#define LITTLE_ENDIAN (1)//小端序
|
||||
|
||||
typedef struct {
|
||||
u8 send_buffer[MODBUS_SENDBUF_LEN];
|
||||
u16 len;
|
||||
}modbus_communication_send_buf_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 id; /*ModbusID*/
|
||||
u8 func; /*功能号*/
|
||||
u16 start_addr; /*起始地址*/
|
||||
u16 reg_number; /*寄存器数量*/
|
||||
u8 *write_data_addr; /*写入寄存器数据地址*/
|
||||
}modbus_analysis_data_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ModbusErrorCode_Success = 0x00,
|
||||
ModbusErrorCode_IllegalFunction = 0x01,
|
||||
ModbusErrorCode_IllegalAddr = 0x02,
|
||||
ModbusErrorCode_IllegalData = 0x03,
|
||||
ModbusErrorCode_DeviceBusy = 0x06
|
||||
}modbus_error_code_e;
|
||||
|
||||
typedef struct proto_Modbus_t proto_Modbus_t;
|
||||
struct proto_Modbus_t
|
||||
{
|
||||
u8 id;
|
||||
u16 (*data_read)(u16); /*Modbus读数据*/
|
||||
modbus_error_code_e (*data_write)(u16,u16); /*Modbus写数据*/
|
||||
void (*init)(void); /*初始化函数*/
|
||||
void (*task)(void); /*任务函数*/
|
||||
void (*data_analysis)(u8 *,u16,void *); /*数据解析*/
|
||||
};
|
||||
|
||||
|
||||
u16 float_to_u16(float float_data,u8 h_l);
|
||||
u16 u32_to_u16(u32 u32_Data,u8 h_l);
|
||||
u32 u8_to_u32(u8 *p_u8_Data,u8 endian);
|
||||
u16 u8_to_u16(u8 *p_u8_Data,u8 endian);
|
||||
|
||||
void u32_to_u8(u32 u32_Data,u8 *p_data,u8 endian);
|
||||
void u16_to_u8(u16 u16_Data,u8 *p_data,u8 endian);
|
||||
|
||||
u32 u32_endian_conv(u32 data);
|
||||
u16 u16_endian_conv(u16 data);
|
||||
|
||||
u16 modbus_lib_crc16(u8 *p_data, u16 len);
|
||||
void modbus_lib_data_read(u8 Id,u16 Addr,u16 Num,void (*UsartSendBuffer)(u8 *,u16 ));
|
||||
void modbus_lib_multiple_data_write(u8 ID,u16 Addr,u16 Num,u16 *Data,void (*UsartSendBuffer)(u8 *,u16 ));
|
||||
void modbus_lib_only_data_write(u8 ID,u16 Addr,u16 Value,void (*UsartSendBuffer)(u8 *,u16 ));
|
||||
u8 modbus_lib_analysis(modbus_analysis_data_t *p_modbus, u8 *p_data, u16 len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,412 @@
|
||||
#include "proto_modbus_master_tdlas.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "os_timer.h"
|
||||
|
||||
#include "bsp_Uart.h"
|
||||
#include "bsp_74HC4067.h"
|
||||
#include "bsp_Flash.h"
|
||||
|
||||
#include "proto_print.h"
|
||||
#include "proto_modbus_lib.h"
|
||||
|
||||
#define TDLAS_MODBUS_ID (0xe8)
|
||||
#define TDLAS_DATA_ENDIAN (LITTLE_ENDIAN) /*配置大小端序*/
|
||||
|
||||
#define PROTO_TDLAS_GET_CURR_DATA_START_ADDR (20000)
|
||||
#define PROTO_TDLAS_SET_ZERO_CALIB_START_ADDR (12)
|
||||
#define PROTO_TDLAS_SET_SPAN_CALIB_START_ADDR (13)
|
||||
#define PROTO_TDLAS_GET_RESET_START_ADDR (0x0000)
|
||||
#define PROTO_TDLAS_GET_FAC_CALIB_START_ADDR (11010)
|
||||
#define PROTO_TDLAS_GET_FAC_CALIB_PARA_SET_START_ADDR (11000)
|
||||
#define PROTO_TDLAS_GET_FAC_CALIB_DATA_START_ADDR (250)
|
||||
|
||||
|
||||
static void proto_tdlas_init(void);
|
||||
static void proto_tdlas_control_zero_calib(u16 calib_value);
|
||||
|
||||
static void proto_tdlas_control_span_calib(u16 CalibValue);
|
||||
static void proto_tdlas_control_reset(void);
|
||||
static void proto_tdlas_control_fac_calib(u16 calib_value,u8 calib_point,u8 temp_point);
|
||||
static void proto_tdlas_control_fac_calib_para_set(s16 temp,u16 press,u16 humidity);
|
||||
static void proto_tdlas_tx_task(void);
|
||||
static void proto_tdlas_rx_task(u8 *p_data,u16 len,void *other_data);
|
||||
static void proto_tdlas_control_fac_calib_data_get(u8 ch);
|
||||
|
||||
/*是哪个串口接收的数据*/
|
||||
static bsp_Uart_t *rx_uart = NULL;
|
||||
|
||||
proto_tdlas_t tdlas=
|
||||
{
|
||||
.modbus_id = TDLAS_MODBUS_ID,
|
||||
|
||||
.init = proto_tdlas_init,
|
||||
.tx_task = proto_tdlas_tx_task,
|
||||
.rx_task = proto_tdlas_rx_task,
|
||||
// .print = proto_tdlas_print_debug_data,
|
||||
|
||||
.control.zero_calib = proto_tdlas_control_zero_calib,
|
||||
.control.span_calib = proto_tdlas_control_span_calib,
|
||||
.control.reset = proto_tdlas_control_reset,
|
||||
.control.fac_calib = proto_tdlas_control_fac_calib,
|
||||
.control.fac_calib_para_set = proto_tdlas_control_fac_calib_para_set,
|
||||
.control.fac_calib_data_get = proto_tdlas_control_fac_calib_data_get,
|
||||
};
|
||||
|
||||
proto_tdlas_t *p_sensor = &tdlas;
|
||||
bsp_Uart_t *p_use_uart = &COM_Uart4;
|
||||
|
||||
static void proto_tdlas_init(void)
|
||||
{
|
||||
COM_Uart4.Rx_DataAnalysis = p_sensor->rx_task;
|
||||
}
|
||||
|
||||
static void proto_tdlas_send(u8 *p_data,u16 len)
|
||||
{
|
||||
COM_Uart4.Send(&COM_Uart4,p_data,len);
|
||||
}
|
||||
|
||||
static void proto_sensor_switch(u8 ch)
|
||||
{
|
||||
UartCH_Config.ch_set(ch);
|
||||
}
|
||||
|
||||
/*零点校准*/
|
||||
static void proto_tdlas_control_zero_calib(u16 calib_value)
|
||||
{
|
||||
u8 i;
|
||||
for(i=0;i<Usr_Flash.FlashData.modbus_read_sensor_num;i++)
|
||||
{
|
||||
p_sensor->sys[i].sys_state = PROTO_TDLAS_SYS_STATE_ZERO_CALIB;
|
||||
p_sensor->set_data.calib_value = calib_value;
|
||||
}
|
||||
}
|
||||
|
||||
/*量程校准 */
|
||||
static void proto_tdlas_control_span_calib(u16 CalibValue)
|
||||
{
|
||||
u8 i;
|
||||
for(i=0;i<Usr_Flash.FlashData.modbus_read_sensor_num;i++)
|
||||
{
|
||||
p_sensor->sys[i].sys_state = PROTO_TDLAS_SYS_STATE_SPAN_CALIB;
|
||||
p_sensor->set_data.calib_value = CalibValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*恢复出厂设置 */
|
||||
static void proto_tdlas_control_reset(void)
|
||||
{
|
||||
u8 i;
|
||||
for(i=0;i<Usr_Flash.FlashData.modbus_read_sensor_num;i++)
|
||||
{
|
||||
p_sensor->sys[i].sys_state = PROTO_TDLAS_SYS_STATE_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*厂家标定*/
|
||||
static void proto_tdlas_control_fac_calib(u16 calib_value,u8 calib_point,u8 temp_point)
|
||||
{
|
||||
u8 i;
|
||||
for(i=0;i<Usr_Flash.FlashData.modbus_read_sensor_num;i++)
|
||||
{
|
||||
p_sensor->sys[i].sys_state = PROTO_TDLAS_SYS_STATE_FAC_CALIB;
|
||||
p_sensor->set_data.calib_value = calib_value;
|
||||
p_sensor->set_data.calib_point = calib_point;
|
||||
p_sensor->set_data.temp_point = temp_point;
|
||||
}
|
||||
}
|
||||
|
||||
/*环境参数设置*/
|
||||
static void proto_tdlas_control_fac_calib_para_set(s16 temp,u16 press,u16 humidity)
|
||||
{
|
||||
u8 i;
|
||||
for(i=0;i<Usr_Flash.FlashData.modbus_read_sensor_num;i++)
|
||||
{
|
||||
p_sensor->sys[i].sys_state = PROTO_TDLAS_SYS_STATE_FAC_CALIB_PARA_SET;
|
||||
p_sensor->set_data.temp = (-1 == temp) ? p_sensor->set_data.temp : temp;
|
||||
p_sensor->set_data.humidity = (0xffff == humidity) ? p_sensor->set_data.humidity : humidity;
|
||||
p_sensor->set_data.press = (0xffff == press) ? p_sensor->set_data.press : press;
|
||||
}
|
||||
}
|
||||
|
||||
/*获取标定数据*/
|
||||
static void proto_tdlas_control_fac_calib_data_get(u8 ch)
|
||||
{
|
||||
if(Usr_Flash.FlashData.modbus_read_sensor_num > ch)
|
||||
{
|
||||
p_sensor->sensor_index = ch;
|
||||
p_sensor->sys[ch].sys_state = PROTO_TDLAS_SYS_STATE_FAC_CALIB_DATA_GET;
|
||||
proto_sensor_switch(ch);
|
||||
}
|
||||
}
|
||||
|
||||
/********发送***********/
|
||||
static void proto_tdlas_tx_curr_data_get(void)
|
||||
{
|
||||
u16 addr = PROTO_TDLAS_GET_CURR_DATA_START_ADDR;
|
||||
u8 len = Usr_Flash.FlashData.modbus_read_reg_num;
|
||||
modbus_lib_data_read(p_sensor->modbus_id,addr,len,proto_tdlas_send);
|
||||
}
|
||||
|
||||
static void proto_tdlas_tx_zero_calib(void)
|
||||
{
|
||||
u16 addr = PROTO_TDLAS_SET_ZERO_CALIB_START_ADDR;
|
||||
u8 len = 1;
|
||||
u16 data[1];
|
||||
data[0] = 0;
|
||||
|
||||
modbus_lib_multiple_data_write(p_sensor->modbus_id,addr,len,data,proto_tdlas_send);
|
||||
}
|
||||
|
||||
static void proto_tdlas_tx_span_calib(void)
|
||||
{
|
||||
u16 addr = PROTO_TDLAS_SET_SPAN_CALIB_START_ADDR;
|
||||
u8 len = 1;
|
||||
u16 data[1];
|
||||
data[0] = p_sensor->set_data.calib_value;
|
||||
modbus_lib_multiple_data_write(p_sensor->modbus_id,addr,len,data,proto_tdlas_send);
|
||||
}
|
||||
|
||||
static void proto_tdlas_tx_Reset(void)
|
||||
{
|
||||
u16 addr = PROTO_TDLAS_GET_RESET_START_ADDR;
|
||||
u8 len = 1;
|
||||
u16 data[1];
|
||||
data[0] = 0x00FE;
|
||||
//modbus_lib_multiple_data_write(p_sensor->modbus_id,addr,len,data,proto_tdlas_send);
|
||||
}
|
||||
|
||||
static void proto_tdlas_tx_fac_calib(void)
|
||||
{
|
||||
u16 addr = PROTO_TDLAS_GET_FAC_CALIB_START_ADDR;
|
||||
u8 len = 1;
|
||||
u16 data[1];
|
||||
data[0] = p_sensor->set_data.calib_value;
|
||||
addr = addr + p_sensor->set_data.temp_point * 10 + p_sensor->set_data.calib_point;
|
||||
modbus_lib_multiple_data_write(p_sensor->modbus_id,addr,len,data,proto_tdlas_send);
|
||||
}
|
||||
|
||||
static void proto_tdlas_tx_fac_calib_para_set(void)
|
||||
{
|
||||
u16 addr = PROTO_TDLAS_GET_FAC_CALIB_PARA_SET_START_ADDR;
|
||||
u8 len = 3;
|
||||
u16 data[3];
|
||||
|
||||
data[0] = *((u16 *)(&p_sensor->set_data.temp)); /*温度*/
|
||||
data[1] = p_sensor->set_data.press; /*压力*/
|
||||
data[2] = p_sensor->set_data.humidity; /*湿度*/
|
||||
|
||||
modbus_lib_multiple_data_write(p_sensor->modbus_id,addr,len,data,proto_tdlas_send);
|
||||
}
|
||||
|
||||
static void proto_tdlas_tx_fac_calib_data_get(void)
|
||||
{
|
||||
u16 addr = PROTO_TDLAS_GET_FAC_CALIB_DATA_START_ADDR;
|
||||
u8 len = 1;
|
||||
u16 data[1];
|
||||
|
||||
data[0] = 3; /*温度*/
|
||||
modbus_lib_multiple_data_write(p_sensor->modbus_id,addr,len,data,proto_tdlas_send);
|
||||
}
|
||||
|
||||
static void proto_tdlas_tx_task(void)
|
||||
{
|
||||
u8 SendFlag = 0;
|
||||
proto_tdlas_sys_t *p_sensor_sys;
|
||||
p_sensor_sys = &p_sensor->sys[p_sensor->sensor_index];
|
||||
|
||||
if(0 == (p_sensor_sys->state_error_flag & (0x00000001 << PROTO_TDLAS_ERROR_FLAG_TIME_OUT)))
|
||||
{
|
||||
if((++p_sensor_sys->tx_time_out_count) > 8)/*通讯超时*/
|
||||
{
|
||||
p_sensor_sys->state_error_flag |= (0x00000001 << PROTO_TDLAS_ERROR_FLAG_TIME_OUT);
|
||||
/*清除数据*/
|
||||
memset(&gas_data[p_sensor->sensor_index],0,sizeof(gas_data_t));
|
||||
}
|
||||
}
|
||||
|
||||
switch(p_sensor_sys->sys_state)
|
||||
{
|
||||
case PROTO_TDLAS_SYS_STATE_INIT:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_CURR_DATA_GET:
|
||||
{
|
||||
proto_tdlas_tx_curr_data_get();
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_ZERO_CALIB:
|
||||
{
|
||||
proto_tdlas_tx_zero_calib();
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_SPAN_CALIB:
|
||||
{
|
||||
proto_tdlas_tx_span_calib();
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_RESET:
|
||||
{
|
||||
proto_tdlas_tx_Reset();
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_FAC_CALIB:
|
||||
{
|
||||
proto_tdlas_tx_fac_calib();
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_FAC_CALIB_PARA_SET:
|
||||
{
|
||||
proto_tdlas_tx_fac_calib_para_set();
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_FAC_CALIB_DATA_GET:
|
||||
{
|
||||
if(0 == p_sensor_sys->send_time)
|
||||
{
|
||||
p_use_uart->relay.flag = 1;
|
||||
proto_tdlas_tx_fac_calib_data_get();
|
||||
}
|
||||
p_sensor_sys->send_time++;
|
||||
if(p_sensor_sys->send_time > 50)
|
||||
{
|
||||
p_use_uart->relay.flag = 0;
|
||||
p_sensor_sys->send_time = 0;
|
||||
p_sensor_sys->sys_state = PROTO_TDLAS_SYS_STATE_CURR_DATA_GET;
|
||||
p_sensor->sensor_index++;
|
||||
if(p_sensor->sensor_index >= Usr_Flash.FlashData.modbus_read_sensor_num)
|
||||
{
|
||||
p_sensor->sensor_index = 0;
|
||||
}
|
||||
proto_sensor_switch(p_sensor->sensor_index);
|
||||
}
|
||||
SendFlag = 1;
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
|
||||
}break;
|
||||
}
|
||||
if(SendFlag)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
p_sensor_sys->send_time++;
|
||||
if(p_sensor_sys->send_time >= 3) /*进入异常*/
|
||||
{
|
||||
p_sensor_sys->state_error_flag |= (0x00000001 << p_sensor_sys->sys_state);/*记录异常状态*/
|
||||
p_sensor_sys->send_time = 0;
|
||||
p_sensor_sys->sys_state = PROTO_TDLAS_SYS_STATE_CURR_DATA_GET;
|
||||
p_sensor->sensor_index++;
|
||||
if(p_sensor->sensor_index >= Usr_Flash.FlashData.modbus_read_sensor_num)
|
||||
{
|
||||
p_sensor->sensor_index = 0;
|
||||
}
|
||||
proto_sensor_switch(p_sensor->sensor_index);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void proto_tdlas_rx_task(u8 *p_data,u16 len,void *other_data)
|
||||
{
|
||||
u8 send_time_flag = 0;
|
||||
u8 modbus_id,cmd;
|
||||
u16 check_crc16,modbus_crc16;
|
||||
u16 *p_u16_temp;
|
||||
u16 i;
|
||||
u8 *p_rx_valid;
|
||||
|
||||
proto_tdlas_sys_t *p_sensor_sys;
|
||||
p_sensor_sys = &p_sensor->sys[p_sensor->sensor_index];
|
||||
|
||||
if( p_use_uart->relay.flag == 1)
|
||||
{
|
||||
p_use_uart->relay.uart->Send(p_use_uart->relay.uart,p_data,len);
|
||||
}
|
||||
|
||||
if(p_sensor->modbus_id != p_data[0])
|
||||
{
|
||||
p_data = &p_data[1];
|
||||
len -= 1;
|
||||
}
|
||||
modbus_id = *p_data;
|
||||
cmd = *(p_data+1);
|
||||
check_crc16 = p_data[len-2] << 8 | p_data[len-1];
|
||||
|
||||
if(modbus_id != p_sensor->modbus_id) return ;
|
||||
if(cmd != 0x04 && cmd != 0x06 && cmd != 0x10 && cmd != 0x41) return ;
|
||||
|
||||
modbus_crc16 = modbus_lib_crc16(p_data,len-2);
|
||||
modbus_crc16 = (modbus_crc16 >> 8) | (modbus_crc16 << 8);
|
||||
|
||||
if(check_crc16 != modbus_crc16) return ;
|
||||
|
||||
if(cmd == 0x41)
|
||||
{
|
||||
p_rx_valid = &p_data[6];
|
||||
}
|
||||
rx_uart = (bsp_Uart_t *)other_data;
|
||||
|
||||
p_sensor_sys->tx_time_out_count = 0;
|
||||
p_sensor_sys->state_error_flag &= (~(0x00000001 << PROTO_TDLAS_ERROR_FLAG_TIME_OUT));
|
||||
|
||||
switch(p_sensor_sys->sys_state)
|
||||
{
|
||||
case PROTO_TDLAS_SYS_STATE_INIT:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_CURR_DATA_GET:
|
||||
{
|
||||
p_u16_temp = (u16 *)&(gas_data[p_sensor->sensor_index]);
|
||||
for(i=0;i<Usr_Flash.FlashData.modbus_read_reg_num;i++)
|
||||
{
|
||||
p_u16_temp[i] = p_rx_valid[i * 2] << 8 | p_rx_valid[i * 2 + 1];
|
||||
}
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_ZERO_CALIB:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_SPAN_CALIB:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_RESET:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_FAC_CALIB:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_FAC_CALIB_PARA_SET:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_TDLAS_SYS_STATE_FAC_CALIB_DATA_GET:
|
||||
{
|
||||
|
||||
}break;
|
||||
}
|
||||
if(send_time_flag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_sensor_sys->sys_state = PROTO_TDLAS_SYS_STATE_CURR_DATA_GET;
|
||||
p_sensor_sys->state_error_flag &= (~(0x00000001 << p_sensor_sys->sys_state));/*消除异常状态*/
|
||||
p_sensor_sys->send_time = 0;
|
||||
p_sensor->sensor_index++;
|
||||
if(p_sensor->sensor_index >= Usr_Flash.FlashData.modbus_read_sensor_num)
|
||||
{
|
||||
p_sensor->sensor_index = 0;
|
||||
}
|
||||
proto_sensor_switch(p_sensor->sensor_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef _PROTO_MODBUS_MASTER_SENSOR_H_
|
||||
#define _PROTO_MODBUS_MASTER_SENSOR_H_
|
||||
#include "main.h"
|
||||
#include "gas_data.h"
|
||||
|
||||
/*NIDR状态*/
|
||||
#define PROTO_TDLAS_SYS_STATE_INIT (0U) /*初始化 */
|
||||
#define PROTO_TDLAS_SYS_STATE_CURR_DATA_GET (1U) /*获取实时数据*/
|
||||
#define PROTO_TDLAS_SYS_STATE_ZERO_CALIB (2U) /*零点校准 */
|
||||
#define PROTO_TDLAS_SYS_STATE_SPAN_CALIB (3U) /*量程校准 */
|
||||
#define PROTO_TDLAS_SYS_STATE_RESET (4U) /*恢复出厂 */
|
||||
#define PROTO_TDLAS_SYS_STATE_FAC_CALIB (5U) /*厂家标定 */
|
||||
#define PROTO_TDLAS_SYS_STATE_FAC_CALIB_PARA_SET (6U) /*厂家标定时的环境参数*/
|
||||
#define PROTO_TDLAS_SYS_STATE_FAC_CALIB_DATA_GET (7U) /*获取标定信息*/
|
||||
|
||||
#define PROTO_TDLAS_ERROR_FLAG_TIME_OUT (30U) /*通讯超时*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*zero_calib)(u16); /*零点校准*/
|
||||
void (*span_calib)(u16); /*量程点校准*/
|
||||
void (*reset)(void); /*恢复出厂设置*/
|
||||
void (*fac_calib)(u16,u8,u8); /*厂家标定时的浓度*/
|
||||
void (*fac_calib_para_set)(s16,u16,u16); /*厂家标定时设置的温度、湿度、压力*/
|
||||
void (*fac_calib_data_get)(u8); /*厂家标定时设置的温度、湿度、压力*/
|
||||
}proto_tdlas_control_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 sys_state;
|
||||
u16 send_time; /*发送次数*/
|
||||
u32 sensor_state; /*传感器状态*/
|
||||
u8 print_flag; /*实时数据打印标志位*/
|
||||
u32 state_error_flag; /*系统错误标志位*/
|
||||
u16 tx_time_out_count; /*协议指令发送次数*/
|
||||
}proto_tdlas_sys_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
u8 calib_point;
|
||||
u8 temp_point;
|
||||
u16 calib_value;
|
||||
s16 temp;
|
||||
u16 humidity;
|
||||
u16 press;
|
||||
}proto_tdlas_set_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 modbus_id;
|
||||
|
||||
u16 sensor_index; /*当前是哪个通道的传感器*/
|
||||
proto_tdlas_set_data_t set_data;
|
||||
proto_tdlas_sys_t sys[SENSOR_NUM];
|
||||
proto_tdlas_control_t control;
|
||||
|
||||
void (*init)(void);
|
||||
void (*tx_task)(void);
|
||||
void (*rx_task)(u8 *,u16,void *);
|
||||
void (*print)(void);
|
||||
void (*warm_task)(void);
|
||||
}proto_tdlas_t;
|
||||
|
||||
extern proto_tdlas_t tdlas;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,362 @@
|
||||
/*对外通讯 modbus从机*/
|
||||
#include "proto_modbus_slave_ex.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "os_timer.h"
|
||||
|
||||
#include "bsp_Uart.h"
|
||||
#include "bsp_Flash.h"
|
||||
|
||||
#include "proto_print.h"
|
||||
#include "proto_modbus_master_tdlas.h"
|
||||
|
||||
static modbus_analysis_data_t modbus_analysis_data;//指令解析结构体
|
||||
static modbus_communication_send_buf_t send_struct;//发送结构体
|
||||
|
||||
static void proto_modbus_communication_data_analysis(u8 *pData, u16 len, void *data);
|
||||
static void proto_modbus_communication_data_send(u8 *pData, u16 len);
|
||||
static void proto_modbus_init(void);
|
||||
static void proto_modbus_task(void);
|
||||
static modbus_error_code_e proto_modbus_data_write(u16 Addr, u16 Value);
|
||||
static u16 proto_modbus_data_read(u16 Addr);
|
||||
|
||||
proto_Modbus_t modbus_slave_ex=
|
||||
{
|
||||
.id = 0x01,
|
||||
.data_read = proto_modbus_data_read,
|
||||
.data_write = proto_modbus_data_write,
|
||||
.data_analysis = proto_modbus_communication_data_analysis,
|
||||
.init = proto_modbus_init,
|
||||
.task = proto_modbus_task,
|
||||
};
|
||||
|
||||
static proto_Modbus_t *p_modbus = &modbus_slave_ex;
|
||||
static bsp_Uart_t * rx_uart;
|
||||
|
||||
static void proto_modbus_communication_data_send(u8 *pData, u16 len)
|
||||
{
|
||||
if(&COM_Uart1 == rx_uart)
|
||||
{
|
||||
COM_Uart1.Send(&COM_Uart1,pData,len);
|
||||
}
|
||||
else if(&COM_Uart4 == rx_uart)
|
||||
{
|
||||
COM_Uart4.Send(&COM_Uart4,pData,len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void proto_modbus_init(void)
|
||||
{
|
||||
p_modbus->id = Usr_Flash.FlashData.modbus_id;
|
||||
COM_Uart1.Rx_DataAnalysis = proto_modbus_communication_data_analysis;
|
||||
COM_Uart4.Rx_DataAnalysis = proto_modbus_communication_data_analysis;
|
||||
}
|
||||
static void proto_modbus_task(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void proto_modbus_communication_data_analysis(u8 *pData, u16 len,void *other_data)
|
||||
{
|
||||
modbus_error_code_e error_code;
|
||||
u16 inx;
|
||||
u16 TempAddr, TempData, crc_16;
|
||||
|
||||
|
||||
if (0 == modbus_lib_analysis(&modbus_analysis_data, pData, len))//检查数据长度 校验是否正确
|
||||
return;
|
||||
if (p_modbus->id != modbus_analysis_data.id && modbus_analysis_data.id != 0xe8)//判断ID是否正确
|
||||
return;
|
||||
|
||||
error_code = ModbusErrorCode_Success;
|
||||
|
||||
|
||||
/* //检查地址是否超出范围
|
||||
if ((modbus_analysis_data.start_addr >= MODBUS_REG_LEN) || (modbus_analysis_data.reg_number >= MODBUS_REG_LEN) ||
|
||||
(modbus_analysis_data.start_addr + modbus_analysis_data.reg_number >= MODBUS_REG_LEN))
|
||||
{
|
||||
ErrorCode = ModbusErrorCode_IllegalAddr;
|
||||
goto Error;
|
||||
}
|
||||
*/
|
||||
rx_uart = (bsp_Uart_t*)other_data;
|
||||
switch (modbus_analysis_data.func)
|
||||
{
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
{
|
||||
TempAddr = modbus_analysis_data.start_addr;
|
||||
send_struct.send_buffer[0] = modbus_analysis_data.id;
|
||||
send_struct.send_buffer[1] = modbus_analysis_data.func;
|
||||
send_struct.send_buffer[2] = 2 * modbus_analysis_data.reg_number;
|
||||
for (inx = 0; inx < modbus_analysis_data.reg_number; inx++)
|
||||
{
|
||||
TempData = proto_modbus_data_read(TempAddr);
|
||||
send_struct.send_buffer[3 + 2 * inx] = (TempData >> 8) & 0xff;
|
||||
send_struct.send_buffer[4 + 2 * inx] = TempData & 0xff;
|
||||
TempAddr++;
|
||||
}
|
||||
crc_16 = modbus_lib_crc16(send_struct.send_buffer, 3 + send_struct.send_buffer[2]);
|
||||
send_struct.send_buffer[3 + send_struct.send_buffer[2]] = crc_16 & 0xff;
|
||||
send_struct.send_buffer[4 + send_struct.send_buffer[2]] = (crc_16 >> 8) & 0xff;
|
||||
send_struct.len = 5 + send_struct.send_buffer[2];
|
||||
}goto Success;
|
||||
/*特殊协议*/
|
||||
case 0x41:
|
||||
{
|
||||
TempAddr = modbus_analysis_data.start_addr;
|
||||
send_struct.send_buffer[0] = modbus_analysis_data.id;
|
||||
send_struct.send_buffer[1] = modbus_analysis_data.func;
|
||||
send_struct.send_buffer[2] = modbus_analysis_data.start_addr >> 8;
|
||||
send_struct.send_buffer[3] = modbus_analysis_data.start_addr & 0xff;
|
||||
send_struct.send_buffer[4] = (2 * modbus_analysis_data.reg_number) >> 8;
|
||||
send_struct.send_buffer[5] = (2 * modbus_analysis_data.reg_number) & 0xff;
|
||||
for (inx = 0; inx < modbus_analysis_data.reg_number; inx++)
|
||||
{
|
||||
TempData = proto_modbus_data_read(TempAddr);
|
||||
send_struct.send_buffer[6 + 2 * inx] = (TempData >> 8) & 0xff;
|
||||
send_struct.send_buffer[7 + 2 * inx] = TempData & 0xff;
|
||||
TempAddr++;
|
||||
}
|
||||
crc_16 = modbus_lib_crc16(send_struct.send_buffer, 6 + 2 * modbus_analysis_data.reg_number);
|
||||
send_struct.send_buffer[6 + 2 * modbus_analysis_data.reg_number] = crc_16 & 0xff;
|
||||
send_struct.send_buffer[7 + 2 * modbus_analysis_data.reg_number] = (crc_16 >> 8) & 0xff;
|
||||
send_struct.len = 8 + 2 * modbus_analysis_data.reg_number;
|
||||
}goto Success;
|
||||
|
||||
case 0x06:
|
||||
{
|
||||
TempAddr = modbus_analysis_data.start_addr;
|
||||
TempData = (modbus_analysis_data.write_data_addr[0] << 8) | modbus_analysis_data.write_data_addr[1];
|
||||
error_code = proto_modbus_data_write(TempAddr, TempData);
|
||||
if (error_code)
|
||||
{
|
||||
goto Error;
|
||||
}
|
||||
|
||||
send_struct.len = 8;
|
||||
send_struct.send_buffer[0] = modbus_analysis_data.id;
|
||||
send_struct.send_buffer[1] = modbus_analysis_data.func;
|
||||
send_struct.send_buffer[2] = modbus_analysis_data.start_addr >> 8;
|
||||
send_struct.send_buffer[3] = modbus_analysis_data.start_addr & 0xff;
|
||||
send_struct.send_buffer[4] = modbus_analysis_data.write_data_addr[0];
|
||||
send_struct.send_buffer[5] = modbus_analysis_data.write_data_addr[1];
|
||||
crc_16 = modbus_lib_crc16(send_struct.send_buffer, 6);
|
||||
send_struct.send_buffer[6] = crc_16 & 0xff;
|
||||
send_struct.send_buffer[7] = (crc_16 >> 8) & 0xff;
|
||||
}break;
|
||||
|
||||
case 0x10:
|
||||
{
|
||||
TempAddr = modbus_analysis_data.start_addr;
|
||||
for (inx = 0; inx < modbus_analysis_data.reg_number; inx++)
|
||||
{
|
||||
TempData = modbus_analysis_data.write_data_addr[2 * inx];
|
||||
TempData = (TempData << 8) | modbus_analysis_data.write_data_addr[2 * inx + 1];
|
||||
error_code = proto_modbus_data_write(TempAddr, TempData);
|
||||
TempAddr++;
|
||||
if (error_code)
|
||||
{
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
send_struct.len = 8;
|
||||
send_struct.send_buffer[0] = modbus_analysis_data.id;
|
||||
send_struct.send_buffer[1] = modbus_analysis_data.func;
|
||||
send_struct.send_buffer[2] = modbus_analysis_data.start_addr >> 8;
|
||||
send_struct.send_buffer[3] = modbus_analysis_data.start_addr & 0xff;
|
||||
send_struct.send_buffer[4] = modbus_analysis_data.reg_number >> 8;
|
||||
send_struct.send_buffer[5] = modbus_analysis_data.reg_number & 0xff;
|
||||
crc_16 = modbus_lib_crc16(send_struct.send_buffer, 6);
|
||||
send_struct.send_buffer[6] = crc_16 & 0xff;
|
||||
send_struct.send_buffer[7] = (crc_16 >> 8) & 0xff;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_code = ModbusErrorCode_IllegalFunction;
|
||||
}
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Success:
|
||||
proto_modbus_communication_data_send(send_struct.send_buffer, send_struct.len);
|
||||
return;
|
||||
|
||||
Error:
|
||||
send_struct.len = 5;
|
||||
send_struct.send_buffer[0] = modbus_analysis_data.id;
|
||||
send_struct.send_buffer[1] = modbus_analysis_data.func | 0x80;
|
||||
send_struct.send_buffer[2] = error_code;
|
||||
crc_16 = modbus_lib_crc16(send_struct.send_buffer, 3);
|
||||
send_struct.send_buffer[3] = crc_16 & 0xff;
|
||||
send_struct.send_buffer[4] = (crc_16 >> 8) & 0xff;
|
||||
proto_modbus_communication_data_send(send_struct.send_buffer, send_struct.len);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* 函数: proto_modbus_data_write
|
||||
* 功能: Modbus写寄存器
|
||||
* 参数: Addr: 地址
|
||||
Value:数据
|
||||
* 返回: 无
|
||||
* 描述: 无
|
||||
******************************************/
|
||||
static modbus_error_code_e proto_modbus_data_write(u16 addr, u16 data)
|
||||
{
|
||||
modbus_error_code_e error_code;
|
||||
u8 temp_point,cali_point;
|
||||
|
||||
error_code = ModbusErrorCode_Success;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
/*温度 压力 湿度*/
|
||||
case 11000:
|
||||
{
|
||||
tdlas.control.fac_calib_para_set(*((u16 *)(&data)),0xffff,0xffff);
|
||||
}break;
|
||||
case 11001:
|
||||
{
|
||||
tdlas.control.fac_calib_para_set(0xffff,data,0xffff);
|
||||
}break;
|
||||
case 11002:
|
||||
{
|
||||
tdlas.control.fac_calib_para_set(0xffff,0xffff,data);
|
||||
}break;
|
||||
|
||||
/*零点校准*/
|
||||
case 11003:
|
||||
{
|
||||
tdlas.control.zero_calib(0);
|
||||
}break;
|
||||
/*量程点校准*/
|
||||
case 11004:
|
||||
{
|
||||
tdlas.control.span_calib(data);
|
||||
}break;
|
||||
|
||||
/*厂家标定*/
|
||||
case 11010 ... 11109:
|
||||
{
|
||||
temp_point = (addr - 11010) / 10;
|
||||
cali_point = (addr - 11010) % 10;
|
||||
tdlas.control.fac_calib(data,cali_point,temp_point);
|
||||
}break;
|
||||
|
||||
/*转发传感器标定信息*/
|
||||
case 11200:
|
||||
{
|
||||
tdlas.control.fac_calib_data_get(data);
|
||||
}break;
|
||||
|
||||
|
||||
/*sn*/
|
||||
case 20000 ... 20004:
|
||||
{
|
||||
Usr_Flash.FlashData.sn[addr - 20000] = data;
|
||||
Usr_Flash.Write();
|
||||
}break;
|
||||
/*modbus_id*/
|
||||
case 20005:
|
||||
{
|
||||
Usr_Flash.FlashData.modbus_id = data;
|
||||
modbus_slave_ex.id = Usr_Flash.FlashData.modbus_id;
|
||||
Usr_Flash.Write();
|
||||
}break;
|
||||
/*modbus_read_reg_num*/
|
||||
case 20006:
|
||||
{
|
||||
if(data > 1000)
|
||||
{
|
||||
error_code = ModbusErrorCode_IllegalData;
|
||||
}
|
||||
else
|
||||
{
|
||||
Usr_Flash.FlashData.modbus_read_reg_num = data;
|
||||
Usr_Flash.Write();
|
||||
}
|
||||
}break;
|
||||
case 20007:
|
||||
{
|
||||
if(data > 16)
|
||||
{
|
||||
error_code = ModbusErrorCode_IllegalData;
|
||||
}
|
||||
else
|
||||
{
|
||||
Usr_Flash.FlashData.modbus_read_sensor_num = data;
|
||||
Usr_Flash.Write();
|
||||
}
|
||||
}break;
|
||||
/*FC打印相关数据*/
|
||||
case 252:
|
||||
{
|
||||
print.set(data);
|
||||
}break;
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* 函数: proto_modbus_data_read
|
||||
* 功能: Modbus读寄存器数据
|
||||
* 参数: Addr: 地址
|
||||
* 返回: 地址对应的数据
|
||||
* 描述: 无
|
||||
******************************************/
|
||||
static u16 proto_modbus_data_read(u16 addr)
|
||||
{
|
||||
u16 data = 0;
|
||||
u16 *p_data;
|
||||
u16 num,offset;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
/*实时数据*/
|
||||
case 0 ... 639:
|
||||
{
|
||||
u16 size;
|
||||
size = sizeof(gas_data_t);
|
||||
/* TDLAS默认读取*/
|
||||
if( size== (2 * Usr_Flash.FlashData.modbus_read_reg_num))
|
||||
{
|
||||
p_data = (u16 *)&gas_data;
|
||||
data = p_data[addr];
|
||||
}
|
||||
else if((2 * Usr_Flash.FlashData.modbus_read_reg_num )< sizeof(gas_data_t))/*其他传感器*/
|
||||
{
|
||||
num = addr / Usr_Flash.FlashData.modbus_read_reg_num;
|
||||
offset = addr % Usr_Flash.FlashData.modbus_read_reg_num;
|
||||
p_data = (u16 *)&gas_data[num];
|
||||
data = p_data[offset];
|
||||
}
|
||||
|
||||
}break;
|
||||
|
||||
/*sn*/
|
||||
case 20000 ... 20004:
|
||||
{
|
||||
data = Usr_Flash.FlashData.sn[addr - 20000];
|
||||
}break;
|
||||
/*modbus_id*/
|
||||
case 20005:
|
||||
{
|
||||
data = Usr_Flash.FlashData.modbus_id;
|
||||
}break;
|
||||
/*modbus_read_reg_num*/
|
||||
case 20006:
|
||||
{
|
||||
data = Usr_Flash.FlashData.modbus_read_reg_num;
|
||||
}break;
|
||||
case 20007:
|
||||
{
|
||||
data = Usr_Flash.FlashData.modbus_read_sensor_num;
|
||||
}break;
|
||||
default:data = 0;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _PROTO_MODBUS_SLAVE_EX_H_
|
||||
#define _PROTO_MODBUS_SLAVE_EX_H_
|
||||
#include "main.h"
|
||||
#include "gas_data.h"
|
||||
#include "proto_modbus_lib.h"
|
||||
|
||||
extern proto_Modbus_t modbus_slave_ex;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "proto_print.h"
|
||||
|
||||
#include "stdio.h"
|
||||
#include "bsp_Uart.h"
|
||||
|
||||
u16 proto_print_data_type;
|
||||
|
||||
void proto_print_datatype_set(u8 type);
|
||||
static void proto_print_task(void);
|
||||
|
||||
proto_print_t print =
|
||||
{
|
||||
.task = proto_print_task,
|
||||
.set = proto_print_datatype_set,
|
||||
};
|
||||
|
||||
proto_print_t *p_print = &print;
|
||||
|
||||
static void proto_print_datatype_set(u8 type)
|
||||
{
|
||||
if(type > PROTO_PRINT_MAX)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(proto_print_data_type == type)
|
||||
{
|
||||
proto_print_data_type = PROTO_PRINT_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
proto_print_data_type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void proto_print_task(void)
|
||||
{
|
||||
switch(proto_print_data_type)
|
||||
{
|
||||
case PROTO_PRINT_NULL:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_PRINT_CURDATA:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_PRINT_WAVE:
|
||||
{
|
||||
|
||||
}break;
|
||||
case PROTO_PRINT_CALIB:
|
||||
{
|
||||
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _PROTO_PRINT_H_
|
||||
#define _PROTO_PRINT_H_
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define PROTO_PRINT_MAX 3
|
||||
|
||||
#define PROTO_PRINT_NULL 0
|
||||
#define PROTO_PRINT_CURDATA 1
|
||||
#define PROTO_PRINT_WAVE 2
|
||||
#define PROTO_PRINT_CALIB 3
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*task)(void);
|
||||
void (*set)(u8);
|
||||
}proto_print_t;
|
||||
|
||||
extern proto_print_t print;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user