类似于TCP三次握手、超时检测、自动重发机制以及主从应答方式的通信任务以及一个任务和多个任务通信时应该如何设计

ba_wang_mao 2020-02-20 02:33:02
设备有4个串口
1、USART1串口会每隔100毫秒接收到【某个外部设备A】发送的一串电压数据。
2、USART2串口会每隔100毫秒接收到【某个外部设备B】发送的一串电流数据。
3、USART3串口和移动终端通信(主从通信模式),移动终端为主站,本设备为从站。
移动终端每隔250毫秒会向本设备发送请求报文,本设备收到移动终端的请求报文后,会将USART1串口采集的电压数据和USART2串口采集的电流数据上传给移动终端。
注:移动终端和本设备通信特点如下, 如果移动终端如果不给本设备发送请求报文,本设备不会给移动终端发送数据。
4、USART4串口和服务器通信。
USART4串口实际上是一个4G转串口模块,该4G转串口模块分为命令模式通信和透传模式通信。当4G转串口模块刚刚上电时为[命令]模式,需要先按照一定的顺序发送握手命令,
握手成功后,即可进入[透传]模式,给服务器传输USART1串口采集的电压数据和USART2串口采集的电流数据。

(4.1)、命令模式
命令模式时,给服务器传输握手信号步骤如下:
第一步:定时200毫秒(时间不需要非常准确)给4G网络发送握手请求报文A。
如果收到4G的应答报文,跳转到第二步;否则重复发送请求报文A
第二步:定时200毫秒(时间不需要非常准确)给4G网络发送握手请求报文B
如果收到4G网络的应答报文,跳转到第三步;
否则重复发送请求报文B,如果自动重发次数超过3,则跳转到第一步,重新发送握手请求报文A。
第三步:给4G网络发送握手请求报文C,然后设备开始等待
如果在10秒内收到4G网络的应答报文,进入【透传模式】;
否则10秒后跳转到第一步,重新发送握手请求报文A。
(4.2)、透传模式
第一步:透传模式时定时每隔1秒给服务器传输USART1串口采集的电压数据和USART2串口采集的电流数据。
第二步:然后等待服务器的应答报文。
第三步:如果连续1分钟没有收到服务器的应答报文,则该4G转串口模块【断电重启】,然后跳转到命令模式第一步重新握手。

5、需要检测USART1通信是否出现通信中断(如果连续1秒钟USART1没有收到数据则认为USART1通信中断)
需要检测USART2通信是否出现通信中断(如果连续1秒钟USART2没有收到数据则认为USART2通信中断)
需要检测USART3通信是否出现通信中断


请问: (1)、这涉及到一个任务和多个任务进行通信,我该如何规划任务?
(2)、一个任务和多个任务通信是使用消息队列好呢?还是使用全局变量+互斥信号量锁定方式呢?
(3)、假设可以使用消息队列进行一个任务和多个任务通信,那么是不是只能编写成下述代码

void USART1_Task ()
{
while (1)
{
等待USART1的信号量;
解析USART1报文,得到电压数据;
发送电压数据到消息队列A; // ---> 消息队列A用于USART1和服务器通信
发送电压数据到消息队列B; // ---> 消息队列B用于USART1和移动终端通信

}
}
...全文
561 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
ba_wang_mao 2020-05-02
  • 打赏
  • 举报
回复
这个问题我已经解决了,在STM32F103VC单片机下编程实现。
ba_wang_mao 2020-04-30
  • 打赏
  • 举报
回复
以下是正解,我在STM32F103VC主板上测试成功

void task(void)
{
uint8_t isr=0;

while (1)
{
switch (isr)
{
case 0:
延时节拍100毫秒
发送报文1
限时等待信号量
IF 应答报文OK
isr=1;
break;
endif
break;

case 1:
延时节拍100毫秒
发送报文2
限时等待信号量
IF 应答报文OK
isr=2;
break;
endif
break;

case 2:
延时节拍100毫秒
发送报文3
限时等待信号量
IF 应答报文OK
isr=3;
break;
endif
break;
case 3:
限时等待消息队列
发送实时报文
break;
}
}
}




worldy 2020-04-26
  • 打赏
  • 举报
回复
创建多个任务 T1:接收串口1数据,并将数据保存在一个缓冲区 T2:接收串口数据2... T3:接收串口3数据 T4:显示数据,循环的将当前T1、T2、T3缓冲区数据进行显示 T5:循环的将T2、T2、T3缓冲区数据打包,发给服务器
ba_wang_mao 2020-04-26
  • 打赏
  • 举报
回复

消息队列规划:
MSG[0] = 1 ---> 保留
MSG[0] = 2 ---> 表示接收到任务5的的SD2405时钟芯片的时间
MSG[1] = 年
MSG[2] = 月
MSG[3] = 日
MSG[4] = 时
MSG[5] = 分
MSG[6] = 秒
MSG[7] = 星期

MSG[0] = 3 --->表示接收到任务3 采集2路DI
MSG[1] = 第1路DI
MSG[2] = 第2路DI
MSG[0] = 4 --->表示接收到任务4 采集2路DI
MSG[1] = 第1路DI
MSG[2] = 第2路DI





void EC20_Task(void *pvParameters)
{
USART2_Configuration();
USART2_DMA_Tx_Configuration();
USART2_DMA_Rx_Configuration();


while(1)
{
EC20_4G_Poll();
}
}



uint16_t EC20_4G_isr = 12;
uint16_t EC20_4G_Outtime = 0x00;
uint16_t EC20_TCP_port_count = 0x00;
char EC20_send_string[MSCOMM_BUFFER_LENGTH];
char EC20_source_string[MSCOMM_BUFFER_LENGTH];
char EC20_target_string[MSCOMM_BUFFER_LENGTH];

void EC20_4G_Poll(void)
{
BaseType_t xResult;
BaseType_t xStatus;


switch (EC20_4G_isr)
{
case 0:
strcpy(EC20_send_string , "AT\r");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
EC20_4G_Outtime_Init();
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "AT\r\r\nOK\r\n");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 1;
}
}
break;

case 1:
if (++EC20_4G_Outtime > 2)
{
EC20_4G_Outtime = 0x00;
EC20_4G_isr = 0;
break;
}
strcpy(EC20_send_string , "ATE1\r");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "ATE1\r\r\nOK\r\n");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 2;
}
}
break;

case 2:
if (++EC20_4G_Outtime > 2)
{
EC20_4G_Outtime = 0x00;
EC20_4G_isr = 0;
break;
}
strcpy(EC20_send_string , "AT+CPIN?\r");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "AT+CPIN?\r\r\n+CPIN: READY\r\n\r\nOK\r\n");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 3;
}
}
break;

case 3:
if (++EC20_4G_Outtime > 2)
{
EC20_4G_Outtime = 0x00;
EC20_4G_isr = 0;
break;
}
strcpy(EC20_send_string , "AT+CREG=?\r");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "AT+CREG=?\r\r\n+CREG:");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 4;
}
}
break;

case 4:
if (++EC20_4G_Outtime > 2)
{
EC20_4G_Outtime = 0x00;
EC20_4G_isr = 0;
break;
}
strcpy(EC20_send_string , "AT+CSQ\r");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "AT+CSQ\r\r\n+CSQ:");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 5;
}
}
break;

case 5:
if (++EC20_4G_Outtime > 2)
{
EC20_4G_Outtime = 0x00;
EC20_4G_isr = 0;
break;
}
strcpy(EC20_send_string , "AT+QIDEACT=1\r");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "AT+QIDEACT=1\r\r\nOK\r\n");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 7;
}
}
break;


case 7:
strcpy(EC20_send_string , "AT+QIOPEN=1,0,\"TCP\",\"218.6.144.60\",5000,0,2\r\0");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "\r\nCONNECT\r\n");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_TCP_port_count = 0x00;
EC20_4G_isr = 20;
break;
}

if (++EC20_TCP_port_count >= 8)
{
EC20_TCP_port_count = 0x00;
EC20_4G_isr = 10;
break;
}
EC20_4G_isr = 0;
}
break;

case 9:
strcpy(EC20_send_string , "AT+QPOWD\r");
MB_USART2.sendCount = EC20_Connect_Buffer_Init(EC20_send_string , MB_USART2.send_buffer);
USART2_Begin_Send();
EC20_4G_isr = 11;
break;

case 10:
GPIO_EC20_RESET_0();
vTaskDelay(1000 / portTICK_RATE_MS);
GPIO_EC20_RESET_1();
EC20_4G_isr = 11;
break;

case 11:
xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string ,"\r\nRDY\r\n");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 0;
break;
}
EC20_4G_isr = 0;
}
break;

case 12:
GPIO_EC20_POWER_SLEEP();
vTaskDelay(200 / portTICK_RATE_MS);
GPIO_EC20_POWER_NO_SLEEP();
vTaskDelay(15000 / portTICK_RATE_MS);
EC20_4G_isr = 10;
break;

case 20:
xStatus = xQueueReceive( xQueue, &Buffer, portMAX_DELAY);
if( xStatus == pdPASS )
{
switch (Buffer[0])
{
case 2:
Over |= 0x01; //bit0=1,表示收到SD2405ALPI_Task任务的消息队列数据
MODBUS_Clock.year = Buffer[1];
MODBUS_Clock.month = Buffer[2];
MODBUS_Clock.day = Buffer[3];
MODBUS_Clock.hour = Buffer[4];
MODBUS_Clock.minute = Buffer[5];
MODBUS_Clock.second = Buffer[6];
MODBUS_Clock.week = Buffer[7];
break;
case 3:
Over |= 0x02; //bit1=1,表示收到DI1_Task任务的消息队列数据
MODBUS_DI1_1 = Buffer[1];
MODBUS_DI1_2 = Buffer[2];
break;
case 4:
Over |= 0x04; //bit2=1,表示收到DI2_Task任务的消息队列数据
MODBUS_DI2_1 = Buffer[1];
MODBUS_DI2_2 = Buffer[2];
break;
}//switch (Buffer[0])
}//if( xStatus == pdPASS )

//收到数据然后整理发送出去
//收到数据然后整理发送出去
//收到数据然后整理发送出去

xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
if (xResult == pdTRUE)
{
strcpy(EC20_target_string , "\r\nNO CARRIER\r\n");
hex_to_string(MB_USART2.mscomm_buffer , EC20_source_string , MB_USART2.receCount);
if (strstr(EC20_source_string , EC20_target_string) != NULL)
{
EC20_4G_Outtime_Init();
EC20_4G_isr = 10;
break;
}
}
break;
}//switch (EC20_4G_isr)
}
ba_wang_mao 2020-02-20
  • 打赏
  • 举报
回复
无论使用uCOSII或FreeRTOS都可以,我很想知道
1、任务该如何规划
2、任务和任务之间该如何通信

27,374

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧