STM32 usb_mem.c和usb_sil.c文件的分析

发布者:SerendipitySoul最新更新时间:2016-10-10 来源: eefocus关键字:STM32  usb_mem.c  usb_sil.c文件 手机看文章 扫描二维码
随时随地手机看文章
这两个c文件都还算是很简单的,先讲讲usb_men.c这个文件。从文件名就能知道跟内存有关,这个文件主要定义了两个函数,一个读双缓冲区PMA的数据PMAToUserBufferCopy(),另一个是写数据到双缓冲区PMA,UserToPMABufferCopy。如果,当你的usb设备接收到了数据,当然数据存放在PMA中了,我们要读出数据就要用到PMAToUserBufferCopy()函数了,如果我们想要发送数据给usb主机,就要将你要发送的数据拷贝到PMA缓冲区中了,这样才能发送出去,原理跟串口类似。

/******************************************************************************* * Function Name : UserToPMABufferCopy * Description : 从用于内存区拷贝数据到PMA(数据包内存区) * Input : pbUsrBuf:指向用户的内存区 * wPMABufAddr:要拷贝到PMA的wPMABufAddr地址处 * wNBytes: 要拷贝的数据长度(单位:字) * Output : None. * Return : None . *******************************************************************************/ void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) { uint32_t n = (wNBytes + 1) >> 1; //n = (wNBytes + 1) / 2,表示多少字 uint32_t i, temp1, temp2; uint16_t *pdwVal; pdwVal = (uint16_t *)(wPMABufAddr * 2 + PMAAddr); //pdwVal存放要将数据存放的地址 for (i = n; i != 0; i--) //开始考被数据 { temp1 = (uint16_t) * pbUsrBuf; pbUsrBuf++; temp2 = temp1 | (uint16_t) * pbUsrBuf << 8; //整合2个16bit数据 *pdwVal++ = temp2; //把整合的数据拷贝PMA内 pdwVal++; //目的指针指向下一个地址 pbUsrBuf++; //源指针指向下一地址 } } /******************************************************************************* * Function Name : PMAToUserBufferCopy * Description : Copy a buffer from user memory area to packet memory area (PMA) * Input : pbUsrBuf指向用户的内存区 * wPMABufAddr PAM的地址 * wNBytes要拷贝的字节数 * Output : None. * Return : None. *******************************************************************************/ void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) { uint32_t n = (wNBytes + 1) >> 1; //n = (wNBytes + 1) / 2,表示多少字 uint32_t i; uint32_t *pdwVal; pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr); //从PAM区中去读1字数据 for (i = n; i != 0; i--) { *(uint16_t*)pbUsrBuf++ = *pdwVal++; //拷贝用户的内存区中 pbUsrBuf++; } }

 
接下去是usb_sil.c文件,这个文件主要是简单接口层的初始化,和端点的读写操作函数。总共有3个函数:USB_SIL_Init();USB_SIL_Write();USB_SIL_Read()。
USB_SIL_Init()函数初始化USB设备的IP和端点。该函数在usb_prop.c的CustomHID_init()中被调用,总之,就是初始化了。

/*******************************************************************************
* Function Name : USB_SIL_Init
* Description : 初始化USB设备IP和端点
* Input : None.
* Output : None.
* Return : Status.
*******************************************************************************/
uint32_t USB_SIL_Init(void)
{
#ifndef STM32F10X_CL

/* USB interrupts initialization */
/* clear pending interrupts */
_SetISTR(0); //禁止所有的中断
wInterrupt_Mask = IMR_MSK;
/* set interrupts mask */
_SetCNTR(wInterrupt_Mask); //使能一些中断

#else

/* Perform OTG Device initialization procedure (including EP0 init) */
OTG_DEV_Init(); //执行初始化程序OTG设备(包括EP0初始化)

#endif /* STM32F10X_CL */

return 0;
}

 
还有的就是两个端点读写数据函数了,端点写函数USB_SIL_Write()共有三个参数:uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize,所以写调用写函数时,要指明端点号、要写数据地址,和要写的数据长度。读函数USB_SIL_Read()只有两个参数:端点号、数要保存的据区地址。

/*******************************************************************************
* Function Name : USB_SIL_Write
* Description : 往选中的端点中写入数据
* Input : bEpAddr:非控制端点的地址
* pBufferPointer:指向要写入端点的缓冲数据
* wBufferSize:要写入的数据长度(单位:字节)
* Output : None.
* Return : Status.
*******************************************************************************/
uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize)
{
#ifndef STM32F10X_CL

UserToPMABufferCopy(pBufferPointer, GetEPTxAddr(bEpAddr & 0x7F), wBufferSize);//把用户数据拷贝到PMA中

SetEPTxCount((bEpAddr & 0x7F), wBufferSize); //更新数据长度的控制寄存器

#else

PCD_EP_Write (bEpAddr, pBufferPointer, wBufferSize); //使用使用PCD接口层函数来写入选择的端点

#endif /* STM32F10X_CL */

return 0;
}

/*******************************************************************************
* Function Name : USB_SIL_Read
* Description : 从选中的端点中读出数据
* Input : bEpAddr:非控制端点的地址
* pBufferPointer:指向要保存的数据区地址
* Output : None.
* Return : 返回读出来的数据长度(单位:字节)
*******************************************************************************/
uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer)
{
uint32_t DataLength = 0;

#ifndef STM32F10X_CL

DataLength = GetEPRxCount(bEpAddr & 0x7F); //从选中的端点中获取接收的数据长度

PMAToUserBufferCopy(pBufferPointer, GetEPRxAddr(bEpAddr & 0x7F), DataLength);//从PMA拷贝数据到用户区

#else

USB_OTG_EP *ep;

ep = PCD_GetOutEP(bEpAddr); //获取选中端点的结构体指针

DataLength = ep->xfer_len; //获取接收到的数据长度

PCD_EP_Read (bEpAddr, pBufferPointer, DataLength); //使用PCD接口层函数读取选中的端口

#endif /* STM32F10X_CL */

return DataLength; //返回接收到的数据长度
}

 

关键字:STM32  usb_mem.c  usb_sil.c文件 引用地址:STM32 usb_mem.c和usb_sil.c文件的分析

上一篇:STM32中断优先级理解及先占优先级和从优先级
下一篇:STM32升级文件的制作

推荐阅读最新更新时间:2024-03-16 15:14

STM32—RCC时钟
前言: 最近在调试STM32L152芯片,本文总结下STM32L152的RCC时钟配置方法。 硬件平台:STM32L152 软件平台:keil v5+cubeMX 函数库:HAL库 内容: RCC:Reset and Clock Control,复位与时钟控制系统。系统复位有三种:系统复位、电源复位、RTC domain复位。复位内容本文暂不详解,本文重点详解Clock Control部分。下面看下STM32L152芯片的时钟框图和cubeMX软件中的时钟框图。 如上图所示,在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①HSI:High Speed Inte
[单片机]
<font color='red'>STM32</font>—RCC时钟
STM32文件systemInit 晶振更改默认晶振8M到12M方法
由于stm32的库默认是外部晶振8M的情况下实现的,所以配置串口波特率的时候也是按8M,包括主频。 如果采用外部晶振12M,配置时钟为72MHZ 。 1)PLL倍频这样改: 8M: RCC- CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);//8*9=72 12M: RCC- CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);//12*6=72 库函数:void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul) 例:RC
[单片机]
STM32大行当道,Microchip却集中发布60余款8位MCU
为满足对 8 位微控制器 (MCU) 的需求,Microchip 一下子推出了 5 个新系列、超过 60 款器件,涵盖PIC 和 AVR。 嵌入式设计正成为电子产品越来越流行和重要的元素。就目前而言,您可以在市场上的绝大多数电子和消费设备中找到 MCU。 支持种类繁多的嵌入式设备需要一个多功能的市场,提供满足大多数应用需求的产品。为了满足这一需求,Microchip 最近发布了五个全新的 8 位 PIC 和 AVR MCU 系列,总计超过 60 款器件。 在本文中,我们将介绍 8 位 MCU,它们为何如此重要,以及 Microchip 的五个新系列带来了什么。 单片机位宽 由于 MCU 可用于许多不同的应用,因
[单片机]
<font color='red'>STM32</font>大行当道,Microchip却集中发布60余款8位MCU
使用STM32CubeMx配置STM32输入捕获功能
输入捕获原理 在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中。当发生捕获事件时,相应的CCxIF标志(TIMx_SR寄存器)被置1,如果开放了中断或者DMA操作,则将产生中断或者DMA请求。如果发生捕获事件时CCxIF标志已经为高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置1。写CCxIF=0可清除CCxIF,或读取存储在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF。 摘自《STM32参考手册中文》 简单解释:定时器一直在计数,如果检测到设置的极性边沿,会把当前的计数值存下来,并触发中断; 比如,
[单片机]
使用STM32CubeMx配置<font color='red'>STM32</font>输入捕获功能
STM32学习笔记 — 之GPIO端口篇
最近刚开始学习STM32,所以从最基本的GPIO开始学起;首先看看STM32的datasheet上对GPIO口的简单介绍: 每个GPI/O 端口有两个32 位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个32 位置位/复位寄存器(GPIOx_BSRR),一个16 位复位寄存器(GPIOx_BRR)和一个32 位锁定寄存器(GPIOx_LCKR)。 GPIO 端口的每个位可以由软件分别配置成多种模式。每个I/O 端口位可以自由编程,然而I/0 端口寄存器必须按32 位字被访问(不允许半字或字节访问)。GPIOx_BSRR 和GPIOx_BRR 寄存器
[单片机]
UCOS2_STM32移植详细过程 (一)
Ⅰ、概述 该文写针对初学µC/OS的朋友,基于以下平台来一步一步移植µC/OS嵌入式操作系统。UCOS移植相关平台: 系统平台:µC/OS-II(最新V2.92版) 硬件平台:STM32F1(适合F1所以系列) 开发平台:Keil(MDK-ARM) V5 1.为什么是µC/OS-II? 原因在于µC/OS-II是一个比较成熟、稳定的系统,与µC/OS-III比较有些机制相对简单很多。当你掌握了µC/OS-II,µC/OS-III很容易就理解了。 2.为什么是STM32F1? 硬件平台是在移植的过程中比较重要的一点,也就是说,不同的硬件平台,移植过程中的端口(uCOS-IIPorts下源文件)存在一定的差异性。 但是同一内核
[单片机]
UCOS2_STM32移植详细过程 (一)
STM32中的结构体是如何组织同类寄存器的
#define PERIPH_BASE ((u32)0x40000000)//端口地址 ?xml:namespace prefix = o ns = urn:schemas-microsoft-com:office:office / #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)//端口地址 #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)//端口地址 #define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)// typedef unsigned long u32; typedef volatil
[单片机]
单片机STM32在开发中常用库函数详解
  1.GPIO初始化函数   用法:   voidGPIO_Configuration(void)   {   GPIO_InitTypeDefGPIO_InitStructure;//GPIO状态恢复默认参数   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_标号|GPIO_Pin_标号;   //管脚位置定义,标号可以是NONE、ALL、0至15。   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//最高输出速度为50MHz   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出   G
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
更多每日新闻
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved