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

井底添蛙 发表了文章 • 5 个评论 • 8203 次浏览 • 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 个评论 • 4374 次浏览 • 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 个评论 • 4687 次浏览 • 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 */
  
}



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

萬~崧~霖 发表了文章 • 25 个评论 • 13447 次浏览 • 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

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

萬~崧~霖 发表了文章 • 17 个评论 • 16925 次浏览 • 2016-07-19 12:32 • 来自相关话题

 
 
  首先呢,你需要安装VS2010----2015都可以版本随便,然后呢肯定要安装visual assist x神器的。这部分自己百度去。
  然后呢你需要visualgdb各项工具,我已经整理好了,网盘奉上:http://yun.baidu.com/s/1jItZ29S
 
  安装俄罗斯版的visualgdb的安装程序,这个版本比较新,而且已经破解了,没有限制!!记得在vs关闭的情况下安装这个程序,到此,你的visualgdb我默认已经安装完成,接下来安装编译器了,以stm32为例,需要使用网盘中的工具链文件夹下的:arm-eabi-gccx--xxxx--x.exe这个类型的编译器,其他的还有msp430版本的gcc等。
以默认路径安装这个编译器,不要修改安装路径,不然后面需要重新设置,比较麻烦。
 
  到此,你的visualgdb和gcc编译器都已经安装完成啦!这个时候你打开vs2015时,会提示辅助插件选择项,大体意思就是需要使用哪个去智能提示代码,选择visual assist x(前提是你安装了)。
 
 





 





 





 





 
这个时候他会提示你下载bsp设备支持包,在网盘里已经有了,直接按下图安装就行了。










选择文件安装stm32的支持包
 





 





 





 





 





 





 





 





 
到此, 使用vs2015创建STM32工程编译,下载就可以调试了,但是,这是使用的visualgdb自带的hal库和freertos系统,不能兼容我们stm32cubemx生成的工程。后面的教程我会尽快写出来!!!
 
   查看全部
 
 
  首先呢,你需要安装VS2010----2015都可以版本随便,然后呢肯定要安装visual assist x神器的。这部分自己百度去。
  然后呢你需要visualgdb各项工具,我已经整理好了,网盘奉上:http://yun.baidu.com/s/1jItZ29S
 
  安装俄罗斯版的visualgdb的安装程序,这个版本比较新,而且已经破解了,没有限制!!记得在vs关闭的情况下安装这个程序,到此,你的visualgdb我默认已经安装完成,接下来安装编译器了,以stm32为例,需要使用网盘中的工具链文件夹下的:arm-eabi-gccx--xxxx--x.exe这个类型的编译器,其他的还有msp430版本的gcc等。
以默认路径安装这个编译器,不要修改安装路径,不然后面需要重新设置,比较麻烦。
 
  到此,你的visualgdb和gcc编译器都已经安装完成啦!这个时候你打开vs2015时,会提示辅助插件选择项,大体意思就是需要使用哪个去智能提示代码,选择visual assist x(前提是你安装了)。
 
 

4.jpg

 

5.jpg

 

6.jpg

 

7.jpg

 
这个时候他会提示你下载bsp设备支持包,在网盘里已经有了,直接按下图安装就行了。

16.jpg


17.jpg

选择文件安装stm32的支持包
 

8.jpg

 

9.jpg

 

10.jpg

 

11.jpg

 

12.jpg

 

13.jpg

 

14.jpg

 

15.jpg

 
到此, 使用vs2015创建STM32工程编译,下载就可以调试了,但是,这是使用的visualgdb自带的hal库和freertos系统,不能兼容我们stm32cubemx生成的工程。后面的教程我会尽快写出来!!!
 
  

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

萬~崧~霖 发表了文章 • 9 个评论 • 16875 次浏览 • 2016-07-18 20:18 • 来自相关话题

  大家都知道,Visual Studio系列开发环境一直超级好用,再看看Keil,IAR之类的,哎!掺不忍睹!所以,逛外国网站时发现了一个超级神器啊----->Visualgdb.总的来说,这个东东就是让你可以在vs2010,vs2013,vs2015等开发环境中像开发windows程序一样,编写代码,调试下载,单步调试条件调试等高级特性也是可以使用的。最重要的是还可以使用VS系列特有的代码图功能,简直不要太吊啊,嘎嘎嘎!
  好了,介绍完成,下面将教你使用这个东东,官网:www.visualgdb.com 国外的,e文有困难的童鞋请开有道翻译o(^▽^)o。 
 
先上图:(电路板在公司,调试界面的图片后面有机会补上)





 
这是一个使用stm32cubemx4.15生成的工程。完美编译!





这是工程编译出来的代码和内存消耗,可以查看详细的使用情况,非常有用!

有需要的顶上,后面的教程我会抽时间尽快写出来,这个东东貌似比较麻烦,涉及到的东西比较多!其实这个东东已经自带了HAL库和Freertos系统,但是呢,和我们的stm32cubemx不兼容,而且版本也比较老旧,最关键是他们(visualgdb官方)很久不更新stm32的hal库和freertos系统。而且cubemx自动初始化并生成c代码这个太爽了,可不想这么放弃咯!!!

  能力强的自己看看官网先捣鼓下...... 查看全部
  大家都知道,Visual Studio系列开发环境一直超级好用,再看看Keil,IAR之类的,哎!掺不忍睹!所以,逛外国网站时发现了一个超级神器啊----->Visualgdb.总的来说,这个东东就是让你可以在vs2010,vs2013,vs2015等开发环境中像开发windows程序一样,编写代码,调试下载,单步调试条件调试等高级特性也是可以使用的。最重要的是还可以使用VS系列特有的代码图功能,简直不要太吊啊,嘎嘎嘎!
  好了,介绍完成,下面将教你使用这个东东,官网:www.visualgdb.com 国外的,e文有困难的童鞋请开有道翻译o(^▽^)o。 
 
先上图:(电路板在公司,调试界面的图片后面有机会补上)

1.jpg

 
这是一个使用stm32cubemx4.15生成的工程。完美编译!

2.jpg

这是工程编译出来的代码和内存消耗,可以查看详细的使用情况,非常有用!

有需要的顶上,后面的教程我会抽时间尽快写出来,这个东东貌似比较麻烦,涉及到的东西比较多!其实这个东东已经自带了HAL库和Freertos系统,但是呢,和我们的stm32cubemx不兼容,而且版本也比较老旧,最关键是他们(visualgdb官方)很久不更新stm32的hal库和freertos系统。而且cubemx自动初始化并生成c代码这个太爽了,可不想这么放弃咯!!!

  能力强的自己看看官网先捣鼓下......

【HAL库每天一例】第004例:GPIO-按键状态判断之扫描式

yingshi 发表了文章 • 5 个评论 • 6771 次浏览 • 2016-05-29 13:33 • 来自相关话题

【HAL库每天一例】系列例程从今天开始持续更新。。。。。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
链接:http://pan.baidu.com/s/1i574oPv
密码:r3s3
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-004. GPIO-按键状态判断之扫描式)

/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: YSF1_HAL-004. GPIO-按键状态判断之扫描式
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:ing10bbs
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */

【1】例程简介
  GPIO输入功能操作实现,之前控制GPIO输出高低电平实现LED灯亮灭,现在是时钟GPIO为输
入模式,按键按下时会改变GPIO的电平,对应的STM32检测到KEY对应IO电平发生变化,得出
按键状态,从而实现LED灯状态改变。  本例程在while(1)无限循环中不断检测按键状态,一
旦发现有状态改变就相应改变LED灯状态。
  在下个例程我们将讲解另外一种按键检测模式--中断式。
 
【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号     IO端口      目标功能引脚        出厂默认设置
  JP3        PB0           LED1               已接入
  JP4        PG6           LED2               已接入
  JP5        PG7           LED3               已接入
 
【3】操作及现象
  使用开发板配套的MINI USB线连接到开发板标示“调试串口”字样的MIMI USB接口为开发板供电。
下载完程序之后,板上三个LED灯全灭状态,按下KEY1或KEY2对应LED和蜂鸣器状态发生改变。

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/












bsp_key.h文件内容:#ifndef __BSP_KEY_H__
#define __BSP_KEY_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 类型定义 --------------------------------------------------------------*/
typedef enum
{
KEY_UP = 0,
KEY_DOWN = 1,
}KEYState_TypeDef;

/* 宏定义 --------------------------------------------------------------------*/
#define KEY1_RCC_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
#define KEY1_GPIO_PIN GPIO_PIN_0
#define KEY1_GPIO GPIOA
#define KEY1_DOWN_LEVEL 1 /* 根据原理图设计,KEY1按下时引脚为高电平,所以这里设置为1 */

#define KEY2_RCC_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE
#define KEY2_GPIO_PIN GPIO_PIN_13
#define KEY2_GPIO GPIOC
#define KEY2_DOWN_LEVEL 0 /* 根据原理图设计,KEY1按下时引脚为低电平,所以这里设置为0 */

/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
void KEY_GPIO_Init(void);
KEYState_TypeDef KEY1_StateRead(void);
KEYState_TypeDef KEY2_StateRead(void);

#endif // __BSP_KEY_H__

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/



bsp_key.c文件内容:/**
******************************************************************************
* 文件名程: bsp_key.c
* 作 者: 硬石嵌入式开发团队
* 版 本: V1.0
* 编写日期: 2015-10-04
* 功 能: 板载独立按键底层驱动函数
******************************************************************************
* 说明:
* 本例程配套硬石stm32开发板YS-F1Pro使用。
*
* 淘宝:
* 论坛:ing10bbs.com
* 版权归硬石嵌入式开发团队所有,请勿商用。
******************************************************************************
*/

/* 包含头文件 ----------------------------------------------------------------*/
#include "key/bsp_key.h"

/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/

/**
* 函数功能: 板载按键IO引脚初始化.
* 输入参数: 无
* 返 回 值: 无
* 说 明:使用宏定义方法代替具体引脚号,方便程序移植,只要简单修改bsp_key.h
* 文件相关宏定义就可以方便修改引脚。
*/
void KEY_GPIO_Init(void)
{
/* 定义IO硬件初始化结构体变量 */
GPIO_InitTypeDef GPIO_InitStruct;

/* 使能(开启)KEY引脚对应IO端口时钟 */
KEY1_RCC_CLK_ENABLE();
KEY2_RCC_CLK_ENABLE();

/* 配置KEY1 GPIO:输入下拉模式 */
GPIO_InitStruct.Pin = KEY1_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(KEY1_GPIO, &GPIO_InitStruct);

/* 配置KEY2 GPIO:输入上拉模式 */
GPIO_InitStruct.Pin = KEY2_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(KEY2_GPIO, &GPIO_InitStruct);

}

/**
* 函数功能: 读取按键KEY1的状态
* 输入参数:无
* 返 回 值: KEY_DOWN:按键被按下;
* KEY_UP :按键没被按下
* 说 明:无。
*/
KEYState_TypeDef KEY1_StateRead(void)
{
/* 读取此时按键值并判断是否是被按下状态,如果是被按下状态进入函数内 */
if(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL)
{
/* 延时一小段时间,消除抖动 */
HAL_Delay(10);
/* 延时时间后再来判断按键状态,如果还是按下状态说明按键确实被按下 */
if(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL)
{
/* 等待按键弹开才退出按键扫描函数 */
while(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL);
/* 按键扫描完毕,确定按键被按下,返回按键被按下状态 */
return KEY_DOWN;
}
}
/* 按键没被按下,返回没被按下状态 */
return KEY_UP;
}

/**
* 函数功能: 读取按键KEY2的状态
* 输入参数:无
* 返 回 值: KEY_DOWN:按键被按下;
* KEY_UP :按键没被按下
* 说 明:无。
*/
KEYState_TypeDef KEY2_StateRead(void)
{
/* 读取此时按键值并判断是否是被按下状态,如果是被按下状态进入函数内 */
if(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL)
{
/* 延时一小段时间,消除抖动 */
HAL_Delay(10);
/* 延时时间后再来判断按键状态,如果还是按下状态说明按键确实被按下 */
if(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL)
{
/* 等待按键弹开才退出按键扫描函数 */
while(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL);
/* 按键扫描完毕,确定按键被按下,返回按键被按下状态 */
return KEY_DOWN;
}
}
/* 按键没被按下,返回没被按下状态 */
return KEY_UP;
}

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/ 查看全部
【HAL库每天一例】系列例程从今天开始持续更新。。。。。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
链接:http://pan.baidu.com/s/1i574oPv
密码:r3s3
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-004. GPIO-按键状态判断之扫描式)

/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: YSF1_HAL-004. GPIO-按键状态判断之扫描式
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:ing10bbs
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */

【1】例程简介
  GPIO输入功能操作实现,之前控制GPIO输出高低电平实现LED灯亮灭,现在是时钟GPIO为输
入模式,按键按下时会改变GPIO的电平,对应的STM32检测到KEY对应IO电平发生变化,得出
按键状态,从而实现LED灯状态改变。  本例程在while(1)无限循环中不断检测按键状态,一
旦发现有状态改变就相应改变LED灯状态。
  在下个例程我们将讲解另外一种按键检测模式--中断式。
 
【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号     IO端口      目标功能引脚        出厂默认设置
  JP3        PB0           LED1               已接入
  JP4        PG6           LED2               已接入
  JP5        PG7           LED3               已接入
 
【3】操作及现象
  使用开发板配套的MINI USB线连接到开发板标示“调试串口”字样的MIMI USB接口为开发板供电。
下载完程序之后,板上三个LED灯全灭状态,按下KEY1或KEY2对应LED和蜂鸣器状态发生改变。

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

CubeMX_1.jpg


CubeMX_2.jpg



bsp_key.h文件内容:
#ifndef __BSP_KEY_H__
#define __BSP_KEY_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* 类型定义 --------------------------------------------------------------*/
typedef enum
{
KEY_UP = 0,
KEY_DOWN = 1,
}KEYState_TypeDef;

/* 宏定义 --------------------------------------------------------------------*/
#define KEY1_RCC_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
#define KEY1_GPIO_PIN GPIO_PIN_0
#define KEY1_GPIO GPIOA
#define KEY1_DOWN_LEVEL 1 /* 根据原理图设计,KEY1按下时引脚为高电平,所以这里设置为1 */

#define KEY2_RCC_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE
#define KEY2_GPIO_PIN GPIO_PIN_13
#define KEY2_GPIO GPIOC
#define KEY2_DOWN_LEVEL 0 /* 根据原理图设计,KEY1按下时引脚为低电平,所以这里设置为0 */

/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
void KEY_GPIO_Init(void);
KEYState_TypeDef KEY1_StateRead(void);
KEYState_TypeDef KEY2_StateRead(void);

#endif // __BSP_KEY_H__

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/



bsp_key.c文件内容:
/**
******************************************************************************
* 文件名程: bsp_key.c
* 作 者: 硬石嵌入式开发团队
* 版 本: V1.0
* 编写日期: 2015-10-04
* 功 能: 板载独立按键底层驱动函数
******************************************************************************
* 说明:
* 本例程配套硬石stm32开发板YS-F1Pro使用。
*
* 淘宝:
* 论坛:ing10bbs.com
* 版权归硬石嵌入式开发团队所有,请勿商用。
******************************************************************************
*/

/* 包含头文件 ----------------------------------------------------------------*/
#include "key/bsp_key.h"

/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/

/**
* 函数功能: 板载按键IO引脚初始化.
* 输入参数: 无
* 返 回 值: 无
* 说 明:使用宏定义方法代替具体引脚号,方便程序移植,只要简单修改bsp_key.h
* 文件相关宏定义就可以方便修改引脚。
*/
void KEY_GPIO_Init(void)
{
/* 定义IO硬件初始化结构体变量 */
GPIO_InitTypeDef GPIO_InitStruct;

/* 使能(开启)KEY引脚对应IO端口时钟 */
KEY1_RCC_CLK_ENABLE();
KEY2_RCC_CLK_ENABLE();

/* 配置KEY1 GPIO:输入下拉模式 */
GPIO_InitStruct.Pin = KEY1_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(KEY1_GPIO, &GPIO_InitStruct);

/* 配置KEY2 GPIO:输入上拉模式 */
GPIO_InitStruct.Pin = KEY2_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(KEY2_GPIO, &GPIO_InitStruct);

}

/**
* 函数功能: 读取按键KEY1的状态
* 输入参数:无
* 返 回 值: KEY_DOWN:按键被按下;
* KEY_UP :按键没被按下
* 说 明:无。
*/
KEYState_TypeDef KEY1_StateRead(void)
{
/* 读取此时按键值并判断是否是被按下状态,如果是被按下状态进入函数内 */
if(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL)
{
/* 延时一小段时间,消除抖动 */
HAL_Delay(10);
/* 延时时间后再来判断按键状态,如果还是按下状态说明按键确实被按下 */
if(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL)
{
/* 等待按键弹开才退出按键扫描函数 */
while(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL);
/* 按键扫描完毕,确定按键被按下,返回按键被按下状态 */
return KEY_DOWN;
}
}
/* 按键没被按下,返回没被按下状态 */
return KEY_UP;
}

/**
* 函数功能: 读取按键KEY2的状态
* 输入参数:无
* 返 回 值: KEY_DOWN:按键被按下;
* KEY_UP :按键没被按下
* 说 明:无。
*/
KEYState_TypeDef KEY2_StateRead(void)
{
/* 读取此时按键值并判断是否是被按下状态,如果是被按下状态进入函数内 */
if(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL)
{
/* 延时一小段时间,消除抖动 */
HAL_Delay(10);
/* 延时时间后再来判断按键状态,如果还是按下状态说明按键确实被按下 */
if(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL)
{
/* 等待按键弹开才退出按键扫描函数 */
while(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL);
/* 按键扫描完毕,确定按键被按下,返回按键被按下状态 */
return KEY_DOWN;
}
}
/* 按键没被按下,返回没被按下状态 */
return KEY_UP;
}

/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

读取F4芯片ID和flash的大小

回复

admin 发起了问题 • 1 人关注 • 0 个回复 • 2385 次浏览 • 2015-12-11 10:54 • 来自相关话题

从垃圾堆里找到个Ch372的USB模块,已经初步调通(用STM32F407模拟并口方式)

okwh 回复了问题 • 2 人关注 • 10 个回复 • 3274 次浏览 • 2015-10-01 19:27 • 来自相关话题

TIM设置步骤

张腾威 发表了文章 • 2 个评论 • 3166 次浏览 • 2015-08-31 17:10 • 来自相关话题

/ Compute the prescaler value to have TIMx counter clock equal to 10000 Hz /
uwPrescalerValue = (uint32_t)(SystemCoreClock / 10000) - 1;

/ Set TIMx instance /
TimHandle.Instance = TIMx;

/* Initialize TIMx peripheral as follows:
+ Period = 10000 - 1
+ Prescaler = (SystemCoreClock/10000) - 1
+ ClockDivision = 0
+ Counter direction = Up
*/
TimHandle.Init.Period = 10000 - 1;
TimHandle.Init.Prescaler = uwPrescalerValue;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
{
/ Initialization Error /
Error_Handler();
}

/-2- Start the TIM Base generation in interrupt mode #[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#/[/size][/size][/size][/size][/size]
/ Start Channel1 /
if (HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
{
/ Starting Error /
Error_Handler();
} 查看全部
/ Compute the prescaler value to have TIMx counter clock equal to 10000 Hz /
uwPrescalerValue = (uint32_t)(SystemCoreClock / 10000) - 1;

/ Set TIMx instance /
TimHandle.Instance = TIMx;

/* Initialize TIMx peripheral as follows:
+ Period = 10000 - 1
+ Prescaler = (SystemCoreClock/10000) - 1
+ ClockDivision = 0
+ Counter direction = Up
*/
TimHandle.Init.Period = 10000 - 1;
TimHandle.Init.Prescaler = uwPrescalerValue;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
{
/ Initialization Error /
Error_Handler();
}

/-2- Start the TIM Base generation in interrupt mode #[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#/[/size][/size][/size][/size][/size]
/ Start Channel1 /
if (HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
{
/ Starting Error /
Error_Handler();
}

关于stm32cube中hal库自带CRC校验的使用例程

admin 发表了文章 • 1 个评论 • 9843 次浏览 • 2015-04-21 10:17 • 来自相关话题

CRC校验在通信中至关重要,所以不得不提一下
所有的STM32芯片都内置了一个硬件的CRC计算模块,可以很方便地应用到需要进行通信的程序中,这个CRC计算模块使用常见的、在以太网中使用的计算多项式:
X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2+ X +1
写成16进制就是:0x04C11DB7






利用cubemx生成的crc程序更简单了,





上面是配置,CRC不需修改任何参数,stm32中的crc是32位的
使用很简单,打开生成的程序后
算了,直接贴代码了


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"
#include "crc.h"
#include "gpio.h"

/[i] USER CODE BEGIN Includes [/i]/

/[i] USER CODE END Includes [/i]/

/[i] Private variables ---------------------------------------------------------[/i]/

/[i] USER CODE BEGIN PV [/i]/

/[i] USER CODE END PV [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
void SystemClock_Config(void);

/[i] USER CODE BEGIN PFP [/i]/

/[i] USER CODE END PFP [/i]/

/[i] USER CODE BEGIN 0 [/i]/
#define BUFFER_SIZE 114
__IO uint32_t uwCRCValue = 0;

static const uint32_t aDataBuffer[BUFFER_SIZE] =
{
0x00001021, 0x20423063, 0x408450a5, 0x60c670e7, 0x9129a14a, 0xb16bc18c,
0xd1ade1ce, 0xf1ef1231, 0x32732252, 0x52b54294, 0x72f762d6, 0x93398318,
0xa35ad3bd, 0xc39cf3ff, 0xe3de2462, 0x34430420, 0x64e674c7, 0x44a45485,
0xa56ab54b, 0x85289509, 0xf5cfc5ac, 0xd58d3653, 0x26721611, 0x063076d7,
0x569546b4, 0xb75ba77a, 0x97198738, 0xf7dfe7fe, 0xc7bc48c4, 0x58e56886,
0x78a70840, 0x18612802, 0xc9ccd9ed, 0xe98ef9af, 0x89489969, 0xa90ab92b,
0x4ad47ab7, 0x6a961a71, 0x0a503a33, 0x2a12dbfd, 0xfbbfeb9e, 0x9b798b58,
0xbb3bab1a, 0x6ca67c87, 0x5cc52c22, 0x3c030c60, 0x1c41edae, 0xfd8fcdec,
0xad2abd0b, 0x8d689d49, 0x7e976eb6, 0x5ed54ef4, 0x2e321e51, 0x0e70ff9f,
0xefbedfdd, 0xcffcbf1b, 0x9f598f78, 0x918881a9, 0xb1caa1eb, 0xd10cc12d,
0xe16f1080, 0x00a130c2, 0x20e35004, 0x40257046, 0x83b99398, 0xa3fbb3da,
0xc33dd31c, 0xe37ff35e, 0x129022f3, 0x32d24235, 0x52146277, 0x7256b5ea,
0x95a88589, 0xf56ee54f, 0xd52cc50d, 0x34e224c3, 0x04817466, 0x64475424,
0x4405a7db, 0xb7fa8799, 0xe75ff77e, 0xc71dd73c, 0x26d336f2, 0x069116b0,
0x76764615, 0x5634d94c, 0xc96df90e, 0xe92f99c8, 0xb98aa9ab, 0x58444865,
0x78066827, 0x18c008e1, 0x28a3cb7d, 0xdb5ceb3f, 0xfb1e8bf9, 0x9bd8abbb,
0x4a755a54, 0x6a377a16, 0x0af11ad0, 0x2ab33a92, 0xed0fdd6c, 0xcd4dbdaa,
0xad8b9de8, 0x8dc97c26, 0x5c644c45, 0x3ca22c83, 0x1ce00cc1, 0xef1fff3e,
0xdf7caf9b, 0xbfba8fd9, 0x9ff86e17, 0x7e364e55, 0x2e933eb2, 0x0ed11ef0
};
uint32_t uwExpectedCRCValue = 0x379E9F06;
/[i] USER CODE END 0 [/i]/

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

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

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_CRC_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-2- Compute the CRC of "aDataBuffer" [/size]############[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/
[/size][/size][/size][/size][/size][/size][/size]
uwCRCValue = HAL_CRC_Accumulate(&hcrc, (uint32_t *)aDataBuffer, BUFFER_SIZE);
/[i][size=16]-3- Compare the CRC value to the Expected one [/size]###[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/
[/size][/size][/size][/size][/size][/size][/size]
if(uwCRCValue != uwExpectedCRCValue)
{
/[i] Wrong CRC value: Turn LED3 on [/i]/
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET);
}
else
{
/[i] Right CRC value: Turn LED1 on [/i]/
while(1)
{
HAL_Delay(1000);
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_6);
}
}
/[i] USER CODE END 2 [/i]/

/[i] Infinite loop [/i]/
/[i] USER CODE BEGIN WHILE [/i]/
while (1)
{
/[i] USER CODE END WHILE [/i]/

/[i] USER CODE BEGIN 3 [/i]/

}
/[i] USER CODE END 3 [/i]/

}

debug调试的话,会看到自动校验的值和我们设定的那个比较值一样,说明运行校验正确!
当然,使用的时候可以将得到的CRC校验值传递到通信方,共上位机校验
结束!

额,再复制点crc相关的东西,
以下内容来自21ic.

下面是用C语言描述的这个计算模块的算法,大家可以把它放在通信的另一端,对通信的正确性进行验证:


DWORD dwPolynomial = 0x04c11db7;
DWORD cal_crc(DWORD *ptr, int len)
{
DWORD xbit;
DWORD data;
DWORD CRC = 0xFFFFFFFF; // init
while (len--) {
xbit = 1 << 31;

data = *ptr++;
for (int bits = 0; bits < 32; bits++) {
if (CRC & 0x80000000) {
CRC <<= 1;
CRC ^= dwPolynomial;
}
else
CRC <<= 1;
if (data & xbit)
CRC ^= dwPolynomial;

xbit >>= 1;
}
}
return CRC;
}


有几点需要说明:

1)上述算法中变量CRC,在每次循环结束包含了计算的余数,它始终是向左移位(既从最低位向最高位移动),溢出的数据位被丢弃。

2)输入的数据始终是以32位为单位,如果原始数据少于32位,需要在低位补0,当然也可以高位补0。

3)假定输入的DWORD数组中每个分量是按小端存储。

4)输入数据是按照最高位最先计算,最低位最后计算的顺序进行。

例如:
如果输入0x44434241,内存中按字节存放的顺序是:0x41, 0x42, 0x43, 0x44。计算的结果是:0xCF534AE1
如果输入0x41424344,内存中按字节存放的顺序是:0x44, 0x43, 0x42, 0x41。计算的结果是:0xABCF9A63

本帖程序前往[资源下载]区,文件名:stm32cube-crc校验例程.zip 查看全部
CRC校验在通信中至关重要,所以不得不提一下
所有的STM32芯片都内置了一个硬件的CRC计算模块,可以很方便地应用到需要进行通信的程序中,这个CRC计算模块使用常见的、在以太网中使用的计算多项式:
X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2+ X +1
写成16进制就是:0x04C11DB7

2009414182656610.gif


利用cubemx生成的crc程序更简单了,

1.png

上面是配置,CRC不需修改任何参数,stm32中的crc是32位的
使用很简单,打开生成的程序后
算了,直接贴代码了


/[i] Includes ------------------------------------------------------------------[/i]/
#include "stm32f4xx_hal.h"
#include "crc.h"
#include "gpio.h"

/[i] USER CODE BEGIN Includes [/i]/

/[i] USER CODE END Includes [/i]/

/[i] Private variables ---------------------------------------------------------[/i]/

/[i] USER CODE BEGIN PV [/i]/

/[i] USER CODE END PV [/i]/

/[i] Private function prototypes -----------------------------------------------[/i]/
void SystemClock_Config(void);

/[i] USER CODE BEGIN PFP [/i]/

/[i] USER CODE END PFP [/i]/

/[i] USER CODE BEGIN 0 [/i]/
#define BUFFER_SIZE 114
__IO uint32_t uwCRCValue = 0;

static const uint32_t aDataBuffer[BUFFER_SIZE] =
{
0x00001021, 0x20423063, 0x408450a5, 0x60c670e7, 0x9129a14a, 0xb16bc18c,
0xd1ade1ce, 0xf1ef1231, 0x32732252, 0x52b54294, 0x72f762d6, 0x93398318,
0xa35ad3bd, 0xc39cf3ff, 0xe3de2462, 0x34430420, 0x64e674c7, 0x44a45485,
0xa56ab54b, 0x85289509, 0xf5cfc5ac, 0xd58d3653, 0x26721611, 0x063076d7,
0x569546b4, 0xb75ba77a, 0x97198738, 0xf7dfe7fe, 0xc7bc48c4, 0x58e56886,
0x78a70840, 0x18612802, 0xc9ccd9ed, 0xe98ef9af, 0x89489969, 0xa90ab92b,
0x4ad47ab7, 0x6a961a71, 0x0a503a33, 0x2a12dbfd, 0xfbbfeb9e, 0x9b798b58,
0xbb3bab1a, 0x6ca67c87, 0x5cc52c22, 0x3c030c60, 0x1c41edae, 0xfd8fcdec,
0xad2abd0b, 0x8d689d49, 0x7e976eb6, 0x5ed54ef4, 0x2e321e51, 0x0e70ff9f,
0xefbedfdd, 0xcffcbf1b, 0x9f598f78, 0x918881a9, 0xb1caa1eb, 0xd10cc12d,
0xe16f1080, 0x00a130c2, 0x20e35004, 0x40257046, 0x83b99398, 0xa3fbb3da,
0xc33dd31c, 0xe37ff35e, 0x129022f3, 0x32d24235, 0x52146277, 0x7256b5ea,
0x95a88589, 0xf56ee54f, 0xd52cc50d, 0x34e224c3, 0x04817466, 0x64475424,
0x4405a7db, 0xb7fa8799, 0xe75ff77e, 0xc71dd73c, 0x26d336f2, 0x069116b0,
0x76764615, 0x5634d94c, 0xc96df90e, 0xe92f99c8, 0xb98aa9ab, 0x58444865,
0x78066827, 0x18c008e1, 0x28a3cb7d, 0xdb5ceb3f, 0xfb1e8bf9, 0x9bd8abbb,
0x4a755a54, 0x6a377a16, 0x0af11ad0, 0x2ab33a92, 0xed0fdd6c, 0xcd4dbdaa,
0xad8b9de8, 0x8dc97c26, 0x5c644c45, 0x3ca22c83, 0x1ce00cc1, 0xef1fff3e,
0xdf7caf9b, 0xbfba8fd9, 0x9ff86e17, 0x7e364e55, 0x2e933eb2, 0x0ed11ef0
};
uint32_t uwExpectedCRCValue = 0x379E9F06;
/[i] USER CODE END 0 [/i]/

int main(void)
{

/[i] USER CODE BEGIN 1 [/i]/

/[i] USER CODE END 1 [/i]/

/[i] MCU Configuration----------------------------------------------------------[/i]/

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

/[i] Configure the system clock [/i]/
SystemClock_Config();

/[i] Initialize all configured peripherals [/i]/
MX_GPIO_Init();
MX_CRC_Init();

/[i] USER CODE BEGIN 2 [/i]/
/[i][size=16]-2- Compute the CRC of "aDataBuffer" [/size]############[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/
[/size][/size][/size][/size][/size][/size][/size]
uwCRCValue = HAL_CRC_Accumulate(&hcrc, (uint32_t *)aDataBuffer, BUFFER_SIZE);
/[i][size=16]-3- Compare the CRC value to the Expected one [/size]###[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[size=16]#[/i]/
[/size][/size][/size][/size][/size][/size][/size]
if(uwCRCValue != uwExpectedCRCValue)
{
/[i] Wrong CRC value: Turn LED3 on [/i]/
HAL_GPIO_WritePin (GPIOF,GPIO_PIN_6,GPIO_PIN_SET);
}
else
{
/[i] Right CRC value: Turn LED1 on [/i]/
while(1)
{
HAL_Delay(1000);
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_6);
}
}
/[i] USER CODE END 2 [/i]/

/[i] Infinite loop [/i]/
/[i] USER CODE BEGIN WHILE [/i]/
while (1)
{
/[i] USER CODE END WHILE [/i]/

/[i] USER CODE BEGIN 3 [/i]/

}
/[i] USER CODE END 3 [/i]/

}

debug调试的话,会看到自动校验的值和我们设定的那个比较值一样,说明运行校验正确!
当然,使用的时候可以将得到的CRC校验值传递到通信方,共上位机校验
结束!

额,再复制点crc相关的东西,
以下内容来自21ic.

下面是用C语言描述的这个计算模块的算法,大家可以把它放在通信的另一端,对通信的正确性进行验证:


DWORD dwPolynomial = 0x04c11db7;
DWORD cal_crc(DWORD *ptr, int len)
{
DWORD xbit;
DWORD data;
DWORD CRC = 0xFFFFFFFF; // init
while (len--) {
xbit = 1 << 31;

data = *ptr++;
for (int bits = 0; bits < 32; bits++) {
if (CRC & 0x80000000) {
CRC <<= 1;
CRC ^= dwPolynomial;
}
else
CRC <<= 1;
if (data & xbit)
CRC ^= dwPolynomial;

xbit >>= 1;
}
}
return CRC;
}


有几点需要说明:

1)上述算法中变量CRC,在每次循环结束包含了计算的余数,它始终是向左移位(既从最低位向最高位移动),溢出的数据位被丢弃。

2)输入的数据始终是以32位为单位,如果原始数据少于32位,需要在低位补0,当然也可以高位补0。

3)假定输入的DWORD数组中每个分量是按小端存储。

4)输入数据是按照最高位最先计算,最低位最后计算的顺序进行。

例如:
如果输入0x44434241,内存中按字节存放的顺序是:0x41, 0x42, 0x43, 0x44。计算的结果是:0xCF534AE1
如果输入0x41424344,内存中按字节存放的顺序是:0x44, 0x43, 0x42, 0x41。计算的结果是:0xABCF9A63

本帖程序前往[资源下载]区,文件名:stm32cube-crc校验例程.zip

(改正)关于不精确定时的延时时间计算方法(不利用TIM,用有限空循环延时)

xddl 回复了问题 • 2 人关注 • 2 个回复 • 2168 次浏览 • 2015-03-03 09:52 • 来自相关话题

关于i2c板间通信的实验和理解

回复

admin 回复了问题 • 3 人关注 • 5 个回复 • 6681 次浏览 • 2015-01-20 11:48 • 来自相关话题

好吧,从明天起开始更新官方提供的stm32cubemx实验程序的ioc文件设置和全程验证

ippouch 回复了问题 • 38 人关注 • 6 个回复 • 9273 次浏览 • 2015-01-13 13:37 • 来自相关话题

关于FreeRTOS的设置分析和官方例程实验

回复

admin 发起了问题 • 6 人关注 • 0 个回复 • 4652 次浏览 • 2014-12-31 17:17 • 来自相关话题