ESP8266:C语言常用知识点
ESP8266开发过程中,常常用到字符串处理,HEX转ASCII, IP地址处理,定时任务处理,TCP/UDP等。特此进行整理,以备不时之需。
字符串处理
定义字符串
uint8 uart_buff[256]; //定义字符串或内存空间,长度256,uart_buff指向首地址
uint8 *pdata; //定义字符串指针,指向字符串
创建字符串
memset(uart_buff,0,sizeof(tcp_send_buff));//字符串清空
sprintf(uart_buff,"%c%c%c",A,B,C);//将A,B,C(宏定义)内容写入字符串
memcpy(uart_buff,pdata,strlen(pdata)) //将pdata指向字符串复制到uart_buff中
查找字符串内容
#define NULL (void *)0
uint8 * p_result=NULL;
p_result = strstr(pdata, (const char *)"CMD1"); //查找字符串中是否包含CMD1,并指向其位置
if(p_rsult!=NULL){ //如果查找到,则进行处理
}
比较字符串内容
uint8 *pdata;
uint8 char_buff[16];
memcpy(pdata,char_buff,strlen(char_buff)); //比较char_buff和pdata内容,如果相同,则返回0
HEX转换为ASCII
HEX转换为字符串,其中pData指向需要转换的字符;pRusult指向转换后的字符,如果输入为0x01,则转换为ASCII 01, 如果输出0x5A则转换为ASCII 5A
void Hex2ASCII(uint8* pResult,uint8* pData){
uint8 i,temp_h,teml_l;
for(i=0;i<strlen(pData);i++){
/**转换高位**/
temp_h = pData[i]/16; //转换高位,例如,0x5A/16 = 5;
if(temp_h>=0&&temp_h<=9) //在0~9之间
temp = temp_h+48; //数字转换为ASCII码
else if(temp_h>=10&&temp_h<=15)
temp = temp_h+55; //数字转换为大写字符,例如A,B,C,D
pResult[i*2] = temp; //存入高位
/**转换低位**/
temp_l = pData[i]%16; //转换低位,例如,0x5A%16 = 0XA;
if(temp_l>=0&&temp_l<=9) //在0~9之间
temp = temp_l+48; //数字转换为ASCII码
else if(temp_l>=10&&temp_l<=15)
temp = temp_l+55; //数字转换为大写字符,例如A,B,C,D
pResult[i*2+1] = temp; //存入低位
}
}
IP地址处理
//把数字转换为IP地址
struct ip_addr {
uint32 addr;
};
#define IP4_ADDR(ipaddr, a,b,c,d) \
(ipaddr)->addr = ((uint32)((d) & 0xff) << 24) | \
((uint32)((c) & 0xff) << 16) | \
((uint32)((b) & 0xff) << 8) | \
(uint32)((a) & 0xff)
//构建server_ip
struct ip_addr sever_ip;
uint8 sever_ip[4]={0};
//将数字组合为ip地址
IP4_ADDR(&sever_ip, sever_ip[0], sever_ip[1], sever_ip[2], sever_ip[3]);
#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
ip4_addr2_16(ipaddr), \
ip4_addr3_16(ipaddr), \
ip4_addr4_16(ipaddr)
/*IP2STR例子,将ip地址转换为4个数字*/
printf("%d.%d.%d.%d\r\n",IP2STR(&info.ip));
/*将ip地址转换为字符串*/
sprintf(send_buff,"{\"ipaddr\":\"%d.%d.%d.%d\"}\r\n",IP2STR(&info.ip));
定时任务
在定时循环中,对计数器计数;
task_cnt++;
在执行循环中,检查计数器,当计数器达到间隔时
if(task_cnt>100){
exeTask();
task_cnt=0;
}
条件定时任务
当条件满足时,开始运行的定时任务;
//定时循环中
if(condition_flag) task_cnt++;
//任务循环中
if(task_cnt>100){
exeTask(); //执行任务;
task_cnt=0; //请定时器
}
大小循环定时任务
程序描述:每隔5S执行一次任务,每次执行时,相同的任务运行5次,每次间隔200ms,例如:设定LED的闪灯方式,每隔5S闪烁一次,每次闪烁时,用200MS间隔闪5次;
程序思路:大循环记录5S时间间隔;小循环记录任务之间间隔;5S时间到,开始小循环计数;小循环200ms时间到,检查执行次数,如果没有超出,则执行任务。否则清除标志位
//大循环定时,在定时任务中检查
if(loop1_flag) loop1_cnt++; //大循环计数器
//小循环定时,在定时任务中检查并计数
if(loop2_flag) loop2_cnt++; //小循环计数器
//一下代码在执行任务中运行
//大循环标志位
if(loop1_cnt>500){
loop2_flag=1; //定时时间到,设置小循环标志
loop1_cnt = 0; //清零loop1计数器
}
//小循环执行
if(loop2_cnt>20){ //小循环计时器时间到
if(task_exe_cnt<5){ //执行次数未到
exeTask(); //执行任务
task_exe_cnt++; //记录执行次数
loop2_cnt=0; //计数器清零
}else{ //任务已经完成了5次
task_exe_cnt=0; //任务次数计时器清零
loop2_cnt = 0;
loop2_flag=0; //计数器标志清零,停止执行
}
}
字符转换为16进制数
物联网应用中,网络传输数据通常为字符串格式,而MCU中执行命令通常为HEX格式,因此需要把字符串转换为16进制。例如:字符串格式的1f中,1为低位数字,f为高位数字,需要将其组合为0x1f这样的数字。
for(i=0; i<CMD_LEN; i++){
if((*(pdata+i*2)>='0') && (*(pdata+i*2)<='9')){
temp = (*(pdata+i*2)-'0')<<4;
}
if((*(pdata+i*2)>='a') && (*(pdata+i*2)<='f')){
temp = (*(pdata+i*2)-'a'+10)<<4;
}
if((*(pdata+i*2)>='A') && (*(pdata+i*2)<='F')){
temp = (*(pdata+i*2)-'A'+10)<<4;
}
if((*(pdata+i*2+1)>='0') && (*(pdata+i*2+1)<='9')){
temp += (*(pdata+i*2+1)-'0')&0xff;
}
if((*(pdata+i*2+1)>='a') && (*(pdata+i*2+1)<='f')){
temp += (*(pdata+i*2+1)-'a'+10)&0xff;
}
if((*(pdata+i*2+1)>='A') && (*(pdata+i*2+1)<='F')){
temp += (*(pdata+i*2+1)-'A'+10)&0xff;
}
cmd_buff[i] = temp;
temp=0;
os_printf("cmd:%x\r\n",cmd_buff[i]);
}
这样,*pdata中的字符串就转换为cmd_buff中的16进制数据了。