添加掉电保护程序文件

This commit is contained in:
DESKTOP-2E6P1Q6\Administrator 2025-10-11 11:42:41 +08:00
parent 6d3f46b8cd
commit 65ce8dea9c
22 changed files with 244 additions and 120 deletions

View File

@ -37,6 +37,9 @@
"gd32f4xx_it.h": "c",
"usbd_transc.h": "c",
"drv_usbd_int.h": "c",
"system_gd32f4xx.h": "c"
"system_gd32f4xx.h": "c",
"photosw.h": "c",
"photoelectric.h": "c",
"statusmonitor.h": "c"
}
}

View File

@ -777,7 +777,7 @@
</option>
<option>
<name>IlinkIcfFile</name>
<state>C:\Users\Administrator\Documents\newPtz\EWARM\iar\GD32F450xE.icf</state>
<state>C:\Users\Administrator\Documents\newPtz\EWARM\iar\GD32F470xE.icf</state>
</option>
<option>
<name>IlinkIcfFileSlave</name>
@ -2252,6 +2252,12 @@
<file>
<name>$PROJ_DIR$\..\drivers\drv_usart.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\drivers\photoelectric.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\drivers\photoelectric.h</name>
</file>
</group>
<group>
<name>GD32F4xx_Peripherals</name>

View File

@ -2922,6 +2922,12 @@
<file>
<name>$PROJ_DIR$\..\drivers\drv_usart.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\drivers\photoelectric.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\drivers\photoelectric.h</name>
</file>
</group>
<group>
<name>GD32F4xx_Peripherals</name>

View File

@ -66,7 +66,8 @@
// #define __SYSTEM_CLOCK_240M_PLL_25M_HXTAL (uint32_t)(240000000)
#endif
#define __SYSTEM_CLOCK_200M_PLL_8M_HXTAL (uint32_t)(200000000)
// #define __SYSTEM_CLOCK_240M_PLL_IRC16M (uint32_t)(240000000)
#define __SYSTEM_CLOCK_240M_PLL_8M_HXTAL (uint32_t)(240000000)
/* The following is to prevent Vcore fluctuations caused by frequency switching.
It is strongly recommended to include it to avoid issues caused by self-removal. */

View File

@ -34,7 +34,7 @@ OF SUCH DAMAGE.
#include "gd32f4xx.h"
#include <stdio.h>
#include "rtthread.h"
// #include "rtthread.h"
#include "delay.h"
#include "drv_adc.h"
#include "drv_i2c.h"
@ -70,16 +70,12 @@ int main(void)
beep_enable();
// rt_thread_mdelay(1000);
delay_ms(250);
delay_ms(500);
beep_disable();
// gd32_usart_init();
i2c_init();
adc_init();
usart_init();
// usart_init();
//测试mb铁电读写
memset(&ttest, 0, sizeof(ttest));
@ -99,8 +95,8 @@ int main(void)
}
/* 写ttest到MB85TEST_ADD地址 */
mb85rc64_write_read(MB85TEST_ADD, (unsigned char *)&ttest, sizeof(ttest), PAGE_WRITE);
uint8_t rx_data = 0;
uint8_t tx_data = 0x61;
// uint8_t rx_data = 0;
// uint8_t tx_data = 'a';
// 进入主循环或启动其他任务
while (1)
{
@ -134,18 +130,18 @@ int main(void)
// beep_disable();
// }
while(RESET == usart_flag_get(USART_PERIPH, USART_FLAG_TBE))
{
// while(RESET == usart_flag_get(USART_PERIPH, USART_FLAG_TBE))
// {
}
//写寄存器
usart_data_transmit(USART_PERIPH, tx_data);
//等待发送完成
while(RESET == usart_flag_get(USART_PERIPH, USART_FLAG_TC))
{
// }
// //写寄存器
// usart_data_transmit(USART_PERIPH, tx_data);
// //等待发送完成
// while(RESET == usart_flag_get(USART_PERIPH, USART_FLAG_TC))
// {
}
usart_flag_clear(USART_PERIPH, USART_FLAG_TC);
// }
// usart_flag_clear(USART_PERIPH, USART_FLAG_TC);//可以不写
// memset(&ttest, 0, sizeof(ttest));

View File

@ -0,0 +1,7 @@
TBE -> 发送数据缓存区为空; 0不空 1
TC -> 发送完成; 0未完成 1完成
RBNE -> 读数据缓存区非空; 0 1不空
BAUD -> 30d41920061a89600
CH1单片机接收PC发送
CH2单片机发送PC接收

Binary file not shown.

View File

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://blog.csdn.net/qq_37120496/article/details/133471283

Binary file not shown.

View File

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://zhuanlan.zhihu.com/p/580512482

View File

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://blog.csdn.net/ZHONGCAI0901/article/details/118302801

View File

@ -233,7 +233,7 @@ float ptz_Voltage_collect_adc1_task()
#endif
/* 间接测量11倍分压/放大 */
adc1_v[adc1_v_num] = (float)value_V / 4095.0 * 3.3;
adc1_v[adc1_v_num] = (float)value_V / 4096.0 * 3.381;
adc1_v_num++;
if(adc1_v_num >= LB_V_TIMES)
@ -283,7 +283,7 @@ float ptz_Current_collect_adc1_task()
#endif
/* 间接测量11倍分压/放大 */
adc1_i[adc1_i_num] = (((float)value_I / 4095.0 * 3.3) - 3.3 / 2) / 0.132;
adc1_i[adc1_i_num] = ((float)value_I / 4096.0 * 3.381) * 10;
adc1_i_num++;
if(adc1_i_num >= LB_I_TIMES)

View File

@ -8,7 +8,7 @@
#include "string.h"
#include "gd32f4xx.h"
#include "delay.h"
#include "rtthread.h"
// #include "rtthread.h"
/* 自定义宏,方便修改通道和引脚 */

View File

@ -8,14 +8,14 @@
#define USART_PERIPH USART0
#define USART_PERIPH_CLK RCU_USART0
#define USART_TX_PIN GPIO_PIN_9
#define USART_RX_PIN GPIO_PIN_10
#define USART_TX_PIN GPIO_PIN_9
#define USART_RX_PIN GPIO_PIN_10
#define USART_GPIO_AF GPIO_AF_7
#define USART_IRQn USART0_IRQn
#define USART_GPIO_AF GPIO_AF_7
// #define USART_IRQn USART0_IRQn
// #define USART_IRQHandler USART0_IRQHandler
// #define USART_IRQHandler_NAME "USART0_IRQHandler"
#define USART_BAUD_RATE 9600
#define USART_BAUD_RATE (9600U)
void usart_init(void);
void usart_colok_config(void);

20
drivers/photoelectric.c Normal file
View File

@ -0,0 +1,20 @@
// #include "photoelectric.h"
// /// 初始化所有光电开关
// /// @param 无
// /// @return 无
// /// @par 修改日志
// /// 杨鹏程于2017-09-14创建
// /// LH修改于2022-05-31
// void ps_init()
// {
// //配置引脚时钟
// rcu_periph_clock_enable(RCU_GPIOE);
// //设置引脚为输入模式:PE7-J3PE8-J4PE9-J5
// gpio_mode_set(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_7);
// gpio_mode_set(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_8);
// gpio_mode_set(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_9);
// }

5
drivers/photoelectric.h Normal file
View File

@ -0,0 +1,5 @@
// #ifndef __PHOTOELECTRIC_H_
// #define __PHOTOELECTRIC_H_
// #include "gd32f4xx.h"

View File

@ -1,7 +1,5 @@
## ADC原理说明
GD32F4系列搭载了高性能的12位逐次逼近型SARADC提供了非常灵活和强大的数据采集功能。其采集方式可以从**操作模式**和**数据转移方式**两个维度来理解。
### 一、按操作模式划分
@ -374,6 +372,17 @@ void adc_routine_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t chann
---
按键配置
```c
static void key_rst_init()
{//使用PE4引脚输入模式
gpio_mode_set(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_4);
}
```
---
| 事件 | 断电保护 | 电压过高保护 | 过流保护 | 一般温度10℃以下故障 | 极限温度10℃以上故障 | 光电开关遮挡 |
| :--: | :----------: | :----------: | :------: | :----------------------: | :----------------------: | -------------------- |
| 响应 | 检测掉电存储 | 断电 | 电机停转 | -(仅故障回传) | 电机停转 | 同时累计遮挡电机停转 |
@ -394,7 +403,7 @@ void adc_routine_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t chann
| ------------- | ------------------------------------ | -------------------------------------- |
| P0 致命 | 严重电流过载、电压过高、温度过高 | 立即停机、断电、报警,并持久化故障状态 |
| P1 高 | 光电挡板遮挡、电流持续过流、电压过低 | 停机、限流、恢复模式,报警上报 |
| P2 中 | 温度接近限制、传感器异常 | 限速、报警上报 |
| P2 中 | 温度较高、(传感器异常) | 限速、报警上报 |
| P3 低(可不用) | 通信错误、较小的传感器波动 | 记录日志,便于后续诊断 |
## 关键设计原则
@ -408,7 +417,12 @@ void adc_routine_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t chann
### 电压监测
- **硬件设计**利用ADC模块或者电压比较器监测主电源电压。
- **故障响应**:过电压和欠电压将触发报警,并在满足条件时进行电机断电、停机。
- **故障响应**:过电压和欠电压将触发报警,并在满足条件时进行电机断电。
### 掉电保护
- **硬件设计**:通过监测电源电压下降,并使用电容保证在掉电瞬间写入系统状态。
- **故障响应**:在掉电事件前保存关键状态数据。
### 电流监测
@ -425,27 +439,21 @@ void adc_routine_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t chann
- **硬件设计**:使用光电传感器或光耦监测挡板状态。
- **故障响应**:检测到遮挡时,立即停机,避免碰撞。
### 掉电保护
- **硬件设计**:通过监测电源电压下降,并使用电容保证在掉电瞬间写入系统状态。
- **故障响应**:在掉电事件前保存关键状态数据。
## 故障上报
错误代码使用统一格式进行上报,确保与上位机的兼容性。
| 错误码 | 错误描述 | 优先级 | 模块 |
| ---------- | -------------------- | ------ | ---------- |
| 0x01010001 | 主电源过压 | P1 | 电源 |
| 0x01010002 | 主电源欠压 | P1 | 电源 |
| 0x02020001 | 电机A持续过流 | P0 | 电流 |
| 0x02020002 | 电机B短路 | P0 | 电流 |
| 0x03030001 | 驱动模块过温 | P1 | 温度 |
| 0x01010001 | 主电源过压 | P0 | 电源 |
| 0x01010002 | 主电源欠压 | P0 | 电源 |
| 0x02020001 | 电机A持续过流 | P1 | 电流 |
| 0x02020002 | 电机B短路 | P1 | 电流 |
| 0x04040001 | 光电挡板左侧遮挡异常 | P1 | 限位传感器 |
| 0x04040002 | 光电挡板右侧开路 | P2 | 限位传感器 |
| 0x04040002 | 光电挡板右侧开路 | P1 | 限位传感器 |
| 0x03030001 | 驱动模块过温 | P2 | 温度 |
| 0x05050001 | 编码器错位 | P2 | 传感器 |
## 测试与验收
### 单元测试
@ -461,77 +469,6 @@ void adc_routine_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t chann
### 验收标准
* 掉电保护成功率99.9%(断电前成功写入状态)
* 电流/电压/温度监测反应时间≤5ms
* 故障上报与记录符合协议,信息完整且准确。
**示例上报报文格式**
```json
{
"error_code": "0x01020005",
"severity": "P1",
"timestamp": "2025-09-30T11:32:14Z",
"voltage_v": 28.3,
"current_a": 1.3,
"temp_c": 52.4,
"encoder_deg": 12.345,
"message": "motor B continuous overcurrent",
//"firmware": "v1.2.3",
"cmd_id": "PT-001"
"mac": "PT-001"
}
```
## C示例代码
```c
// 电流监测中断处理示例
void OVERCURRENT_IRQHandler(void) {
// 立即切断驱动使能
Motor_DisableDriver(MOTOR_B);
// 读取电流并记录
float current = adc_read(CURRENT_B);
log_error(ERROR_CODE_OVERCURRENT(MOTOR_B), "Overcurrent detected", current);
// 上报错误至上位机
ReportErrorToHost(ERROR_CODE_OVERCURRENT(MOTOR_B));
// 进入等待人工复位模式
EnterSafeLoop();
}
// 掉电ISR 保存最小状态
volatile bool power_failing = false;
void POWER_FALL_IRQHandler(void) {
if (power_failing) return;
power_failing = true;
// 禁止新动作立即切断PWM
Motor_StopAllPWMImmediate();
// 采集快照
Snapshot_t snap;
snap.magic = SNAP_MAGIC;
snap.timestamp = rtc_get_time();
snap.voltage = adc_read(VOLTAGE_CHANNEL);
snap.current = adc_read(CURRENT_CHANNEL);
snap.temp = adc_read(TEMP_CHANNEL);
snap.encoder_pos = encoder_get_position();
snap.error_flags = global_error_flags;
// 计算CRC并保存
snap.crc = crc32((uint8_t*)&snap, sizeof(snap) - sizeof(snap.crc));
FRAM_Write(SNAPSHOT_ADDR, (uint8_t*)&snap, sizeof(snap));
// 启动刹车机制
Hardware_EnableBrake();
// 进入安全循环
EnterSafeLoop();
}
```
* 掉电保护成功率99.9%(断电前成功写入状态):
* 电流/电压/温度监测反应时间≤5ms
* 故障上报与记录符合协议,信息完整且准确:

34
drivers/statusmonitor.c Normal file
View File

@ -0,0 +1,34 @@
#include "statusmonitor.h"
PowerOffData power_off_data;
char ptz_power_off_data_save(unsigned short int add)
{
PowerOffData power_off_data_b;
int i;
memcpy(&power_off_data.hori_as5047d, &g_ptz.hori_as5047d, sizeof(g_ptz.hori_as5047d));
memcpy(&power_off_data.vert_as5047d, &g_ptz.vert_as5047d, sizeof(g_ptz.vert_as5047d));
power_off_data.vert_angle = g_ptz.vert_angle_actual;
power_off_data.hori_angle = g_ptz.hori_angle_actual;
for(i = 0; i < PTZ_POWER_OFF_DATA_SAVE_NUM; i++)
{
memset(&power_off_data_b, 0, sizeof(power_off_data_b));
mb85rc64_write_read(add, (unsigned char *)&power_off_data, sizeof(power_off_data), PAGE_WRITE);
mb85rc64_write_read(add, (unsigned char *)&power_off_data_b, sizeof(power_off_data_b), ADDR_READ);
// mb85rc64_page_write(add, (unsigned char *)&power_off_data, sizeof(power_off_data));
// mb85rc64_add_read(add, (unsigned char *)&power_off_data_b, sizeof(power_off_data_b));
if(memcmp(&power_off_data_b, &power_off_data, sizeof(power_off_data)) == 0)//判断擦除数据是否正确
{
BSP_OS_SemPost(&ptz_power_off_mutex);
return 1;
}
}
BSP_OS_SemPost(&ptz_power_off_mutex);
return 0;
}

94
drivers/statusmonitor.h Normal file
View File

@ -0,0 +1,94 @@
#ifndef _STATUSMONITOR_H_
#define _STATUSMONITOR_H_
#include "gd32f4xx.h"
#include "drv_adc.h"
#include "mb85rc64.h"
typedef struct _PtzAs5047D_
{
///as5047d云台基准位置初始角度值
float as5047d_ptz_init_angle;
///as5047d角度相对于云台角度最大值
float as5047d_ptz_angle_max;
///磁编码器角度换算成云台角度对应的一次函数斜率K
float as5047d_ptz_angle_K;
///as5047d相对于云台的角度的滤波角度当前值
float as5047d_ptz_angle_wf_actual;
///as5047d相对于云台的角度的滤波角度上一次的值
float as5047d_ptz_angle_wf_last;
///as5047d相对于云台的角度当前实际值
float as5047d_ptz_angle_actual;
///as5047d相对于云台的角度上一次值
float as5047d_ptz_angle_last;
///云台转动范围对应的磁编码应当转动的总角度:
///as5047d_ptz_angle_max = as5047d_cycle_num * 360 + as5047d_remain_angle
///as5047d除开转动的整圈数外多出的不满足整圈的度数
float as5047d_remain_angle;
///as5047d转动的整圈数的数值
int as5047d_cycle_num;
///as5047d转动的整圈数计数转动一圈加减1
int as5047d_cycle_count;
int as5047d_cycle_count_last;
//int as5047d_cycle_count_last_last;
///as5047d采集到的实时角度值
float as5047d_angle_actual;
///as5047d的转向
char as5047d_dir;
///as5047d的数据读错次数
//unsigned int as5047d_read_error_count;
///as5047d采集到的上一次实时角度值
float as5047d_angle_last;
///as5047d采集到的实时角度值与上一次实时角度值的差值
float as5047d_angle_difference;
///as5047d的状态,0处于自检初始化1 数据能够正常使用, 0xff故障
char as5047d_state;
///as5047d的数据是否全部清除,0 不需要清除, 1清除数据
char as5047d_data_reset;
///磁编码器测转速
///as5047d磁编码器转速
float as5047d_speed_actual;
///测试as5047d磁编码器转速起始角度a
float as5047d_speed_angle_a;
///测试as5047d磁编码器转速结束角度b
float as5047d_speed_angle_b;
///测试as5047d磁编码器转速起始角度a、结束角度b之间的差值
float as5047d_speed_angle_c;
///测试as5047d磁编码器转速起始角度a、结束角度b之间的上一次差值
float as5047d_speed_angle_c_last;
unsigned int time_now;
unsigned int time_end;
unsigned int time;
}PtzAs5047D;
typedef struct _PowerOffData_
{
PtzAs5047D hori_as5047d;
PtzAs5047D vert_as5047d;
float hori_angle;
float vert_angle;
float power_down_offset_anle;
unsigned short int num;//编号,数字越大,表示存储的数据越新,主要用于判断最后一次保存的数据
float crc;
}PowerOffData;