针对STM32F103CB UCOSII实时操作系统实现当检测设备在先后,向在线设备发送多帧数据完成后再向下一在线设备发送多帧数据,依次类推。如果设备在线,但是设备接收数据失败,导致发送不成功的情况进行处理,跳过通信失败的设备。对数据发送到一半导致的通信出错进行处理,重试3次不成功后跳过当前设备,继续向下一在线设备发送数据。具体的代码实现如下:
1.定义信号量
OS_EVENT *I2C_Receive_Complete_Sem;// 定义I2C接收数据完成信号量
OS_EVENT *I2C_Send_Wait_Sem;// 定义I2C发送数据等待信号量
OS_EVENT *DeviceQueue;//消息队列指针
void *DeviceQueueEntries[16];//消息队列存储地址,最大支持16个消息
2.检测设备是否在线
//设备是否在线检测任务
void TaskCheckDevices(void *pdata) {
OS_CPU_SR cpu_sr = 0; // CUP状态寄存器
while (1) {
for (int deviceIndex = 0; deviceIndex < sizeof(slave_addresses) / sizeof(slave_addresses[0]); deviceIndex++) {
uint8_t deviceAddress = slave_addresses[deviceIndex];
OS_ENTER_CRITICAL(); // 进入临界区,禁止中断
int isOnline = I2C_CheckDevice(I2C1, deviceAddress);
OS_EXIT_CRITICAL(); // 退出临界区,允许中断
if (isOnline) {
OSQPost(DeviceQueue, (void*)(uintptr_t)deviceAddress);
}
else {
printf(" Device 0x%02X is offline, skipping...\r\n", deviceAddress);
}
}
OSTimeDlyHMSM(0, 0, 10, 0); // 每10秒检查一次
}
}
3.发送数据
void TaskSend(void *pdata) {
OS_CPU_SR cpu_sr;
uintptr_t msg;
u8 err;
while (1) {
msg = (uintptr_t)OSQPend(DeviceQueue, 0, &err); // 等待设备地址从队列中获取
if (err == OS_ERR_NONE) {
uint8_t deviceAddress = (uint8_t)msg;
int deviceIndex = -1;
//查找设备在数组中的索引
for (int i = 0; i < sizeof(slave_addresses)/sizeof(slave_addresses[0]); i++) {
if (slave_addresses[i]==deviceAddress) {
deviceIndex = i;
break;
}
}
//检查从机地址
if (deviceIndex == -1) {
printf(" TaskSend: Device address not found in slave_addresses array.\n");
continue;
}
// 检查设备状态
if (device_status[deviceIndex]) {
printf(" TaskSend: Device 0x%02X is marked as unavailable, skipping...\n", deviceAddress);
continue;
}
OSSemPend(I2C_Send_Wait_Sem, 0, &err); // 等待设备数据发送完毕
if (err == OS_ERR_NONE) {
responseAddress = deviceAddress;
handle_tx_chmc_data(); // 处理发送数据准备工作
for (frameIndex = 0; frameIndex < sizeof(buffers)/sizeof(buffers[0]); frameIndex++) {
int retryCount = 0;
bool send_success = false;
while (retryCount < MAX_RETRY_COUNT &&!send_success) {
OS_ENTER_CRITICAL(); // 开启临界区
send_success = i2c_master_send_buffer_data(responseAddress, buffers[frameIndex], bufferSizes[frameIndex]);
printf(" ||Send %s command<====================>0x%02X \n", commandsNames[frameIndex], responseAddress);
OS_EXIT_CRITICAL(); // 结束临界区
// 检查特定错误码,设备在线发送数据出错时
if ((send_success == false && I2CErrorCode == 5) || (send_success == false && I2CErrorCode == 6)){
printf(" TaskSend:Device 0x%02X send data failed \r\n",deviceAddress);
device_status[deviceIndex]=false;
break;
}
if (!send_success) {
retryCount++;
OSTimeDlyHMSM(0, 0, 0, 500); // 等待500ms后重试
// 检测设备状态
OS_ENTER_CRITICAL();
int isOnline = I2C_CheckDevice(I2C1, deviceAddress);
OS_EXIT_CRITICAL();
if (!isOnline) {
printf(" TaskSend: Device 0x%02X is offline during retry, marking as unavailable.\n", deviceAddress);
device_status[deviceIndex]=false; // 标记设备为不可用
break; // 跳过该设备
}
}
}
if (!send_success) {
printf(" TaskSend: Failed to send data to device 0x%02X after %d retries, marking as unavailable.\n", deviceAddress, MAX_RETRY_COUNT);
device_status[deviceIndex]=false; // 标记设备为不可用
break; // 跳过该设备
}
OSSemPost(I2C_Receive_Complete_Sem); // 授权接收任务
OSTimeDlyHMSM(0, 0, 0, 50);
OSSemPost(I2C_Send_Wait_Sem); // 释放发送权限
}
}
} else {
printf(" TaskSend: Error during queue pend.\n");
}
}
}