⚠️
嗨,...感谢您来论坛。令人兴奋的消息!我们现在正在迁至我们的新论坛平台,将提供更好的功能,并包含在主对话框网站中。所有帖子和帐户都已迁移。我们现在只接受新论坛上的流量 - 请发布任何新线程https://www.dialog-seminile.com/support.。我们将在未来几天修复错误/优化搜索和标记。
10个帖子/ 0新
最后一篇
hamiddhosseini
离线
最后一次露面:7个月1周前
加入:2020-05-12上午
UART中断

亲爱的对话支持团队,

我试图通过UART接收一些数据,经过一些处理后通过BLE发送它。到目前为止,我用了ble_app_peripheralBLE_UART.示例以创建我需要的东西。

渴望我用了一个app_easy_timer.每2秒启动一个调控器来处理任何接收到的数据并通过BLE发送它们。这个总督会使用UART_RECEIVE()直接存储器存取模式。然而,这完美无缺;我想提高程序的响应时间,这意味着我希望总督总是等待UART进行数据传输开始。

我尝试了以下几个,但在循环中缩短后程序崩溃。

volatile bool SOM_RECEIVED = false;Static void uart_receive_intr_cb(uint16_t length){Static uint8_t index = 0;Static uint8_t temp_length = 0;if (index == 1){if (index == 1){temp_length = temp_queue[index];指数+ +;返回;} else if ((index>1) && (index < temp_length + 3)){queue[index] = temp_queue[index];指数+ +;返回;} else if (index == (temp_length+3)){queue[index] = temp_queue[index]; uart_receive_finished = true; data_received_cnt = length; SOM_RECEIVED = false; index = 0; return; } else{ SOM_RECEIVED = false; index = 0; return; } } else if (temp_queue[index] == SOM_CHAR ){ queue[index] = temp_queue[index]; index ++; SOM_RECEIVED = true; return; } else{ index = 0; SOM_RECEIVED = false; uart_receive_finished = false; data_received_cnt = 0; return; } } void uart_receive_intr_example(uart_t* uart) { uart_receive_finished = false; data_received_cnt = 0; uart_register_rx_cb(uart, uart_receive_intr_cb); uart_receive(uart, (uint8_t *)temp_queue, TEMP_QUEUE_MAX_LENGTH, UART_OP_INTR); while ((!uart_receive_finished)); if (chk_queue(data_received_cnt)) { printf_string(UART2,"B"); for (int8_t i = 0; i < buffer_received_cnt; i++) printf_byte(uart,buffer[i]); process_buffer((uint8_t *)buffer,buffer_received_cnt); } }

我在等待一个SOM字符,数据的长度和数据本身。也就是说;我将这些值存储在队列中,在接收到一个数据包后,我正在改变uart_receive_finished.为真。

我有以下问题:

1-有一种方法,板可以一直等待数据(收听UART)在后台?板子应该运行它的正常进程(可能是检查当前状态以及是否接收了任何数据的状态机),同时始终等待和存储通过UART传入的数据。

2-我猜我当前的代码有一个问题与时间超时(有或没有看门狗问题仍然存在!)我试着修改UART_RX_TIMEOUT_ISR S.o它会阻止无限循环,但这并不起。你能解释一下这个中断和超时吗?

问候,

哈米德

设备:
JK_DIALOG.
离线
最后一次露面:3个月1周前
职员
加入:2016-08-22 23:07
嗨,我想你正在服用

嗨,我认为你正在采用正确的方法来与中断例子。当然,UART示例和BLE示例之间的差异是SDK。我猜你正在阻止:

虽然((!uart_receive_finished));

这导致看门狗开火。

我所做的就是如下:

1)在user_callbacks_config.h的.app_on_init回调中使用uart_register_rx_cb和和uart_initialize初始化uart驱动

2)在user_callback_config中创建自己的函数,指向.app_on_system_powered(这是一个钩子直接进入主循环)。

3)现在,在你的uart回调函数设置你的uart_received_data标志时,你得到有效的数据。

4)在app_on_system_powered回调中,检查标志,如果没有设置,允许它返回。

SDK运行调度程序一旦App_on_System_Powered已运行,因此不应阻止一段时间。

请让我知道这可不可以帮你。

/ Jon.

hamiddhosseini
离线
最后一次露面:7个月1周前
加入:2020-05-12上午
非常感谢乔恩,

非常感谢乔恩,

我已经实现了您在这里提到的步骤,实际上我对整个系统有了更好的理解。换句话说app_asynch_proc.在主循环中让Shccululer保持直接app_on_system_powered返回A.去睡觉命令。

然而,你提到的步骤似乎不起作用。当我运行程序时,看门狗就会在广告开始后立即启动并停止程序。这是我的user_app_on_system_powered:

arch_main_loop_callback_ret_t user_app_on_system_powered(空白)
{
如果(!uart_receive_finished){
返回keep_powered;
}
别的{
返回GOTO_SLEEP;
}
}

实际上,当我在这个函数的开始处放置一个断点时,我能够遵循所需的路径,使程序在仍然等待uart_receive_finished.。但是,删除了Break Poin并允许程序继续其过程将导致我无法追踪的崩溃。

问候,

哈米德

JK_DIALOG.
离线
最后一次露面:3个月1周前
职员
加入:2016-08-22 23:07
嗨哈米德,

嗨哈米德,

只有当UART完全完成时,才应该返回GOTO_SLEEP。但看门狗在这里开火是意料之中的事。看门狗只在主循环中被“馈入”,一旦你返回了GOTO_SLEEP。这在.app_on_system_powered的user_callback_config.h的注释中也提到了。

如果你在一段时间内返回KEEP_POWERED,请在你的循环中使用以下代码行:

wdg_reload (WATCHDOG_DEFAULT_PERIOD);

/ Jon.

hamiddhosseini
离线
最后一次露面:7个月1周前
加入:2020-05-12上午
亲爱的乔恩,

亲爱的乔恩,

我已经实施了我们讨论的更改。我的代码现在看起来像这样:

//在主循环中arch_main.c while(1) {do {wdg_reload(WATCHDOG_DEFAULT_PERIOD);//调度所有挂起的事件} while (app_asynch_proc() != GOTO_SLEEP);//如果应用程序返回GOTO_SLEEP,则授予控制给应用程序,尝试关闭电源//如果应用程序返回GOTO_SLEEP,则user_peripheral.c arch_main_loop_callback_ret_t user_app_on_system_powered(无效){if (!uart_receive_finished){//wdg_reload(WATCHDOG_DEFAULT_PERIOD);返回KEEP_POWERED;其他}{connected_governor ();返回KEEP_POWERED;}} //在我的代码#定义TEMP_QUEUE_MAX_LENGTH 1 static char temp_queue;Void uart_receive_intr_cb(uint16_t length){static uint8_t index = 0;Static uint8_t temp_length = 0; if (SOM_RECEIVED){ if (index == 1){ temp_length = temp_queue; index ++; return; } else if ((index>1) && (index < temp_length + 3)){ queue[index] = temp_queue; index ++; return; } else if (index == (temp_length+3)){ queue[index] = temp_queue; uart_receive_finished = true; data_received_cnt = length; SOM_RECEIVED = false; index = 0; return; } else{ SOM_RECEIVED = false; index = 0; return; } } else if (temp_queue == NC_SOM_TYPE_SENSOR ){ queue[index] = temp_queue; index ++; SOM_RECEIVED = true; return; } else{ index = 0; SOM_RECEIVED = false; uart_receive_finished = false; data_received_cnt = 0; return; } } void uart_receive_intr_init(uart_t *uart){ //Configure the UART to receive more data uart_receive_finished = false; data_received_cnt = 0; uart_register_rx_cb(uart, uart_receive_intr_cb); uart_receive(uart, (uint8_t *)temp_queue, TEMP_QUEUE_MAX_LENGTH, UART_OP_INTR); } void uart_receive_intr_example(uart_t* uart) { if (chk_queue(data_received_cnt)){ process_buffer((uint8_t *)buffer,buffer_received_cnt); } //Reconfigure the UART to reset the receiving! uart_receive_intr_init(uart); }

然而,现在我有另一个问题。在接收到第一个字节并返回到UART中断处理程序后,对于下一个字节,接收机线路状态中断被射击并在无限循环中,导致程序崩溃。我怀疑我必须以某种方式释放或冲洗接收缓冲区,可以向我提供一些指示吗?

问候,

哈米德

JK_DIALOG.
离线
最后一次露面:3个月1周前
职员
加入:2016-08-22 23:07
嗨哈米德,

嗨哈米德,

几个评论。

1) wdog已经在主循环中重新加载,你应该避免修改这个文件。

2)您是否在任何事务期间重新配置UART ?您应该只需要设置一次UART,然后将在每个字节上触发中断。如果您在传输期间重新配置UART,这将导致帧/奇偶校验错误。

/ Jon.

hamiddhosseini
离线
最后一次露面:7个月1周前
加入:2020-05-12上午
1)好的,自从我以后想到

1)好的,我想既然我要保持cpu运行一段时间,我应该在调度程序循环中重新加载看门狗。然而,它已经在主循环的末尾重新加载,因此;我删除了主文件(wdog_reload.在调度程序循环中)。谢谢你的评论。

2)每次接受未完成后,我正在重新配置UART。似乎这导致了这个问题。我也删除了这个部分。

现在当我在启动广告后一步一步地运行程序时,这个过程进行得很顺利。换句话说,主循环检查去睡觉每一次都在等待uart_receive_finished.。但是,当我正常运行该程序时,看门狗再次被解雇。正如我可以跟踪的那样,WatchDog在循环中触发。似乎仍然存在无限循环的问题?

JK_DIALOG.
离线
最后一次露面:3个月1周前
职员
加入:2016-08-22 23:07
嗨哈米德,

嗨哈米德,

请在user_app_on_system_powered的看门狗重新加载中添加回来,但只是将它放在if()语句之外:

wdg_reload (WATCHDOG_DEFAULT_PERIOD);

/ Jon.

hamiddhosseini
离线
最后一次露面:7个月1周前
加入:2020-05-12上午
亲爱的乔恩,

亲爱的乔恩,

非常感谢,现在看门狗的问题解决了。但是,我还是有个问题接收线路状态错误中断。

我试着尽可能地简化代码。在这段代码中,uart应该只等待一个特殊字符。

//user_peripheral.chrach_main_loop_callback_ret_t user_app_on_system_powered(void){wdg_reload(watchdog_default_period);如果(!uart_receive_finished){return keep_powered;其他}{connected_governor ();返回KEEP_POWERED;}} //我的文件void连接_governor(){//将在UART_RECEIVE_FININMENT上调用此函数。//它检查收到的消息并包含状态机。UART_RECEIVE_INTR_EXAMPLE(UART2);//重新配置UART以重置接收!UART_RECEIVE_INTR_INIT(UART2);void uart_receive_intr_cb(uint16_t长度){if(temp_queue_1 == som_char){uart_receive_finishing = true; return; } } void uart_receive_intr_init(uart_t *uart){ //Configure the UART to receive more data uart_receive_finished = false; data_received_cnt = 0; uart_register_rx_cb(uart, uart_receive_intr_cb); uart_receive(uart, (uint8_t *)(&temp_queue_1), 1, UART_OP_INTR); } void uart_receive_intr_example(uart_t* uart) { printf_string(uart,"SOM"); }
通常,我希望UART等待这个字符(SOM_CHAR),在接收到这个字符后,UART应该开始记录给定长度的传入数据(在本例中是第二个传输字节)。

如果我将队列表单1byte的大小更改为一些更大的数字,则程序将起作用,但我必须等待队列满满的回调。这将增加我的系统的响应时间和减少QoS。此外,此队列大小需要大于任何收到的消息。
在UART配置似乎完好无损时,我找不到接收线状态错误后面的原因。

问候,

哈米德

hamiddhosseini
离线
最后一次露面:7个月1周前
加入:2020-05-12上午
好的,最后我已经管理了

好了,我终于成功了。

非常感谢Jon