CubeMX配置stm32 F103RCT6实现USB bulk传输

乌龟也会飞 发表了文章 • 21 个评论 • 5512 次浏览 • 2018-09-07 14:47 • 来自相关话题

友情提示请全屏查看(By荒野大嫖客)ST官方虽然提供很多关于USB固件库集成的(像什么VCP HID等等),但是吧在我们实际的项目开发中VCP(虚拟串口基本不用吧)另外官方提供的驱动程序都是ST厂商标志的,这对于我们来说给客户产品的时候驱动商标是别人公司好像挺不好的,故此鉴于项目的实际开发所需我们一般都是实现一个自定义的USB协议而非什么VCP 大容量的U盘之类的来通信(当然有这个需要的除外).于是就想ST把USB底层的协议都已经搞定了那么修修改改就应该能实现我所需要的了,在这过程中由于对USB协议不必熟悉弄起来不容易,其余的论坛上下载动不动就是要金币或者去买他的开发板才给你源码,或者动不动就是什么VCP来冒充根本就不是我所需要的 本文为cubeMX实现bulk批量传输,实现过程借鉴了网上最小量修改实现HID双向通信http://www.stm32cube.com/article/138 在此致谢Digital_Chip 由于HID的通信速率相对来说不是很高,如果要进行大数据量高速度传输就有可能不太满足条件,故此使用bulk传输是一个不错的选择,好了废话就说这么多了,我把过程发出来一是作为自己弄这个的一个总结将来需要时自己好看一下,二是给其余所需要的人提供点思路,完全免费的啊,不想他们动不动就是你买我开发板我给你源码 (火大)   荒野大嫖客太穷了(呜呜)历时两天才搞定,资质较差如果看官觉得有用给个赞吧一 条件cubeMX4.26.1 MDK5 F1的固件库 芯片stm32F103RCT6(F1系列根据自己的板子来选,我手边没有F4的固定可能有些函数不一样,不过也可以作为一种参考来实现F4)1,开启外部晶振 开启debug功能(我是SWD,如果板载是SWD接口不开启此功能的话第二次下载程序就会下载不进去 需要在复位状态下下载)  开启USB外设 在中间件上选择CDC(虚拟串口,需要用它来改)二:配置系统时钟72MHz(根据自己需要) USB为48MHz(必须)三:更改USB的中间件(可以不更改 自己做实验的话) 如果项目的话更改(比如PID VID更改为自己公司的去掉ST公司的字符串等)我做如下更改1024纪念程序员 鲁班大师(我的最爱,虽然比较坑都一年多了还在钻石 呜呜)四:初始化生成代码五:修改描述符 将usbd_des.c中的USBD_FS_DeviceDesc[USB_LEN_DEV_DESC]数组修改为如下六修改配置描述符 接口描述符等七:将下面的__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] 和__ALIGN_BEGIN uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] 数组中的内容修改成和上面的一样就不贴图了八将USB_CDC_CONFIG_DESC_SIZ   修改为32九:定义两个变量 用于缓存数据 (全局的啊,其他.c文件可以访问的 我放在main.c中定义的 申明在头文件 其余所使用的地方包含该头文件) 并修改USBD_CDC_Init入下第二张图片十 :修改USBD_CDC_DataOut如下十一:在main.c的头文件中加载如下头文件 并修改main.c中的while(1)循环如下实现bulk通信回环好到此所有的bulk更改部分已经完成了,下面是见证奇迹的石头,编译程序下载程序不贴图了(由于我之前就做成功了,PID 和VID就是1024所以下完程序后插上USB就自动加载驱动了为了更好的展示效果我将本次的工程的PID和VID更改为如下,展示目前不能加载驱动)下载程序后重新插上USB在电脑的设备管理器中看到了我们的鲁班大师 智商250标志但是是黄色的因为没有驱动嘛右键属性看PID和VID是我们后设置的 可以使用电脑的计算机程序员模式转换至此USB bulk传输过程设备已经完成了验证,下面为试验可以进行通信我是用的是VISA来做驱动的打开NI_VISA Driver Wizard 进入如下界面选择USB 电机next 选中我们的设备 ranh然后一路狂点next知道finish最后驱动制作完成然后重新打开设备管理器查看我们的设备 驱动加载正常 没有了黄色图标以上为驱动制作加载完成,这只是证明了能够识别了,但是能不能通信呢请看下面 还是VISA 目前制作简单测试啊没有写专门的上位机 打开VISA Interactive ctrol 双击我们的设备双击后进入以下界面 可以看到我们设备的一些信息选择input/output界面在发送兰中写入要发送的数据,随便发目前只做了回环没有定义什么命令之类的发送什么,那么就应该回什么点击write变成如下情况点击Read后变成了如下界面通过以上两张图片对比发现我们实现了回环测试发送什么就接受到什么 以上证明了我们的设计是符合要求的,用于项目的话还需要进行相关的数据进行协议组织,同时增加方式提高传输速度等                                                                    以上整理提供by荒野大嫖客     如果有幸你读到这篇文章给个赞吧 查看全部

友情提示请全屏查看(By荒野大嫖客)

ST官方虽然提供很多关于USB固件库集成的(像什么VCP HID等等),但是吧在我们实际的项目开发中VCP(虚拟串口基本不用吧)另外官方提供的驱动程序都是ST厂商标志的,这对于我们来说给客户产品的时候驱动商标是别人公司好像挺不好的,故此鉴于项目的实际开发所需我们一般都是实现一个自定义的USB协议而非什么VCP 大容量的U盘之类的来通信(当然有这个需要的除外).于是就想ST把USB底层的协议都已经搞定了那么修修改改就应该能实现我所需要的了,在这过程中由于对USB协议不必熟悉弄起来不容易,其余的论坛上下载动不动就是要金币或者去买他的开发板才给你源码,或者动不动就是什么VCP来冒充根本就不是我所需要的 本文为cubeMX实现bulk批量传输,实现过程借鉴了网上最小量修改实现HID双向通信http://www.stm32cube.com/article/138 在此致谢Digital_Chip 

由于HID的通信速率相对来说不是很高,如果要进行大数据量高速度传输就有可能不太满足条件,故此使用bulk传输是一个不错的选择,好了废话就说这么多了,我把过程发出来一是作为自己弄这个的一个总结将来需要时自己好看一下,二是给其余所需要的人提供点思路,完全免费的啊,不想他们动不动就是你买我开发板我给你源码 (火大)   荒野大嫖客太穷了(呜呜)历时两天才搞定,资质较差如果看官觉得有用给个赞吧

一 条件cubeMX4.26.1 MDK5 F1的固件库 芯片stm32F103RCT6(F1系列根据自己的板子来选,我手边没有F4的固定可能有些函数不一样,不过也可以作为一种参考来实现F4)

1,开启外部晶振 开启debug功能(我是SWD,如果板载是SWD接口不开启此功能的话第二次下载程序就会下载不进去 需要在复位状态下下载)  开启USB外设 在中间件上选择CDC(虚拟串口,需要用它来改)

image.png

二:配置系统时钟72MHz(根据自己需要) USB为48MHz(必须)

image.png

三:更改USB的中间件(可以不更改 自己做实验的话) 如果项目的话更改(比如PID VID更改为自己公司的去掉ST公司的字符串等)我做如下更改1024纪念程序员 鲁班大师(我的最爱,虽然比较坑都一年多了还在钻石 呜呜)

image.png

四:初始化生成代码

image.png

五:修改描述符 将usbd_des.c中的USBD_FS_DeviceDesc[USB_LEN_DEV_DESC]数组修改为如下

image.png六修改配置描述符 接口描述符等
image.png

七:将下面的__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] 和__ALIGN_BEGIN uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] 数组中的内容修改成和上面的一样就不贴图了

八将USB_CDC_CONFIG_DESC_SIZ   修改为32

image.png

九:定义两个变量 用于缓存数据 (全局的啊,其他.c文件可以访问的 我放在main.c中定义的 申明在头文件 其余所使用的地方包含该头文件) 并修改USBD_CDC_Init入下第二张图片


image.png

image.png



十 :修改USBD_CDC_DataOut如下

image.png


十一:在main.c的头文件中加载如下头文件 并修改main.c中的while(1)循环如下实现bulk通信回环

image.png

image.png

好到此所有的bulk更改部分已经完成了,下面是见证奇迹的石头,编译程序下载程序不贴图了(由于我之前就做成功了,PID 和VID就是1024所以下完程序后插上USB就自动加载驱动了为了更好的展示效果我将本次的工程的PID和VID更改为如下,展示目前不能加载驱动)

image.png


下载程序后重新插上USB在电脑的设备管理器中看到了我们的鲁班大师 智商250标志但是是黄色的因为没有驱动嘛

image.png

右键属性看PID和VID是我们后设置的 可以使用电脑的计算机程序员模式转换

image.png


至此USB bulk传输过程设备已经完成了验证,下面为试验可以进行通信我是用的是VISA来做驱动的

打开NI_VISA Driver Wizard 

image.png


进入如下界面


image.png


选择USB 电机next 

image.png

选中我们的设备 ranh然后一路狂点next知道finish最后驱动制作完成

然后重新打开设备管理器查看我们的设备 驱动加载正常 没有了黄色图标

image.png

image.png

以上为驱动制作加载完成,这只是证明了能够识别了,但是能不能通信呢请看下面 还是VISA 目前制作简单测试啊没有写专门的上位机 打开VISA Interactive ctrol 双击我们的设备

image.png

双击后进入以下界面 可以看到我们设备的一些信息

image.png

选择input/output界面

image.png

在发送兰中写入要发送的数据,随便发目前只做了回环没有定义什么命令之类的发送什么,那么就应该回什么

点击write变成如下情况

image.png

点击Read后变成了如下界面

image.png

通过以上两张图片对比发现我们实现了回环测试发送什么就接受到什么 以上证明了我们的设计是符合要求的,用于项目的话还需要进行相关的数据进行协议组织,同时增加方式提高传输速度等

                                                                    以上整理提供by荒野大嫖客     如果有幸你读到这篇文章给个赞吧



多路扫描AD转换,用DMA传输的例子(用STM32CUBEMX)

心中有个梦 回复了问题 • 56 人关注 • 32 个回复 • 27875 次浏览 • 2018-09-03 15:46 • 来自相关话题

分享一个由串口uart接收命令,来动态调整tim定时器pwm模式脉冲宽度的小实验

想飞的四轴 回复了问题 • 44 人关注 • 19 个回复 • 12944 次浏览 • 2018-08-17 12:20 • 来自相关话题

(转)基于STM32Cube库的Timer捕获应用

admin 发表了文章 • 0 个评论 • 1759 次浏览 • 2018-06-14 09:19 • 来自相关话题

当使用Timer做捕获输入时,有时候需要将捕获得到的数据通过DMA方式写到定义好的数据或数组中,本文将详细介绍使用CubeMX配置PWM捕获功能,用户可以直接得到输入的PWM信号的频率以及占空比,Cube库可以很方便配置。实验过程中,当配置超过两个以上的Timer通道DMA时会遇到一些问题,本文也对其进行了说明并给出了解决方案。Timer2的PWM信号捕获功能√使用Timer的IC1,IC2两个捕获输入通道,两个通道的外部管脚输入配置为相同TI1通道;√两个通道的捕获输入极性,一个为Active,另外一个为Inactive;√其中一个TI1FP1作为触发输入,从模式配置为复位模式;√这样CCR1为PWM输入的频率值,CCR2为占空比值(正/负)。使用STM32CubeMX对外设进行初始化配置:Step1: TIM1的输出PWM波作为捕获输入的被测信号,输出管脚为PA8Step2: TIM2的输入管脚为PA5(CH1)Step3: 配置TIM2的输入捕获参数Step4: 捕获数据直接通过DMA方式保存到RAM变量Update_Value1和Update_Value2。Step5: 测试读取到的CCR1、CCR2的数据与Update_Value1、Update_Value2对应,PWM波的频率和占空比都可以捕获得到。实验过程要点提示在stm32f3xx_hal_tim.c库文件中的HAL_TIM_IC_Start_DMA函数中会将状态置忙。但在函数结尾配置完毕后没有将该状态位复位,如果客户在其用户程序中使用了这个函数,这会导致该状态位始终为忙,后续任何对该状态的判断配置都将无法执行:因此需要在函数的最后将状态复位:本文小结本文重点介绍利用STM32CubeMX初始化配置工具和STM32Cube库如何通过TIMER的捕获功能完成对频率、占空比的测试,同时我们对如何解决实验过程中遇到的一些问题,做了特别提示。我们知道STM32Cube库非常庞大,虽难尽善尽美,但一定会越来越强大、越来越完善。本文转自:https://mp.weixin.qq.com/s/e2M22gpqFmOKee36MFe9oQ感谢ST人的分享和付出! 查看全部

当使用Timer做捕获输入时,有时候需要将捕获得到的数据通过DMA方式写到定义好的数据或数组中,本文将详细介绍使用CubeMX配置PWM捕获功能,用户可以直接得到输入的PWM信号的频率以及占空比,Cube库可以很方便配置。

实验过程中,当配置超过两个以上的Timer通道DMA时会遇到一些问题,本文也对其进行了说明并给出了解决方案。

Timer2的PWM信号捕获功能


使用Timer的IC1,IC2两个捕获输入通道,两个通道的外部管脚输入配置为相同TI1通道;

两个通道的捕获输入极性,一个为Active,另外一个为Inactive;

其中一个TI1FP1作为触发输入,从模式配置为复位模式;

这样CCR1为PWM输入的频率值,CCR2为占空比值(正/负)。

webwxgetmsgimg.jpg


使用STM32CubeMX对外设进行初始化配置:


Step1: TIM1的输出PWM波作为捕获输入的被测信号,输出管脚为PA8

Step2: TIM2的输入管脚为PA5(CH1)

webwxgetmsgimg (1).jpg

Step3: 配置TIM2的输入捕获参数

webwxgetmsgimg (2).jpg

Step4: 捕获数据直接通过DMA方式保存到RAM变量Update_Value1和Update_Value2。

webwxgetmsgimg (3).jpg

Step5: 测试读取到的CCR1、CCR2的数据与Update_Value1、Update_Value2对应,PWM波的频率和占空比都可以捕获得到。


webwxgetmsgimg (4).jpg


实验过程要点提示


在stm32f3xx_hal_tim.c

库文件中的HAL_TIM_IC_Start_DMA函数中会将状态置忙。

webwxgetmsgimg (5).jpg

但在函数结尾配置完毕后没有将该状态位复位,如果客户在其用户程序中使用了这个函数,这会导致该状态位始终为忙,后续任何对该状态的判断配置都将无法执行:

webwxgetmsgimg (6).jpg

因此需要在函数的最后将状态复位:

webwxgetmsgimg (7).jpg

本文小结

本文重点介绍利用STM32CubeMX初始化配置工具和STM32Cube库如何通过TIMER的捕获功能完成对频率、占空比的测试,同时我们对如何解决实验过程中遇到的一些问题,做了特别提示。我们知道STM32Cube库非常庞大,虽难尽善尽美,但一定会越来越强大、越来越完善。



本文转自:https://mp.weixin.qq.com/s/e2M22gpqFmOKee36MFe9oQ


感谢ST人的分享和付出!

CAN的Loopback模式例程的设置及程序分析

虎扑最大的吊 回复了问题 • 6 人关注 • 7 个回复 • 5480 次浏览 • 2018-06-10 19:56 • 来自相关话题

抛砖引玉:一步一步Hal库学习usb虚拟串口功能CDC或者叫VCP

星期五 回复了问题 • 47 人关注 • 22 个回复 • 33907 次浏览 • 2018-03-03 19:05 • 来自相关话题

一步步实现stm32F103RBT6的DFU实验记录

Playnetics 回复了问题 • 9 人关注 • 6 个回复 • 9417 次浏览 • 2018-01-07 21:16 • 来自相关话题

分享:利用stm32cube的Hal库以四线方式操作LCD1602的方法和操作示例

红烧鱼 回复了问题 • 7 人关注 • 9 个回复 • 4828 次浏览 • 2017-07-19 23:41 • 来自相关话题

Encoder模式的分析方法和使用技巧(利用Tim1定时器encoder接口)

admin 发表了文章 • 5 个评论 • 5078 次浏览 • 2017-06-09 11:24 • 来自相关话题

测试工具:keil5 , stm32cubemx , stm32F407discovery板卡, 广数凯恩帝数控CNC电子手轮(5V六端子100脉冲)应为discovery板并没有内置手轮的差分式外部电路,所以手轮我只用到了vcc ,gnd ,A+,B+这四个端子分别接到了5V,0V,PE11,PE9这几个引脚上面,硬件未滤波,只是提供演示参考.以下是cubemx中的配置信息1,选中tim1的encoder模式2,根据discovery板设置时钟3,配置tim1的各种参数,这里我随意设置的,2分频,重载值为10000,各个io口是上升沿计数,这里我编码器模式使用的是TT1,因为我不想用那么复杂的多沿计数,只计数TT1的通道脉冲,这样方便程序的编写使用.滤波我设置的3模式,不知道效果如何.下面是TIM1的两个管脚的配置,PE9和PE11的,因为电子手轮输出的是高低电平,所以板卡就不需要上下拉了,直接用OD模式最好.4,编译生成代码,然后打开工程.在main.c文件中user0处添加两个变量,分别准备存储方向信号和脉冲信号/* USER CODE BEGIN 0 */
uint32_t uwDirection = 0;
uint32_t pulsecount = 0;
/* USER CODE END 0 */在main()函数中添加encoder的启动和初始化计数器值为0    /* USER CODE BEGIN 2 */
    HAL_TIM_Encoder_Start(&htim1,TIM_CHANNEL_ALL);
    //初始化计数器值为0
    __HAL_TIM_SetCounter(&htim1,0);
    /* USER CODE END 2 */然后在大循环while中添加获取方向信号和脉冲数量的代码    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        //获取转动方向,0正转,1反转
        uwDirection = __HAL_TIM_DIRECTION_STATUS(&htim1);

        //获取计数器计数值,即手轮脉冲计数
        pulsecount = __HAL_TIM_GetCounter(&htim1);

    }ok,代码编写完成了.编译烧写,然后点击keil的调试按钮调试这里我们分别在uwDirection和pulsecount上面点击右键,选择add 到 watch1中另外也添加htm1到观察1中然后点击左侧的全速运行,此时可以看到watch1观察口里是没有任何变化的,这时候你转动手轮,里面的值开始变化正转手轮pulsecount的计数开始从0一个一个增加,反转一下减少一个数值,同样的正转的时候direction一直是0,反转的时候就变成了1具体的操作可以看此贴顶部第一个动态图片.此次教程结束.具体到怎么去用这个encoder,还要考虑定时器的重载事件update,所以还要启用tim的update中断,在中断中记录中断的次数,然后结合你的autoreload数相乘得到实际的转动脉冲数.这里不再具体讲述. 查看全部

1496977140559287.png

GIF.gif

测试工具:

keil5 , stm32cubemx , stm32F407discovery板卡, 广数凯恩帝数控CNC电子手轮(5V六端子100脉冲)

blob.png

应为discovery板并没有内置手轮的差分式外部电路,所以手轮我只用到了vcc ,gnd ,A+,B+这四个端子

分别接到了5V,0V,PE11,PE9这几个引脚上面,硬件未滤波,只是提供演示参考.


以下是cubemx中的配置信息

1,选中tim1的encoder模式

blob.png

2,根据discovery板设置时钟

blob.png

3,配置tim1的各种参数,这里我随意设置的,2分频,重载值为10000,各个io口是上升沿计数,这里我编码器模式使用的是TT1,因为我不想用那么复杂的多沿计数,只计数TT1的通道脉冲,这样方便程序的编写使用.滤波我设置的3模式,不知道效果如何.

blob.png

下面是TIM1的两个管脚的配置,PE9和PE11的,因为电子手轮输出的是高低电平,所以板卡就不需要上下拉了,直接用OD模式最好.

blob.png

4,编译生成代码,然后打开工程.

在main.c文件中user0处添加两个变量,分别准备存储方向信号和脉冲信号

/* USER CODE BEGIN 0 */
uint32_t uwDirection = 0;
uint32_t pulsecount = 0;
/* USER CODE END 0 */

在main()函数中添加encoder的启动和初始化计数器值为0

    /* USER CODE BEGIN 2 */
    HAL_TIM_Encoder_Start(&htim1,TIM_CHANNEL_ALL);
    //初始化计数器值为0
    __HAL_TIM_SetCounter(&htim1,0);
    /* USER CODE END 2 */

然后在大循环while中添加获取方向信号和脉冲数量的代码

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

        /* USER CODE BEGIN 3 */
        //获取转动方向,0正转,1反转
        uwDirection = __HAL_TIM_DIRECTION_STATUS(&htim1);

        //获取计数器计数值,即手轮脉冲计数
        pulsecount = __HAL_TIM_GetCounter(&htim1);

    }

ok,代码编写完成了.

编译烧写,然后点击keil的调试按钮调试

blob.png

这里我们分别在uwDirection和pulsecount上面点击右键,选择add 到 watch1中

另外也添加htm1到观察1中

blob.png

然后点击左侧的全速运行,

此时可以看到watch1观察口里是没有任何变化的,这时候你转动手轮,里面的值开始变化

正转手轮pulsecount的计数开始从0一个一个增加,反转一下减少一个数值,同样的正转的时候direction一直是0,反转的时候就变成了1


具体的操作可以看此贴顶部第一个动态图片.


此次教程结束.

具体到怎么去用这个encoder,还要考虑定时器的重载事件update,所以还要启用tim的update中断,在中断中记录中断的次数,然后结合你的autoreload数相乘得到实际的转动脉冲数.这里不再具体讲述.


(转)通过配置SPI1完成W25X16的读写

²º¹5¾ 回复了问题 • 6 人关注 • 2 个回复 • 3176 次浏览 • 2017-06-07 12:00 • 来自相关话题

STM32F042F6P6-USB设备开发最小系统之键盘示例

井底添蛙 发表了文章 • 5 个评论 • 6365 次浏览 • 2017-06-03 00:14 • 来自相关话题

最常见的USB设备要数鼠标和键盘了,STM32F042F6P6这块小板(这里可购买,留言有优惠:购买链接)的鼠标示例已经写了,现在来写下模拟键盘的示例.不多说,开始配置,打开STM32CubeMX,选择STM32F042F6P6芯片,开启pin脚映射,打开USB设备,选择USB设备为HID,设置按键和LED对应引脚的输入输出模式:配置按键和LED引脚的状态及备注名:可以在此修改USB设备名称、厂家、PID\VID等:配置工程输出参数,然后生成并打开工程:按图中所示打开usbd_hid.c文件,找到HID_MOUSE_ReportDesc数组定义处(默认生产HID设备为Mouse,这里数组名不影响,只要里面的描述符是键盘的就行),修改成如下数据: 0x05, 0x01, // USAGE_PAGE (Generic Desktop) //63
 0x09, 0x06, // USAGE (Keyboard)
 0xa1, 0x01, // COLLECTION (Application)
 0x05, 0x07, // USAGE_PAGE (Keyboard)
 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
 0x15, 0x00, // LOGICAL_MINIMUM (0)
 0x25, 0x01, // LOGICAL_MAXIMUM (1)
 0x75, 0x01, // REPORT_SIZE (1)
 0x95, 0x08, // REPORT_COUNT (8)
 0x81, 0x02, // INPUT (Data,Var,Abs)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x08, // REPORT_SIZE (8)
 0x81, 0x03, // INPUT (Cnst,Var,Abs)
 0x95, 0x05, // REPORT_COUNT (5)
 0x75, 0x01, // REPORT_SIZE (1)
 0x05, 0x08, // USAGE_PAGE (LEDs)
 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
 0x29, 0x05, // USAGE_MAXIMUM (Kana)
 0x91, 0x02, // OUTPUT (Data,Var,Abs)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x03, // REPORT_SIZE (3)
 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
 0x95, 0x06, // REPORT_COUNT (6)
 0x75, 0x08, // REPORT_SIZE (8)
 0x15, 0x00, // LOGICAL_MINIMUM (0)
 0x25, 0x65, // LOGICAL_MAXIMUM (101)
 0x05, 0x07, // USAGE_PAGE (Keyboard)
 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
 0x81, 0x00, // INPUT (Data,Ary,Abs)
 0xc0, // END_COLLECTION再打开usbd_hid.h文件,修改HID_MOUSE_REPORT_DESC_SIZE的值为63.编译工程,下载到板子上,插上USB线连接到电脑上,是不是识别出为键盘设备了呢?继续修改main.c文件,添加头文件#include "usbd_hid.h"添加一个数组变量,用于传输键盘参数的,byte0是传控制键;byte1是保留键,不用改;byte3~byte7都可以存放传输的按键值 /*
 * buffer[0] - bit0: Left CTRL
 *           -bit1: Left SHIFT
 *           -bit2: Left ALT
 *           -bit3: Left GUI
 *           -bit4: Right CTRL
 *           -bit5: Right SHIFT
 *           -bit6: Right ALT
 *           -bit7: Right GUI 
 * buffer[1] - Padding = Always 0x00
 * buffer[2] - Key 1
 * buffer[3] - Key 2
 * buffer[4] - Key 3
 * buffer[5] - Key 4
 * buffer[6] - Key 5
 * buffer[7] - Key 6
 */
 uint8_t buffer[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};添加按键检测及传输键值到电脑的代码: if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 0)
 {
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
 
  buffer[0] = 0x02; //shift
  buffer[2] = 0x04; // a
  USBD_HID_SendReport(&hUsbDeviceFS, buffer, 8); //send
  HAL_Delay(15); //delay
 
  buffer[0] = 0x00;
  buffer[2] = 0x00;
  USBD_HID_SendReport(&hUsbDeviceFS, buffer, 8);
  HAL_Delay(15);
 
  while(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 0)
  HAL_Delay(15);
 }
 else
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);对应键值可和此文件中的HID Usage ID对应,是16进制(如字符‘a’对应键值为0x04),pdf文件在附件中有(USB_HIDtoKBScanCodeTranslationTable.pdf):再编译文件下载到板子上,试试按下按键时是不是在电脑上就输入了一个大写的‘A’呢? 查看全部

最常见的USB设备要数鼠标和键盘了,STM32F042F6P6这块小板(这里可购买,留言有优惠:购买链接)的鼠标示例已经写了,现在来写下模拟键盘的示例.

不多说,开始配置,打开STM32CubeMX,选择STM32F042F6P6芯片,开启pin脚映射,打开USB设备,选择USB设备为HID,设置按键和LED对应引脚的输入输出模式:

配置按键和LED引脚的状态及备注名:

可以在此修改USB设备名称、厂家、PID\VID等:

配置工程输出参数,然后生成并打开工程:

按图中所示打开usbd_hid.c文件,找到HID_MOUSE_ReportDesc数组定义处(默认生产HID设备为Mouse,这里数组名不影响,只要里面的描述符是键盘的就行),修改成如下数据:

 0x05, 0x01, // USAGE_PAGE (Generic Desktop) //63
 0x09, 0x06, // USAGE (Keyboard)
 0xa1, 0x01, // COLLECTION (Application)
 0x05, 0x07, // USAGE_PAGE (Keyboard)
 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
 0x15, 0x00, // LOGICAL_MINIMUM (0)
 0x25, 0x01, // LOGICAL_MAXIMUM (1)
 0x75, 0x01, // REPORT_SIZE (1)
 0x95, 0x08, // REPORT_COUNT (8)
 0x81, 0x02, // INPUT (Data,Var,Abs)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x08, // REPORT_SIZE (8)
 0x81, 0x03, // INPUT (Cnst,Var,Abs)
 0x95, 0x05, // REPORT_COUNT (5)
 0x75, 0x01, // REPORT_SIZE (1)
 0x05, 0x08, // USAGE_PAGE (LEDs)
 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
 0x29, 0x05, // USAGE_MAXIMUM (Kana)
 0x91, 0x02, // OUTPUT (Data,Var,Abs)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x03, // REPORT_SIZE (3)
 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
 0x95, 0x06, // REPORT_COUNT (6)
 0x75, 0x08, // REPORT_SIZE (8)
 0x15, 0x00, // LOGICAL_MINIMUM (0)
 0x25, 0x65, // LOGICAL_MAXIMUM (101)
 0x05, 0x07, // USAGE_PAGE (Keyboard)
 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
 0x81, 0x00, // INPUT (Data,Ary,Abs)
 0xc0, // END_COLLECTION

再打开usbd_hid.h文件,修改HID_MOUSE_REPORT_DESC_SIZE的值为63.

编译工程,下载到板子上,插上USB线连接到电脑上,是不是识别出为键盘设备了呢?

继续修改main.c文件,添加头文件

#include "usbd_hid.h"

添加一个数组变量,用于传输键盘参数的,byte0是传控制键;byte1是保留键,不用改;byte3~byte7都可以存放传输的按键值

 /*
 * buffer[0] - bit0: Left CTRL
 *           -bit1: Left SHIFT
 *           -bit2: Left ALT
 *           -bit3: Left GUI
 *           -bit4: Right CTRL
 *           -bit5: Right SHIFT
 *           -bit6: Right ALT
 *           -bit7: Right GUI 
 * buffer[1] - Padding = Always 0x00
 * buffer[2] - Key 1
 * buffer[3] - Key 2
 * buffer[4] - Key 3
 * buffer[5] - Key 4
 * buffer[6] - Key 5
 * buffer[7] - Key 6
 */
 uint8_t buffer[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

添加按键检测及传输键值到电脑的代码:

 if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 0)
 {
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
 
  buffer[0] = 0x02; //shift
  buffer[2] = 0x04; // a
  USBD_HID_SendReport(&hUsbDeviceFS, buffer, 8); //send
  HAL_Delay(15); //delay
 
  buffer[0] = 0x00;
  buffer[2] = 0x00;
  USBD_HID_SendReport(&hUsbDeviceFS, buffer, 8);
  HAL_Delay(15);
 
  while(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 0)
  HAL_Delay(15);
 }
 else
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);

对应键值可和此文件中的HID Usage ID对应,是16进制(如字符‘a’对应键值为0x04),pdf文件在附件中有(USB_HIDtoKBScanCodeTranslationTable.pdf):

再编译文件下载到板子上,试试按下按键时是不是在电脑上就输入了一个大写的‘A’呢?

STM32F446RE+Cube_I2C_DMA 玩转DS3231

【福清】Paderboy 发表了文章 • 6 个评论 • 3583 次浏览 • 2017-04-02 08:57 • 来自相关话题

1.使用Cube配置F446RE 内部时钟:HSI 2.配置I2C1 作为读写DS3231的通讯方式3.配置串口2,输出调试信息4.配置串口和I2C通过DMA方式接收数据好了直接上图。。。 简单暴力。。。。。 主频开到最大。。 配置串口DMA+中断(用到IDLE空闲中断接收数据) I2C 配置400Khz的 只配置了I2C DMA_Rx的配置 保存工程。。。 下面上些,截图。。。创建 DS3231数据结构 BCD到DEC 和 DEC到BCD的转化函数 I2C读取回调函数,处理接收的数据(以及激活DS3231内部温度转换) 获取DS3231内部温度后处理函数 串口输出时间和温度函数 设置DS3231时间函数(通过串口接收数据转换成BCD后写入DS3231) 串口数据接收函数 好了现在看下调试过程的截图 演示:     调试过程总结:使用Cube+HAL库非常方便建立工程和直接调用HAL库的I2C函数,直接读取DS3231的数据,经过处理后,通过串口输出非常便捷高效。。。调试过程中,遇到了,些问题(就是对DS3231的时间设定问题,串口接收的数据都准确,但是在写入DS3231的过程中,有时候不能成功设置时间,而且成功几率很低。最后发现了问题所在(就是我在设置I2C NVI 中断优先等级不够优先,所以造成被其他中断抢占了。导致设置时间失败。。)修改中断优先等级解决上述问题。。) 。。STM32F446RE_I2C_DS3231_DMA.rar 查看全部

1.使用Cube配置F446RE 内部时钟:HSI 
2.配置I2C1 作为读写DS3231的通讯方式
3.配置串口2,输出调试信息
4.配置串口和I2C通过DMA方式接收数据



好了直接上图。。。 简单暴力。。。。。


 

主频开到最大。。

 

配置串口DMA+中断(用到IDLE空闲中断接收数据)
 

I2C 配置400Khz的

 

只配置了I2C DMA_Rx的配置

 

保存工程。。。

 

下面上些,截图。。。创建 DS3231数据结构

 

BCD到DEC 和 DEC到BCD的转化函数

 

I2C读取回调函数,处理接收的数据(以及激活DS3231内部温度转换)

 


获取DS3231内部温度后处理函数
 


串口输出时间和温度函数

 


设置DS3231时间函数(通过串口接收数据转换成BCD后写入DS3231)

 


串口数据接收函数

 


好了现在看下调试过程的截图 演示:

 


 

 

 

 


调试过程总结:使用Cube+HAL库非常方便建立工程和直接调用HAL库的I2C函数,直接读取DS3231的数据,经过处理后,通过串口输出非常便捷高效。。。
调试过程中,遇到了,些问题(就是对DS3231的时间设定问题,串口接收的数据都准确,但是在写入DS3231的过程中,有时候不能成功设置时间,而且成功几率很低。最后发现了问题所在(就是我在设置I2C NVI 中断优先等级不够优先,所以造成被其他中断抢占了。导致设置时间失败。。)修改中断优先等级解决上述问题。。) 。。

STM32F446RE_I2C_DS3231_DMA.rar


STM32Cube MX实验一 点亮LED

_Lumia 发表了文章 • 4 个评论 • 4056 次浏览 • 2016-08-23 22:18 • 来自相关话题

提示 : 可直接粘贴图片截图!1. 如何新建工程,以及设置LED的GPIO就不写了,网站上有教程的。
2. STM32 初学,分享一下自己在学习板上的简单的练习程序,代码在实验板上测试通过。


led.c 文件
#include "led.h"

/** 配置led用到的端口、引脚 */
const struct GPIO_LED led[] =
{
    GPIOD, GPIO_PIN_2,
    GPIOD, GPIO_PIN_3,
    GPIOD, GPIO_PIN_4,
    GPIOD, GPIO_PIN_7,
};

#define NUM_LEDS (sizeof(led) / sizeof(struct GPIO_LED))


/**
 * @brief   点亮led驱动程序 可同时点亮多个 
 * @param   val 多个LED组合
 * @return  None
 * @note    例如: led_on(LED_0 | LED_1)
 */
void led_on(uint16_t val) 
{
    uint8_t n;
    
    for(n = 0; n < NUM_LEDS; n++)
    {
        if (val & (1 << n)) 
        {
            HAL_GPIO_WritePin(led[n].port, led[n].pin, GPIO_PIN_SET);        
        }        
    }    
}

/**
 * @brief   熄灭led驱动程序 可同时熄灭多个 
 * @param   val 多个LED组合
 * @return  None
 * @note    例如: led_off(LED_0 | LED_1)
 */
void led_off(uint16_t val) 
{
    uint8_t n;
    
    for(n = 0; n < NUM_LEDS; n++)
    {
        if (val & (1 << n)) 
        {
            HAL_GPIO_WritePin(led[n].port, led[n].pin, GPIO_PIN_RESET);        
        }        
    }     
}

led.h 文件
#ifndef __LED_H
#define __LED_H

#include "stm32f1xx_hal.h"

struct GPIO_LED
{
    GPIO_TypeDef      *port;
    uint16_t          pin;
};

#define    LED_0        0x01    
#define    LED_1        0x02    
#define    LED_2        0x04    
#define    LED_3        0x08    
#define    LED_4        0x10
#define    LED_5        0x20
#define    LED_6        0x40
#define    LED_7        0x80
#define    LED_ALL        0xFFFF

void    led_on(uint16_t val);
void    led_off(uint16_t val) ;

#endif 

主函数
int main(void)
{

  /* USER CODE BEGIN 1 */
    uint8_t i = 0;
  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
      i = (i >= 3)? 0 : i + 1;
      led_on(LED_0 << i);
      delay_n_ms(500);
      led_off(LED_0 << i);
      delay_n_ms(500);
  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
  
} 查看全部

提示 : 可直接粘贴图片截图!

1. 如何新建工程,以及设置LED的GPIO就不写了,网站上有教程的。
2. STM32 初学,分享一下自己在学习板上的简单的练习程序,代码在实验板上测试通过。


led.c 文件
#include "led.h"

/** 配置led用到的端口、引脚 */
const struct GPIO_LED led[] =
{
    GPIOD, GPIO_PIN_2,
    GPIOD, GPIO_PIN_3,
    GPIOD, GPIO_PIN_4,
    GPIOD, GPIO_PIN_7,
};

#define NUM_LEDS (sizeof(led) / sizeof(struct GPIO_LED))


/**
 * @brief   点亮led驱动程序 可同时点亮多个 
 * @param   val 多个LED组合
 * @return  None
 * @note    例如: led_on(LED_0 | LED_1)
 */
void led_on(uint16_t val) 
{
    uint8_t n;
    
    for(n = 0; n < NUM_LEDS; n++)
    {
        if (val & (1 << n)) 
        {
            HAL_GPIO_WritePin(led[n].port, led[n].pin, GPIO_PIN_SET);        
        }        
    }    
}

/**
 * @brief   熄灭led驱动程序 可同时熄灭多个 
 * @param   val 多个LED组合
 * @return  None
 * @note    例如: led_off(LED_0 | LED_1)
 */
void led_off(uint16_t val) 
{
    uint8_t n;
    
    for(n = 0; n < NUM_LEDS; n++)
    {
        if (val & (1 << n)) 
        {
            HAL_GPIO_WritePin(led[n].port, led[n].pin, GPIO_PIN_RESET);        
        }        
    }     
}

led.h 文件
#ifndef __LED_H
#define __LED_H

#include "stm32f1xx_hal.h"

struct GPIO_LED
{
    GPIO_TypeDef      *port;
    uint16_t          pin;
};

#define    LED_0        0x01    
#define    LED_1        0x02    
#define    LED_2        0x04    
#define    LED_3        0x08    
#define    LED_4        0x10
#define    LED_5        0x20
#define    LED_6        0x40
#define    LED_7        0x80
#define    LED_ALL        0xFFFF

void    led_on(uint16_t val);
void    led_off(uint16_t val) ;

#endif 

主函数
int main(void)
{

  /* USER CODE BEGIN 1 */
    uint8_t i = 0;
  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
      i = (i >= 3)? 0 : i + 1;
      led_on(LED_0 << i);
      delay_n_ms(500);
      led_off(LED_0 << i);
      delay_n_ms(500);
  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
  
}



利用U盘通过FatFs烧写BIN文件到flash实现芯片的在线编程(stm32F407+FatFs+USBdisk+Flash)

回复

admin 回复了问题 • 12 人关注 • 1 个回复 • 4202 次浏览 • 2016-07-27 12:03 • 来自相关话题

使用VS2015配合stm32cubemx开发嵌入式STM32(三)

萬~崧~霖 发表了文章 • 25 个评论 • 11870 次浏览 • 2016-07-22 17:38 • 来自相关话题

 
 终于进入正题了,如果没看过前面两部分的,请绕道前去先看看前面的两个部分,不然有些时候不太明白!!
 
开始上图:
  
 




 





 





 





 





 





 





 





 
换个背景!!!!!!!!!!!!!!!!!
 





 





 





 





 





 





 





 





 





 





 
 
 
好啦,到此,stm32cubemx工程导入vs2015就可以了,但是还是有很多参数设置没讲,后面有机会再发上来,喜欢就点赞吧!!!!!!!!!!!!有问题可以发我邮件:wansonglintbw@126.com 查看全部
 
 终于进入正题了,如果没看过前面两部分的,请绕道前去先看看前面的两个部分,不然有些时候不太明白!!
 
开始上图:
  
 
1.jpg

 

2.jpg

 

3.jpg

 

4.jpg

 

5.jpg

 

6.jpg

 

7.jpg

 

8.jpg

 
换个背景!!!!!!!!!!!!!!!!!
 

9.jpg

 

10.jpg

 

11.jpg

 

12.jpg

 

13.jpg

 

14.jpg

 

15.jpg

 

16.jpg

 

17.jpg

 

18.jpg

 
 
 
好啦,到此,stm32cubemx工程导入vs2015就可以了,但是还是有很多参数设置没讲,后面有机会再发上来,喜欢就点赞吧!!!!!!!!!!!!有问题可以发我邮件:wansonglintbw@126.com