Skip to content

1. 下载源码

建议使用 GIT 下载源码,命令如下:

bash
git clone https://github.com/Ai-Thinker-Open/emMCP.git

▫️目录结构

bash
emMCP
├── example               ------> 示例代码文件加
   ├── STM32F10xRTOS_MCP ------> STM32F103 CMake 示例
   └── ...
├── port                  ------> emMCP 移植接口文件夹
   ├── uartPort.h        ------> emMCP 移植接口头文件
   └── uartPort.c        ------> emMCP 移植接口源文件
└── uart-mcp              ------> emMCP 串口通讯文件夹
    ├──cJSON              ------> cJSON
  ├── cJSON.h        ------> cJSON 头文件
  └── cJSON.c        ------> cJSON 源文件
    ├── emMCP.h           ------> emMCP 头文件
    └── emMCP.c           ------> emMCP 源文件

3. 引入 emMCP 库

portuart-mcp 文件夹复制到你的项目当中,并引用 emMCP.h 文件使用 emMCP 的所有资源。

示例中提供了 STM32F103 的 CMake 示例(STM32F10xRTOS_MCP),你可以参考它来配置你的项目。

4. 移植接口

emMCP 是一个适用于串口通讯的库,因此你只需要实现串口通讯的底层函数。

▫️实现串口发送和接收

重要

请务必自行完成MCU的串口驱动,并确保串口接收函数能够正确接收数据,建议使用DMA方式接收串口数据。发送函数能够正常发送完整的数据包。

▫️移植 emMCP

  • 首先打开 port/uartPort.c 文件
  • 在函数int uartPortSendData(char *data, int len) 当中调用你的串口发送函数,将 datalen 作为参数传入。例如:
    c
    int uartPortSendData(char *data, int len)
    {
    	// 在此处实现串口发送函数
    	if (data == NULL || len <= 0)
    	{
    		return -1;
    	}
    	return HAL_UART_Transmit(&huart2, (uint8_t *)data, len, 100);
    }
  • 在 MCU 的串口接收函数当中调用 int uartPortRecvData(char *data, int len) 的接收函数,例如:
    c
    void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) 
    {
    	if (huart->Instance == USART2) {
    		HAL_UARTEx_ReceiveToIdle_DMA(huart, (uint8_t *)rxBuffer, sizeof(rxBuffer));
    		//调用emMCP接收函数
    		uartPortRecvData((char *)rxBuffer, Size);
    		__HAL_DMA_ENABLE_IT(&hdma_usart2_rx, DMA_IT_TC);
    	}
    }
  • 延时函数的实现,在 port/port.h 文件中,将延时函数在宏#define emMCP_delay 中实现,例如:
    c
    #define emMCP_delay osDelay
  • 内存管理函数的实现,在 port/port.h 文件中,将内存管理函数在宏#define emMCP_malloc#define emMCP_free 中实现,例如:
    c
    #define emMCP_malloc malloc
    #define emMCP_free free

5. 初始化 emMCP

你可在任何未执行主函数的地方初始化 emMCP,例如在 main() 函数之前,或者在一个单独的初始化函数中。初始化 emMCP 的代码示例如下:

c
static emMCP_t emMCP_dev;

int main(void)
{
	emMCP_Init(&emMCP_dev);
	whiet(1)
	{
		//主循环执行
	}
}

6. 循环执行 emMCP_TickHandler()

emMCP 内置了一个简单的状态机,需要循环地调用 emMCP_TickHandler() 处理数据,以减轻当使用中断函数时的负担。推荐在主循环中调用 emMCP_TickHandler(),例如:

c
static emMCP_t emMCP_dev;

int main(void)
{
	emMCP_Init(&emMCP_dev);
	whiet(1)
	{
		emMCP_TickHandler(10);
	}
}

7. 是否移植成功?

完成以上步骤之后,编译你的项目,确保编译成功,并且没有报错。按照以下步骤验证是否移植OK:

  • 下载程序到MCU
  • 对 AI 模组说“你好小安”
  • 观察串口输出,如果看到类似以下输出,则表示 emMCP 已经成功移植到你的 MCU 上:
bash
[DEBUG] emMCP_EventCallback:78: emMCP_EventCallback: event:8,type:4,param:2.WakeUP

8. emMCP 更多使用请参考:如何使用?

Released under the MIT License.