1. 串口及网络的驱动封装
调试串口用了uart1,这里不用microlib的话,重定向printf的功能,可以用下面的代码
struct __FILE{
int handle;
};
FILE __stdout;
int fputc(int c , FILE * f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&c,1,100);
return c;
}
教程中说,用microlib的话,后期用操作系统会有问题。
网络功能的封装,主要涉及到uart2串口的接收数据的解析,应用前面笔记的思路,这里任然是采用了串口发送数据超时时间的思路,配合定时器计时,来确定是否发送完成一帧数据。这样的可以,通过定义一个环形队列用来缓存串口2的接收数据。教程中在命令发送的时候,定义了一个环形队列用来接收发送命令之后,返回的命令数据。接收数据的时候,又重新定义了,另外一个环形队列保存数据。这样就有个问题,当有uart2接收数据的时候,就需要进行判断,看时命令之后的返回数据,还是传送的数据信息。传送的数据信息有特征,以+IPD开始的。教程中,还专门的用了一个状态机的方法,对每次接收的数据进行了分析判断,如果是接收到+IPD标志的数据,则要存到一个环形队列中,如果是命令的返回数据,则存到另外一个环形队列中。我这边处理的时候,就是当检查到一帧数据接收完成之后,如果是+IPD的特征的数据,就将环形队列中的数据拷贝出来,就可以了,更加的方便统一。
/* 读取网络数据 */
int driver_net_recvSocket(char * socket, int timeout)
{
while(timeout!=0) // 超时时间内判断接收数据
{
if(1==is_timeDelay_ok()) // 接收字符串完成
{
break; // 成功接收字符串,则跳出循环
}
HAL_Delay(1); // 阻塞延时 1ms
timeout--;
}
if(timeout==0)
{
// printf("receive time out!rn"); // 接收超时
return -1;
}
if(0==strstr((char *)cmdNetFIFO.fifo,"+IPD")) // 对比字符串是包含 +IPD
{
// printf("rn receive failure!rn");
return -1;
}
else
{
strcpy(socket,(char *)cmdNetFIFO.fifo); // 字符串拷贝到socket
driver_ringFIFO_clear(&cmdNetFIFO); // 清空接收FIFO缓冲
}
return 0;
}
进行通讯实验时候,笔记本电脑和esp8266连接同一个wifi,然后通过软件,选择TCP主机,上面有IP和端口,程序中TCP连接的时候,要跟这个IP和端口一致。
2. 各层的封装
在前面的教程中,介绍过程序的层次,由于采用了FreeRTOS,程序层次如下:
如果有相同属性的,将其封装成为一类对象,比如按键、LED和调试串口,对这几个外设的操作无外乎就是读写操作,所以将这三个整合到了一起,变成了一个IODev,输入输出设备。其实网络设备也是读写,但是其还有其它更复杂的操作,所以将网络设备独立了出去。 这样做其实就是一个面向对象的一种编程思想,将具体的外设对象,将他们的属性抽象出来整合到一个结构体中,以后这个抽象的结构体就可以代表某个具体的外设对象。而对于不同对象的功能或者操作函数,我们其实就是进行了一层一层的封装。
平台层的作用就是将上层的设备层和应用层与底层的驱动层进行隔离,上层的接口都是固定的,只有底层的驱动可能会跟随不同平台的处理器有变化,那当我们将工程像另外一个平台进行移植的时候,上层的应用代码几乎都可以不改变,只需要写好底层的驱动就好,然后再去平台层进行对应封装,这样就提高了可移植性。
本文章来源于互联网,如有侵权,请联系删除!原文地址:百问网七天物联网智能家居第6篇
(1)技术选型 针对物联网管理平台主要负责设备管理、指令下发、上报数据图表展示等功能.结合当前流程的主流前端技术框架应用情况考虑如下: 前端开发技术选型可采用vue3.0+typescript+elementUI(组件库)+htm…