本帖最后由 shiyongzhu 于 2015-10-13 22:45 编辑
拿到F446有段时间了,这段时间主要对F446开发板的USB功能进行了一下学习。
F446开发板的功能还是比较强大的,其既有全速的USB还有高速的USB接口,而且都支持OTG功能,可以说完全满足的开发者的各种的不同需求。因此本人打算使用F446开发板做个鼠标,也算是抛砖引玉了。
当前进行STM32 MCU开发,有两种库工选择,即标准外设库和hal库(cubemx生成),hal库开发方法是ST公司极力推广的开发方法,因此本帖采用这种开发方法。
1、 使用cubemx生成代码 (1)打开cubemx的更新软件STM32CubeUpdater,检查是否有F446开发板的固件库(需要1.8.0版本)。如图没有,则进行更新。 (2)打开cubemx程序,选择New Project建立新的工程。再Board Selector中选择Nucleo类型的 F446RE开发板。 点击OK则得到工程模板,进入Pinout界面进行引脚配置,开启USB_OTG_FS外设为Device模式,即将开发板作为外设设备,开启该外设后右侧封装图中PA11、PA12将会进行示意表示。为了生成USB设备基本的代码还需要配置MiddleWares中的USB_DEVICE IP为Human Interface Device Class(HID)。 然后进行时钟配置,注意当使用内部时钟作为锁相环的输入时,无法使系统时钟达到最大的180MHz,经测试100MHz可以达到,因此按照100MHz配置,USB外设采用专用的48MHz时钟。 2、 代码修改 (1)根据以上的配置最终可以生成需要的代码模板,该代码实现了USB设备的枚举过程。在主程序中加入led.c、delay.c代码,主程序代码如下: /* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "usb_device.h"
/* USER CODE BEGIN Includes */
#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid.h"
#include "delay.h"
#include "led.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
//¼ÆÊýÆ÷
volatile uint32_t count_millsecond; //ϵͳ¼ÆÊýÆ÷
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void HAL_SYSTICK_Callback(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t led_time;
uint8_t HID_Buffer[4]={0x00,0x0a,0x22,0x00};
/* 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();
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if((Check_Delay(led_time))) //µç»úÔËÐÐʱLEDÉÁ˸
{
led_time = Set_Delay(250);
Led_Change();
USBD_HID_SendReport(&hUsbDeviceFS, HID_Buffer, 4);
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
// RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 100;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 8;
RCC_OscInitStruct.PLL.PLLR = 2;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
HAL_PWREx_ActivateOverDrive();
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CK48;
PeriphClkInitStruct.PLLSAI.PLLSAIM = 16;
PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2;
PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4;
PeriphClkInitStruct.PLLSAIDivQ = 1;
PeriphClkInitStruct.Clk48ClockSelection = RCC_CK48CLKSOURCE_PLLSAIP;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__GPIOC_CLK_ENABLE();
__GPIOH_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PA2 PA3 */
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PA5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/*
* º¯ÊýÃû³Æ: HAL_SYSTICK_Callback();
* ¹¦ÄÜÃèÊö: ϵͳ¼ÆʱÆ÷Öжϴ¦Àíº¯Êý
* ÊäÈë²ÎÊý: void
* ·µ»Ø²ÎÊý: ÎÞ
*/
void HAL_SYSTICK_Callback()
{
count_millsecond++;
}
/* USER CODE END 4 */
(2)为了让顺利的运行,还需要根据USB协议规定,全速设备须在数据D+上上拉1.5K电阻。 由于源程序代码有8MB多,没法直接上传,有需要代码的可以私信我。
|