基于stm32的4G模块点灯实验

news2024/10/21 9:17:19

led模块功能封装

#include "led.h"
#include "sys.h"

//初始化GPIO函数
void led_init(void)
{
		GPIO_InitTypeDef gpio_initstruct;
		//打开时钟
		__HAL_RCC_GPIOB_CLK_ENABLE();
		//调用GPIO初始化函数
	gpio_initstruct.Pin  = GPIO_PIN_8 | GPIO_PIN_9;
	gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;
	gpio_initstruct.Pull = GPIO_PULLUP;//上拉
	gpio_initstruct.Speed= GPIO_SPEED_FREQ_HIGH;
		HAL_GPIO_Init(GPIOB,&gpio_initstruct);
		//关闭LED
	led1_off();
	led3_off();
		
		
}


//点亮LED的函数


void led1_on(void)
{
  	//由电路图可知,将GPIO拉低
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);

}
//熄灭LED1的函数

void led1_off(void)
{
		//由电路图可知,将GPIO拉低
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);


}
//翻转LED1状态的函数

void led1_toggle(void)
{
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);


}

void led3_on(void)
{
  	//由电路图可知,将GPIO拉低
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);

}
//熄灭LED1的函数

void led3_off(void)
{
		//由电路图可知,将GPIO拉低
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);


}
//翻转LED1状态的函数

void led3_toggle(void)
{
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);


}

4G模块功能代码及指令

内网穿透

1. 内网穿透

内网穿透的原理就像在内网和外网之间搭建了一座桥梁,使得外部网络可以穿过内网的障碍,直接访问内部 的设备。

2. 花生壳配置

案例演示

 右边是通过官网的方式来连接的

4G模块

上位机配置: 1. 选择端口号(根据自己的端口选择) 2. 选择波特率(默认115200) 3. 打开串口 4. 点击进入配置,上位机会自动发送AT指令进行配置 5. 读取参数,此命令可以读取4g模块的详细信息,并打印带基本信息栏(这一步很重要,否则在第九步的 时候会出现问题) 6. 选择链路1 7. 默认是连接亿佰特的服务器 这边我们需要修改成我们自己的,具体从花生壳获取(是一串域名,或者 IP地址,他都支持,根据自己获取到的填写就可以) 8. 输入从花生壳获取的端口号 9. 点击保存配置(对应第五步,我们很多的配置需要获取到模块默认配置,保存时才会不改变) 10. 点击重启(重启后默认进入透传模式,无需在做其他操作,直接链接到串口助手上即可发送与接收信 息)

不用自己敲指令,有专门的上位机

服务端

进入AT模式后在链接2中,复制映射IP时不能复制端口,否则,外网与内容能连接但是不能通讯通过接口

重启之后就默认进入透传模式

TCPC代表端口

填入的是映射出来的地址

 4G模块可以左边能接收到,但是右边收不到

网络调试助手的TCP client打不开

解决问题1

联系快速的断连

有时候是连接的但是确实断的

解决方法

网络调试2 助手在协议类型为TCP Client打不开的情况则,需连接WiFi模块的wifi使其处在同一网段下,如果电脑连接路由器家庭WiFi则与服务器不是同一网段。

就会出现连接不了的情况

功能代码

头文件

#include "sys.h"
#include "e840.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"

/* UART收发缓冲大小 */
#define E840_RX_BUF_SIZE            128
#define E840_TX_BUF_SIZE            64

/* 错误代码 */
#define E840_EOK                     0      /* 没有错误 */
#define E840_ERROR                   1      /* 通用错误 */
#define E840_ETIMEOUT                2      /* 超时错误 */
#define E840_EINVAL                  3      /* 参数错误 */


void e840_init(uint32_t baudrate);//所以增加新添加一个
uint16_t e840_receive_data(char *recv_data);
void e840_test(void);

uint8_t e840_tx_buf[E840_TX_BUF_SIZE];
uint8_t e840_rx_buf[E840_RX_BUF_SIZE]; 

uint16_t e840_cnt = 0 ,e840_cntPre = 0; /* es840接收缓冲区 */

UART_HandleTypeDef e840_handle;             /* esp8266句柄 */
#include "sys.h"
#include "e840.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"
uint8_t e840_tx_buf[E840_TX_BUF_SIZE];
uint8_t e840_rx_buf[E840_RX_BUF_SIZE]; 

uint16_t e840_cnt = 0 ,e840_cntPre = 0; /* es840接收缓冲区 */

UART_HandleTypeDef e840_handle;             /* esp8266句柄 */



/**
 * @brief       串口1初始化函数
 * @param       baudrate: 波特率, 根据自己需要设置波特率值
 * @retval      无
 */
void e840_uart_init(uint32_t baudrate)//正常会有启动的流程只是作为一个串口的初始化
{
    /*esp8266 初始化设置*/
    e840_handle.Instance = USART2;                                         /* USART1 */
    e840_handle.Init.BaudRate = baudrate;                                  /* 波特率 */
    e840_handle.Init.WordLength = UART_WORDLENGTH_8B;                      /* 字长为8位数据格式 */
    e840_handle.Init.StopBits = UART_STOPBITS_1;                           /* 一个停止位 */
    e840_handle.Init.Parity = UART_PARITY_NONE;                            /* 无奇偶校验位 */
    e840_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;                      /* 无硬件流控 */
    e840_handle.Init.Mode = UART_MODE_TX_RX;                               /* 收发模式 */
    HAL_UART_Init(&e840_handle);                                           /* HAL_UART_Init()会使能e840 */
}


/**
 * @brief       esp8266接收缓冲区清除
 * @param       无
 * @retval      无
 */
void e840_rx_clear(void)
{
    memset(e840_rx_buf, 0, sizeof(e840_rx_buf));                          /* 清空接收缓冲区 */
    e840_cnt = 0;                                                       /* 接收计数器清零 */
}

/**
 * @brief       串口1中断服务函数
 * @note        在此使用接收中断及空闲中断,实现不定长数据收发
 * @param       无
 * @retval      无
 */
void USART2_IRQHandler(void)
{
    uint8_t receive_data = 0;   
    if(__HAL_UART_GET_FLAG(&e840_handle, UART_FLAG_RXNE) != RESET){        /* 获取接收RXNE标志位是否被置位 */
        if(e840_cnt >= sizeof(e840_rx_buf))                            /* 如果接收的字符数大于接收缓冲区大小, */
            e840_cnt = 0;                                               /* 则将接收计数器清零 */
        HAL_UART_Receive(&e840_handle, &receive_data, 1, 1000);            /* 接收一个字符 */
        e840_rx_buf[e840_cnt++] = receive_data;                        /* 将接收到的字符保存在接收缓冲区 */
    }

    if (__HAL_UART_GET_FLAG(&e840_handle, UART_FLAG_IDLE) != RESET)        /* 获取接收空闲中断标志位是否被置位 */
    {
        printf("recv: %s\r\n", e840_rx_buf);                               /* 将接收到的数据打印出来 */
        e840_rx_clear();
        __HAL_UART_CLEAR_IDLEFLAG(&e840_handle);                           /* 清除UART总线空闲中断 */
    }
}



uint8_t e840_wait_receive(void)
{
	if(e840_cnt == 0)
			return E840_ERROR;
	if(e840_cnt == e840_cntPre)
	{
		e840_cnt = 0;
		return E840_EOK;
	}
		e840_cntPre = e840_cnt;
		return E840_ERROR;
}

uint8_t e840_send_command(char *cmd,char *res)//发送一个指令去   在指定时间内返回回来 否则没有接收到一个返回值
{
	uint8_t timeout_out = 250;
	
	e840_rx_clear(); //防止忍心内的数据影响
	HAL_UART_Transmit(&e840_handle,(uint8_t *)cmd,strlen(cmd),100);//发送命令 cmd在这里是一个uint8_t的数据 长度 阻塞的值
	//等待
	while(timeout_out--)//不停的等待
	{
		if(e840_wait_receive() == E840_EOK)
		{
			if(strstr((const char*)e840_rx_buf, res) != NULL)//判断是否又有期待的字符串
			return E840_EOK;
		}
		delay_ms(10);
		}
		return E840_ERROR;//否则接收错误
	
}

//只是内部处理外部是不知道的用不了,为了便于外部能获取RX_BUF接收缓冲区内容接收到多少的数据,可以将接收到的字符,对代码进行修改
//复制一份给TX_BUF
//接收的函数通返回值传出来,这样RX_bUF就能传出来 memcpy(recv_data,)

uint16_t e840_receive_data(char *recv_data)
{
	if(e840_wait_receive() == E840_EOK)
	{
		printf("esp8266 recv: %s\r\n", e840_rx_buf);
		memcpy(recv_data, e840_rx_buf,strlen((const char *)e840_rx_buf));
		e840_rx_clear(); //清空之前一样的,清空为下一次数据做准备,用recv_data作为返回值
		return strlen((const char *)recv_data);
	}
	
	return 0;//没有接收到数据
}

//发送的函数  不定长数据 参数不固定
void e840_send_data(char *fmt, ...)
{
	va_list ap;
	uint16_t len;
	
	va_start(ap,fmt);
	vsprintf((char *)e840_tx_buf,fmt, ap);
	va_end(ap);
	
	len = strlen((const char*)e840_tx_buf);
	HAL_UART_Transmit(&e840_handle, e840_tx_buf, len,100);//发送
}




void e840_init(uint32_t baudrate)//所以增加新添加一个
{
		e840_uart_init(baudrate);
	
}		


//测试函数

main函数代码

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "e840.h"
#include "string.h"
int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    led_init();	/* LED初始化 */

		uart1_init(115200);
		e840_init(115200);
		

		printf("helloworld!\r\n");
		char recv_data[E840_RX_BUF_SIZE];//接收传入参数
    while(1)
    { 
      			
			e840_receive_data(recv_data);//接收到数据tcp服务器传输过来的字符串
			if(strstr(recv_data, "ON") != NULL)//判断字符串有ON,打开风扇					
			led1_on();
				
			else if(strstr(recv_data, "OFF") != NULL)
					led1_off();
			
			delay_ms(10);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2219930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何将LiDAR坐标系下的3D点投影到相机2D图像上

将激光雷达点云投影到相机图像上做数据层的前融合,或者把激光雷达坐标系下标注的物体点云的3d bbox投影到相机图像上画出来,都需要做点云3D点坐标到图像像素坐标的转换计算,也就是LiDAR 3D坐标转像素坐标。 看了网上一些文章都存在有错误或者…

Android 第5种启动模式:singleInstancePerTask

Android 第5种启动模式:singleInstancePerTask 随着 Android 版本的更新,应用启动模式逐渐丰富。在 Android 12 中,新增了一种启动模式——singleInstancePerTask。它是继 standard、singleTop、singleTask 和 singleInstance 之后的第五种启…

一起搭WPF架构之LiveCharts.Wpf的简单了解与安装

一起搭WPF架构之LiveCharts.Wpf的简单了解与安装 前言LiveCharts.Wpf介绍LiveCharts.Wpf的安装总结 前言 根据项目需求,我单独留了一个界面用于进行数据分析。数据分析的内容考虑是采用图表的形式将SQLite数据库中存储的数据进行绘制成图,以便数据分析。…

HTB:Broker[WriteUP]

目录 连接至HTB服务器并启动靶机 1.Which open TCP port is running the ActiveMQ service? 使用fscan对靶机开放端口进行扫描 使用nmap对靶机开放端口进行脚本、服务信息扫描 2.What is the version of the ActiveMQ service running on the box? 3.What is the 2023 …

windows下安装VirtualBox7.1.4

记录详细的安装过程与遇到的问题; 下载地址 virtualbox官网 清华镜像源下载 下载完成后文件: 双击打开; 报错了 意思是需要pc上先安装Microsoft Visual C 2019 https://learn.microsoft.com/zh-cn/cpp/windows/latest-supported-vc-redi…

C++ 中的线程、锁、条件变量。

线程 0.Linux中有POSIX标准的线程&#xff0c;Boost库中也支持线程&#xff08;比如thread_group 和 upgrade_lock &#xff09;&#xff0c;C11<thread>头文件中也提供了相应的API支持我们使用线程。它们三个&#xff0c;你学会一个&#xff0c;自然触类旁通。 1.创建…

Java-类与对象-下篇

关于类与对象&#xff0c;内容较多&#xff0c;我们分为两篇进行讲解&#xff1a; &#x1f4da; Java-类与对象-上篇&#xff1a;————<传送门:Java-类与对象-上篇-CSDN博客> &#x1f4d5; 面向对象的概念 &#x1f4d5; 类的定义格式 &#x1f4d5; 类的使用 …

特斯拉Optimus:展望智能生活新篇章

近日&#xff0c;特斯拉举办了 "WE ROBOT" 发布会&#xff0c;发布会上描绘的未来社会愿景&#xff0c;让无数人为之向往。在这场吸引全球无数媒体的直播中&#xff0c;特斯拉 Optimus 人形机器人一出场就吸引了所有观众的关注。从多家媒体现场拍摄的视频可以看出来&…

【C++】C++11新特性——右值引用,来看看怎么个事儿

&#x1f680;个人主页&#xff1a;小羊 &#x1f680;所属专栏&#xff1a;C 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 前言一、左值引用和右值引用二、右值引用和移动语义2.1 移动构造2.2 移动赋值2.3 STL容器插入接口2.4 左值右值相互…

【C++复习】经典笔试题

文章目录 八大排序快排过程 卡特兰数反转链表链表的回文结构左叶子之和另一棵树的子树归并排序类与对象编程训练杨辉三角字符串乘积二叉树前序遍历成字符串数组的交集二叉树的非递归前序遍历连续子数组的最大乘积 八大排序 插冒归稳定 快排过程 以 [3,4,6,1,2,4,7] 为例&#…

【计网笔记】以太网

经典以太网 总线拓扑 物理层 Manchester编码 数据链路层 MAC子层 MAC帧 DIX格式与IEEE802.3格式 IEEE802.3格式兼容DIX格式 前导码&#xff08;帧开始定界符SOF&#xff09; 8字节 前7字节均为0xAA第8字节为0xAB前7字节的Manchester编码将产生稳定方波&#xff0c;用于…

steam游戏模拟人生3缺少net framework 3.5安装不成功错误弹窗0x80070422怎么修复

模拟人生3在Steam上运行时提示缺少.NET Framework 3.5并出现错误代码0x80070422&#xff0c;通常意味着.NET Framework 3.5功能没有正确启用&#xff0c;或者安装过程中出现了问题。以下是解决这个问题的步骤&#xff1a; 1.启用Windows功能 按下Win R键&#xff0c;输入opti…

【论文学习与撰写】论文里的Mathtype公式复制粘贴,跨文档复制后错码/错位问题的解决

1、描述 问题&#xff1a;论文的草稿已经写好&#xff0c;里面的公式之类的都已经一个个打上去了 但是把草稿里的正文和公式粘贴在另一个文档里的时候&#xff0c;会出些公式格式错误的情况 那该怎么操作保证复制后的公式保持原格式呢 选中复制的内容&#xff0c;在另一个文…

MySQL【知识改变命运】10

联合查询 0.前言1.联合查询在MySQL里面的原理2.练习一个完整的联合查询2.1.构造练习案例数据2.2 案例&#xff1a;⼀个完整的联合查询的过程2.2.1. 确定参与查询的表&#xff0c;学⽣表和班级表2.2.2. 确定连接条件&#xff0c;student表中的class_id与class表中id列的值相等2.…

【c++篇】:解析c++类--优化编程的关键所在(一)

文章目录 前言一.面向过程和面向对象二.c中的类1.类的引入2.类的定义3.类的封装和访问限定符4.类的作用域5.类的实例化6.类对象模型 三.this指针1.this指针的引出2.this指针的特性3.C语言和c实现栈Stack的对比 前言 在程序设计的广袤宇宙中&#xff0c;C以其强大的功能和灵活性…

[k8s理论知识]6.k8s调度器

k8s默认调度器 k8s调度器的主要职责&#xff0c;就是为一个新创建出来的pod寻找一个适合的节点Node。这包括两个步骤&#xff0c;第一&#xff0c;从所有集群的节点中&#xff0c;根据调度算法挑选出所有可以运行该pod的节点&#xff0c;第二&#xff0c;从第一步的结果中&…

Java项目-基于springboot框架的企业客户信息反馈系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

Windows环境下Qt Creator调试模式下qDebug输出中文乱码问题

尝试修改系统的区域设置的方法&#xff1a; 可以修复问题。但会出现其它问题&#xff1a; 比如某些软件打不开&#xff0c;或者一些软件界面的中文显示乱码&#xff01; 暂时没有找到其它更好的办法。

10-Docker安装Redis

10-Docker安装Redis Docker安装Redis 以 Redis 6.0.8 为例&#xff1a; docker pull redis:6.0.8直接pull会出现以下错误 [rootdocker ~]# docker pull redis:6.0.8 Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request can…

[Python学习日记-50] Python 中的序列化模块 —— pickle 和 json

[Python学习日记-50] Python 中的序列化模块 —— pickle 和 json 简介 pickle 模块 json 模块 pickle VS json 简介 什么叫序列化&#xff1f; 序列化指的是将对象转换为可以在网络上传输或者存储到文件系统中的字节流的过程。序列化使得对象可以被保存、传输和恢复&#…