模拟PWM波的自适应取阈值算法

前言:
  单片机开发中,我们常常接触到的波形就是PWM波,一般都是0~3.3V的数字PWM波,很少涉及模拟PWM波。两者有什么不同呢?模拟PWM波不只有高低电平,还有中间的一些变化过程,且波形可能也不是规整的矩形波,再者它的电压可能超过3.3v导致无法直接用单片机IO口识别,PWM无法直接捕获到上升下降沿。
  如果你预算充足,开发的设备也不是非常的小型话,可以容纳额外的电路,那么你可以考虑从硬件上增加一些运放电路或整形电路,尽可能将模拟PWM变为数字PWM,如果不行就得考虑串联电阻来分压,然后代码中通过AD采样到数据后进行算法处理。

1 自适应算法

1.1 自适应取阈值算法思路:

模拟PWM波的自适应取阈值算法

前言:
  单片机开发中,我们常常接触到的波形就是PWM波,一般都是0~3.3V的数字PWM波,很少涉及模拟PWM波。两者有什么不同呢?模拟PWM波不只有高低电平,还有中间的一些变化过程,且波形可能也不是规整的矩形波,再者它的电压可能超过3.3v导致无法直接用单片机IO口识别,PWM无法直接捕获到上升下降沿。
  如果你预算充足,开发的设备也不是非常的小型话,可以容纳额外的电路,那么你可以考虑从硬件上增加一些运放电路或整形电路,尽可能将模拟PWM变为数字PWM,如果不行就得考虑串联电阻来分压,然后代码中通过AD采样到数据后进行算法处理。

1 自适应算法

1.1 自适应取阈值算法思路:

自适应算法思路.png

这里的MAX,MIN,LOW电压值都是不确定的,受传输距离和干扰影响。

1.2 具体算法:

  1. 求出PWM波采样值的MAX和MIN值:监测波形20ms(大于周期15.01ms),采集这段时间内的最大的20个采样值和最小的20个采样值(使用插入排序),舍弃20个数据的头尾各2个共4个数据,对十六个数据求平均值(求和后右移4位)。得出PWM的MAX和MIN值。
  2. 识别PWM波开始输出的第一个上升沿:差值MAXMINDiff = MAX - MIN, 监测波形20ms,寻找采样值从小于MIN + MAXMINDiff/3(避免1/3除法运算,1/3 = 5/15 约等于5/16 = 4/16 + 1/16 = 1/4 + 1/16 = >>2 + >>4)跳变到大于MAX - MAXMINDiff/3(且小于MIN + MAXMINDiff/3的持续时间需大于一个25kHz的周期,PWM输出期间半个周期就会有一个上升沿,若持续一个周期都未出现认为当前处于无PWM输出阶段)的上升沿。最大采集20ms,如果期间识别到上升沿则会提前结束,这段时间是不固定的。
  3. 识别PWM波的波峰值High和波谷值Low:PWM开始输出后进行1ms(理论PWM输出时间为1.28ms,监测时间需小于此)的监测,方法同步骤1,求出Low平均值, High平均值等于MAX平均值。
  4. 取阈值:求出差值HighLowDiff = High - Low,采样值取SampleHigh = High - HighLowDiff/3(1/3运算同步骤3), SampleLow = Low + HighLowDiff/3。
  5. 根据需要阈值也可选取为(SampleHigh + SampleLow)/2。

  c代码实现(这段代码我在一个自动测试程序中一直在使用,暂未发现问题):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//自适应求阈值函数,用于区分模拟PWM的上升下降沿。此函数工作在32MHz晶振下
en_result_t GetThreshold_SelfAdaption(uint16_t* pu16AdcRegHighThd, uint16_t* pu16AdcRegLowThd)
{
uint32_t u32MaxMinSampleTime = 640000; //取出20ms(至少要大于一个周期时间)时间内SELF_ADAPTION_NUM个最小的采样值和SELF_ADAPTION_NUM个最大的采样值
uint32_t u32LowSampleTime = 32000; //取出1ms(不能大于1.28ms的PWM输出时间)时间内SELF_ADAPTION_NUM个最小的采样值,用于确定u16AvgVLow
uint16_t u16Vmax[SELF_ADAPTION_NUM] = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, //0:小 19:大
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u};
uint16_t u16Vmin[SELF_ADAPTION_NUM] = {65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, //0:大 19:小
65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u};
uint16_t u16VLow[SELF_ADAPTION_NUM] = {65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, //0:大 19:小
65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u};
uint16_t u16AvgVmax = 0u; //最大采样值平均值
uint16_t u16AvgVmin = 0u; //最小采样值平均值
uint16_t u16AvgVHigh = 0u; //模拟PWM波峰采样值平均值
uint16_t u16AvgVLow = 0u; //模拟PWM波谷采样值平均值
uint32_t u32Sum = 0u; //采样值之和
uint32_t u32TIMCnt = 0u; //定时器计数值
uint16_t u16AdcResult = 0u; //AD采样值
uint8_t u8StateFlg = TRUE; //用于标识当前采样值处于波峰还是波谷,False:波谷 TRUE:波峰
uint8_t u8StatePreFlg = TRUE; //u8StateFlg的历史值
uint8_t u8MaxToMinFlg = FALSE; //检测波谷跳变到波峰的标志,TRUE:检测到,FALSE:未检测到
int8_t i = 0;
int8_t j = 0;
uint16_t u16DiffValue = 0u; //u16VLow和u16VHign的差值
uint16_t u16DiffValue_5_16 = 0u; //差值的5/16,接近1/3
uint32_t u32LatestMaxTime = 0u; //最新采样值处于u16AvgVmax附近的时间
uint32_t u32KeepMinTime = 0u; //采样电压值持续保持在u16AvgVmin附近的时间
uint32_t u32SpaceDiffCntJuge = 1280u; //间隔计数差值判断标准, 1/25000 * 32000000 = 1280,32M下25KHz一个周期计数值为1280,大于此间隔则认为是长间隔。
en_result_t enResult = Ok;

//取一段时间内的采样值最小值和最大值(分别取最小/最大的SELF_ADAPTION_NUM个)
u16AdcResult = 0u;
Bt_Run(TIM1); //BT TIM1定时器开始计时
while(u32TIMCnt < u32MaxMinSampleTime)
{
Adc_Start(); //ADC转换开始
Adc_GetResult(&u16AdcResult); //获取ADC转换值

if(u16AdcResult > u16Vmax[0]) //大于u16Vmax中最小的则新增
{
//插入排序,小到大排
for(i = SELF_ADAPTION_NUM - 1; i >= 0; i--) //从数组右往左找
{
if(u16Vmax[i] < u16AdcResult) //找到第一个比采样值小的
{
//往左移动,0号最小的被移出
for(j = 0; j < i; j++)
{
u16Vmax[j] = u16Vmax[j+1];
}

//插入采样值
u16Vmax[i] = u16AdcResult;
break;
}
}
}

if(u16AdcResult < u16Vmin[19]) //小于u16Vmin中最大的则新增
{
//插入排序,小到大排
for(i = 0; i < SELF_ADAPTION_NUM; i++) //从数组左往右找
{
if(u16Vmin[i] > u16AdcResult) //找到第一个比采样值大的
{
//往右移动,19号最大的被移出
for(j = SELF_ADAPTION_NUM - 1; j > i; j--)
{
u16Vmin[j] = u16Vmin[j-1];
}

//插入采样值
u16Vmin[i] = u16AdcResult;
break;
}
}
}

u32TIMCnt = Bt_Cnt32Get(TIM1); //获取计时数
}

//获取采样值最大最小平均值
//采样值最大值平均值
for(i = 2, u32Sum = 0; i < SELF_ADAPTION_NUM - 2; i++) //舍弃首位各两个,做16个的平均值,用移位避免除法
{
u32Sum = u32Sum + u16Vmax[i];
}
u16AvgVmax = u32Sum >> 4;

//采样值最小值平均值
for(i = 2, u32Sum = 0; i < SELF_ADAPTION_NUM - 2; i++) //舍弃首位各两个,做16个的平均值,用移位避免除法
{
u32Sum = u32Sum + u16Vmin[i];
}
u16AvgVmin = u32Sum >> 4;

if(u16AvgVmax > u16AvgVmin) //异常检查
{
//求模拟PWM波峰波谷采样值平均值
//波峰采样值平均值
u16AvgVHigh = u16AvgVmax;

//波谷采样值平均值
//找到从u16AvgVmin跳变到u16AvgVmax的上升沿,此后开始一段时间的最小采样值求取
Bt_Cnt32Set(TIM1, 0u); //计数值清零
u32TIMCnt = 0u;
u8MaxToMinFlg = FALSE;
u16AdcResult = 0u;
u16DiffValue = u16AvgVmax - u16AvgVmin;
u16DiffValue_5_16 = (u16DiffValue >> 2) + (u16DiffValue >> 4); //1/4 + 1/16 = 5/16 接近1/3
while(u32TIMCnt < u32MaxMinSampleTime)
{
Adc_Start(); //ADC转换开始
Adc_GetResult(&u16AdcResult); //获取ADC转换值

if(u16AdcResult < u16AvgVmin + u16DiffValue_5_16) //认为处于最小值范围
{
u8StateFlg = FALSE;
u32KeepMinTime = u32TIMCnt - u32LatestMaxTime;
}
else if(u16AdcResult > u16AvgVmax - u16DiffValue_5_16) //认为处于最大值范围
{
u8StateFlg = TRUE;
u32LatestMaxTime = u32TIMCnt;
}

if((u8StateFlg == TRUE) && (u8StatePreFlg == FALSE) && (u32KeepMinTime >= u32SpaceDiffCntJuge )) //由波谷变到波峰
{
u8MaxToMinFlg = TRUE; //标记从波谷跳到波峰
break;
}

u8StatePreFlg = u8StateFlg;

u32TIMCnt = Bt_Cnt32Get(TIM1); //获取计时数
}

if(u8MaxToMinFlg == TRUE) //识别到跳变
{
Bt_Cnt32Set(TIM1, 0u); //计数值清零
u32TIMCnt = 0u;
u16AdcResult = 0u;
while(u32TIMCnt < u32LowSampleTime)
{
Adc_Start(); //ADC转换开始
Adc_GetResult(&u16AdcResult); //获取ADC转换值

if(u16AdcResult < u16VLow[SELF_ADAPTION_NUM - 1]) //小于u16Vmin中最大的则新增
{
//插入排序,小到大排
for(i = 0; i < SELF_ADAPTION_NUM; i++) //从数组左往右找
{
if(u16VLow[i] > u16AdcResult) //找到第一个比采样值大的
{
//往右移动,19号最大的被移出
for(j = SELF_ADAPTION_NUM - 1; j > i; j--)
{
u16VLow[j] = u16VLow[j-1];
}

//插入采样值
u16VLow[i] = u16AdcResult;
break;
}
}
}

u32TIMCnt = Bt_Cnt32Get(TIM1); //获取计时数
}

//PWM波部分采样值最大值平均值
for(i = 2, u32Sum = 0; i < SELF_ADAPTION_NUM - 2; i++) //舍弃首位各两个,做16个的平均值,用移位避免除法
{
u32Sum = u32Sum + u16VLow[i];
}
u16AvgVLow = u32Sum >> 4;

if(u16AvgVHigh > u16AvgVLow) //异常检查
{
u16DiffValue = u16AvgVHigh - u16AvgVLow;
u16DiffValue_5_16 = (u16DiffValue >> 2) + (u16DiffValue >> 4); //1/4 + 1/16 = 5/16 接近1/3
*pu16AdcRegHighThd = u16AvgVHigh - u16DiffValue_5_16;
*pu16AdcRegLowThd = u16AvgVLow + u16DiffValue_5_16;
}
else
{
enResult = Error;
}
}
else //检测时间内未识别到波谷到波峰的跳变
{
enResult = Error;
}
}
else
{
enResult = Error;
}

Bt_Stop(TIM1); //定时器停止
Bt_Cnt32Set(TIM1, 0u); //计数值清零

return enResult;
}

这里的MAX,MIN,LOW电压值都是不确定的,受传输距离和干扰影响。

1.2 具体算法:

  1. 求出PWM波采样值的MAX和MIN值:监测波形20ms(大于周期15.01ms),采集这段时间内的最大的20个采样值和最小的20个采样值(使用插入排序),舍弃20个数据的头尾各2个共4个数据,对十六个数据求平均值(求和后右移4位)。得出PWM的MAX和MIN值。
  2. 识别PWM波开始输出的第一个上升沿:差值MAXMINDiff = MAX - MIN, 监测波形20ms,寻找采样值从小于MIN + MAXMINDiff/3(避免1/3除法运算,1/3 = 5/15 约等于5/16 = 4/16 + 1/16 = 1/4 + 1/16 = >>2 + >>4)跳变到大于MAX - MAXMINDiff/3(且小于MIN + MAXMINDiff/3的持续时间需大于一个25kHz的周期,PWM输出期间半个周期就会有一个上升沿,若持续一个周期都未出现认为当前处于无PWM输出阶段)的上升沿。最大采集20ms,如果期间识别到上升沿则会提前结束,这段时间是不固定的。
  3. 识别PWM波的波峰值High和波谷值Low:PWM开始输出后进行1ms(理论PWM输出时间为1.28ms,监测时间需小于此)的监测,方法同步骤1,求出Low平均值, High平均值等于MAX平均值。
  4. 取阈值:求出差值HighLowDiff = High - Low,采样值取SampleHigh = High - HighLowDiff/3(1/3运算同步骤3), SampleLow = Low + HighLowDiff/3。
  5. 根据需要阈值也可选取为(SampleHigh + SampleLow)/2。

  c代码实现(这段代码我在一个自动测试程序中一直在使用,暂未发现问题):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//自适应求阈值函数,用于区分模拟PWM的上升下降沿。此函数工作在32MHz晶振下
en_result_t GetThreshold_SelfAdaption(uint16_t* pu16AdcRegHighThd, uint16_t* pu16AdcRegLowThd)
{
uint32_t u32MaxMinSampleTime = 640000; //取出20ms(至少要大于一个周期时间)时间内SELF_ADAPTION_NUM个最小的采样值和SELF_ADAPTION_NUM个最大的采样值
uint32_t u32LowSampleTime = 32000; //取出1ms(不能大于1.28ms的PWM输出时间)时间内SELF_ADAPTION_NUM个最小的采样值,用于确定u16AvgVLow
uint16_t u16Vmax[SELF_ADAPTION_NUM] = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, //0:小 19:大
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u};
uint16_t u16Vmin[SELF_ADAPTION_NUM] = {65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, //0:大 19:小
65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u};
uint16_t u16VLow[SELF_ADAPTION_NUM] = {65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, //0:大 19:小
65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u, 65535u};
uint16_t u16AvgVmax = 0u; //最大采样值平均值
uint16_t u16AvgVmin = 0u; //最小采样值平均值
uint16_t u16AvgVHigh = 0u; //模拟PWM波峰采样值平均值
uint16_t u16AvgVLow = 0u; //模拟PWM波谷采样值平均值
uint32_t u32Sum = 0u; //采样值之和
uint32_t u32TIMCnt = 0u; //定时器计数值
uint16_t u16AdcResult = 0u; //AD采样值
uint8_t u8StateFlg = TRUE; //用于标识当前采样值处于波峰还是波谷,False:波谷 TRUE:波峰
uint8_t u8StatePreFlg = TRUE; //u8StateFlg的历史值
uint8_t u8MaxToMinFlg = FALSE; //检测波谷跳变到波峰的标志,TRUE:检测到,FALSE:未检测到
int8_t i = 0;
int8_t j = 0;
uint16_t u16DiffValue = 0u; //u16VLow和u16VHign的差值
uint16_t u16DiffValue_5_16 = 0u; //差值的5/16,接近1/3
uint32_t u32LatestMaxTime = 0u; //最新采样值处于u16AvgVmax附近的时间
uint32_t u32KeepMinTime = 0u; //采样电压值持续保持在u16AvgVmin附近的时间
uint32_t u32SpaceDiffCntJuge = 1280u; //间隔计数差值判断标准, 1/25000 * 32000000 = 1280,32M下25KHz一个周期计数值为1280,大于此间隔则认为是长间隔。
en_result_t enResult = Ok;

//取一段时间内的采样值最小值和最大值(分别取最小/最大的SELF_ADAPTION_NUM个)
u16AdcResult = 0u;
Bt_Run(TIM1); //BT TIM1定时器开始计时
while(u32TIMCnt < u32MaxMinSampleTime)
{
Adc_Start(); //ADC转换开始
Adc_GetResult(&u16AdcResult); //获取ADC转换值

if(u16AdcResult > u16Vmax[0]) //大于u16Vmax中最小的则新增
{
//插入排序,小到大排
for(i = SELF_ADAPTION_NUM - 1; i >= 0; i--) //从数组右往左找
{
if(u16Vmax[i] < u16AdcResult) //找到第一个比采样值小的
{
//往左移动,0号最小的被移出
for(j = 0; j < i; j++)
{
u16Vmax[j] = u16Vmax[j+1];
}

//插入采样值
u16Vmax[i] = u16AdcResult;
break;
}
}
}

if(u16AdcResult < u16Vmin[19]) //小于u16Vmin中最大的则新增
{
//插入排序,小到大排
for(i = 0; i < SELF_ADAPTION_NUM; i++) //从数组左往右找
{
if(u16Vmin[i] > u16AdcResult) //找到第一个比采样值大的
{
//往右移动,19号最大的被移出
for(j = SELF_ADAPTION_NUM - 1; j > i; j--)
{
u16Vmin[j] = u16Vmin[j-1];
}

//插入采样值
u16Vmin[i] = u16AdcResult;
break;
}
}
}

u32TIMCnt = Bt_Cnt32Get(TIM1); //获取计时数
}

//获取采样值最大最小平均值
//采样值最大值平均值
for(i = 2, u32Sum = 0; i < SELF_ADAPTION_NUM - 2; i++) //舍弃首位各两个,做16个的平均值,用移位避免除法
{
u32Sum = u32Sum + u16Vmax[i];
}
u16AvgVmax = u32Sum >> 4;

//采样值最小值平均值
for(i = 2, u32Sum = 0; i < SELF_ADAPTION_NUM - 2; i++) //舍弃首位各两个,做16个的平均值,用移位避免除法
{
u32Sum = u32Sum + u16Vmin[i];
}
u16AvgVmin = u32Sum >> 4;

if(u16AvgVmax > u16AvgVmin) //异常检查
{
//求模拟PWM波峰波谷采样值平均值
//波峰采样值平均值
u16AvgVHigh = u16AvgVmax;

//波谷采样值平均值
//找到从u16AvgVmin跳变到u16AvgVmax的上升沿,此后开始一段时间的最小采样值求取
Bt_Cnt32Set(TIM1, 0u); //计数值清零
u32TIMCnt = 0u;
u8MaxToMinFlg = FALSE;
u16AdcResult = 0u;
u16DiffValue = u16AvgVmax - u16AvgVmin;
u16DiffValue_5_16 = (u16DiffValue >> 2) + (u16DiffValue >> 4); //1/4 + 1/16 = 5/16 接近1/3
while(u32TIMCnt < u32MaxMinSampleTime)
{
Adc_Start(); //ADC转换开始
Adc_GetResult(&u16AdcResult); //获取ADC转换值

if(u16AdcResult < u16AvgVmin + u16DiffValue_5_16) //认为处于最小值范围
{
u8StateFlg = FALSE;
u32KeepMinTime = u32TIMCnt - u32LatestMaxTime;
}
else if(u16AdcResult > u16AvgVmax - u16DiffValue_5_16) //认为处于最大值范围
{
u8StateFlg = TRUE;
u32LatestMaxTime = u32TIMCnt;
}

if((u8StateFlg == TRUE) && (u8StatePreFlg == FALSE) && (u32KeepMinTime >= u32SpaceDiffCntJuge )) //由波谷变到波峰
{
u8MaxToMinFlg = TRUE; //标记从波谷跳到波峰
break;
}

u8StatePreFlg = u8StateFlg;

u32TIMCnt = Bt_Cnt32Get(TIM1); //获取计时数
}

if(u8MaxToMinFlg == TRUE) //识别到跳变
{
Bt_Cnt32Set(TIM1, 0u); //计数值清零
u32TIMCnt = 0u;
u16AdcResult = 0u;
while(u32TIMCnt < u32LowSampleTime)
{
Adc_Start(); //ADC转换开始
Adc_GetResult(&u16AdcResult); //获取ADC转换值

if(u16AdcResult < u16VLow[SELF_ADAPTION_NUM - 1]) //小于u16Vmin中最大的则新增
{
//插入排序,小到大排
for(i = 0; i < SELF_ADAPTION_NUM; i++) //从数组左往右找
{
if(u16VLow[i] > u16AdcResult) //找到第一个比采样值大的
{
//往右移动,19号最大的被移出
for(j = SELF_ADAPTION_NUM - 1; j > i; j--)
{
u16VLow[j] = u16VLow[j-1];
}

//插入采样值
u16VLow[i] = u16AdcResult;
break;
}
}
}

u32TIMCnt = Bt_Cnt32Get(TIM1); //获取计时数
}

//PWM波部分采样值最大值平均值
for(i = 2, u32Sum = 0; i < SELF_ADAPTION_NUM - 2; i++) //舍弃首位各两个,做16个的平均值,用移位避免除法
{
u32Sum = u32Sum + u16VLow[i];
}
u16AvgVLow = u32Sum >> 4;

if(u16AvgVHigh > u16AvgVLow) //异常检查
{
u16DiffValue = u16AvgVHigh - u16AvgVLow;
u16DiffValue_5_16 = (u16DiffValue >> 2) + (u16DiffValue >> 4); //1/4 + 1/16 = 5/16 接近1/3
*pu16AdcRegHighThd = u16AvgVHigh - u16DiffValue_5_16;
*pu16AdcRegLowThd = u16AvgVLow + u16DiffValue_5_16;
}
else
{
enResult = Error;
}
}
else //检测时间内未识别到波谷到波峰的跳变
{
enResult = Error;
}
}
else
{
enResult = Error;
}

Bt_Stop(TIM1); //定时器停止
Bt_Cnt32Set(TIM1, 0u); //计数值清零

return enResult;
}