USB协议学习笔记 - 虚拟串口Virtual Port Com LED控制
前言
- STM32 的USB 可以虚拟成一个串口,功能还挺强,感觉比HID好用
- 这里使用USB 虚拟的串口,做个控制LED的小程序
- 控制LED这里使用自定义的AT命令方式,如红灯亮:
AT+LEDR_ON
,红灯灭:AT+LEDR_OFF
程序如下
- 首先STM32 USB虚拟成串口的操作,参考前面的文章
LED.c
#include "led.h"/* all LEDS gpio init */
void leds_gpio_init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};LEDR_GPIO_RCC_ENABLE();LEDG_GPIO_RCC_ENABLE();LEDB_GPIO_RCC_ENABLE();HAL_GPIO_WritePin(LEDR_GPIO_PORT, LEDR_GPIO_PINS, GPIO_PIN_SET);HAL_GPIO_WritePin(LEDG_GPIO_PORT, LEDG_GPIO_PINS, GPIO_PIN_SET);HAL_GPIO_WritePin(LEDB_GPIO_PORT, LEDB_GPIO_PINS, GPIO_PIN_SET);GPIO_InitStruct.Pin = LEDR_GPIO_PINS;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(LEDR_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = LEDG_GPIO_PINS;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(LEDG_GPIO_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = LEDB_GPIO_PINS;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(LEDB_GPIO_PORT, &GPIO_InitStruct);
}/* LEDR power control */
void LEDR_power_ctrl(unsigned int bon)
{if (bon == 0x01) /* LEDR ON */{HAL_GPIO_WritePin(LEDR_GPIO_PORT, LEDR_GPIO_PINS, GPIO_PIN_RESET);}else{HAL_GPIO_WritePin(LEDR_GPIO_PORT, LEDR_GPIO_PINS, GPIO_PIN_SET);}
}/* LEDG power control */
void LEDG_power_ctrl(unsigned int bon)
{if (bon == 0x01) /* LEDG ON */{HAL_GPIO_WritePin(LEDG_GPIO_PORT, LEDG_GPIO_PINS, GPIO_PIN_RESET);}else{HAL_GPIO_WritePin(LEDG_GPIO_PORT, LEDG_GPIO_PINS, GPIO_PIN_SET);}
}/* LEDB power control */
void LEDB_power_ctrl(unsigned int bon)
{if (bon == 0x01){HAL_GPIO_WritePin(LEDB_GPIO_PORT, LEDB_GPIO_PINS, GPIO_PIN_RESET);}else{HAL_GPIO_WritePin(LEDB_GPIO_PORT, LEDB_GPIO_PINS, GPIO_PIN_SET);}
}
led.h
#ifndef __LED_H__
#define __LED_H__#include "stm32l4xx_hal.h"#define LEDR_GPIO_RCC_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define LEDR_GPIO_PORT GPIOE
#define LEDR_GPIO_PINS GPIO_PIN_7#define LEDG_GPIO_RCC_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define LEDG_GPIO_PORT GPIOE
#define LEDG_GPIO_PINS GPIO_PIN_8#define LEDB_GPIO_RCC_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define LEDB_GPIO_PORT GPIOE
#define LEDB_GPIO_PINS GPIO_PIN_9void leds_gpio_init(void);
void LEDG_power_ctrl(unsigned int bon);
void LEDR_power_ctrl(unsigned int bon);
void LEDB_power_ctrl(unsigned int bon);#endif
- 这里修改
usbd_cdc_if.c
中的串口数据接收函数:CDC_Receive_FS
extern void ata_buff_put(uint8_t *buf);
/*** @brief Data received over USB OUT endpoint are sent over CDC interface* through this function.** @note* This function will issue a NAK packet on any OUT packet received on* USB endpoint until exiting this function. If you exit this function* before transfer is complete on CDC interface (ie. using DMA controller)* it will result in receiving more data while previous ones are still* not sent.** @param Buf: Buffer of data to be received* @param Len: Number of data received (in bytes)* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL*/static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{/* USER CODE BEGIN 6 */USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);USBD_CDC_ReceivePacket(&hUsbDeviceFS);ata_buff_put(UserRxBufferFS); /* recv user command */return (USBD_OK);/* USER CODE END 6 */
}
main.c
#include "main.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"
#include <stdio.h>
#include <stdarg.h>
#include "led.h"void SystemClock_Config(void);
static void MX_GPIO_Init(void);#define ENABLE_ATA_TEST
#define DBG_BUFF_MAX_LEN 256
#define ATA_BUFF_MAX_LEN 256static uint8_t ata_buf[ATA_BUFF_MAX_LEN] = { 0 };
static uint8_t ata_recv_flag = 0x00;void ata_buff_put(uint8_t *buf)
{if (buf == 0)return;strncpy((char *)ata_buf, (const char *)buf, ATA_BUFF_MAX_LEN);ata_recv_flag = 0x01;
}void usb_vcom_puts(uint8_t *buf)
{CDC_Transmit_FS(buf, strlen((const char *)buf));
}/* debug print : support float double */
int printk(const char *fmt, ...)
{va_list args;static char log_buf[DBG_BUFF_MAX_LEN] = { 0 };va_start(args, fmt);int length = vsnprintf(log_buf, sizeof(log_buf) - 1, fmt, args);usb_vcom_puts((uint8_t *)log_buf);return length;
}void ata_notify_handler(void)
{#ifdef ENABLE_ATA_TESTif (ata_recv_flag == 0)return;uint8_t sendbuffer[ATA_BUFF_MAX_LEN];if (strlen((char *)ata_buf) <= 5) /* AT+XX\r\n */return;memset(sendbuffer,0,sizeof(sendbuffer));if(strncmp((char *)ata_buf,"AT+LEDR_ON",strlen("AT+LEDR_ON"))==0) /* LEDR ON */{LEDR_power_ctrl(1);printk("OK\r\n");}else if(strncmp((char *)ata_buf,"AT+LEDR_OFF",strlen("AT+LEDR_OFF"))==0) /* LEDR OFF */{LEDR_power_ctrl(0);printk("OK\r\n");}else if(strncmp((char *)ata_buf,"AT+LEDG_ON",strlen("AT+LEDG_ON"))==0) /* LEDG ON */{LEDG_power_ctrl(1);printk("OK\r\n");}else if(strncmp((char *)ata_buf,"AT+LEDG_OFF",strlen("AT+LEDG_OFF"))==0) /* LEDG OFF */{LEDG_power_ctrl(0);printk("OK\r\n");}else if(strncmp((char *)ata_buf,"AT+LEDB_ON",strlen("AT+LEDB_ON"))==0) /* LEDB ON */{LEDB_power_ctrl(1);printk("OK\r\n");}else if(strncmp((char *)ata_buf,"AT+LEDB_OFF",strlen("AT+LEDB_OFF"))==0) /* LEDB OFF */{LEDB_power_ctrl(0);printk("OK\r\n");}else{printk("NO CMD found! %s\r\n", ata_buf);}ata_recv_flag = 0x00;
#endif
}int main(void)
{uint32_t cnt = 0x00;HAL_Init();SystemClock_Config();MX_GPIO_Init();leds_gpio_init();MX_USB_DEVICE_Init();HAL_Delay(2000);printk("%s : STM32 USB Virtual Port Com LED Test!\r\n", __func__, cnt);while (1){ata_notify_handler();}
}
烧写验证
- 编译下载后,电脑端打开串口助手,并打开STM32虚拟的USB串口
- 尝试在串口助手发送:
AT+LEDG_OFF
AT+LEDG_ON
等LED指令(注意追加回车换行),发现LED可以正常的控制亮灭
小结
- USB 虚拟串口,功能还是挺使用的,可以用于普通的串口的输入与输出,可以用于通信与控制,比USB HID要简单一些
- 继续研究USB的应用(使用),并不断的整理USB相关的资料,深入学习USB协议与应用技术
USB协议学习笔记 - 虚拟串口Virtual Port Com LED控制相关推荐
- USB协议学习笔记 - 虚拟串口Virtual Port Com用于LOG打印
前言 上一篇讲了STM32 USB 虚拟串口的功能实现,可以通过STM32输出信息到PC端 这篇简单的做个应用:打印LOG(日志)信息到虚拟串口 操作方法 基于上篇的STM32 USB Virtual ...
- USB协议学习笔记 - CUSTOM HID 设备
简介 这里使用STM32平台进行USB 协议的学习与USB 设备的调试开发 USB HID设备,协议较固定,无法实现数据的自由接收与发送 USB CUSTOM HID设备(自定义HID协议)可以实现简 ...
- USB协议学习笔记 - CUSTOM HID控制LED
简介 前面了解了 STM32 CUSTOM HID 设备,但是有几个细节没有处理好,如接收到主机的报告后,如何接收到指定的数组,并实现通信功能,如控制LED亮灭? 还有就是CUSTOM HID设备的[ ...
- KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记3——串口Stdio实现
KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记3--串口Stdio实现 一.介绍 任务目标 二.工程创建 三.软件设计 第一步,BSP构建 1, 添加前面的pll_config文件 2 ...
- Servlet和HTTP请求协议-学习笔记02【Servlet_体系结构与urlpartten配置、HTTP请求协议】
Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...
- Qt5学习笔记之串口助手四:增加16进制/ASCII切换、周期发送
目录 1. 概述 2. 16进制/ASCII发送 2.1 功能实现 2.2 界面修改 3. 接收框显示发送内容 3.1 以16进制/ASCII显示 3.1.1 界面修改 3.1.2 功能实现 3.2 ...
- 极客HTTP协议学习笔记破冰篇(1-7)
极客HTTP协议学习笔记破冰篇(1-7) 前言 各篇章笔记链接 一.学习笔记 1.HTTP的前世今生 2.HTTP是什么 3.与HTTP相关的各种概念(上) 4.与HTTP相关的各种概念(下) 5.常 ...
- Servlet和HTTP请求协议-学习笔记01【Servlet_快速入门-生命周期方法、Servlet_3.0注解配置、IDEA与tomcat相关配置】
Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...
- stm32学习笔记----双串口同时打开时的printf()问题
stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...
最新文章
- 19行关键代码,带你轻松入门PaddlePaddle单机训练
- 线扫相机——机器视觉中无限制物体的检测
- 为什么深度学习不能取代传统的计算机视觉技术?
- MySQL 命令行下执行.sql脚本
- 真是O(1)吗?想清楚了没?
- 如何测试一个网页登陆界面
- easycode不推荐使用_为什么?mysql不推荐使用uuid或者雪花id作为主键?
- mysql 递归查找父节点_MYSQL递归查询所有父节点
- 拓端tecdat|R语言用逻辑回归、决策树和随机森林对信贷数据集进行分类预测
- 算法:二叉树从树叶到根部每层构成的数组队列107. Binary Tree Level Order Traversal II
- 【平面设计基础】01:抠图—薄、透、露的朦胧美
- linux中的段定义的,Linux中的段
- SkipList算法原理分析
- 卡方检验值转换为P值
- 关于跳跃连接 卷积网络
- 极力推荐的微信小程序,超级实用,一定要收藏
- Vue+ElementUI table表格分页
- 杨绛与钱钟书,人世间最理想的婚姻
- mac系统安装手机安装包
- 分享一个基于QT的自定义串口助手