历史上的今天
返回首页

历史上的今天

今天是:2025年03月11日(星期二)

正在发生

2019年03月11日 | STM32 USB学习笔记5

2019-03-11 来源:eefocus

主机环境:Windows 7 SP1


开发环境:MDK5.14


目标板:STM32F103C8T6


开发库:STM32F1Cube库和STM32_USB_Device_Library


承接前文,对于上层应用而言只剩下CDC类接口文件即usbd_cdc_interface,该文件主要为实现CDC类接口所用到的物理资源以及逻辑资源,需要参考通信设备通用串行总线类定义版本1.2以及PSTN设备通用串行总线通信类子类规范版本1.2,这两个文档都可以在USB组织官网上下载得到,首先看下usbd_cdc_interface.h文件,如下:



/* Define to prevent recursive inclusion -------------------------------------*/

#ifndef __USBD_CDC_IF_H

#define __USBD_CDC_IF_H

 

/* Includes ------------------------------------------------------------------*/

#include "usbd_cdc.h"

 

/* Exported types ------------------------------------------------------------*/

/* Exported constants --------------------------------------------------------*/

/* User can use this section to tailor USARTx/UARTx instance used and associated 

   resources */

/* Definition for USARTx clock resources */

#define USARTx                           USART1

#define USARTx_CLK_ENABLE()              __HAL_RCC_USART1_CLK_ENABLE();

#define DMAx_CLK_ENABLE()                __HAL_RCC_DMA1_CLK_ENABLE()

#define USARTx_RX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()

#define USARTx_TX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE() 

 

#define USARTx_FORCE_RESET()             __HAL_RCC_USART1_FORCE_RESET()

#define USARTx_RELEASE_RESET()           __HAL_RCC_USART1_RELEASE_RESET()

 

/* Definition for USARTx Pins */

#define USARTx_TX_PIN                    GPIO_PIN_9

#define USARTx_TX_GPIO_PORT              GPIOA  

#define USARTx_RX_PIN                    GPIO_PIN_10

#define USARTx_RX_GPIO_PORT              GPIOA 

 

/* Definition for USARTx's NVIC: used for receiving data over Rx pin */

#define USARTx_IRQn                      USART1_IRQn

#define USARTx_IRQHandler                USART1_IRQHandler

 

/* Definition for USARTx's DMA: used for transmitting data over Tx pin */

#define USARTx_TX_DMA_STREAM             DMA1_Channel4

#define USARTx_RX_DMA_STREAM             DMA1_Channel5

 

/* Definition for USARTx's NVIC */

#define USARTx_DMA_TX_IRQn               DMA1_Channel4_IRQn

#define USARTx_DMA_RX_IRQn               DMA1_Channel5_IRQn

#define USARTx_DMA_TX_IRQHandler         DMA1_Channel4_IRQHandler

#define USARTx_DMA_RX_IRQHandler         DMA1_Channel5_IRQHandler

 

/* Definition for TIMx clock resources */

#define TIMx                             TIM3

#define TIMx_CLK_ENABLE                  __HAL_RCC_TIM3_CLK_ENABLE

#define TIMx_FORCE_RESET()               __HAL_RCC_USART1_FORCE_RESET()

#define TIMx_RELEASE_RESET()             __HAL_RCC_USART1_RELEASE_RESET()

 

/* Definition for TIMx's NVIC */

#define TIMx_IRQn                        TIM3_IRQn

#define TIMx_IRQHandler                  TIM3_IRQHandler

 

/* Periodically, the state of the buffer "UserTxBuffer" is checked.

   The period depends on CDC_POLLING_INTERVAL */

#define CDC_POLLING_INTERVAL             5 /* in ms. The max is 65 and the min is 1 */

 

extern USBD_CDC_ItfTypeDef  USBD_CDC_fops;

 

/* Exported macro ------------------------------------------------------------*/

/* Exported functions ------------------------------------------------------- */

#endif /* __USBD_CDC_IF_H */

 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

这其中主要是一些物理资源的定义,需要用到一个串口资源(且使用DMA方式发送数据),一个定时器资源(定时读取从串口接收到的数据并发往USB接口)。这里虽然列出了两个DMA通道,但在实现中只用到了TX的DMA发送一个通道,文件末尾有一个CDC类接口数据结构USBD_CDC_ItfTypeDef,如下:



typedef struct _USBD_CDC_Itf

{

  int8_t (* Init)          (void);

  int8_t (* DeInit)        (void);

  int8_t (* Control)       (uint8_t, uint8_t * , uint16_t);   

  int8_t (* Receive)       (uint8_t *, uint32_t *);  

 

}USBD_CDC_ItfTypeDef;

有关该结构的说明可以在USB器件库文档中找到,如下:

由上可以看出这里只有OUT传输而没有IN传输,VCP模型很简单就只有简单的收发数据以及一些属性的修改等,因此这里的CDC接口接口内容不多。下面查看一下usbd_cdc_interface.c文件,其内容是CDC类物理以及逻辑接口的具体实现。文件开头申请了两块缓冲区用于数据的收发,如下:



#define APP_RX_DATA_SIZE  2048

#define APP_TX_DATA_SIZE  2048

 

uint8_t UserRxBuffer[APP_RX_DATA_SIZE];/* Received Data over USB are stored in this buffer */

uint8_t UserTxBuffer[APP_TX_DATA_SIZE];/* Received Data over UART (CDC interface) are stored in this buffer */

uint32_t BuffLength;

uint32_t UserTxBufPtrIn = 0;/* Increment this pointer or roll it back to

                               start address when data are received over USART */

uint32_t UserTxBufPtrOut = 0; /* Increment this pointer or roll it back to

                                 start address when data are sent over USB */ 


两块缓冲区是循环使用,其中的RX、TX是针对USB模块而言,各2K字节。在文件头部还有一个新的数据结构USBD_CDC_LineCodingTypeDef,该结构很简单,如下:


typedef struct

{

  uint32_t bitrate;

  uint8_t  format;

  uint8_t  paritytype;

  uint8_t  datatype;

}USBD_CDC_LineCodingTypeDef;

对应着串口的各个属性,有关LineCoding的相关信息可以在PSTN120文档中找到,如下:

并且罗列了各个属性的取值范围,由此可以看出默认状态下串口属性为:115200波特率、1个停止位,8个数据位,无校验。接着查看CDC类接口的实现函数,首先是硬件资源的初始化操作:



USBD_CDC_ItfTypeDef USBD_CDC_fops = 

{

  CDC_Itf_Init,

  CDC_Itf_DeInit,

  CDC_Itf_Control,

  CDC_Itf_Receive

};

 

/* Private functions ---------------------------------------------------------*/

 

/**

  * @brief  CDC_Itf_Init

  *         Initializes the CDC media low layer

  * @param  None

  * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL

  */

static int8_t CDC_Itf_Init(void)

{

  /*##-1- Configure the UART peripheral ######################################*/

  /* Put the USART peripheral in the Asynchronous mode (UART Mode) */

  /* USART configured as follows:

      - Word Length = 8 Bits

      - Stop Bit    = One Stop bit

      - Parity      = No parity

      - BaudRate    = 115200 baud

      - Hardware flow control disabled (RTS and CTS signals) */

  UartHandle.Instance        = USARTx;

  UartHandle.Init.BaudRate   = 115200;

  UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

  UartHandle.Init.StopBits   = UART_STOPBITS_1;

  UartHandle.Init.Parity     = UART_PARITY_NONE;

  UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;

  UartHandle.Init.Mode       = UART_MODE_TX_RX;

  

  if(HAL_UART_Init(&UartHandle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler();

  }

  

  /*##-2- Put UART peripheral in IT reception process ########################*/

  /* Any data received will be stored in "UserTxBuffer" buffer  */

  if(HAL_UART_Receive_IT(&UartHandle, (uint8_t *)UserTxBuffer, 1) != HAL_OK)

  {

    /* Transfer error in reception process */

    Error_Handler();

  }

  

  /*##-3- Configure the TIM Base generation  #################################*/

  TIM_Config();

  

  /*##-4- Start the TIM Base generation in interrupt mode ####################*/

  /* Start Channel1 */

  if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)

  {

    /* Starting Error */

    Error_Handler();

  }

  

  /*##-5- Set Application Buffers ############################################*/

  USBD_CDC_SetTxBuffer(&USBD_Device, UserTxBuffer, 0);

  USBD_CDC_SetRxBuffer(&USBD_Device, UserRxBuffer);

  

  return (USBD_OK);

}

 

/**

  * @brief  CDC_Itf_DeInit

  *         DeInitializes the CDC media low layer

  * @param  None

  * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL

  */

static int8_t CDC_Itf_DeInit(void)

{

  /* DeInitialize the UART peripheral */

  if(HAL_UART_DeInit(&UartHandle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler();

  }

  return (USBD_OK);

}

这里主要是串口资源的初始化,按照LineCoding中默认的属性初始化串口资源,并进一步调用之前stm32f1xx_hal_msp.c文件中的HAL_UART_MspInit(),HAL_UART_MspDeInit()方法。此外开启串口接收中断接收字节数据,同时初始化定时器资源,如下:


/**

  * @brief  TIM_Config: Configure TIMx timer

  * @param  None.

  * @retval None.

  */

static void TIM_Config(void)

{  

  /* Set TIMx instance */

  TimHandle.Instance = TIMx;

  

  /* Initialize TIM3 peripheral as follows:

       + Period = 10000 - 1

       + Prescaler = ((SystemCoreClock/2)/10000) - 1

       + ClockDivision = 0

       + Counter direction = Up

  */

  TimHandle.Init.Period = (CDC_POLLING_INTERVAL*1000) - 1;

  TimHandle.Init.Prescaler = 84-1;

  TimHandle.Init.ClockDivision = 0;

  TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;

  if(HAL_TIM_Base_Init(&TimHandle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler();

  }

}

这个没什么说的,在CDC_Itf_Init()函数的末尾有两个设置缓冲区的函数,USBD_CDC_SetTxBuffer()、USBD_CDC_SetRxBuffer(),这两个函数在USB器件库的类文件中,后面再分析,这里知道其作用即可。下面类分析CDC_Itf_Control()函数,该函数管理CDC类请求,如下:


/**

  * @brief  CDC_Itf_Control

  *         Manage the CDC class requests

  * @param  Cmd: Command code            

  * @param  Buf: Buffer containing command data (request parameters)

  * @param  Len: Number of data to be sent (in bytes)

  * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL

  */

static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length)

  switch (cmd)

  {

  case CDC_SEND_ENCAPSULATED_COMMAND:

    /* Add your code here */

    break;

 

  case CDC_GET_ENCAPSULATED_RESPONSE:

    /* Add your code here */

    break;

 

  case CDC_SET_COMM_FEATURE:

    /* Add your code here */

    break;

 

  case CDC_GET_COMM_FEATURE:

    /* Add your code here */

    break;

 

  case CDC_CLEAR_COMM_FEATURE:

    /* Add your code here */

    break;

 

  case CDC_SET_LINE_CODING:

    LineCoding.bitrate    = (uint32_t)(pbuf[0] | (pbuf[1] << 8) |\

                            (pbuf[2] << 16) | (pbuf[3] << 24));

    LineCoding.format     = pbuf[4];

    LineCoding.paritytype = pbuf[5];

    LineCoding.datatype   = pbuf[6];

    

    /* Set the new configuration */

    ComPort_Config();

    break;

 

  case CDC_GET_LINE_CODING:

    pbuf[0] = (uint8_t)(LineCoding.bitrate);

    pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8);

    pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16);

    pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24);

    pbuf[4] = LineCoding.format;

    pbuf[5] = LineCoding.paritytype;

    pbuf[6] = LineCoding.datatype;     

    

    /* Add your code here */

    break;

 

  case CDC_SET_CONTROL_LINE_STATE:

    /* Add your code here */

    break;

 

  case CDC_SEND_BREAK:

     /* Add your code here */

    break;    

    

  default:

    break;

  }

  

  return (USBD_OK);

}

USB请求在USB器件库文档中分为三类:标准请求、特定类请求、特定厂商请求。其中标准请求由默认的控制端点0接收处理,另外两类请求由回调函数传递到特定类代码进行处理,这里的CDC_Itf_Control()函数即为回调函数最终实现者,其处理CDC类的特定请求,这些请求可以在PSTN120协议文档以及CDC120协议文档中找到,如下:


在CDC_Itf_Control()可以处理以上请求,但在具体实现上只处理了个别请求,即SET_LINE_CODING和GET_LINE_CODING,代码中各个请求的定义如下:



/*---------------------------------------------------------------------*/

/*  CDC definitions                                                    */

/*---------------------------------------------------------------------*/

#define CDC_SEND_ENCAPSULATED_COMMAND               0x00

#define CDC_GET_ENCAPSULATED_RESPONSE               0x01

#define CDC_SET_COMM_FEATURE                        0x02

#define CDC_GET_COMM_FEATURE                        0x03

#define CDC_CLEAR_COMM_FEATURE                      0x04

#define CDC_SET_LINE_CODING                         0x20

#define CDC_GET_LINE_CODING                         0x21

#define CDC_SET_CONTROL_LINE_STATE                  0x22

#define CDC_SEND_BREAK                              0x23

可以看到各个请求的值与PSTN120协议文档中的值相一致,而CDC_SEND_ENCAPSULATED_COMMAND和CDC_SEND_ENCAPSULATED_RESPONSE的值没有在PSTN120协议文档中,其是在CDC120协议文档中定义的。当我们在PC端上的串口工具中修改串口通信的属性时就会触发CDC_SET_LINE_CODING请求,同时也可以通过CDC_GET_LINE_CODING请求来获取当前串口通信的属性值,在CDC_SET_LINE_CODING请求中通过ComPort_Config()函数类重新配置串口,如下:


/**

  * @brief  ComPort_Config

  *         Configure the COM Port with the parameters received from host.

  * @param  None.

  * @retval None.

  * @note   When a configuration is not supported, a default value is used.

  */

static void ComPort_Config(void)

{

  if(HAL_UART_DeInit(&UartHandle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler();

  }

  

  /* set the Stop bit */

  switch (LineCoding.format)

  {

  case 0:

    UartHandle.Init.StopBits = UART_STOPBITS_1;

    break;

  case 2:

    UartHandle.Init.StopBits = UART_STOPBITS_2;

    break;

  default :

    UartHandle.Init.StopBits = UART_STOPBITS_1;

    break;

  }

  

  /* set the parity bit*/

  switch (LineCoding.paritytype)

  {

  case 0:

    UartHandle.Init.Parity = UART_PARITY_NONE;

    break;

  case 1:

    UartHandle.Init.Parity = UART_PARITY_ODD;

    break;

  case 2:

    UartHandle.Init.Parity = UART_PARITY_EVEN;

    break;

  default :

    UartHandle.Init.Parity = UART_PARITY_NONE;

    break;

  }

  

  /*set the data type : only 8bits and 9bits is supported */

  switch (LineCoding.datatype)

  {

  case 0x07:

    /* With this configuration a parity (Even or Odd) must be set */

    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

    break;

  case 0x08:

    if(UartHandle.Init.Parity == UART_PARITY_NONE)

    {

      UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

    }

    else 

    {

      UartHandle.Init.WordLength = UART_WORDLENGTH_9B;

    }

    

    break;

  default :

    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

    break;

  }

  

  UartHandle.Init.BaudRate = LineCoding.bitrate;

  UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;

  UartHandle.Init.Mode       = UART_MODE_TX_RX;

  

  if(HAL_UART_Init(&UartHandle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler();

  }

 

  /* Start reception: provide the buffer pointer with offset and the buffer size */

  HAL_UART_Receive_IT(&UartHandle, (uint8_t *)(UserTxBuffer + UserTxBufPtrIn), 1);

}

在ComPort_Config()函数的最后再次开启串口接收中断用于接收字节数据,在缓冲区后面追加。SetLineConding和GetLineCoding请求的数据格式如下:


这个要配合SETUP包的结构定义才方便理解,如SetLineCoding请求中bmRequestType值为00100001B对照SETUP包结构可知其为类请求且接收者是接口,wValue为0,wIndex为接口号,wLength为后面数据长度,针对Line Coding结构而言该值为7,wIndex的值在接收者为端点和接口时含义不同,如下:

对于此例而言我们使用的是后者,即低8位标记接口号。接着分析CDC_Itf_Receive()函数,如下:



/**

  * @brief  CDC_Itf_DataRx

  *         Data received over USB OUT endpoint are sent over CDC interface 

  *         through this function.

  * @param  Buf: Buffer of data to be transmitted

  * @param  Len: Number of data received (in bytes)

  * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL

  */

static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len)

{

  HAL_UART_Transmit_DMA(&UartHandle, Buf, *Len);

  return (USBD_OK);

}

该函数也很简单,将从USB接口收到的数据直接通过串口DMA方式发送出去,至此CDC类接口的回调函数分析完毕,还剩下几个中断回调函数,首先看下串口接收中断回调函数,如下:


/**

  * @brief  Rx Transfer completed callback

  * @param  huart: UART handle

  * @retval None

  */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

  /* Increment Index for buffer writing */

  UserTxBufPtrIn++;

  

  /* To avoid buffer overflow */

  if(UserTxBufPtrIn == APP_RX_DATA_SIZE)

  {

    UserTxBufPtrIn = 0;

  }

  

  /* Start another reception: provide the buffer pointer with offset and the buffer size */

  HAL_UART_Receive_IT(huart, (uint8_t *)(UserTxBuffer + UserTxBufPtrIn), 1);

}

该回调很简单循环使用USB发送缓冲区,当接收完一个字节后移动USB发送缓冲区下标立即开启下一个字节的接收。接着查看串口发送完成中断回调函数,虽然这里串口发送是使用DMA方式,但在Cube库中会开启三个中断回调函数:半传输完成、传输完成以及错误处理,其中传输完成的回调函数中会进一步调用串口发送完成的回调函数,同时,错误处理的回调函数也会进一步调用串口的错误回调函数,二者如下:


/**

  * @brief  Tx Transfer completed callback

  * @param  huart: UART handle

  * @retval None

  */

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)

{

  /* Initiate next USB packet transfer once UART completes transfer (transmitting data over Tx line) */

  USBD_CDC_ReceivePacket(&USBD_Device);

}

 

/**

  * @brief  UART error callbacks

  * @param  UartHandle: UART handle

  * @retval None

  */

void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)

{

  /* Transfer error occured in reception and/or transmission process */

  Error_Handler();

}

这里主要看下串口发送完成中断回调函数,其调用USBD_CDC_ReveivePacket()函数来开启下一个USB数据包的接收,该函数在后面再具体分析。现在就只剩下定时器回调函数了,前面已经分析如何把从USB接收到的数据通过串口发送出去,但从串口接收到的数据还没有通过USB发出,定时器的回调函数就是实现该过程的,如下:


/**

  * @brief  TIM period elapsed callback

  * @param  htim: TIM handle

  * @retval None

  */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

  uint32_t buffptr;

  uint32_t buffsize;

  

  if(UserTxBufPtrOut != UserTxBufPtrIn)

  {

    if(UserTxBufPtrOut > UserTxBufPtrIn) /* rollback */

    {

      buffsize = APP_RX_DATA_SIZE - UserTxBufPtrOut;

    }

    else 

    {

      buffsize = UserTxBufPtrIn - UserTxBufPtrOut;

    }

    

    buffptr = UserTxBufPtrOut;

    

    USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t*)&UserTxBuffer[buffptr], buffsize);

    

    if(USBD_CDC_TransmitPacket(&USBD_Device) == USBD_OK)

    {

      UserTxBufPtrOut += buffsize;

      if (UserTxBufPtrOut == APP_RX_DATA_SIZE)

      {

        UserTxBufPtrOut = 0;

      }

    }

  }

}

首先是判断UserTxBufPtrOut和UserTxBufPtrIn是否相等以便检测是否在串口中收到了数据,如果不想等则表明在串口中接收到了数据,就要将这些数据通过USB模块发送出去,二者不相等时就需要计算需要通过USB发送的字节数即buffsize的计算,Out比In大时表明缓冲区有循环,则先把末尾数据发送完毕,等下次定时器达到时再从头发送即可。计算完数据量后通过USBD_CDC_SetTxBuffer()函数来设置发送缓冲区及数据大小,通过USBD_CDC_TransmitPacket()函数来开启USB发送,并更新UserTxBufPtrOut数值。至此usbd_cdc_interface文件分析完毕,后面可以开始分析USB器件库了。


推荐阅读

史海拾趣

Belden Wire and Cable公司的发展小趣事

随着业务的不断扩展,Belden公司于1910年搬迁至芝加哥更大的区域,并在产品线上增加了橡胶绝缘电线。这一举措不仅扩大了公司的生产规模,也进一步丰富了产品种类,满足了市场的多样化需求。随后,百通工程师于1927年发明的软橡胶塞技术,进一步推动了公司的技术创新和业务拓展。

ELMOS公司的发展小趣事

ELMOS作为一家欧洲公司,在世界各地都设有研发和销售办事处。这种全球化的布局使得ELMOS能够更好地了解不同市场的需求,为客户提供更加贴近市场的产品和服务。同时,通过与全球各地的客户和合作伙伴的紧密合作,ELMOS不断拓展其国际市场份额,进一步提升了公司的国际影响力。

Good-Ark公司的发展小趣事
定期检查电路各部件的工作状态,及时更换损坏的元件,确保电路长期稳定运行。
Curtis Electromusic Specialties Inc公司的发展小趣事

在电子行业的激烈竞争中,CUI公司凭借其在材料科学领域的深厚积累,成功研发出了一种新型高性能碘化亚铜材料。这种材料不仅具有优异的导电性能,而且稳定性极高,能够在极端环境下保持稳定的性能。凭借这一技术创新,CUI公司的产品迅速获得了市场的认可,并在多个关键领域得到广泛应用,从而实现了公司的快速发展。

Celduc Relais公司的发展小趣事

Celduc Relais公司自创立之初,便以技术创新为核心驱动力。在公司的早期发展阶段,研发团队成功开发了一款具有颠覆性的继电器产品,该产品在性能、稳定性和寿命等方面均达到了行业领先水平。这一突破性的技术创新不仅为公司赢得了市场的广泛认可,也为后续的产品线扩展和技术升级奠定了坚实基础。

Daito Communication Apparatus Co Ltd公司的发展小趣事

自1948年成立以来,Daito公司一直致力于电子元器件的研发与生产。在公司的早期阶段,他们意识到保险丝在电子设备中的重要性,并决定投入大量资源进行研发。经过数年的努力,Daito公司成功开发出了高精度报警保险丝,这一创新产品凭借其卓越的性能和可靠性,迅速在市场上获得了认可。

高精度报警保险丝的成功并没有让Daito公司停止创新的步伐。他们不断对保险丝的失效原因与寿命进行预测和分析,通过全面质量管理,使产品质量得到了显著的提高。同时,Daito公司还将各系列保险丝的额定值多层次化,以满足不同客户的需求,扩大了顾客的选择余地。

问答坊 | AI 解惑

PCB设计技巧百问(1-10)

1、如何选择PCB板材? 选择PCB板材必须在满足设计需求和可量产性及成本中间取得平衡点。设计需求包含电气和 机构这两部分。通常在设计非常高速的PCB板子(大于GHz的频率)时这材质问题会比较重要。 例如,现在常用的FR-4材质,在几个GHz的频率时 ...…

查看全部问答>

USB CCID

最近在做usb,ccid部分的东西,每次在读入ccid descriptor的内容后电脑就会自动重启,很费解,有哪位朋友做过类似的东西希望能指点一下! 谢谢!…

查看全部问答>

如何判断USB HOST功能正常与否

调了好长时间的OTG的HOST功能. 现在有点眉目,但是如何判断HOST功能已经正常了? 现在U盘插上去后,灯闪了一下就灭了. 打印消息说, 已探测到外部设备插入,而且识别了设备的速度,然后就等待port的状态变化... 这种现象正常吗? 我 ...…

查看全部问答>

WINCE下驱动项目外包

现有两个WINCE下驱动项目外包: 1、S3C2416下驱动16C554多串口芯片的驱动程序 2、S3C2416的声音驱动(芯片的驱动代码有2442平台下的可以做参考) 有意者请加QQ嵌入式外包群:48348107 谢谢各位!…

查看全部问答>

串口传输的奇怪问题

Hi all 由于使用芯片的升级,公司使用的vxworks(5.4)的BSP包也随之升级,使用的是tornado2.02 现在目标板的bootrom烧进去,可以正常启动 可是不知道为什么,下载vxworks的映像文件的时候常常出错,提示 rpccore target server can\'t decode arg ...…

查看全部问答>

看到许多朋友抱怨LPC17xx的资料难找,发一套全套示例代码

这是一套基于LPC17XX各个模块的示例代码,开发环境是基于KEIL MDK的,我现在用LPC1756做开发,也是初次接触。 这套资料还比较齐全,给了我不少帮助,希望对你们有用。…

查看全部问答>

2011年竞赛题目分析

本帖最后由 paulhyde 于 2014-9-15 04:02 编辑 2011年的国赛题目已经出来了。我大致看了一下,今年的题目大致可以分为四类,比以前分的类要少。下面大致说一下个人的理解。 今年的题目大致可分为四类:电源类、控制类、放大类、仪器仪表类。其中 ...…

查看全部问答>

求个cc2530套件下载地址

求个cc2530套件下载地址,本人装了一个但说应用程序初始化(0xc0000135)失败,不知道怎么解决??求大侠指点,3q…

查看全部问答>

第二季铁电开发板名单出了吗?

如题,第二季的铁电名单怎么还没出啊? 我是第一期的,还在礼品还未收到,也不知是什么? 这效率是不是该提高点了。…

查看全部问答>

初学 lm3s316 i2c proteus 仿真

用最简单的轮询方式(用延时代替),代码如下: SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);   SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C); //G ...…

查看全部问答>