C语言之面向对象

  • Post author:
  • Post category:其他


C语言之面向对象_网关

  1. 概述

    嵌入式设备与外界通信大多是串口,若想通过以太网、WIFI、BLE等通信,则需要外接对应的模块来实现,但每种通信方式对应的网络协议却不相同,

    为了实现代码复用及减少模块间的耦合,借用面向对象的方式: 只关注通信的属性:接收,处理,发送; 至于具体的通信行为,则由每个通信协议内部实现。

    将上述分为两个模块:通信的属性–> 协议解析器; 具体通信行为–> 命令解析器



  1. 模块解析

    2.1 协议解析器

    2.1.1 数据结构
			struct ProtocolInterfaceStruct		//协议接口
			{
				void (*Protocol_Init) (Protocol_Init_parameters);
				void (*Protocol_process) (Protocol_process_parameters);
				void (*Protocol_sender) (Protocol_sender_parameters);
				void (*Protocol_error) (Protocol_error_parameters);
			}
			
			typedef ProtocolInterfaceStruct *ProtocolInterface;
			typedef protocol_struct *Protocol;
			
			struct protocol_struct			//协议结构
			{
				char* protocol_name;
				E_PROTOCOL_TYPE protocol_type;
				ProtocolInterface protocol_interface;
			}
	2.1.2 模块伪代码实现
		2.1.2.1 协议模块
			每个协议创建一个.c文件: uart.c, ble.c, tcp.c ```
			在每个.c 文件中创建上述结构体实例。
			例如uart.c中:
				static struct ProtocolInterface g_uart_protocol_interface = 
				{
					uart_init,
					uart_process,
					uart_sender,
					uart_error
				};
				static struct protocol_struct g_uart_protocol = 
				{
					"uart_protocol",
					P_UART,
					&g_uart_protocol_interface;
				};
				//获取protocol的处理函数
				Protocol Uart_Get_Protocol_Handler(void)
				{
					return &g_uart_protocol;
				}
		2.1.2.2 通用模块
			在外部通用文件里,例如 protocol.c, 
				Protocol_Init();
				Protocol_Process();
				Protocol_Sender();
				Protocol_error();
				
				通过串口号获取对应protocol 的处理函数:
				Protocol Get_Protocol_Handler(Uart_NUM uart_num)
				{
					Protocol protocol = NULL;
					//check uart_num
					
					switch(uart_num)
					{
						case uart_usart:
							protocol = Uart_Get_Protocol_Handler();
						case ble_usart:
							protocol = Ble_Get_Protocol_Handler();
						case tcp_usart:
							protocol = Tcp_Get_Protocol_Handler();
						default:
						break;
					}
					return protocol;
				}
				协议接口通用函数,例如 初始化:
				void Protocol_Init(Protocol protocol, Protocol_Init_parameters)
				{
					// 检查protocol
					if( protocol == NULL)
					{
						//debug msg
					}
					else
					{
						protocol->protocol_interface->Protocol_Init(Protocol_Init_parameters);
					}
				}
2.2 命令解析器
	命令解析器:设置一个列表数组,数组索引为协议类型,数组元素包括命令,命令对应的处理函数,最大的命令数等, 初始化时先注册对应的cmd 和 handler, 接收到命令
	后, 检查命令是否被注册,并调用对应的 cmd_handler , 
	2.2.1 数据结构
			//命令枚举
			typedef enum
			{
				cmd1,
				cmd2,
				cmd3,
				//```
			}Protocol_Cmd;
			//命令处理函数指针
			typedef Protocol_Return (*Protocol_Handler) (Protocol_Handler_parameters);
			命令处理结构体
			struct ProtocolCmdHandler
			{
				Protocol_Cmd cmd;				//命令
				Protocol_Handler handler;		//命令对应的处理函数
			}
			typedef struct ProtocolCmdHandler* PROTOCOL_CMD_HANDLER;
			//命令模块结构体
			struct Protocol_CMD_Handler_Struct
			{
				Uart_NUM uart_num;
				PROTOCOL_CMD_HANDLER cmd_handler_list;
				uint16_t max_cmd;
				bool init_flag;
			}
			//命令处理列表
			static struct Protocol_CMD_Handler_Struct g_protocol_cmd_handler[max_uart_num] = {max_uart_num, NULL, 0, false};
	2.2.2 模块伪代码实现
		2.2.2.1 通用命令处理函数 protocol_cmd.c
//清空链表
				Protocol_Command_Handler_Clear();
				//初始化协议对应列表
				Protocol_Command_Handler_Init();
				//协议处理
				Protocol_Command_Handler_Process();
				//注册命令处理函数
				Protocol_Command_Handler_Register();
				//根据协议获取对应命令的处理函数
				Protocol_Command_Handler_GetHandle();
				
				//初始化
				void Protocol_Command_Handler_Init(Uart_NUM uart_num, uint16_t max_cmd)
				{
					if((uart_num < max_uart_num) &&
					   (is_protocol_available(uart_num) == true) &&
					   g_protocol_cmd_handler[uart_num].init_flag == false)
					{
						//分配空间
						g_protocol_cmd_handler[uart_num].uart_num = uart_num;
						g_protocol_cmd_handler[uart_num].max_cmd_handler = max_cmd;
						g_protocol_cmd_handler[uart_num].cmd_handler_list = (PROTOCOL_CMD_HANDLER)malloc(max_cmd * sizeof(struct ProtocolCmdHandler));

						if(g_protocol_cmd_handler[uart_num].cmd_handler_list != NULL)
						{
							//初始化有链表非空,清空链表
							Protocol_Command_Handler_Clear(uart_num);
						}

						g_protocol_cmd_handler[uart_num].init_flag = true;
					}
				}
				//获取命令处理函数
				PROTOCOL_CMD_HANDLER  Protocol_Command_Handler_GetHandle(Uart_NUM uart_num, Protocol_Cmd command)
				{
					PROTOCOL_CMD_HANDLER  handler_p = g_protocol_cmd_handler[uart_num].cmd_handler_list;
					PROTOCOL_CMD_HANDLER  handler_r = NULL;

					if((uart_num < max_uart_num) &&
					   (g_product_protocol_cmd_handlers[uart_num].cmd_handler_list != NULL) &&
					   (is_protocol_available(uart_num) == true))
					{
						while (handler_p->command != max_uart_num)
						{
							//获取命令对应的处理函数
							if (handler_p->command == command)
							{
								handler_r = handler_p;
								break;
							}
							handler_p++;
						}
					}
					return handler_r;
				}
		2.2.2.2 协议模块处理
			uart_cmd_handle.c
				//初始化
				uart_cmd_handle_init()
				{
					//初始化处理列表里usart的结构体
					Protocol_Command_Handler_Init(uart_usart, usart_max_cmd);
					
					//usart 命令注册
					Protocol_Command_Handler_Register(uart_usart, cmd1, cmd1_handler);
					Protocol_Command_Handler_Register(uart_usart, cmd2, cmd2_handler);
				}
3. 数据流

	串口接收任务uart_task,调用 Protocol_Process 接口处理接收到的数据,Protocol_Process 内调用对应的处理函数,如 uart_process, 处理完成后,
	例如需要将 uart 的数据转发到 tcp ,调用 Protocol_Sender, 内部调用 tcp_sender, 将uart 的数据转发到 tcp 上去



版权声明:本文为weixin_45444963原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。