OpenHarmony中AT模块的代码理解(2) 原创 精华
再见南丫岛
发布于 2022-3-17 21:56
浏览
2收藏
开启AT模块的第二篇帖子的整理。第一篇帖子链接如下:OpenHarmony中AT模块的代码理解(1)。
1、at_uart_task_body
hi_void *at_uart_task_body(hi_void* param)
{
hi_unref_param(param);
hi_char ch;
hi_s32 n;
for (;;) {
if (g_at_input_func == NULL) {
n = hi_uart_read(g_at_uart_port, (hi_u8 *)&ch, 1);
} else {
n = g_at_input_func((UINT8 *)&ch, 1);
}
if (n != 1) {
(hi_void)hi_sleep(AT_UART_SLEEP);
continue;
}
if ((hi_lpc_get_type() != HI_NO_SLEEP) && (g_at_check_empty == HI_TRUE)) {
g_at_have_uart_data = HI_TRUE;
hi_timer_start(g_at_uart_timer_handle, HI_TIMER_TYPE_ONCE, AT_WAIT_TIME, timer_handle, 0);
}
at_parse_uart_char(ch);
}
}
该函数的为一个任务,是一个循环函数。除去睡眠的逻辑外,注意的代码功能是通过串口获取一个字节数据。然后使用at_parse_uart_char(ch)函数进行处理。g_at_input_func函数的功能为模拟接收数据,主要用于测试,可以先不考虑。
2、at_parse_uart_char
hi_void at_parse_uart_char(hi_char ch)
{
switch (g_at_ctrl.at_state) {
case AT_IDLE:
g_busy_count = 0;
at_cmd_line_parse(ch);
break;
case AT_CMD_PROCESS:
hi_cpup_load_check_proc(hi_task_get_current_id(), LOAD_SLEEP_TIME_DEFAULT);
if (ch == '\n') {
if (g_busy_count >= SOFT_REBOOT_MAX_BUSY_CNT) {
g_busy_count = 0;
hi_soft_reboot(HI_SYS_REBOOT_CAUSE_AT_BUSY);
}
hi_at_printf("busy!\r\n");
g_busy_count++;
}
break;
case AT_DATA_RECVING:
g_busy_count = 0;
if (at_data_recving() != HI_ERR_SUCCESS) {
break;
}
at_get_send_data(ch);
break;
case AT_DATA_SENDING:
hi_cpup_load_check_proc(hi_task_get_current_id(), LOAD_SLEEP_TIME_DEFAULT);
if (g_at_ctrl.is_first_over_data) {
g_at_ctrl.is_first_over_data = HI_FALSE;
hi_at_printf("busy!\r\n");
}
break;
case AT_TRANSPARENT:
hi_at_printf("==TBD==\r\n");
break;
default:
break;
}
}
函数主要是有5个状态机的切换。
typedef enum {
AT_IDLE,//空闲模式
AT_CMD_PROCESS,//命令处理模式
AT_DATA_RECVING,//数据正在接收
AT_DATA_SENDING,//数据正在发送
AT_TRANSPARENT,//未实现
} at_state_machine;
在AT_IDLE状态下,at_cmd_line_parse(ch);继续处理接收到的字符。是我们主业务逻辑的函数。
在AT_CMD_PROCESS状态下,输入的字符会被扔掉,且如果数据的指令行数超过次,则会触发软重启操作。这样操作的好处,还不清楚。
在AT_DATA_RECVING和AT_DATA_SENDING状态,处理的典型场景是AT+IPSEND发送TCP/UDP数据的时候。
协议中注明了\0作为发送结束符,如果要发送\0,需转义成\0。这样,就比较好理解hi_void at_get_send_data(hi_char c)的处理模式了。
3、at_cmd_line_parse
hi_void at_cmd_line_parse(hi_char c)
{
hi_char ch = c;
static hi_u32 i = 0;
static hi_s32 key_value = 0;
static hi_u32 enter_flag = 0;
if ((i == 0) && (ch != '\n')) {
(hi_void)memset_s(g_at_buf, CMD_MAX_LEN, 0, CMD_MAX_LEN);
}
if (ch == '\n') {
if (i == 0) {
hi_at_printf("\r\nERROR\r\n");
g_at_ctrl.at_state = AT_IDLE;
return;
}
if (enter_flag == (i - 1)) {
i = 0;
g_at_ctrl.at_state = AT_CMD_PROCESS;
at_notify();
}
return;
}
enter_flag = 0;
if (ch == '\r') {
if (i == 0) {
hi_at_printf("\r\nERROR\r\n");
g_at_ctrl.at_state = AT_IDLE;
return;
}
if (i < (CMD_MAX_LEN - 1)) {
g_at_buf[i] = '\0';
}
enter_flag = i;
i++;
return;
}
if (at_key_filter(ch, &i, &key_value) != HI_ERR_SUCCESS) {
return;
}
if (ch != '\n') {
at_cmd_print_back(i, ch);
i++;
}
key_value = STAT_NOMAL_KEY;
}
该函数主要是几个if的条件判断。
if (ch != '\n') {
at_cmd_print_back(i, ch);
i++;
}
当字符串没有到截止符(\R\N)的时候,将接受到的字符通过at_cmd_print_back存储在g_at_buf中。
当if (ch == ‘\r’) 和if (ch == ‘\n’)两个判断的结合,即结尾是\r\n且字符串不为空的时候,将g_at_ctrl.at_state = AT_CMD_PROCESS切换模式,并且发送at_notify(),来通知数据处理的任务,进行AT命令的数据处理。
本篇文章就先介绍到这里。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-3-17 21:56:46修改
赞
4
收藏 2
回复
相关推荐
关键函数终于来喽