[已解决]RTC_Alarm_IRQHandler() 中断中发送邮件,邮箱打断

发表在 RTC2019-5-31 17:38 [复制链接] 10 562

本帖最后由 tcsun 于 2019-6-6 16:21 编辑 & e+ w0 x: g% e
$ ^: |2 M+ [+ i/ O
                     RTC_Alarm_IRQHandler() 中断中发送邮件,邮箱可以接收到邮件,但运行一半就被打断。( P, ?( T6 S; u( }6 ~7 [0 v

3 W8 [& @5 ~$ O' Wbsp:   stm32f103x bsp
: r3 V7 L( @! f& T' X/ ~! L4 y
$ G" W$ u' E; `- {$ [; K问题描述:3 d9 L: _' f5 y1 S3 F- c, ]
               项目使用stm32f103ve rtc 闹钟 中断,作为定时开关控制。rtc 部分都已正常,我是想设置好闹钟后,当闹钟中断时在HAL_RTC_AlarmAEventCallback() 里
+ k) U% B( z) @, ~( `通过邮箱给继电器模块发一个继电器动作的邮件。但发现如果在HAL_RTC_AlarmAEventCallback()里给邮箱发送的邮件,在继电器模块里是可以接收到的,并且数据也正确,但就是进入不了switch(), 感觉一进到这里就被打断了。不跑switch 部分的代码。
" H% e5 u, g$ P( X) b+ R6 f             但我如果在main() 线程函数 里直接给邮箱发送同样的邮件,是可以实现功能的,是可以进入到switch()部分,并且正确执行操作。
" F& Y& e; \/ G- D' r! T3 N
& n! v2 w) b0 v! d' K% `  l9 F! g在HAL_RTC_AlarmAEventCallback() 里通过邮箱给继电器模块发一个继电器动作的邮件可以接收正确的数据,但不进入到case RTC_ALARM_MB:里进行相应的处理。具体信息如下 :
' n' A8 g' ^. U8 {: j% x5 a/ @
" W# R( R2 ~% Y: [  p% J9 a
& x. ?& _3 z0 T. u& A
$ @" q' L% t$ E$ `) B==========================================================================================================
) P. H1 C2 f2 K6 ^: D2 @$ x; Y0 T具体代码如下:3 T4 y; K9 S1 x# Z/ R1 v# Q2 I/ ?
. Z: Y* u' y- u/ w+ M" \
继电器部分 线程代码 :
7 r  Y( g6 |, X- S' ~0 m
( h2 k% p% v! N, r9 I
: O: P& Q( M* V: Z+ F6 f8 t/*****************************************************************
) ~. R4 L7 x" [. X- O* @brief   :Ctr_Watch_thread_entry()  9 `0 l! K% o6 }! Y2 \# ^
* @param   :继电器模块线程入口函数0 c) _0 v7 L8 Z/ P+ D5 i9 t
* @retval  :无- A6 Q* t. x9 M# j7 F6 d7 z
****************************************************************/
6 i5 \+ [1 a: \: i8 tvoid Ctr_Watch_thread_entry(void* parameter); r8 S3 c) l4 f2 r' [' N  E* n
{5 `4 t; _0 w" ~
        rt_err_t result = RT_EOK;
5 s8 s3 }- q( {5 Y3 \/ V    char *mb;. y1 a4 f2 B  ]8 o5 q# X: f
    /* 邮箱控制块 */
& v8 ?) D% g$ u4 A+ n6 @% I: f    struct rt_mailbox mb_ctr;               ///继电器控制事件
; A. n9 p4 }# e( y2 O7 L
& {4 {. y1 M1 |+ S! v/ o( c    /* 用于放邮件的内存池 */
' [' n$ F3 \: A" I$ d; @0 V: R    static char mb_pool[32];                   & {1 A& F5 U6 l. n
; J2 D3 a5 R: A
# d- P- L8 s- `# ^* _, W
    /* 初始化邮箱对象 */
2 B1 n& C% r( Z5 I) T; ]8 m    result = rt_mb_init(&mb_ctr,
. w+ g% L$ i( y4 D                        "mb_relay",                 /* 名称是 mb_relay */
7 m% }; K8 t3 w- n% r+ F                        &mb_pool[0],                /* 邮箱用到的内存池是 mb_pool */9 s6 ~2 P0 o1 g2 f" T
                        sizeof(mb_pool) / 4,        /* 邮箱中的邮件数目,因为一封邮件占 4 字节 */3 p  f5 \0 L6 t; B* b
                        RT_IPC_FLAG_FIFO);          /* 采用 FIFO 方式进行线程等待 */9 z4 b. X' u+ E2 K  b# J
    if (result != RT_EOK): ]; Y( @$ m: L' U8 U% z# {
    {( X4 w5 i( |' {
        rt_kprintf("init mailbox failed.\n");
4 H! O3 m8 O: L5 m+ O9 q//        return -1;5 W, x5 h! E' U9 I& ?4 d) Y: n
    }. v/ W$ e. e$ H

3 L5 K3 U; G. v7 X        while(1)7 I$ D2 _" w4 |1 n9 H/ L
        {
5 P# b, {' l2 ?1 v7 B) U1 t& x        if (rt_mb_recv(&mb_ctr, (rt_uint32_t *)&mb, RT_WAITING_FOREVER) == RT_EOK)* D  a, ~- N/ v! P& F; h
        {- U& W  ~3 G# _
            rt_kprintf("mb[0]=%02X mb[1]=%02X mb[2]=%02X mb[3]=%02X \n", mb[0], mb[1], mb[2], mb[3]);
, m  p% B1 s2 O5 Y/ l            switch(mb[0])) _2 Q# ~$ |" S, Z
            { : @: U# Z4 f$ y. h7 f
                case RTC_ALARM_MB:7 q4 z- D- M' y2 _; i  [
                {   
. ]- z$ f2 k2 K' J2 p                  rt_kprintf("RTC_ALARM_MB alarm_flg=%d \n",relay_ctr.alarm_flg);
5 j( ^! h0 w& @& p                  if(relay_ctr.alarm_flg == 1)      // 0没有设置rtc闹钟 ,1:合闸闹钟已设置 ,2:拉闸闹钟已设置
. h8 ?6 P) s5 j& Q) m                  {! p; C2 f1 Q- G* U4 ?) s
                     relay_sw_on();
' U, F4 f1 L- l  Y7 a                     if(set_alarm(relay_ctr.off.hour,relay_ctr.off.min,0)== RT_EOK)  M  c/ g3 u9 w" J* V8 ?; [$ V6 S9 Y
                           relay_ctr.alarm_flg  = 2;
7 c  g9 ?: [" W0 M  i0 [5 @. \7 f7 y" Y                  }  p4 m1 C# N7 [  j- u+ b9 d2 b
                  else if(relay_ctr.alarm_flg == 2) + D/ C( r8 j9 X2 h% d! k, F4 [
                  {( }7 i- R3 ^/ U. F) W" z
                      relay_sw_off();
' W$ X) p9 x5 d- B$ S  t  c  T5 q                      if(set_alarm(relay_ctr.on.hour,relay_ctr.on.min,0)== RT_EOK)
$ F* j/ `4 m7 k8 p5 j6 R* Q                           relay_ctr.alarm_flg  = 1;
3 Q4 r, a  b* B" @5 F7 e                  }
) d6 m. l( P) ?" Q5 r$ h( m
& c6 D6 J6 Z8 b; q# ^) G: O' @! l                    break;  a/ S7 i2 Q8 ]$ r/ l; w' |, Y3 l
                }
6 L" g- K8 M. D6 e' {                case MANUAL_CONTROL_MB:( V/ o  f& u0 _6 T4 \: a" `
                {   
. L5 y5 a9 x$ z* q, h- Y                    if(mb[1]==0x01) relay_sw_on();                       4 O1 U5 E7 ?% G
                    else relay_sw_off();2 o2 T: Z5 j/ f7 q' G2 D* W
                    break;; x: ~  x2 ]( Y% o
                } $ _; B5 k  _/ S
                case RELAY_MODE_MB:
3 z* W0 F4 T& O8 N                {   # n" l! T3 I& H$ U0 I! G
                    relay_ctr.mode = mb[1];1 D# C  H3 `9 \& c. j& o: X$ T5 P
                    break;% E" s& b8 ]8 a, s# i! O' S6 H
                } 8 |  \3 I9 Q8 K8 e6 y( _4 \) ]
                case SET_ON_TIME_MB:
% E' u5 b' p' g' ]( k+ q: }+ C                {
& Y, R$ v$ o; Y                    uint32_t now_sec,on_sec;% [5 d. w; l9 o9 U/ d
                    relay_ctr.on.hour = mb[2];, k1 o. U+ E' I1 Z1 o
                    relay_ctr.on.min  = mb[3];& j: U4 z/ F0 w! t% p% W
                    now_sec = get_second_of_today();* |8 X1 Y; l( j# b) \, `  A
                    on_sec = relay_ctr.on.hour * 3600 + relay_ctr.on.min *60;+ E, S0 ?+ R' q" C
                    if((now_sec < on_sec )||(relay_ctr.alarm_flg ==0))
6 Z8 N2 S. F" A  g" X                    {
0 c7 W7 _$ R1 C5 k0 X' B. a                       if(set_alarm(relay_ctr.on.hour,relay_ctr.on.min,0)== RT_EOK)
+ B$ `3 Q1 \$ D) m1 V) Y1 n                           relay_ctr.alarm_flg  = 1;! I# X2 |* k0 k. j# P
                    }
2 G6 i, ^- ^4 v* w                    break;
* W7 F& d& S) A' H6 }: Z                } 1 t5 c! ~# c$ @- C
                case SET_OFF_TIME_MB:: B- [* B' n2 W: P0 H
                {   
9 B: T2 l* F1 @                    uint32_t now_sec,off_sec;" w8 @" O* s- R  B/ S. c. g- }
                    relay_ctr.off.hour = mb[2];
- p5 B/ q- G0 e: s% h* J1 ?# q                    relay_ctr.off.min  = mb[3];( y- h& g' R# [& Z
                    now_sec = get_second_of_today();
! x  `( }/ f) P5 ^: a$ Z9 J                    off_sec = relay_ctr.on.hour * 3600 + relay_ctr.on.min *60;! ^! P. m, i4 B2 }
                    if((now_sec < off_sec )&&(relay_ctr.alarm_flg ==0))
6 ~3 g( W: T1 H                    {! R  h& k: f0 |) r
                       if(set_alarm(relay_ctr.off.hour,relay_ctr.off.min,0)== RT_EOK)- L5 k8 W0 P0 G$ t
                           relay_ctr.alarm_flg  = 2;; @& [; `; e, ^0 i
                    }                    & h4 w7 M8 c% a# q- x! w) g  e
                    break;
9 f5 g* Y- n; x% \$ S% \! o                }
( A, a: e/ f& ~( U" S- d                default:- `; s8 Z( O2 ]
                    break;                . {4 S. C) {6 W
            }2 A5 q( I, ]! ]6 j: g! [

) r$ |1 t! X& O- Z1 G            /* 延时 100ms */
2 E) ^" w' |) c) x1 L+ \7 X' x            rt_thread_mdelay(400);+ P8 A, X9 J% l" B3 Q
        }      
" _0 I& n0 o0 e# G0 t    }5 s. F1 R+ L" j# |  g+ X6 C
}! T8 f' T/ N7 l$ U  B  W5 t3 t
+ y9 h! Z; J$ r

  ]  i. o3 k( b5 A: q============================================================================================2 E8 Q; ^  B8 t% |: s  D7 J
rtc alarm 中断函数:
4 |/ P, Z  D. K2 j) m6 C. y4 n/*****************************************************************  B) k/ C  @1 G: t- u
* @function :RTC_Alarm_IRQHandler()# _8 |- u; A1 K. \. W
* @brief   : RTC 闹钟中断函数 。6 G3 c* @6 M" _/ g0 O4 F/ `
* @param   : 无. ]; y' j: F; m, M: J; M
* @retval  : 无1 Z, b( Q6 h* B2 G1 i% t. N
****************************************************************/( y- `: [; a1 `3 q. M- W  D
void RTC_Alarm_IRQHandler(void)
. S# Y& p: Z; Y# F! N* \{
: s: w9 s) ~& g7 s9 H7 M4 g. y   // enter interrupt
9 v' N. V) O( F8 l( @7 R   rt_interrupt_enter();) h1 \+ Y# f0 K% ^' J) @4 Q
        HAL_RTC_AlarmIRQHandler(&RTC_Handler);( z' K9 {, ~, p% c
   rt_interrupt_leave();
2 p( f9 g4 {5 I; v}
& |# e+ i( D! \# \- W$ P0 t! A1 a8 ~+ I5 e+ P; M3 r

- \& A: }* L+ k4 Q' {+ u
+ ^& C8 {1 [6 R+ e5 E9 b* H==================================================================================================
% C! o% t  V; W) W3 z5 h$ KRTC 闹钟中断回调函数 :# R1 D; A0 j; o$ G1 ?4 ?: l2 P
+ {2 a0 p" R% G) ?) j- l1 d1 n
p_Mb: 是全局的邮箱句柄,先已用p_Mb =(rt_mailbox_t)rt_object_find("mb_relay",RT_Object_Class_MailBox); 找到。* l6 o, g: r  E, e

8 X" P( r+ e% Z% K5 a( L/ s' ]+ F" T*****************************************************************& a: {. `) h6 k3 P% ?9 m* c
* @function :HAL_RTC_AlarmAEventCallback()( E/ v& T  s% y
* @brief   : RTC 闹钟中断回调函数 。
* J& I1 R. P0 q9 R6 z* @param   : *hrtc:硬件RTC 句柄指针( @; h$ j# U% j7 H+ P# c. K
* @retval  : 无
# K0 w0 M3 E6 K& z( n. ~' T****************************************************************/        
1 n' R. h7 K5 Y9 p1 P; @) Kvoid HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc), H/ }" @. ~/ M! Z1 |6 w1 B, k7 P
{3 ]8 ]/ Y1 r' I3 C6 A
2 X# J( q( S7 r- x0 t; Z; a
    char bm_rtc_alarm[4]={0x06,0x00,0x00,0x00}; 1 |3 f0 W, J+ p' P; o

1 r' @) z4 y1 s! Z
) Q4 z  \7 l# ?" y" }$ t    rt_kprintf("ALARM EvenCallback \n");   
! s. v; W+ e8 Q9 w2 `5 i6 z1 p. b    rt_enter_critical();
& y' V/ b' h4 h, L2 F! T: M5 Y    if(p_Mb!=NULL)
8 M! `" E( `$ m4 e6 ]( W    {5 R- ?% i! \% i# \+ O, N
        rt_mb_send(p_Mb, (rt_uint32_t)&bm_rtc_alarm);                    //发送邮件+ `5 @% g" ]3 I) x8 ~
        rt_kprintf("mb_send done!\n");
5 b7 O$ s% M% W- l    }
9 y: Z" Q8 s6 w    rt_exit_critical();
1 u( ^$ ]( ]4 K1 q}, r+ d& R4 m! |( l
4 M' X8 h  {) y, c
9 h/ ]5 A( b! b' L$ }2 D3 r1 Y
================================================================================================
" Y$ A2 }! j" ^+ k  f
- f" O' C4 P/ `main.c 里的继电器调试函数: 发送0x06,0x00,0x00,0x00 邮件数据是可以进入到case RTC_ALARM_MB:里的,是可以执行继电器控制代码的。
9 X8 o& o, I$ _0 h$ H, d/*****************************************************************0 q# Y' X8 s+ A
* @function : relay(uint8_t stats,uint8_t h,uint8_t min)! g0 H! p9 E! _
* @brief    : 继电器调试函数
" [  l, W5 s. F+ G1 q* @param    : stats:1手动控制,2:定时开,3,定时关,4:rtc alarm
8 k! x/ i- i& i. c: W- v* @retval   :
7 ~/ }& M! L" K! B, G) G, w* K: ]****************************************************************/
* z% v' O, R& O/ zvoid relay(uint8_t stats,uint8_t h,uint8_t min)
+ n' o3 s: K2 q8 A) t{
' c2 |% J, y  Q" ?  char bm_test[4]={0x10,0x00,0x00,0x00}; ' e! u; g7 j4 H4 K3 S7 a7 M

3 a- X# y- @$ o  b  switch(stats)
+ }( g/ B$ g5 F" ^7 ]3 |# j, O+ E  {
7 X! z9 D. n; c" a/ A0 E      case 1: bm_test[0]= 0x10;bm_test[1] = h; break;% A- P4 y* b' [
      case 2: bm_test[0]= 0x20;bm_test[2] = h;bm_test[3] = min;break;
0 x$ D( F9 @* w1 l0 C% H      case 3: bm_test[0]= 0x21;bm_test[2] = h;bm_test[3] = min;break;% ~. j7 d5 B4 G: R+ {
      case 4: bm_test[0]= 0x06;
, v% |) D8 B( Y3 a$ s9 _  }
% S+ U/ U, r8 i8 T& g" H4 e" j: w' `! i) q
  rt_mb_send(p_Mb_crt, (rt_uint32_t)&bm_test);
! m5 M2 j1 k) f( R8 S- _; S}  {# `. M4 o; k& Q0 G( A
FINSH_FUNCTION_EXPORT(relay,relay control 1:ON 0:OFF) ! ]' l9 i7 K8 Z, i
, G9 X# p: D) P/ p9 V* i
6 I, L4 _) `( k, E& n" s- w
. m0 u  X: i' _) ?7 @
下面是用rtc 中断发送的邮件数据,不能进入到case RTC_ALARM_MB: 的打印信息:8 |. g9 D9 }0 _5 `$ u% f
5 w7 Z2 U, K& `+ B4 ~/ ^' `% ^4 i0 p
ss
/ D7 \# o' {$ g8 l4 `) e$ D
ng.png
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-5-31 17:51:04 | 显示全部楼层
上面添加另一张图片老是出问题,在下面补上。
' D& U5 r0 `! _- V1 q, k! R  |& x2 o) F' ~' z; j3 i( r" R% u" F
下图是在main.c 里用继电器调试函数发送的邮件数据 是可以进入到case RTC_ALARM_MB: 的打印信息:
OK.png
使用道具 举报 回复
发表于 2019-5-31 17:52:21 | 显示全部楼层
哪位大神帮忙看一下是什么原因?
使用道具 举报 回复
发表于 2019-6-5 09:50:03 | 显示全部楼层
哪能帮忙指导一下!感谢了!
使用道具 举报 回复
发表于 2019-6-5 10:38:49 | 显示全部楼层
你在中断发送的内容跟在main.c里发送的数据不一样。怀疑是你发送的0x06在switch里面没有对应的值。
使用道具 举报 回复
发表于 2019-6-5 12:06:34 | 显示全部楼层
zhangjun 发表于 2019-6-5 10:38
& p8 B" l: m- k1 ^  e1 P/ |  ?0 w你在中断发送的内容跟在main.c里发送的数据不一样。怀疑是你发送的0x06在switch里面没有对应的值。 ...

* D: B$ ^) C4 H0 ~7 S4 s dd.jpg 4 f9 i/ Q# [4 O, O$ p( w! t5 [

3 |  c5 `, d0 b6 n1 f感谢!
$ Z2 ]& _  T3 z: g4 W: y8 ^! J6 w. w
我对过,数据是一样的。7 h* W& X- M% o
使用道具 举报 回复
发表于 2019-6-5 13:01:40 | 显示全部楼层
楼主可以发下工程吗,这么看想不出来是啥原因。
使用道具 举报 回复
发表于 2019-6-5 14:25:10 | 显示全部楼层
zhangjun 发表于 2019-6-5 13:01! r, ?  N- G" X2 s8 @
楼主可以发下工程吗,这么看想不出来是啥原因。
0 q* w- c7 @, \* J2 }
工程如附件,因为文件较大我只保留了libraries 文件夹里的STM32F1xx_HAL 文件和HAL_Drivers 文件。( P# e6 e9 {% I5 }( V) B; v7 s5 |

3 D) ~, v; w1 X- o# }另外:HAL_Drivers/文件下的drv_rtc.c 我有修改。
; A% w% T. E' W/ i  q' Q/ y
$ T6 j9 ?3 d6 |+ p/ G4 d# l
! h. A3 h/ j. v+ }' \' L. Z3 N7 m1 e. V; ~
$ k0 q% P5 @  h8 v. j: r

stm32.rar

4.23 MB, 下载次数: 181

使用道具 举报 回复
发表于 2019-6-5 14:29:00 | 显示全部楼层
tcsun 发表于 2019-6-5 14:252 N  `3 f! O/ O" y' o! l3 S
工程如附件,因为文件较大我只保留了libraries 文件夹里的STM32F1xx_HAL 文件和HAL_Drivers 文件。7 d8 [3 N$ b2 _3 a  O3 i2 M' d! y

) s: I0 e4 {9 M另外 ...

6 u* K5 O1 @# s9 e另外在\libraries\STM32F1xx_HAL\STM32F1xx_HAL_Driver\Src\文件夹下增加了stm32f1xx_hal_rtc_refactor.c 文件
使用道具 举报 回复
发表于 2019-6-5 18:27:38 | 显示全部楼层
调试好了,( c3 W# Z* n* H" Q9 k
1,rt_mb_send 只是发送了一个指针,接收也只是接收了一个指针,数据本身并没有通过邮箱发送
  ^! L$ r4 n4 p, P5 @0 l) d2,但是你发送的指针是指向一个栈上的局部变量,这个变量在你代码发送邮件的函数退出后就可能被其他值覆盖。所以造成数据被改变了。
3 z! {) _8 s$ P, M7 w  c3,解决方法是把HAL_RTC_AlarmAEventCallback函数里面的
  1. char bm_rtc_alarm[4]={0x06,0x00,0x00,0x00};
复制代码
放到外面让他成为全局变量。
使用道具 举报 回复
发表于 2019-6-6 16:20:46 | 显示全部楼层
zhangjun 发表于 2019-6-5 18:27
0 ]* ~% x* J  z4 b调试好了,0 D8 F) F& x3 _8 E% m$ ?" _2 s/ B
1,rt_mb_send 只是发送了一个指针,接收也只是接收了一个指针,数据本身并没有通过邮箱发送
8 O$ U+ o/ @" x- y2 y6 H/ N8 v2 ...
" N$ E  [! D# Y& i
zhangjun:/ O: G4 i6 A; {$ Y/ v! i
- ~8 ?( n- o% R! P  s! _
非常感谢!按你的方法已OK!
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表