当我们在定义函数中采用函数指针作为参数时,
头文件(,h文件)中, 使用如下代码:
#ifdef __cplusplus
extern "C"{
#endif //
ESP_Error_t esp8266_sendcmd(const char* cmd, const char* response, uint8_t (*cmd_function)(ESP_MSG_LIST));
#ifdef __cplusplus
}
#endif // __cplusplus
在.c文件中直接定义函数:
ESP_Error_t esp8266_sendcmd(const char* cmd,const char* response, uint8_t (*cmd_function)(ESP_MSG_LIST)){
// .....
}
此时, 如果采用 --cpp11 为定义(一般需要采用这个, Keil工程中才能用C++代码)时, 直接编译会出现如下报错
Error: L6218E: Undefined symbol esp8266_sendcmd (referred from esp8266_driver.o).
即没有识别到对应的函数, 这个是因为, .c 文件中的函数指针仍然是按照
解决办法是在你编写的 .c 文件中, 再单独加入一个 extern “C”{} , 完整代码如下:
(这个是在.c文件中把带函数指针这部分再括起来)
#ifdef __cplusplus
extern "C"{
#endif
/// @brief send the command, wait for response string
/// @param cmd string with command (must end with "\\r\\n")
/// @param response string need to check for response (such as "OK")
/// @param cmd_function if the response is get, it will call cmd_function and send current ESP_MSG_LIST
/// for this function, return 0: execute successfully return 1: execute failed
/// @return if return ESP_RES_OK, command executed successfully.
/// @note data received during cmd execution will be ignored, and ESP_CMD_LIST will always be cleared after execution
ESP_Error_t esp8266_sendcmd(const char* cmd,const char* response, uint8_t (*cmd_function)(ESP_MSG_LIST)){
ESP_Error_t result = ESP_RES_CMD_NO_RESPONSE_ERR;
_esp8266_sendstring(cmd);
esp_timeout_counter = 0; // reset the counter
while (esp_timeout_counter < ESP8266_RESPONSE_TIMEOUT + extra_command_timeout){
Delay_ms(1);
uint8_t res;
res = _esp8266_receive_msg_cb(); // 1: try receive msg to CMD List
if (res) return ESP_RES_RxBUFFER_FULL; // detect if the buffer is full (if full, try execute command once);
// compare the ESP_Cmd_List and response string,
for (int i=0; i < ESP_Cmd_List.cmd_buffer_length; i++){
if (strcmp(ESP_Cmd_List.cmd_buffer[i], response) == 0) { // if get the response expected
uint8_t r1 = 0;
if (cmd_function!=NULL) r1 = cmd_function(ESP_Cmd_List); // r1 = 0 execute successfully, or failed
if (!r1) result = ESP_RES_OK;
else result = ESP_RES_CMD_EXEC_FAIL;
_esp8266_clearCmdList(); // after execution, clear the command list
return result;
}
}
esp_timeout_counter++;
}
_esp8266_clearCmdList(); // always clear this buff
// timeout error handeling
if (esp_timeout_counter >= ESP8266_RESPONSE_TIMEOUT + extra_command_timeout){
esp_timeout_counter = 0;
_esp8266_clearRxBuffer();
result = ESP_RES_CMD_NO_RESPONSE_ERR;
}
return result;
}
#ifdef __cplusplus
}
#endif
编译成功
另外文末也顺便提一下, 我最近在写 STM32 的 ESP8266 的AT 指令驱动代码(用于c8t6, ret6等等), 目前这个工程已经开源到 我的仓库https://github.com/FRIEDparrot/ESP8266_AT_Command_Driver
(虽然目前不是特别完善,但是是一个纯C语言的可扩展和移植能力比较强的库, 也欢迎读者来 star ,使用和贡献代码[doge]).
这一期就到这里了, 之后可能ESP8266写完会专门弄一篇相关的来讲一下。