⚠️
大家好. .感谢来到论坛。令人兴奋的消息!我们现在正在转移到新的论坛平台的过程中,它将提供更好的功能,并包含在主对话网站。所有的帖子和账号已经迁移。我们现在只接受新论坛的流量-请发布任何新的帖子在//www.xmece.com/support.我们会在接下来的几天修复bug /优化搜索和标记。
10个帖子/ 0个新帖子
最后发表
hamiddhosseini
离线
最后看到:9个月,3个星期前
加入:2020-05-12 12:04
UART中断

亲爱的对话支持团队:

我正在尝试通过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;Static uint8_t temp_length = 0;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等待和存储传入数据。

我猜我当前的代码有超时的问题(不管有没有看门狗,这个问题仍然存在!)我试过修改uart_rx_timeout_isr年代它会停止无限循环,但这不起作用。你能解释一下这个中断和超时吗?

问候,

哈米德

设备:
JK_Dialog
离线
最后看到:5个月4个星期前
工作人员
加入: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.h中创建你自己的指向.app_on_system_powered的函数(这是一个直接进入主循环的钩子)。

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

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

一旦app_on_system_powered运行了,SDK就会运行调度程序,因此在一段时间内不会被阻塞。

如果有帮助请告诉我。

/乔恩

hamiddhosseini
离线
最后看到:9个月,3个星期前
加入:2020-05-12 12:04
非常感谢,乔恩,

非常感谢,乔恩,

我已经实现了你在这里提到的步骤,实际上我对整个系统有了一点更好的理解。换句话说app_asynch_proc在主循环中让shceduler继续,直到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.然而,删除断点并允许程序继续其进程将导致崩溃,这是我无法跟踪的。

问候,

哈米德

JK_Dialog
离线
最后看到:5个月4个星期前
工作人员
加入:2016-08-22 23:07
嗨哈米德,

嗨哈米德,

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

如果要长时间返回Keep_Power后,请使用循环中的以下代码行:

wdg_reload(watchdog_default_period);

/乔恩

hamiddhosseini
离线
最后看到:9个月,3个星期前
加入:2020-05-12 12:04
亲爱的乔恩,

亲爱的乔恩,

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

//在Arch_Main.cn中的主循环中(1){do {wdg_recoad(watchdog_default_period);//安排所有待处理的事件计划_while_ble_on();} whiled(app_asynch_proc()!= goto_sleep);//授予控件到应用程序,尝试向下电//如果应用程序返回,如果应用程序返回到user_peripheral.chart.ch_main_loop_callback_ret_t user_app_on_system_powered(void){if(!uart_receive_finished){// wdg_recoad(watchdog_default_period);返回KEEP_POWERED;其他}{connected_governor ();返回KEEP_POWERED;在我的代码中#define temp_queue_max_length 1 static char temp_queue;void UART_RECEIVE_INTR_CB(UINT16_T长度){静态UINT8_T索引= 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
离线
最后看到:5个月4个星期前
工作人员
加入:2016-08-22 23:07
嗨哈米德,

嗨哈米德,

一些评论。

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

2)您是否在任何交易期间重新配置UART?您只需要设置UART一次,然后中断将在每个字节上启动。如果在传输过程中重新配置UART,则会导致帧/奇偶校验错误。

/乔恩

hamiddhosseini
离线
最后看到:9个月,3个星期前
加入:2020-05-12 12:04
好吧,我想既然我

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

2)每次接收完成后,我重新配置UART。似乎这就是问题所在。我把这部分也去掉了。

现在,当我开始做广告后,一步一步地运行程序,整个过程进行得很顺利。换句话说,主循环检查GO_TO_SLEEP每次等待uart_receive_finished.但是,当我正常运行程序时,看门狗又被触发了。我可以跟踪这个,看门狗在while循环中被触发。看来无限循环还有问题?

JK_Dialog
离线
最后看到:5个月4个星期前
工作人员
加入:2016-08-22 23:07
嗨哈米德,

嗨哈米德,

请在你的user_app_on_system_powered中添加watchdog reload,但只是把它放在if()语句之外:

wdg_reload(watchdog_default_period);

/乔恩

hamiddhosseini
离线
最后看到:9个月,3个星期前
加入:2020-05-12 12:04
亲爱的乔恩,

亲爱的乔恩,

非常感谢,现在看门狗的问题是固定的。但是,我仍然有问题接收线路状态错误中断。

我试图尽可能简化代码。在此代码中,UART应该只是等待一个特殊的角色。

//user_peripheral.c arch_main_loop_callback_ret_t user_app_on_system_powered(void) {wdg_reload(WATCHDOG_DEFAULT_PERIOD);如果(!uart_receive_finished){返回KEEP_POWERED;其他}{connected_governor ();返回KEEP_POWERED;} //我的文件void connected_governor(){//这个函数将被调用在uart_receive_finished。//它检查接收到的消息并包含状态机。uart_receive_intr_example (UART2);//重新配置UART以重置接收!uart_receive_intr_init (UART2);} void uart_receive_intr_cb(uint16_t length){if (temp_queue_1 == SOM_CHAR){uart_receive_finished = 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应该开始为给定长度记录传入的数据(它是在这种情况下的第二发送字节)。

如果我改变队列的大小从1字节到一些更大的数字,程序将工作,但我必须等待队列满了,以有回调。这将增加系统的响应时间并降低QOS。而且,这个队列的大小需要大于任何接收到的消息。
我找不到在uart配置似乎完好无损时触发接收行状态错误背后的原因。

问候,

哈米德

hamiddhosseini
离线
最后看到:9个月,3个星期前
加入:2020-05-12 12:04
好吧,我终于做到了

好的,最后我已经设法做了它的工作。

非常感谢Jon