STM32CubeMX学习(二) USB CDC 双向通信

news2024/12/23 17:39:47

STM32CubeMX学习(二) USB CDC 双向通信

  • 简介
  • CubeMX新建工程(串口+LED)
  • 测试串口和LED
  • 串口接收
  • 测试USB CDC通信

简介

利用正点原子F407探索者开发板,测试基于USB CDC的双向数据通信。

CubeMX新建工程(串口+LED)

设置时钟源
在这里插入图片描述
在这里插入图片描述

设置调试器
在这里插入图片描述
设置LED
在这里插入图片描述
设置串口
在这里插入图片描述
设置USB OTG
在这里插入图片描述
在这里插入图片描述

Pinout预览
在这里插入图片描述
工程管理
在这里插入图片描述
在上图里,可以把Heap Size和Stack Size改大点,使得USB数据通信更流畅。

在这里插入图片描述
选中红框里的选项主要是为了工程打包后给他人直接使用。

最后点击GENERATE CODE生成工程。

测试串口和LED

usart.h中引入头文件stdio.h

/* USER CODE BEGIN Includes */
#include "stdio.h"	//引入此文件,为重定向printf
/* USER CODE END Includes */

usart.c中添加重定向代码

/* USER CODE BEGIN 1 */
// 重定向printf函数
int fputc(int ch,FILE *f)
{
    uint8_t temp[1]={ch};
    HAL_UART_Transmit(&huart1,temp,1,2);
		return 0;
}
/* USER CODE END 1 */

为了方便调试,在main.c中加入以下宏定义

/* USER CODE BEGIN PD */
#define USER_MAIN_DEBUG

#ifdef USER_MAIN_DEBUG
#define user_main_printf(format, ...) printf( format "\r\n",##__VA_ARGS__)
#define user_main_info(format, ...)   printf("main.info:" format "\r\n",##__VA_ARGS__)
#define user_main_debug(format, ...)  printf("main.debug:" format "\r\n",##__VA_ARGS__)
#define user_main_error(format, ...)  printf("main.error:" format "\r\n",##__VA_ARGS__)
#else
#define user_main_printf(format, ...)
#define user_main_info(format, ...)
#define user_main_debug(format, ...)
#define user_main_error(format, ...)
#endif
/* USER CODE END PD */

main.c中添加代码

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      printf("Enter main while loop!\r\n");
      user_main_debug("Main debug!\n");
      HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
      HAL_Delay(500);
      HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
      HAL_Delay(500);
  }
  /* USER CODE END 3 */

设置下载后自动运行,编译运行,连接串口调试助手,观察现象
在这里插入图片描述
编译下载后,重启发现LED1(绿灯)在闪烁,串口收到字符数据。

如果程序没有反应或者仿真后发现程序一直卡死在 BEAB BKPT 0xAB,解决方法:MDK选择设置,TARGET ,勾选Use MicroLIB
在这里插入图片描述

串口接收

在usbd_cdc_if.c中,有发送函数和接收函数。发送函数CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)不需要修改,接收函数CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)需要修改再使用。
在usbd_cdc_if.c中定义变量

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
  unsigned char CDC_Receive_Buffer[64]; //数据缓冲区数组的大小可以根据你想要的收发的数据大小变更
  unsigned char CDC_Receive_Length;
/* USER CODE END PV */

修改CDC_Receive_FS函数

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
    memcpy(CDC_Receive_Buffer, Buf, *Len);
    CDC_Receive_Length = *Len;
    
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

测试USB CDC通信

main.c中,添加如下代码:

...
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
...
/* USER CODE BEGIN PV */
unsigned char CDC_Transmit_Buffer[64] = {1,2,3,4,5,6,7,8,9,}; //USB发送缓存
unsigned char CDC_Transmit_Count = 0;//USB发送数据计数
extern unsigned char CDC_Receive_Buffer[]; 
extern unsigned char CDC_Receive_Length;
extern uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
/* USER CODE END PV */
...
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      CDC_Transmit_FS(CDC_Transmit_Buffer, 64);
      HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
      HAL_Delay(500);
      CDC_Transmit_FS(CDC_Receive_Buffer,CDC_Receive_Length);
      HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
      HAL_Delay(500);
  }
  /* USER CODE END 3 */
}

编译后下载,点击发送按钮,测试结果如下图:
在这里插入图片描述

Bus Hound捕获情况如下:
在这里插入图片描述

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

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

相关文章

ES6+ 面试常问题

一、let const var 的区别 1. var: 没有块级作用域的概念,有函数作用域和全局作用域的概念全局作用域性下创建变量会被挂在到 windows 上存在变量提升同一作用域下,可以重复赋值创建未初始化,值为 undefined 2. let&#xff1a…

2023年末,软件测试面试题总结与分享

大家好,最近有不少小伙伴在后台留言,得准备年后面试了,又不知道从何下手!为了帮大家节约时间,特意准备了一份面试相关的资料,内容非常的全面,真的可以好好补一补,希望大家在都能拿到…

天擎终端安全管理系统clientinfobymid存在SQL注入漏洞

产品简介 奇安信天擎终端安全管理系统是面向政企单位推出的一体化终端安全产品解决方案。该产品集防病毒、终端安全管控、终端准入、终端审计、外设管控、EDR等功能于一体,兼容不同操作系统和计算平台,帮助客户实现平台一体化、功能一体化、数据一体化的…

《PCI Express体系结构导读》随记 —— 第I篇 第1章 PCI总线的基本知识(16)

接前一篇文章:《PCI Express体系结构导读》随记 —— 第I篇 第1章 PCI总线的基本知识(15) 1.3 PCI总线的存储器读写总线事务 1.3.5 Delayed传送方式 如前文所述,当处理器使用Non-Posted总线周期对PCI设备进行操作、或者PCI设备使…

Android MVVM 写法

前言 Model:负责数据逻辑 View:负责视图逻辑 ViewModel:负责业务逻辑 持有关系: 1、ViewModel 持有 View 2、ViewModel 持有 Model 3、Model 持有 ViewModel 辅助工具:DataBinding 执行流程:View &g…

linux源码编译升级安装openssl3.0.1导致系统启动失败的问题解决

前两天在安装curl的时候,提示openssl版本太老了,原有的版本是openssl1.0的版本,需要将其升级到openssl3的版本。 直接使用命令行sudo apt install默认安装的还是openssl1.1.1版本,因此决定使用源码自行安装。 具体的安装过程就不赘…

webpack打包批量替换路径(string-replace-webpack-plugin插件)

string-replace-webpack-plugin 是一个用于在 webpack 打包后的文件中替换字符串的插件。它可以用于将特定字符串替换为其他字符串,例如将敏感信息从源代码中移除或对特定文本进行本地化处理。比如文件的html、css、js中的路径地址想批量更改一下 http://localhost:…

海德堡UV灯电源维修eta Plus Elc PE22-400-210

uv灯电源维修故障包括: 1、电压不稳:检查uv打印机的电压,设置一个稳压箱即可。 2、温度过高:uv打印机温度过高也会影响uv灯,可以更换为水冷式循环降温。 3、水箱里的信号线接触不好:将两边的信号线对调&…

leetcode刷题记录07(2023-04-30)【二叉树展开为链表 | 买卖股票的最佳时机 | 二叉树中的最大路径和(递归) | 最长连续序列(并查集)】

114. 二叉树展开为链表 给你二叉树的根结点 root ,请你将它展开为一个单链表: 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。 展开后的单链表应该与二叉树 先序遍历 顺…

ArcGIS批量计算shp面积并导出shp数据总面积(建模法)

在处理shp数据时, 又是我们需要知道许多个shp字段的批量计算,例如计算shp的总面积、面积平均值等,但是单个查看shp文件的属性进行汇总过于繁琐,因此可以借助建模批处理来计算。 首先准备数据:一个含有多个shp的文件夹。…

前后端分离nodejs+vue+ElementUi网上订餐系统69b9

课题主要分为两大模块:即管理员模块和用户模块,主要功能包括个人中心、用户管理、菜品类型管理、菜品信息管理、留言反馈、在线交流、系统管理、订单管理等; 运行软件:vscode 前端nodejsvueElementUi 语言 node.js 框架:Express/k…

Lumerical------按键中断程序执行

Lumerical------中断程序执行 引言正文 引言 在 Lumerical 中,很多时候我们需要通过 sweep 的方式来获取我们想要的结果,然而,有时候当我们运行程序后发现书写的脚本有问题时,我们想要强行终止程序的执行,该怎么办呢&…

代码随想录-刷题第四十二天

0-1背包理论基础 0-1背包问题介绍 0-1背包问题:有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 0-1背包问题可以使用回溯法进…

Collector收集器的高级用法

Collectors收集器的高级用法 场景1:获取关联的班级名称 原先如果需要通过关联字段拿到其他表的某个字段,只能遍历List匹配获取 for (Student student : studentList) {Long clazzId student.getClazzId();// 遍历班级列表,获取学生对应班级…

【ArkTS入门】ArkTS开发初探:语言特点和开发特点

什么是ArkTS? ArkTS是一个为鸿蒙组件而生的框架,语法亲人好用。基于TypeScript,ArkTS拓展了声明式UI、状态管理等的能力,从本质上来讲,是TypeScript的扩展,主要服务于前端。 ArkTS的开发可以满足“一次开…

vue-cli3/webpack打包时去掉console.log调试信息

文章目录 前言一、terser-webpack-plugin是什么?二、使用配置vue-cli项目 前言 开发环境下,console.log调试信息,有助于我们找到错误,但在生产环境,不需要console.log打印调试信息,所以打包时需要将consol…

【React源码 - ReactDom.render发生了什么】

在React开发中,在入口文件我们都会执行ReactDom.render来讲整个应用挂载在主document中,那其中发生了什么,React是如何讲我们写的JSX代码,一步一步更新Fiber进而挂载渲染的呢。本文主要是基于react17.0.2的源码以及自己的理解来简…

thinkphp+vue+mysql企业车辆管理系统m117l

“企业车辆管理系统”是运用php语言和vue框架,以Mysql数据库为基础而发出来的。为保证我国经济的持续性发展,必须要让互联网信息时代在我国日益壮大,蓬勃发展。伴随着信息社会的飞速发展,企业车辆管理系统所面临的问题也一个接一个…

大数据背后的绿色收割:基于Hadoop的农产品价格信息智能分析

大数据背后的绿色收割:基于Hadoop的农产品价格信息智能分析 引言正文1. 数据获取与准备2. 数据清洗与处理3. Hadoop数据分析引擎的运用4. MySQL数据库的集成5. 创新性的可视化6. 结论与展望 结语 引言 随着信息技术的不断发展,农业领域也在数字化的浪潮…

C++ Primer Plus----第十二章--类和动态内存分布

本章内容包括:对类成员使用动态内存分配;隐式和显式复制构造函数;隐式和显式重载赋值运算符;在构造函数中使用new所必须完成的工作;使用静态类成员;将定位new运算符用于对象;使用指向对象的指针…