你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32数组越界异常中断经验分享

[复制链接]
攻城狮Melo 发布时间:2024-5-25 16:14
这两天遇到一个问题,大概就是程序跑一半嗝屁了,然后嗝屁在了一个非常奇怪的地方。! {7 X' Y( ~2 I
9 \5 i# L9 @0 C* I; l7 F, c
微信图片_20240525161422.png   Z: {' K8 F6 H' F! u' Y% ~3 g; H# F

) R: h: M, F3 s' |, z6 D首先呢,我是怀疑变量出问题了,因为很显然,我们卡在了赋值这里,难不成是double类型的赋值出现了问题?
' [( k3 u" z, L% S( I- Q. m; J
" M. f+ P  L# U7 P* R5 f( g& U
首先我尝试将double类型修改为了float类型,这里虽然觉得很大的可能并不是这个的原因,但是没有办法,程序确确实实卡在了这么个奇怪的地方,我当然也怀疑单片机在处理双精度浮点数是不是出问题了。
7 i8 t, u$ b( r
5 r$ F% ^; w4 [' B" N6 n% H
不过随着我修改完数据类型,问题并没有得到有效的解决,程序依旧是在这里卡住。
4 H% A& H2 Y6 x
9 F3 h) d0 D% _* i
不过有一点非常奇怪,程序是在这个地方卡住没有错,但是卡住的位置会在这两个语句之间切换,就是可能是这条语句,也可能下一条语句!这时候我已经有一点懵逼了,不过为了确认程序卡在了哪里(通常这个情况是进异常中断了)我们暂停程序,查看程序指针当前的位置。
# w; w+ F6 O4 c) h
/ ^( _: ]" Q$ j/ c  X
  1. void HardFault_Handler(void): |( y& Q4 D8 r, Q
  2. {
    + B* g7 z9 l, @! V6 p0 b
  3.   /* USER CODE BEGIN HardFault_IRQn 0 */
    $ `0 a" W/ _% ?+ y; g0 R
  4. % _& ?5 ^  J! I; Z' I

  5. , m0 h; [# l! g+ |6 G* @; @
  6.   /* USER CODE END HardFault_IRQn 0 */' ~$ f+ H6 B# i1 y
  7.   while (1)( b( c# {* d0 N0 V1 \
  8.   {' Z+ [1 u6 U5 D7 l2 f8 |, O2 E
  9.     /* USER CODE BEGIN W1_HardFault_IRQn 0 */4 E- V2 t9 }$ _5 ?7 p! f1 ]
  10.     /* USER CODE END W1_HardFault_IRQn 0 */
    - O8 ?% a' b8 H, ]; r# D3 l
  11.   }
    " [6 m7 |/ f7 n# N* P, h  v* A1 n/ J
  12. }
复制代码

+ |7 Y! ~& ?1 h: f0 ^3 ?我发现程序指针所在的位置非常的奇怪,程序指针这时候卡在的地方是一个异常中断没错,但是这个中断回调函数的所在.c文件居然是dma的附属文件,没错这份工程是开了ADC的DMA采样的,采样的数据是传输进入DMA的。" b# L3 C5 H, T: V) v9 H
% r  f" g3 e- H4 x
这说明问题的主要的原因和DMA有关系,并且查看关于这个中断的说明造成这个中断的主要原因是:
! j$ C. I9 O( \6 D1.未完成硬件初始化而使用硬件5 C. j+ ~! ]& L  d- ~, D2 f
2.数据越界+ e1 w' |/ z5 \5 X, }; x4 h9 G2 u
3.野指针
% ?/ g; w3 e+ M: @  d# Z& F! M( ~- c1 U2 ?1 U: E- C: W  d# [# I
其实这三个的问题都可以归类为指针问题,而由于我的程序是初始化部分是正常执行的,那么可以排除硬件初始化未完成导致的异常。
1 g7 T: M: _1 ^  V% x5 s9 t
# E: k7 h( \5 H+ }, ?" ?
至于野指针也几乎没有出现使用指针而未声明的情况。4 p* d7 @/ Y) U! s9 ?4 ?( e9 n7 u0 V

- H8 ]. @+ K# R1 g! J
因此大概率是数组越界导致的原因,结合出现在DMA文件的报错,猜测可能是由于DMA传输的时候,缓存区和缓存区大小不匹配,导致传入数据的时候,索引超出发生数组越界错误。
; Y& _. E: P$ Z- R$ Y
  1. HAL_UART_Transmit (&huart1,(uint8_t*)message1,strlen(message1),100);6 u) a6 u2 Q' b+ i. U& O6 b
  2. end();
    / I& v# b+ K0 {
  3.   HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);6 q$ p8 Z" e" w
  4.   HAL_ADCEx_Calibration_Start(&hadc1);  //ad校准  
    7 I: K- L1 @& ?! o0 ?/ J3 V
  5.   HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_Value,1024);
复制代码
, v& b. O1 o' V
之后去查看DMA的缓存区,发现其数组大小是100(其实这时候我就知道了)因为我之前使用ADC信号的缓存区大小通常是1024的,再不济也是2的倍数,因为这样子好方便计算机处理。
, m% c# A7 z) Y! _) M
2 f/ o' M5 ~/ p' a 微信图片_20240525161419.png
' b9 k. D% }. ]5 e+ v6 o
8 b+ f% C2 z. _+ v) W9 c
所以这里的主要原因还是在于DMA传输的时候数组越界问题。" v) B' j- Y5 Z8 q1 c: I2 l( n

3 N9 Q3 w( B) M, B+ M# U
而ADC的触发采样则正好是定时器触发,定时器触发越界之后刚好卡在了那段话。6 c8 T" i8 ~! g3 v2 I* t
6 Q. V" O, z, g( b4 x# N' T# T
这类也提醒大家,一定要注意编程习惯,如果在编程中我们习惯性的使用宏定义的方式来编程,就能即方便而又能有效的规避掉这类的错误。
! G( A! {3 _% t: l
- \% M* [. ]( c* [1 Z- e
同样的关于STM32的中断源除了我们常见的硬件中断例如定时器,外部中断等等。
4 e) b2 t) {3 @% `# g$ M+ v4 `, n% Z/ P7 I- y- f! ?3 m  G# K' c. }
还不能忽略了其软件中断,包括一些硬件错误,未知命令错误以及我们程序员自己出现的错误,因此关注我们的中断错误类型可以有效地避免我们的程序出现很多异常的错误。也可以帮助我们更快地修改我们的异常代码。
8 Y% p. i! _) @. `' C* u* s6 e; I) x5 p
$ X  e+ _: x0 W7 M+ P( F
1 u: R9 b+ i/ M0 Z4 u& O5 s, \
转载自:电路小白  B0 w2 I$ q& C% Z. l
如有侵权请联系删除! _& a& O0 {! j  K& H8 x$ u+ w' n6 ?5 x
* Z! c5 v6 u2 R2 m% s) j
3 [! V; i1 B$ p* J

5 `0 x7 g2 [' v( G& E; d, h
5 ?+ ~* _( M  a: R
赞 收藏 评论0 发布时间:2024-5-25 16:14

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版