RTC

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

发布于 2019-05-31 17:38:45
    本帖最后由 tcsun 于 2019-6-6 16:21 编辑


RTC_Alarm_IRQHandler() 中断中发送邮件,邮箱可以接收到邮件,但运行一半就被打断。

bsp: stm32f103x bsp

问题描述:
项目使用stm32f103ve rtc 闹钟 中断,作为定时开关控制。rtc 部分都已正常,我是想设置好闹钟后,当闹钟中断时在HAL_RTC_AlarmAEventCallback() 里
通过邮箱给继电器模块发一个继电器动作的邮件。但发现如果在HAL_RTC_AlarmAEventCallback()里给邮箱发送的邮件,在继电器模块里是可以接收到的,并且数据也正确,但就是进入不了switch(), 感觉一进到这里就被打断了。不跑switch 部分的代码。
但我如果在main() 线程函数 里直接给邮箱发送同样的邮件,是可以实现功能的,是可以进入到switch()部分,并且正确执行操作。

在HAL_RTC_AlarmAEventCallback() 里通过邮箱给继电器模块发一个继电器动作的邮件可以接收正确的数据,但不进入到case RTC_ALARM_MB:里进行相应的处理。具体信息如下 :



==========================================================================================================
具体代码如下:

继电器部分 线程代码 :


/*****************************************************************
* @brief :Ctr_Watch_thread_entry()
* @param :继电器模块线程入口函数
* @retval :无
****************************************************************/
void Ctr_Watch_thread_entry(void* parameter)
{
rt_err_t result = RT_EOK;
char *mb;
/* 邮箱控制块 */
struct rt_mailbox mb_ctr; ///继电器控制事件

/* 用于放邮件的内存池 */
static char mb_pool[32];


/* 初始化邮箱对象 */
result = rt_mb_init(&mb_ctr,
"mb_relay", /* 名称是 mb_relay */
&mb_pool[0], /* 邮箱用到的内存池是 mb_pool */
sizeof(mb_pool) / 4, /* 邮箱中的邮件数目,因为一封邮件占 4 字节 */
RT_IPC_FLAG_FIFO); /* 采用 FIFO 方式进行线程等待 */
if (result != RT_EOK)
{
rt_kprintf("init mailbox failed.\n");
// return -1;
}

while(1)
{
if (rt_mb_recv(&mb_ctr, (rt_uint32_t *)&mb, RT_WAITING_FOREVER) == RT_EOK)
{
rt_kprintf("mb[0]=%02X mb[1]=%02X mb[2]=%02X mb[3]=%02X \n", mb[0], mb[1], mb[2], mb[3]);
switch(mb[0])
{
case RTC_ALARM_MB:
{
rt_kprintf("RTC_ALARM_MB alarm_flg=%d \n",relay_ctr.alarm_flg);
if(relay_ctr.alarm_flg == 1) // 0没有设置rtc闹钟 ,1:合闸闹钟已设置 ,2:拉闸闹钟已设置
{
relay_sw_on();
if(set_alarm(relay_ctr.off.hour,relay_ctr.off.min,0)== RT_EOK)
relay_ctr.alarm_flg = 2;
}
else if(relay_ctr.alarm_flg == 2)
{
relay_sw_off();
if(set_alarm(relay_ctr.on.hour,relay_ctr.on.min,0)== RT_EOK)
relay_ctr.alarm_flg = 1;
}

break;
}
case MANUAL_CONTROL_MB:
{
if(mb[1]==0x01) relay_sw_on();
else relay_sw_off();
break;
}
case RELAY_MODE_MB:
{
relay_ctr.mode = mb[1];
break;
}
case SET_ON_TIME_MB:
{
uint32_t now_sec,on_sec;
relay_ctr.on.hour = mb[2];
relay_ctr.on.min = mb[3];
now_sec = get_second_of_today();
on_sec = relay_ctr.on.hour * 3600 + relay_ctr.on.min *60;
if((now_sec < on_sec )||(relay_ctr.alarm_flg ==0))
{
if(set_alarm(relay_ctr.on.hour,relay_ctr.on.min,0)== RT_EOK)
relay_ctr.alarm_flg = 1;
}
break;
}
case SET_OFF_TIME_MB:
{
uint32_t now_sec,off_sec;
relay_ctr.off.hour = mb[2];
relay_ctr.off.min = mb[3];
now_sec = get_second_of_today();
off_sec = relay_ctr.on.hour * 3600 + relay_ctr.on.min *60;
if((now_sec < off_sec )&&(relay_ctr.alarm_flg ==0))
{
if(set_alarm(relay_ctr.off.hour,relay_ctr.off.min,0)== RT_EOK)
relay_ctr.alarm_flg = 2;
}
break;
}
default:
break;
}

/* 延时 100ms */
rt_thread_mdelay(400);
}
}
}


============================================================================================
rtc alarm 中断函数:
/*****************************************************************
* @function :RTC_Alarm_IRQHandler()
* @brief : RTC 闹钟中断函数 。
* @param : 无
* @retval : 无
****************************************************************/
void RTC_Alarm_IRQHandler(void)
{
// enter interrupt
rt_interrupt_enter();
HAL_RTC_AlarmIRQHandler(&RTC_Handler);
rt_interrupt_leave();
}



==================================================================================================
RTC 闹钟中断回调函数 :

p_Mb: 是全局的邮箱句柄,先已用p_Mb =(rt_mailbox_t)rt_object_find("mb_relay",RT_Object_Class_MailBox); 找到。

*****************************************************************
* @function :HAL_RTC_AlarmAEventCallback()
* @brief : RTC 闹钟中断回调函数 。
* @param : *hrtc:硬件RTC 句柄指针
* @retval : 无
****************************************************************/
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{

char bm_rtc_alarm[4]={0x06,0x00,0x00,0x00};


rt_kprintf("ALARM EvenCallback \n");
rt_enter_critical();
if(p_Mb!=NULL)
{
rt_mb_send(p_Mb, (rt_uint32_t)&bm_rtc_alarm); //发送邮件
rt_kprintf("mb_send done!\n");
}
rt_exit_critical();
}


================================================================================================

main.c 里的继电器调试函数: 发送0x06,0x00,0x00,0x00 邮件数据是可以进入到case RTC_ALARM_MB:里的,是可以执行继电器控制代码的。
/*****************************************************************
* @function : relay(uint8_t stats,uint8_t h,uint8_t min)
* @brief : 继电器调试函数
* @param : stats:1手动控制,2:定时开,3,定时关,4:rtc alarm
* @retval :
****************************************************************/
void relay(uint8_t stats,uint8_t h,uint8_t min)
{
char bm_test[4]={0x10,0x00,0x00,0x00};

switch(stats)
{
case 1: bm_test[0]= 0x10;bm_test[1] = h; break;
case 2: bm_test[0]= 0x20;bm_test[2] = h;bm_test[3] = min;break;
case 3: bm_test[0]= 0x21;bm_test[2] = h;bm_test[3] = min;break;
case 4: bm_test[0]= 0x06;
}

rt_mb_send(p_Mb_crt, (rt_uint32_t)&bm_test);
}
FINSH_FUNCTION_EXPORT(relay,relay control 1:ON 0:OFF)



下面是用rtc 中断发送的邮件数据,不能进入到case RTC_ALARM_MB: 的打印信息:

ss

ng.png

查看更多

关注者
0
被浏览
918
10 个回答
tcsun
tcsun 2019-05-31
上面添加另一张图片老是出问题,在下面补上。

下图是在main.c 里用继电器调试函数发送的邮件数据 是可以进入到case RTC_ALARM_MB: 的打印信息:
OK.png
tcsun
tcsun 2019-05-31
哪位大神帮忙看一下是什么原因?
tcsun
tcsun 2019-06-05
哪能帮忙指导一下!感谢了!
zhangjun
zhangjun 2019-06-05
你在中断发送的内容跟在main.c里发送的数据不一样。怀疑是你发送的0x06在switch里面没有对应的值。
tcsun
tcsun 2019-06-05
zhangjun 发表于 2019-6-5 10:38
你在中断发送的内容跟在main.c里发送的数据不一样。怀疑是你发送的0x06在switch里面没有对应的值。 ...


dd.jpg

感谢!

我对过,数据是一样的。
zhangjun
zhangjun 2019-06-05
楼主可以发下工程吗,这么看想不出来是啥原因。
tcsun
tcsun 2019-06-05
zhangjun 发表于 2019-6-5 13:01
楼主可以发下工程吗,这么看想不出来是啥原因。


工程如附件,因为文件较大我只保留了libraries 文件夹里的STM32F1xx_HAL 文件和HAL_Drivers 文件。

另外:HAL_Drivers/文件下的drv_rtc.c 我有修改。





下载附件[stm32.rar]
tcsun
tcsun 2019-06-05
tcsun 发表于 2019-6-5 14:25
工程如附件,因为文件较大我只保留了libraries 文件夹里的STM32F1xx_HAL 文件和HAL_Drivers 文件。

另外 ...


另外在\libraries\STM32F1xx_HAL\STM32F1xx_HAL_Driver\Src\文件夹下增加了stm32f1xx_hal_rtc_refactor.c 文件
zhangjun
zhangjun 2019-06-05
调试好了,
1,rt_mb_send 只是发送了一个指针,接收也只是接收了一个指针,数据本身并没有通过邮箱发送
2,但是你发送的指针是指向一个栈上的局部变量,这个变量在你代码发送邮件的函数退出后就可能被其他值覆盖。所以造成数据被改变了。
3,解决方法是把HAL_RTC_AlarmAEventCallback函数里面的
char bm_rtc_alarm[4]={0x06,0x00,0x00,0x00}; 
放到外面让他成为全局变量。
tcsun
tcsun 2019-06-06
zhangjun 发表于 2019-6-5 18:27
调试好了,
1,rt_mb_send 只是发送了一个指针,接收也只是接收了一个指针,数据本身并没有通过邮箱发送
2 ...


zhangjun:

非常感谢!按你的方法已OK!

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友