以上文件中使用UCOSII消息队列检测设备是否在线,如果设备不在线跳过不在线设备向在线设备连续发送和接收7帧不同I2C数据后再向下一设备发送7帧不同数据的代码有何问题,为什么不能实现向在线设备发送连续发送7帧数据,请帮我用详细的代码实现
时间: 2024-09-14 11:16:10 浏览: 10
当前代码的问题在于发送任务(`TaskSend`)中的循环发送逻辑可能不会如预期那样对每个在线设备连续发送7帧不同的I2C数据。具体原因如下:
1. 在每次成功发送一帧后,会通过信号量 `OSSemPost(I2C_Receive_Complete_Sem)` 触发接收任务 `TaskReceiveI2C` 来接收该帧的应答。但是,在接收到应答并再次触发 `OSSemPost(I2C_Receive_Comple_Sem)` 后,并未保证发送任务能够立即获取到CPU执行权从而继续发送下一条指令;这可能导致发送任务在发送完第一帧之后就被其他更高优先级的任务抢占了CPU执行权,导致未能连续发送剩余的数据包给同一个设备。
### 解决方案
为了使发送任务能够在确认一个设备在线的情况下对该设备连续发送多帧数据而不被中断,可以考虑调整以下部分代码:
#### 修改建议
将对单个设备连续发送多个帧的部分封装成一个新的子任务,这样当这个子任务启动的时候它就可以获得更高的优先级来确保连续发送过程不会被打断。下面是一种改进后的示例代码片段:
```c
// 创建新的任务用于连续发送数据
#define SEND_CONTINUOUSLY_PRIO 7 // 新任务的较高优先级
OS_STK SendContinuouslyTaskStk[I2C_STK_SIZE];
void TaskSendContinuously(void *pdata) {
u8 err;
uint8_t deviceAddr = (uint8_t)(uintptr_t)pdata;
// 对单个设备连续发送7帧数据
for (int i = 0; i < 7; i++) {
OS_ENTER_CRITICAL();
handle_tx_chmc_data();
uint32_t sendResult = i2c_master_send_buffer_data(deviceAddr, buffers[i], bufferSizes[i]);
OS_EXIT_CRITICAL();
if (sendResult == I2C_ERROR_TIMEOUT) {
printf("Timeout occurred when sending to 0x%02X", deviceAddr);
break;
}
printf(" ||send %s command=======>0x%02X", commandsNames[i], deviceAddr);
OSSemPost(I2C_Receive_Complete_Sem); // 授权接收任务
// 等待接收任务完成
OSSemPend(I2C_Receive_Complete_Sem, 0, &err);
if (err != OS_ERR_NONE) {
printf("Error waiting for I2C receive completion");
break;
}
}
OSTaskResume(SEND_TASK_PRIO); // 恢复主发送任务
}
// 主发送任务修改
void TaskSend(void *pdata) {
u8 err;
uintptr_t msg;
while (1) {
msg = (uintptr_t)OSQPend(DeviceQueue, 0, &err);
if (err == OS_ERR_NONE) {
responseAddress = msg;
// 挂起主发送任务并启动新任务进行连续发送
OSTaskSuspend(SEND_TASK_PRIO);
OSTaskCreate(TaskSendContinuously, (void *)(uintptr_t)responseAddress,
&SendContinuouslyTaskStk[I2C_STK_SIZE - 1], SEND_CONTINUOUSLY_PRIO);
}
}
}
```
如此一来,每当发现一个设备在线时,就会创建一个新的高优先级任务专门负责对该设备发送7帧数据。这种做法不仅使得系统能够更好地保证数据传输的连贯性,还能简化原有发送任务的设计复杂度。