STM32F103C8T6第4天:串口实验(非中断和中断)、hc01蓝牙、esp8266WIFI、4g

1. 串口基本介绍(332.36)

常用函数介绍

串口发送/接收函数:

  • HAL_UART_Transmit(); 串口发送数据,使用超时管理机制
  • HAL_UART_Receive(); 串口接收数据,使用超时管理机制
  • HAL_UART_Transmit_IT(); 串口中断模式发送
  • HAL_UART_Receive_IT(); 串口中断模式接收
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,
      uint8_t *pData, uint16_t Size, uint32_t Timeout)

作用:以阻塞的方式发送指定字节的数据

  • 形参 1 :UART_HandleTypeDef 结构体类型指针变量
  • 形参 2:指向要发送的数据地址
  • 形参 3:要发送的数据大小,以字节为单位
  • 形参 4:设置的超时时间,以ms单位
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart,
      uint8_t *pData, uint16_t Size)

作用:以中断的方式接收指定字节的数据

  • 形参 1 是 UART_HandleTypeDef 结构体类型指针变量
  • 形参 2 是指向接收数据缓冲区
  • 形参 3 是要接收的数据大小,以字节为单位

此函数执行完后将清除中断,需要再次调用以重新开启中断。

串口中断回调函数:

  • HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数
  • HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //发送中断回调函数
  • HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //接收中断回调函数

状态标记变量:

  • USART_RX_STA(符合变量的命名规则下 可重新命名):
    • 从 0 开始,串口中断接收到一个数据(一个字节)就自增 1。当数据读取全部 OK 时候(回车和换行符号来的时
      候),那么 USART_RX_STA 的最高位置 1,表示串口数据接收全部完毕了,然后 main 函数里面可以处理数据
      了。
      在这里插入图片描述

串口接收中断流程

在这里插入图片描述

2. 串口实验 (非中断)(333.37)

  • 需求: 接受串口工具发送的字符串,并将其发送回串口工具。
  • 硬件接线:
    • TX – A10
    • RX – A9
    • gnd – gnd (5v 实测可以不接)
      一定要记得交叉接线!!
  • 串口配置:
  1. 选定串口
    在这里插入图片描述
  2. 选择模式(异步通讯)
    在这里插入图片描述
  3. 串口配置
    在这里插入图片描述
  4. 使用MicroLIB库
    从魔术棒打开,这个勾勾一定要打上,否则 printf 无法重映射!
    在这里插入图片描述
  • STM32CubeMx工程配置
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 串口调试助手的一些设置
    在这里插入图片描述
    在这里插入图片描述
  • 代码(11.uart1_test/MDK-ARM)
#include <stdio.h>
#include <string.h>
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
int main(void)
{
	unsigned char ch[20] = {0};//char(acter)
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();//串口初始化
	HAL_UART_Transmit(&huart1, (uint8_t *) "hello world\n", strlen("hello world\n"), 100);//超时100
  while (1)
  {
		HAL_UART_Receive(&huart1, ch, 19, 100);//有\0所以要20-1
		//HAL_UART_Transmit(&huart1, ch, strlen((const char *)ch), 100);
		printf("%s", ch);//printf重定向(串口输出)
		memset(ch, 0, strlen((const char *)ch));//清空
  }
}

3. 串口实验 (中断)(334.38)

  • 需求: 通过中断的方法接受串口工具发送的字符串,并将其发送回串口工具。
  • 硬件接线:(同上)
    • TX – A10
    • RX – A9
    • gnd – gnd (5v 实测可以不接)
      一定要记得交叉接线!!
  • 串口配置:
    前4步同上
  1. 打开中断
    在这里插入图片描述
  • 代码(12.uart2_test/MDK-ARM)
#include <stdio.h>
//串口接收缓存(1字节)
uint8_t buf=0;
//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200
// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];
// 接收状态
// bit15,   接收完成标志
// bit14,   接收到0x0d
// bit13~0,  接收到的有效字节数目
uint16_t UART1_RX_STA = 0;
// 接收完成(一个字节)回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  // 判断中断是由哪个串口触发的
  if(huart->Instance == USART1)
 {
    // 判断接收是否完成(UART1_RX_STA bit15 位是否为1)
    if((UART1_RX_STA & 0x8000) == 0)//如果不是1即没有接收完成
   {
      // 如果已经收到了 0x0d (回车),
      if(UART1_RX_STA & 0x4000)
     {
        // 则接着判断是否收到 0x0a (换行)
        if(buf == 0x0a)
          // 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1
          UART1_RX_STA |= 0x8000;
        else
          // 否则认为接收错误,重新开始
          UART1_RX_STA = 0;
     }
      else   // 如果没有收到了 0x0d (回车)
     {
        //则先判断收到的这个字符是否是 0x0d (回车)
        if(buf == 0x0d)
       {
          // 是的话则将 bit14 位置为1
          UART1_RX_STA |= 0x4000;
       }
        else
       {
          // 否则将接收到的数据保存在缓存数组里
          UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
          UART1_RX_STA++;
          // 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
          if(UART1_RX_STA > UART1_REC_LEN - 1)
            UART1_RX_STA = 0;
       }
     }
   }
    // 重新开启中断
    HAL_UART_Receive_IT(&huart1, &buf, 1);
 }
}
int fputc(int ch, FILE *f)//printf重定向(串口输出)
{   
  unsigned char temp[1]={ch};
  HAL_UART_Transmit(&huart1,temp,1,0xffff); 
  return ch;
}
int main()
{
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
    MX_USART1_UART_Init();

	HAL_UART_Receive_IT(&huart1, &buf, 1);
	while (1)
	{
	/* USER CODE END WHILE */
	/* USER CODE BEGIN 3 */
	  //判断判断串口是否接收完成
	  if(UART1_RX_STA & 0x8000)
	 {
	    printf("收到数据:");
	    // 将收到的数据发送到串口
	    HAL_UART_Transmit(&huart1, UART1_RX_Buffer, UART1_RX_STA & 0x3fff, 0xffff);
	    // 等待发送完成
	    while(huart1.gState != HAL_UART_STATE_READY);
	    printf("\r\n");
	    // 重新开始下一次接收
	    UART1_RX_STA = 0;
	 }
	 printf("Hello Jessie!\r\n");
	 HAL_Delay(2000);//每两秒检测一次
	}
}

4. 蓝牙插座_风扇_灯(非中断)(335.39)

项目需求

  • 通过蓝牙模块,实现手机控制蓝牙插座/风扇/灯。
  • 本质:
  1. 采用蓝牙的透传功能;
  2. 控制 IO 口的输出。

项目框图

在这里插入图片描述

硬件清单

  • HC01 蓝牙模块
  • CH340 USB串口工具
  • 杜邦线

项目设计

  • HC01_TX – RX1(A10)
  • HC01_RX – TX1(A9)
  • gnd – gnd (5v 实测可以不接)

项目实现(串口非中断法)

  • STM32CubeMx工程配置(串口非中断法)
    • 第2节基础之上 设置gpio口
      在这里插入图片描述
  • 代码(13.bluetooth_led_project1/MDK-ARM)
while (1)
  {
		HAL_UART_Receive(&huart1, ch, 19, 100);//有\0所以要20-1
		//HAL_UART_Transmit(&huart1, ch, strlen((const char *)ch), 100);
		printf("%s", ch);//printf重定向(串口输出)
		if(!strcmp((char *)ch, "open"))//字符串比较 相等返回0
		{
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);//点亮
			if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET)//进一步判断
				printf("LED1已打开\r\n");
		}
		else if (!strcmp((char *)ch, "close"))
		{
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);//熄灭
			if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
				printf("LED1已关闭\r\n");
		}
		else
		{//如果不是以上指令
			if(ch[0] != '\0')
				printf("指令发送错误:%s\r\n", ch);
		}
		memset(ch, 0, strlen((char *)ch));//清空
  }

在这里插入图片描述

5. 蓝牙插座_风扇_灯(中断)(334.40)

  • 蓝牙的波特率是9600
    在这里插入图片描述
  • 代码(14.bluetooth_led_project2/MDK-ARM)
while (1)
  {
		//判断判断串口是否接收完成
		if(UART1_RX_STA & 0x8000)
		{
			printf("收到数据:");
			// 将收到的数据发送到串口
			HAL_UART_Transmit(&huart1, UART1_RX_Buffer, UART1_RX_STA & 0x3fff, 0xffff);
			// 等待发送完成
			while(huart1.gState != HAL_UART_STATE_READY);
			printf("\r\n");
			if(!strcmp((char *)UART1_RX_Buffer, "open"))//字符串比较 相等返回0
			{
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);//点亮
				if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET)//进一步判断
					printf("LED1已打开\r\n");
			}
			else if (!strcmp((char *)UART1_RX_Buffer, "close"))
			{
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);//熄灭
				if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
					printf("LED1已关闭\r\n");
			}
			else
			{//如果不是以上指令
				if(UART1_RX_Buffer[0] != '\0')
					printf("指令发送错误:%s\r\n", UART1_RX_Buffer);
			}
			memset(UART1_RX_Buffer, 0, strlen((char *)UART1_RX_Buffer));//清空
			// 重新开始下一次接收
			UART1_RX_STA = 0;
		}
		//printf("Hello Jessie!\r\n");
		HAL_Delay(40);
  }
}

在这里插入图片描述
在这里插入图片描述

6. WiFi插座_风扇_灯(项目概述)(337.41)

项目需求

  • 通过ESP8266模块,实现手机控制wifi插座/风扇/灯。

项目框图

在这里插入图片描述

硬件清单

  • ESP8266 WIFI模块
  • CH340 USB串口工具
  • 杜邦线

项目设计

在这里插入图片描述

  • 串口1用于与ESP8266通讯,串口2连接PC,用于打印log,查看系统状态。

项目实现

  • 注意:
  1. 工作中一般不直接在中断服务函数里处理数据,而是在收到数据后直接丢给队列,再处理数据;
  2. 在中断服务函数里尽量减少使用延时函数及打印函数。

7. ESP工作为AP路由模式并当成服务器(338.42)

  • 基于uart2_test:
    在这里插入图片描述
    在这里插入图片描述
  • 代码(15.wifi_led_project1/MDK-ARM)(AP模式)

8. 上官二号当路由和服务器模式控制(339.43)

  • STA模式
    在这里插入图片描述
    在这里插入图片描述
  • 代码(16.wifi_led_project2/MDK-ARM)(STA模式)

9. 上官二号通过4g模块控制LED(340.44)

项目需求

  • 通过4G模块,实现电脑控制插座/风扇/灯。

项目框图

在这里插入图片描述

  • 注意: 由于硬件的限制,上官二号无法直接带动 4G 模块,可以将 4G 模块的 VCC 和 GND 插到 CH340 的 5V 和GND 里。

硬件清单

  • 4G模块
  • CH340
  • 杜邦线

项目设计

  1. 服务器搭建:参照C51课程;
  2. 代码修改:直接复用上节课的代码,把不相关的代码删除即可

4g – USB.ttl:配置4g模块的波特率、心跳包、内网穿透ip连接

  1. 先建立一个服务器
    在这里插入图片描述
  2. 利用花生壳软件 内网穿透
    在这里插入图片描述
  3. 设置波特率(cubemx中的串口都是设置的115200 要保持一致)、设置心跳包内容和时间、让4g连接socket服务器(公网ip地址)
    在这里插入图片描述
  4. 观察到 一直在接收心跳包
    在这里插入图片描述

回到正题

  • 先测试 open、close 指令是否成功(结果:成功点亮和熄灭)
  • 注意:指令要换新行(shift+enter)
    在这里插入图片描述
  • 删除多余的代码
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 再次测试指令(结果:成功点亮和熄灭)
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用户画像与用户分层

用户画像是重要的数据产品和运营抓手&#xff0c;指能够描述和刻画用户信息和的数据指标。通过用户画像&#xff0c;业务经营团队可以充分、深入、准确地了解用户在不同生命周期的特征&#xff0c;来制定高效的用户经营策略。用户画像&#xff0c;不论 Persona 还是 Profile &a…

java笔记(一)

一、Java的三大平台 1.Java SE (必学) java语言的标准版&#xff0c;用于桌面开发&#xff0c;是其他两个版本的基础。 桌面应用适合的语言其实是c和C合适&#xff0c;复杂动画等加载时java很慢。 2.Java ME(现在很少用) java语言的小型版本&#xff0c;适用于嵌入式电子设备或…

AI机器学习实战 | 使用 Python 和 scikit-learn 库进行情感分析

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…

【图像分类】【深度学习】【Pytorch版本】 GoogLeNet(InceptionV3)模型算法详解

【图像分类】【深度学习】【Pytorch版本】 GoogLeNet(InceptionV3)模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】 GoogLeNet(InceptionV3)模型算法详解前言GoogLeNet(InceptionV3)讲解Factorized Convolutions卷积分解InceptionV3结构ⅠInceptionV3结构ⅡInc…

根据关键词搜索阿里巴巴商品数据列表接口|阿里巴巴商品列表数据接口|阿里巴巴商品API接口|阿里巴巴API接口

阿里巴巴也提供了根据关键词搜索商品数据列表的接口&#xff0c;方便开发者根据关键词搜索商品并进行相关操作。 请求参数可以包括&#xff1a; q&#xff1a;搜索关键字 start_price&#xff1a;开始价格 end_price&#xff1a;结束价格 page&#xff1a;页码 cat&#xff1…

9步打造个人ip

什么是个人IP&#xff1f; 就是一个人创造出来的属于自己的有个性有价值的&#xff0c;能让他人记住你&#xff0c;信任你&#xff0c;认可你的东西。 如何强化个人IP呢&#xff1f; 需要一些必要的条件如专业性、耐心、勤奋等等要知道&#xff0c;打造IP是一个见效慢的过程&am…

Multisim数电仿真实验——SOS循环序列信号发生器

目录 一、前言二、设计思路2.1序列信号的实现2.2SOS信号的循环再现 三、最终电路图 一、前言 SOS电路是一种简单而重要的电子电路&#xff0c;用于产生和传输紧急信号。我们将介绍SOS电路的连接思路&#xff0c;包括所需的组件选择以及信号的连接方式。 二、设计思路 2.1序列…

复杂度分析

目录 一.算法效率 二.大O渐进表示法 三.时间复杂度 常见的时间复杂度&#xff1a; 时间复杂度计算练习&#xff1a; 四.空间复杂度 常见的空间复杂度&#xff1a; 空间复杂度计算练习&#xff1a; 一.算法效率 追求算法效率&#xff1a; 找到问题解法&#xff1a;算法需…

什么是原生IP与广播IP?如何区分?为什么需要用原生IP?

在代理IP中&#xff0c;我们常常听到原生IP与广播IP&#xff0c;二者有何区别&#xff1f;如何区分呢&#xff1f;下面为大家详细讲解。 一、什么是原生IP 原生IP地址是互联网服务提供商&#xff08;ISP&#xff09;直接分配给用户的真实IP地址&#xff0c;无需代理或转发。此…

轻量封装WebGPU渲染系统示例<32>- 若干线框对象(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/WireframeEntityTest.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: export class WireframeEntityTest {private mRsc…

拜耳阵列(Bayer Pattern)以及常见彩色滤波矩阵(CFA)

一、拜耳阵列的来源 图像传感器将光线转化成电流&#xff0c;光线越亮&#xff0c;电流的数值就越大&#xff1b;光线越暗&#xff0c;电流的数值就越小。图像传感器只能感受光的强弱&#xff0c;无法感受光的波长。由于光的颜色由波长决定&#xff0c;所以图像传播器无法记录…

博客系统页面设计

目录 前言 1.预期效果 1.1博客列表页效果 1.2博客详情页效果 1.3博客登陆页效果 2.实现博客列表页 2.1实现导航栏 2.2实现版心 2.3实现个人信息 2.4实现博客列表 3.实现博客正文页 3.1引入导航栏 3.2引入版心 3.3引入个人信息 3.4实现博客正文 4.实现博客登陆页…

【寒武纪(7)】MLU的cntoolkit:Cambricon-BANG架构和使用分析,MLU并行计算的硬件抽象、编程模型以及调优思路

文章目录 硬件抽象1存储1.1.1 存储层次访存一致 计算模型1 Core核内同步和并行2 核间并行和同步 编程模型1、Kernel计算规模 任务类型执行示例 性能调优性能调优实践参考 cambricon BANG架构是基础的&#xff0c;高度抽象的&#xff0c;向用户暴露统一编程模型和编程接口&#…

Go 理解零值

在 Go 语言中&#xff0c;零值&#xff08;Zero Value&#xff09;是指在声明变量但没有显式赋值的情况下&#xff0c;变量会被自动赋予一个默认值。这个默认值取决于变量的类型&#xff0c;不同类型的变量会有不同的零值。零值是 Go 语言中的一个重要概念&#xff0c;因为它确…

Pytest UI自动化测试实战实例

环境准备 序号库/插件/工具安装命令1确保您已经安装了python3.x2配置python3pycharmselenium2开发环境3安装pytest库 pip install pytest 4安装pytest -html 报告插件pip install pytest-html5安装pypiwin32库(用来模拟按键)pip install pypiwin32 6安装openpyxl解析excel文…

教你如何优化MySQL慢查询SQL语句?快速提升系统性能!

前言 应用系统性能测试过程中&#xff0c;性能优化是绕不开的话题&#xff0c;对测试人员而言&#xff0c;性能优化的第一站就是SQL语句的优化与分析。因此本文主要以MySQL数据库为例&#xff0c;介绍常见的慢查询SQL语句执行效率分析与优化方法和简单示例&#xff0c;为致力于…

【原创】V2024中化解电力行业设备表的五年难题

我这个人今生注定不能“大富大贵”&#xff0c;因为我的缺点实在太多了&#xff0c;其中非常重要的一项是&#xff1a;脸盲&#xff01;简单来说就是很容易把不同的人搞混&#xff0c;记住名字的时候没记住面相&#xff0c;记住面相的时候又把名字给忘了&#xff0c;尴尬的人生…

Pod详细介绍

目录 Pod 1、Pod基础概念 2、集群中Pod的使用方式 1&#xff09;一个Pod中运行一个容器 2&#xff09;一个Pod中运行多个容器 3、Pod的类型 1&#xff09;控制器管理的Pod 2&#xff09;自助式Pod 3&#xff09;静态Pod 4、Pod中容器的分类 1&#xff09;基础容器&#xf…

day26_css

今日内容 零、 复习昨日 一、CSS 零、 复习昨日 HTML - 页面基本骨架结构,内容展现 CSS - 美化页面,布局 JS - 动起来 一 、引言 1.1CSS概念 ​ 层叠样式表(英文全称&#xff1a;Cascading Style Sheets)是一种用来表现HTML&#xff08;标准通用标记语言的一个应用&#xff09;…