CSDR华为云_小熊派开发实践丨小熊派+合宙Cat.1接入云服务器

摘要:使用小熊派开发板,以合宙的AIR724为通信模组(Cat.1),以AT指令方式,通过mqtt协议接入云服务器。

本贴使用小熊派开发板+合宙的Air724(Cat.1模组),接入自己搭建的EMQ服务器

一、实验准备

1.实验环境

一块stm32开发板(推荐使用小熊派),以及数据线

已经安装STM32CubeMX

已经安装KeilMDK,并导入stm32开发板对应的芯片包(小熊派使用的是STM32L431RCT6)

一个Cat.1模块(Uart接口,AT指令)以及杜邦线

f2e124b4fb8eb0d9ed35bd81e419acff.png

4b7d6be118a41cf168a3ddb018005a13.png

2.目标效果

通过CubeMX创建工程并配置参数

通过串口2,以AT指令控制通信模组

Cat.1发送相应的AT指令接入云服务器

通过MQTT协议,完成数据订阅、发布

二、通过CubeMX生产MDK工程

A.芯片选择

打开CubeMX,进入芯片选择:

a282f9be1991db52dc619f92688b21e7.png

选择自己的stm32芯片(即STM32L431RCT6):

e29661a2a2583a4669c9a497c9f8a91d.png

B.时钟源RCC设置

更改系统时钟源

系统时钟默认使用内部的高速时钟(HSI),选择使用HSE,时钟更精确

设置外部时钟对应的端口

1087348ad42c657933435f27341c02fd.png

配置时钟树

STM32L431RCT6系统时钟最大可以为80MHz,我们配置到最大即可

48a61cb656c325b61d2b15e59e113c50.png

C.参数配置(对应端口设置)

1)配置USART1

使用USART,模式为异步,波特率为115200,无硬件流控制

f54396b4ede072a3f3d3fe1bb66a500f.png

2)配置UART2,连接Cat.1

Cat.1模组烧录有AT固件,当然合宙的也支持Luat开发,我们为了更方便学习,就是要AT指令开发

我们使用小熊派的Uart2,小熊派引出的引脚为PA2->USART_TX,PA3->USART_RX

其他选项,波特率设置为9600,其他默认即可

20da79c57a33591dd31dddd4da85c430.png

3)打开Uart2中断,并开启接收DMA

开启中断

bded27e25ccdb02d0027be33c5e110c9.png

打开接收DMA

bc6d85a6d5fb4c6c396cd935ba7203a6.png

最后,生成代码就OK了

D.工程设置

一些基础的设置,包括工程名、存储位置、工程环境、工程中各个文件的组成

24d12dbf57a7801ca3b4a3daef1ff323.png

280a615ae344672cf17b5a0a4af2931c.png

E.生成代码

5660e5b49dcd1ac1477080a847829b9d.png

三、编写相应代码

1. 串口1输出重定向

我们知道printf是打印函数,原理是根据传入的字符串参数格式化打印输出到stdout中。我们需要让printf打印到串口之中,只需要在usart.c文件中模仿printf写一个输出函数即可

在添加头文件

/* USER CODE BEGIN 0 */

#include

#include

#include

/* USER CODE END 0 */

写输出函数

/* USER CODE BEGIN 1 */

void UsartPrintf(UART_HandleTypeDef *huart, char *fmt,...)

{

unsigned char UsartPrintfBuf[296];

va_list ap;

unsigned char *pStr = UsartPrintfBuf;

va_start(ap, fmt);

vsprintf((char *)UsartPrintfBuf, fmt, ap); //格式化

va_end(ap);

while(*pStr != 0)

{

USART1->TDR = *pStr++;

while((USART1->ISR & 0x40) == 0);

}

}

//注意:在usart.h中添加void UsartPrintf(UART_HandleTypeDef *huart, char *fmt,...);

//使用方法:UsartPrintf(&huart1;,"hello world\r\n");

/* USER CODE END 1 */

注意:自己添加的代码,需要在begin和end之间

2.通信的主要代码

我们创建两个文件,分别是Cat1.h和Cat.c

同时,完善串口2的收发功能,加入串口回调函数保证数据的完整

a).串口回调函数

因为在进行发送AT指令后,接受的数据要进行处理;一方处理速度跟不上,因此加入一个串口回调函数

//串口回调函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

if(huart->Instance == USART2)

{

if(Usart2type.UsartRecLen>0) //证明还有未完成数据

{

memcpy(&Usart2type.Usart2RecBuffer[Usart2type.UsartRecLen],Usart2type.Usart2DMARecBuffer,Usart2type.UsartDMARecLen); //转存到待处理区域

Usart2type.UsartRecLen += Usart2type.UsartDMARecLen;

}

else

{

memcpy(Usart2type.Usart2RecBuffer,Usart2type.Usart2DMARecBuffer,Usart2type.UsartDMARecLen); //转存到待处理区域

Usart2type.UsartRecLen = Usart2type.UsartDMARecLen;

}

memset(Usart2type.Usart2DMARecBuffer, 0x00, sizeof(Usart2type.Usart2DMARecBuffer)); //先清空DMA缓冲区

Usart2type.UsartRecFlag = 1;

}

}

b).串口2空闲中断

当发送或接受完成一组数据后,进入空闲中断

函数如下

void USART2_IRQHandler(void)

{

/* USER CODE BEGIN USART2_IRQn 0 */

if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) ==SET) //触发空闲中断

{

uint16_t temp = 0;

__HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除串口2空闲中断标志位

HAL_UART_DMAStop(&huart2); //关闭DMA

temp = huart2.Instance->ISR; //清除SR状态寄存器 F0 ISR

temp = huart2.Instance->RDR; //读取DR数据寄存器 F0 RDR 用来清除中断

temp = hdma_usart2_rx.Instance->CNDTR; //获取DMA中未传输的数据个数

Usart2type.UsartDMARecLen = USART2_DMA_REC_SIE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数

HAL_UART_RxCpltCallback(&huart2); //串口接收回调函数

}

/* USER CODE END USART2_IRQn 0 */

HAL_UART_IRQHandler(&huart2);

/* USER CODE BEGIN USART2_IRQn 1 */

HAL_UART_Receive_DMA(&huart2,Usart2type.Usart2DMARecBuffer,USART2_DMA_REC_SIE); //重新打开DMA接收

/* USER CODE END USART2_IRQn 1 */

}

C).AT指令通信流程

主要的AT指令如下

tsATCmds ATCmds[] =

{

{"AT\r\n","OK",200,NO_REC,10}, //测试

{"AT+CIMI\r\n","4600",200,NO_REC,10}, // 移动卡号

{"AT+CSQ\r\n","+CSQ",200,NO_REC,10}, //信号

{"AT+CEREG?\r\n","+CEREG: 0,1",200,NO_REC,10}, //网络

{"AT+CGATT?\r\n","+CGATT:1",200,NO_REC,10}, //驻网

{"AT+CCLK?\r\n","+CCLK",200,NO_REC,10}, //时间

{"AT+MCONFIG=0001,door,2020\r\n","OK",200,NO_REC,10}, //MQTT参数

//{"AT+MCONFIG=111,device1,123456\r\n","OK",200,NO_REC,100},

{"AT+MDISCONNECT\r\n","",200,NO_REC,5}, //断开MQTT连接

{"AT+MIPCLOSE\r\n","",200,NO_REC,5}, //断开TCP连接

{"AT+MIPSTART=123.56.117.8,1883\r\n","CONNECT OK",200,NO_REC,5}, //建立TCP连接

{"AT+MCONNECT=1,60\r\n","CONNACK OK",200,NO_REC,5}, //建立MQTT连接

{"AT+MSUB=","SUBACK",200,NO_REC,5}, //订阅主题

{"AT+MPUB=","OK",200,NO_REC,5}, //发布主题

{"AT+MQTTSTATU\r\n","+MQTTSTATU",200,NO_REC,5}, //状态

//AT+MQTTSTATU 0-离线 1-正常 2-需发送MCONNECT

{"AT+RESET\r\n","",200,NO_REC,5}//重启

};

四、编译+下载

点击编译后,0 error,0 warning

6eb61eb9bab5877a0ca9882f507174ae.png

小熊派连接在电脑上,代码下载到开发板

b9fee2b0a574707c25dd3689b05dfe04.png

五、连接硬件

1.将Cat.1的uart1_tx连接小熊派uart2_rx,cat.1的uart1_rx连接小熊派uart2_tx;Gnd连Gnd;

注意:一定要连接GND哦,需要共地的。

2.调试

此时,我们进行最后一次调试;将小熊派串口1用作串口打印,打开串口调试助手,查看运行状态(在每次发送指令后进行printf()打印相应信息)。

附件中包含CubeMX工程、MDK工程

下一步,打算将此设备接入华为云IoTDA,更好的完成设备管理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 PHP 中,可以使用递归函数来查找文件夹并获取其内部的文件,包括其所有子目录中的文件。下面是一个示例代码: ```php function scan_dir($dir) { $files = array(); if (is_dir($dir)) { $handle = opendir($dir); while (($file = readdir($handle)) !== false) { if ($file != "." && $file != "..") { if (is_dir($dir . "/" . $file)) { $files = array_merge($files, scan_dir($dir . "/" . $file)); } else { array_push($files, $dir . "/" . $file); } } } closedir($handle); } return $files; } // 使用示例 $dir = "/path/to/dir"; // 指定目录路径 $files = scan_dir($dir); // 获取目录下所有文件 foreach ($files as $file) { // 处理每个文件 echo $file . "\n"; } ``` 上面的代码中,我们定义了一个名为 scan_dir 的递归函数,该函数接受一个目录路径作为参数,并返回一个包含该目录及其所有子目录中所有文件的数组。在函数中,我们使用 opendir 函数打开目录,然后使用 readdir 函数遍历目录中的所有文件。对于每个文件,我们判断它是文件夹还是文件,如果是文件夹,则递归调用 scan_dir 函数来获取其内部的文件,否则将该文件路径添加到结果数组中。最后,我们使用 closedir 函数关闭目录,并返回结果数组。 需要注意的是,由于递归函数会遍历所有子目录中的文件,因此在处理大型目录时可能会消耗大量的时间和内存。如果需要处理大型目录,建议使用迭代函数来遍历目录,并在处理每个文件时进行必要的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值