当前位置:首页 > 单片机 > 单片机
[导读]这次要讲讲如何用USB升级单片机代码。以前曾经做过串口升级,网络升级,升级的基本原理都类似,只不过升级的工具不同罢了,串口升级当然是用串口了,网络升级用的是TCP/IP,USB升级当然用的是USB了。下面就来讲讲USB

这次要讲讲如何用USB升级单片机代码。以前曾经做过串口升级,网络升级,升级的基本原理都类似,只不过升级的工具不同罢了,串口升级当然是用串口了,网络升级用的是TCP/IP,USB升级当然用的是USB了。下面就来讲讲USB升级的实现。

修改部分部分都在USB_User组里:

我们一个一个文件讲过来。

首先讲讲hw_config.c,这个文件跟之前工程差不多。由于演示的需要,我们在这个文件里初始化一个按键引脚,并定义按键读取函数,该按键决定代码是否升级,如果程序一开始,该按键按下,则进入升级模式,否则跳转到升级程序代码处:



/*******************************************************************************

* Function Name : DFU_Button_Config.

* Description : 配置DFU模式选择按键.

* Input : None.

* Output : None.

* Return : None.

*******************************************************************************/

void DFU_Button_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DFU, ENABLE);


/* 配置DFU按键*/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_InitStructure.GPIO_Pin = DFU_ENTER_PIN;

GPIO_Init(DFU_ENTER, &GPIO_InitStructure);

}


/*******************************************************************************

* Function Name : DFU_Button_Read.

* Description : 读取DFU按键是否按下

* Input : None.

* Output : None.

* Return : 返回0:按键按下;1:按键没有按下

*******************************************************************************/

uint8_t DFU_Button_Read (void)

{

return GPIO_ReadInputDataBit(DFU_ENTER, DFU_ENTER_PIN);

}


usb_desc.c这个文件自然要修改的,USB的功能属性等全在这里定义。首先必须关注下设备描述度符,这里有一点需要强调,就是厂商ID域的值必须为0483,否则电脑不识别USB,产品ID可以自定义。

/* USB标准设备描述符*/

uint8_t DFU_DeviceDescriptor[DFU_SIZ_DEVICE_DESC] =

{

0x12, /*bLength:长度,设备描述符的长度为18字节*/

USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType:类型,设备描述符的编号是0x01*/

0x00, /*bcdUSB:所使用的USB版本为2.0*/

0x02,

0x00, /*bDeviceClass:设备所使用的类代码*/

0x00, /*bDeviceSubClass:设备所使用的子类代码*/

0x00, /*bDeviceProtocol:设备所使用的协议*/

0x40, /*bMaxPacketSize:最大包长度为64字节*/

0x83, /*idVendor:厂商ID为0x1234*/

0x04,

0x11, /*idProduct:产品ID为0x1010*/

0xDF,

0x00, /*bcdDevice:设备的版本号为2.00*/

0x02,

1, /*iManufacturer:厂商字符串的索引*/

2, /*iProduct:产品字符串的索引*/

3, /*iSerialNumber:设备的序列号字符串索引*/

0x01 /*bNumConfiguration:设备有1种配置*/

}; /* DFU设备描述符 */


接下去是配置描述符集合,配置描述符不需要修改。但之后的接口描述符的bNumEndpoints域(该接口所使用的端点数)需要设置成0,因为USB DFU值需要端点0,不不需要其他的端点;接口描述符的bInterfaceClass(该接口所使用的类)域的值为0xFE,表示使用DFU类接口;接口描述符的bInterfaceSubClass(该接口所用的子类)设置成0x01,表示boot用途;接口描述符的nInterfaceProtocol设置成0x2,即DFU模式;最后还要设置接口字符串描述符的索引值为4。接下去是DFU功能描述符,这里设置bmAttribute域USB的属性为0x0B(具体意义看下面代码);DetachTimeOut(超时时间)设置成0XFF,表示超时时间为255ms;接下去设置TransferSize:(传输的长度)为0x400,注意这里是用两字节小端模式表示。

/* USB配置描述符集合(配置、接口、端点、类、厂商)(Configuration, Interface, Endpoint, Class, Vendor */

uint8_t DFU_ConfigDescriptor[DFU_SIZ_CONFIG_DESC] =

{

0x09, /*bLength:长度,设备字符串的长度为9字节*/

USB_CONFIGURATION_DESCRIPTOR_TYPE, /*bDescriptorType:类型,配置描述符的类型编号为0x2*/

DFU_SIZ_CONFIG_DESC, /*wTotalLength:配置描述符的总长度为41字节*/

0x00,

0x01, /*bNumInterfaces:配置所支持的接口数量1个*/

0x01, /*bConfigurationValue:该配置的值*/

0x00, /*iConfiguration:该配置的字符串的索引值,该值为0表示没有字符串*/

0xC0, /* bmAttributes:设备的一些特性,0xc0表示自供电,不支持远程唤醒

D7:保留必须为1,D6:是否自供电,D5:是否支持远程唤醒,D4~D0:保留设置为0*/

0x32, /*从总线上获得的最大电流为100mA */

// 0x96, /*MaxPower:设备需要从总线上获取多少电流,单位为2mA,0x96表示300mA*/



/****** Descriptor of DFU interface 0 Alternate setting 0***********/

0x09, /*bLength:长度,接口描述符的长度为9字节 */

USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType:接口描述符的类型为0x4 */

0x00, /*bInterfaceNumber:该接口的编号*/

0x00, /*bAlternateSetting:该接口的备用编号 */

0x00, /*bNumEndpoints:该接口所使用的端点数*/

0xFE, /*bInterfaceClass该接口所使用的类为 DFU*/

0x01, /*bInterfaceSubClass:该接口所用的子类 1=BOOT, 0=no boot */

0x02, /*nInterfaceProtocol :DFU模式*/


4, /* iInterface:接口字符串描述符的索引 */


/******************** DFU功能描述符********************/

0x09, /*blength:DFU描述符的长度为9字节*/

0x21, /*功能描述符的类型为0x21*/

0x0B, /*bmAttribute


bitCanDnload = 1 (bit 0)下载性能

bitCanUpload = 1 (bit 1)上传性能

bitManifestationTolerant = 0 (bit 2)设备在心事阶段后是否可通过USB通讯

bitWillDetach = 1 (bit 3)接收到DFU_DETACH命令时会进行总线detach-attac

Reserved (bit4-6)保留

bitAcceleratedST = 0 (bit 7) 该为置1,设备将会上传速度增加到4096字节/命令*/

0xFF, /*DetachTimeOut:超时时间 255 ms*/

0x00,

wTransferSizeB0,

wTransferSizeB1, /* TransferSize:传输的长度为1024 Byte*/

0x1A, /* bcdDFUVersion:DFU协议版本*/

0x01

};


接下去的语言字符串描述符、厂商字符串描述符、产品字符串描述符、序列号字符串描述符都不详细介绍了。

/* 语言ID描述符 */

uint8_t DFU_StringLangId[DFU_SIZ_STRING_LANGID] =

{

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在嵌入式开发中,STM32的时钟系统因其灵活性和复杂性成为开发者关注的焦点。然而,看似简单的时钟配置背后,隐藏着诸多易被忽视的陷阱,轻则导致系统不稳定,重则引发硬件损坏。本文从时钟源选择、PLL配置、总线时钟分配等关键环...

关键字: STM32 时钟系统

在嵌入式系统开发中,STM32系列微控制器的内部温度传感器因其低成本、高集成度特性,广泛应用于设备自检、环境监测等场景。然而,受芯片工艺差异和电源噪声影响,其原始数据存在±1.5℃的固有误差。本文从硬件配置、校准算法、软...

关键字: STM32 温度传感器

在能源效率与智能化需求双重驱动下,AC-DC转换器的数字控制技术正经历从传统模拟方案向全数字架构的深刻变革。基于STM32微控制器的PFM(脉冲频率调制)+PWM(脉冲宽度调制)混合调制策略,结合动态电压调整(Dynam...

关键字: AC-DC STM32

当前智能家居产品需求不断增长 ,在这一背景下 ,对现有浇花装置缺陷进行了改进 ,设计出基于STM32单片机的全 自动家用浇花机器人。该设计主要由机械结构和控制系统构成 ,机械结构通过麦克纳姆轮底盘与喷洒装置的结合实现机器...

关键字: STM32 麦克纳姆轮 安全可靠 通过性强

用c++编程似乎是让你的Arduino项目起步的障碍吗?您想要一种更直观的微控制器编程方式吗?那你需要了解一下Visuino!这个图形化编程平台将复杂电子项目的创建变成了拖动和连接块的简单任务。在本文中,我们将带您完成使...

关键字: Visuino Arduino ESP32 STM32

基于STM32与LoRa技术的无线传感网络凭借其低功耗、广覆盖、抗干扰等特性,成为环境监测、工业自动化等场景的核心解决方案。然而,如何在复杂电磁环境中实现高效休眠调度与动态信道优化,成为提升网络能效与可靠性的关键挑战。本...

关键字: STM32 LoRa

在实时控制系统、高速通信协议处理及高精度数据采集等对时间敏感的应用场景中,中断响应延迟的优化直接决定了系统的可靠性与性能上限。STM32系列微控制器凭借其灵活的嵌套向量中断控制器(NVIC)、多通道直接内存访问(DMA)...

关键字: STM32 DMA

数字电源技术向高功率密度、高效率与高动态响应方向加速演进,STM32微控制器凭借其基于DSP库的算法加速能力与对LLC谐振变换器的精准控制架构,成为优化电源动态性能的核心平台。相较于传统模拟控制或通用型数字控制器,STM...

关键字: STM32 数字电源

STM32微控制器凭借其针对电机控制场景的深度优化,成为高精度、高可靠性驱动系统的核心选择。相较于通用型MCU,STM32在电机控制领域的核心优势集中体现在FOC(磁场定向控制)算法的硬件加速引擎与PWM死区时间的动态补...

关键字: STM32 电机控制

无线充电技术加速渗透消费电子与汽车电子领域,基于Qi协议的无线充电发射端开发成为智能设备能量补给的核心课题。传统模拟控制方案存在响应滞后、参数调整困难等问题,而基于STM32的数字PID控制结合FOD(Foreign O...

关键字: STM32 无线充电
关闭