亲爱的Dialog支持团队:
我试图通过UART接收一些数据,并经过一些处理后通过BLE发送它。到目前为止,我使用的是ble_app_peripheral而且ble_uart来创造我需要的东西。
最初我用的是app_easy_timer每2秒启动一个调控器来处理任何接收到的数据并通过BLE发送。这个调控器将使用uart_receive ()在直接存储器存取模式。然而,这个方法非常有效;我希望增加程序的响应时间,这意味着我希望调控器始终等待uart开始数据传输。
我尝试了以下方法,但程序在到达while循环后崩溃。
volatile bool SOM_RECEIVED = false;Static void uart_receive_intr_cb(uint16_t length){Static uint8_t index = 0;静态uint8_t temp_length = 0;if (SOM_RECEIVED){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为true。
我有以下几个问题:
1-是否有一种方法可以让电路板一直在后台等待数据(听UART) ?板子应该运行它的正常进程(可能是一个状态机,检查当前状态以及是否接收到任何数据),同时总是通过UART等待和存储传入的数据。
2-我猜我当前的代码有一个超时的问题(有或没有看门狗的问题仍然存在!)我试过修改uart_rx_timeout_isr年代它会停止无限循环,但那不起作用。你能解释一下这次中断和暂停吗?
问候,
哈米德
关键词:
设备:
你好,我认为你用中断例子的方法是正确的。uart示例和ble示例之间的区别当然在于SDK。我猜你是在阻止:
这会导致看门狗开火。
我要做的是:
1)使用uart_register_rx_cb和user_callbacks_config.h中的.app_on_init回调中的uart_initialize初始化uart驱动程序
2)在user_callback_config.h中创建自己的指向.app_on_system_powered的函数(这是一个直接进入主循环的钩子)。
3)现在,在你的uart回调函数设置你的uart_received_data标志,当你得到有效的数据。
4)在app_on_system_powered回调中,检查标志,如果它没有设置,允许它返回。
一旦app_on_system_powered运行,SDK就会运行调度器,因此在一段时间内不应该阻塞它。
如果有帮助,请告诉我。
/乔恩
非常感谢,乔恩,
我已经实现了你在这里提到的步骤,实际上我对整个系统有了更好的理解。换句话说app_asynch_proc在主循环中一直开到app_on_system_powered返回一个GO_TO_SLEEP命令。
然而,你提到的步骤似乎并不奏效。当我运行程序时,看门狗在广告开始后立即开火并停止程序。这是我的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.然而,删除断点并允许程序继续其进程将导致崩溃,这是我无法追踪的。
问候,
哈米德
嗨哈米德,
只有UART完全完成时才应该返回GOTO_SLEEP。但看门狗会在这里开火。当您返回GOTO_SLEEP时,看门狗只在主循环中“喂食”。这也在.app_on_system_powered的user_callback_config.h的注释中提到。
如果你要在一段较长的时间内返回KEEP_POWERED,请在循环中使用以下代码行:
wdg_reload (WATCHDOG_DEFAULT_PERIOD);
/乔恩
亲爱的乔恩,
我已经实现了我们讨论过的更改。我的代码现在看起来是这样的:
然而,现在我遇到了另一个问题。当接收到第一个字节并返回到UART中断处理程序时,对于下一个字节,接收线状态中断触发并处于无限循环,导致程序崩溃。我怀疑我必须以某种方式释放或刷新接收缓冲区,您能给我一些说明吗?
问候,
哈米德
嗨哈米德,
一些评论。
1) wdog已经在主循环中被重新加载,你应该避免修改这个文件。
2)您是否在任何事务期间重新配置UART ?您应该只需要设置一次UART,然后中断将在每个字节上触发。如果在传输过程中重新配置UART,将导致帧/奇偶校验错误。
/乔恩
1)好吧,我想既然我要保持cpu运行一段时间,我应该在调度程序循环中重新加载看门狗。然而,它已经在主循环的末尾被重新加载了,因此;我删除了对主文件的修改(wdog_reload在调度程序循环中)。谢谢你的评论。
2)我在每次接收完成后重新配置UART。似乎这就是问题的原因。我也把这部分去掉了。
现在开始广告后,我一步一步地运行程序,过程进行得很顺利。换句话说,主循环检查GO_TO_SLEEP每一次都在等待uart_receive_finished.然而,当我正常运行程序,看门狗再次被解雇。当我可以跟踪这个时,看门狗在这个while循环中被触发。看来无限循环还是有问题的?
嗨哈米德,
请在你的user_app_on_system_powered中添加看门狗reload,但只是把它放在if()语句之外:
wdg_reload (WATCHDOG_DEFAULT_PERIOD);
/乔恩
亲爱的乔恩,
非常感谢,现在看门狗的问题已经解决了。然而,我仍然有一个问题接收线路状态错误中断。
我已经尽可能地简化了代码。在这段代码中,uart应该只等待一个特殊字符。
如果我将队列的大小从1byte改为一些更大的数字,程序将工作,但我必须等待队列已满才有回调。这将增加系统的响应时间并降低QOS。此外,该队列的大小需要大于任何接收到的消息。
我找不到接收器行状态错误被触发的原因,而uart配置似乎是完整的。
问候,
哈米德
好吧,我终于成功了。
非常感谢,乔恩