用户工具

站点工具


icore3_arm_hal_20

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
icore3_arm_hal_20 [2020/04/17 17:28]
fmj
icore3_arm_hal_20 [2022/03/18 15:08] (当前版本)
sean
行 2: 行 2:
 |技术支持电话|**0379-69926675-801** ​ ||| |技术支持电话|**0379-69926675-801** ​ |||
 |技术支持邮件|Gingko@vip.163.com ​ ||| |技术支持邮件|Gingko@vip.163.com ​ |||
-|技术论坛|http://​www.eeschool.org ​ ||| 
 ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
 |  V1.0  |  2020-04-17 ​ |  gingko ​ |  初次建立 ​ | |  V1.0  |  2020-04-17 ​ |  gingko ​ |  初次建立 ​ |
行 21: 行 20:
 {{ :​icore3:​icore3_cube_20_3.png?​direct | }} {{ :​icore3:​icore3_cube_20_3.png?​direct | }}
 4. 配置调试引脚 4. 配置调试引脚
-{{ :icore3:icore3_cube_19_4.png?direct | }}+{{ :icore3:icore3_cube_20_4.png?direct | }}
 5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output 5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output
 {{ :​icore3:​icore3_cube_20_5.png?​direct | }} {{ :​icore3:​icore3_cube_20_5.png?​direct | }}
行 66: 行 65:
  
 ==== 一、 实验目的与意义 ==== ==== 一、 实验目的与意义 ====
-  - 了解STM32 USB HOST结构 +  - 了解STM32 USB HOST结构 
-  - 了解STM32 USB HOST特征 +  - 了解STM32 USB HOST特征 
-  - 掌握STM32 HAL库中USBH_MSC的配置方法 +  - 掌握STM32 HAL库中USBH_MSC的配置方法 
-  - 掌握USBH_MSC 使用方法 +  - 掌握USBH_MSC 使用方法 
-  - 掌握Keil MDK集成开发环境使用方法+  - 掌握Keil MDK集成开发环境使用方法
  
 ==== 二、 实验设备及平台 ==== ==== 二、 实验设备及平台 ====
行 84: 行 83:
   * MSC是一种计算机和移动设备之间的传输协议,它允许一个通用串行总线(USB)设备来访问主机的计算设备,使两者之间进行文件传输。   * MSC是一种计算机和移动设备之间的传输协议,它允许一个通用串行总线(USB)设备来访问主机的计算设备,使两者之间进行文件传输。
   * USB大容量存储设备类(The USB mass storage device class)是一种计算机和移动设备之间的传输协议,它允许一个通用串行总线(USB)设备来访问主机的计算设备,使两者之间进行文件传输   * USB大容量存储设备类(The USB mass storage device class)是一种计算机和移动设备之间的传输协议,它允许一个通用串行总线(USB)设备来访问主机的计算设备,使两者之间进行文件传输
-=== 2、USB_MSC HOST ===  ​* 普通列表项目+=== 2、USB_MSC HOST ===  ​
   * USB MSC设备中的固件(firmware)或者硬件(hardware),必须要实现下面这些功能:   * USB MSC设备中的固件(firmware)或者硬件(hardware),必须要实现下面这些功能:
     * 检测和响应通用的USB Request和USB总线上的事件。     * 检测和响应通用的USB Request和USB总线上的事件。
行 102: 行 101:
 {{ :​icore3:​icore3_arm_hal_20_1.png?​direct |}} {{ :​icore3:​icore3_arm_hal_20_1.png?​direct |}}
   * 如上图,我们U盘实现的功能,主要就是数据的读写,而Device和Host之间的数据通信,主要有两种:   * 如上图,我们U盘实现的功能,主要就是数据的读写,而Device和Host之间的数据通信,主要有两种:
-  ​* CBI:主要用于Floppy设备,所以新的设备,都很少用此协议 +    ​* CBI:主要用于Floppy设备,所以新的设备,都很少用此协议 
-  * BOT:Bulk-Only Transport,也称BBB(Bulk/​Bulk/​Bulk),而对于BOT/​BBB来说,对其提高USB总线利用率,提高了USB速度后,就是对应的UASP协议,故此处称UASP为BOT的增强版的协议。+    * BOT:Bulk-Only Transport,也称BBB(Bulk/​Bulk/​Bulk),而对于BOT/​BBB来说,对其提高USB总线利用率,提高了USB速度后,就是对应的UASP协议,故此处称UASP为BOT的增强版的协议。
 === 5、USBH_MSC实验介绍 === === 5、USBH_MSC实验介绍 ===
   * 硬件框架图:   * 硬件框架图:
-{{ :​icore3:​icore3_arm_hal_20_2.png?​direct |}}+{{ :​icore3:​icore3_arm_hal_20_2.png?​direct&​600 ​|}}
   * USBH_MSC实验是用STM32F407的USB接口实现iCore3作为主机对U盘(即USB大容量存储器)实现读/写操作并通过串口打印到电脑上并显示的实验。   * USBH_MSC实验是用STM32F407的USB接口实现iCore3作为主机对U盘(即USB大容量存储器)实现读/写操作并通过串口打印到电脑上并显示的实验。
-  ​* **实验内容**:通过cube MX库提供的代码来实现STM32对U盘或者读卡器等大容量USB存储设备的读写操作,本实验是向存储设备中新建一个名为test.txt的文件,并向文件中写入数据,待写入成功后,读出文件的内容,并通过终端显示出来。+  * 实验内容: 
 +    ​* 通过cube MX库提供的代码来实现STM32对U盘或者读卡器等大容量USB存储设备的读写操作,本实验是向存储设备中新建一个名为test.txt的文件,并向文件中写入数据,待写入成功后,读出文件的内容,并通过终端显示出来。
  
 ==== 四、 实验程序 ==== ==== 四、 实验程序 ====
行 116: 行 116:
 int main(void)  ​ int main(void)  ​
 {  ​ {  ​
-  /* USER CODE BEGIN 1 */  ​ 
-  int i;  ​ 
-  unsigned char buffer[64];  ​ 
-  unsigned char send_buffer[64];  ​ 
-  static int counter;  ​ 
-  RTC_DateTypeDef sDate;  ​ 
-  RTC_TimeTypeDef sTime;  ​ 
-  /* USER CODE END 1 */  ​ 
   HAL_Init();  ​   HAL_Init();  ​
   SystemClock_Config();  ​   SystemClock_Config();  ​
-  /* Initialize all configured peripherals */  ​ 
   MX_GPIO_Init();  ​   MX_GPIO_Init();  ​
-  ​MX_RTC_Init();   +  ​MX_UART4_Init();   
-  ​MX_USB_DEVICE_Init();   +  ​MX_FATFS_Init();   
-  ​/* USER CODE BEGIN WHILE */  +  ​MX_USB_HOST_Init(); ​  
 +  uart4.printf("​\x0c"​);​ 
 +  uart4.printf("​\033[1;​32;​40m"​); ​   
 +  uart4.printf("​\r\nHello,​ I am iCore3.\r\n"​); ​     ​
   while (1)  ​   while (1)  ​
   {  ​   {  ​
-    ​/* USER CODE END WHILE */   +    ​MX_USB_HOST_Process();   
-        if(systick.second_flag == 1){   +    ​LED_RED_ON;  ​
-            systick.second_flag = 0;   +
-            ​if(hUsbDeviceHS.dev_state == USBD_STATE_CONFIGURED){ ​  +
-                if(counter ++ % 2){   +
-                    HAL_RTC_GetTime(&​hrtc,​ &sTime, RTC_FORMAT_BIN);  ​ +
-                    HAL_RTC_GetDate(&​hrtc,​ &sDate, RTC_FORMAT_BIN); ​  +
-                    memset(send_buffer,​0,​64);​  +
-                    sprintf((char *)send_buffer,"​time:​%02d:​%02d:​%02d ​ %02d-%02d-%02d",​sTime.Hours,​sTime.Minutes,​sTime.Seconds,​sDate.Year,​sDate.Month,​sDate.Date);​ +
-                    USBD_HID_SendReport(&​hUsbDeviceHS,​send_buffer,​64); ​  +
-                }else{ ​  +
-                    memset(send_buffer,​0,​64); ​  +
-                    if(ARM_KEY_STATE == KEY_DOWN) ​  +
-                        sprintf((char *)send_buffer,"​key:​KEY PRESS"​); ​  +
-                    else   +
-                        sprintf((char *)send_buffer,"​key:"​); ​  +
-                    USBD_HID_SendReport(&​hUsbDeviceHS,​send_buffer,​64);​  +
-                }          +
-            }          +
-        }   +
-        //​接收命令处理 +
-        if(usb_receive_flag == 1){   +
-            usb_receive_flag = 0;   +
-            memcpy(buffer,​usb_receive_buffer,​usb_receive_counter); ​  +
-            memset(usb_receive_buffer,​0,​usb_receive_counter); ​  +
-            for(i = 0;i < 64;​i++){ ​  +
-                buffer[i] = tolower(buffer[i]); ​  +
-            }   +
-            command_process(buffer); ​  +
-        }        ​+
   }  ​   }  ​
-  +
 </​code>​ </​code>​
-  * 主函数的while循环中通过定时器定时向主机发送时间数据。再过USB处理函数机发送过来的据进接收处理并送入处理函数进行处理实现相应功能。 +  * 对于USB机,需要调用一个重要函数MX_USB_HOST_Process该函数用于实现USB主机通信的核心状态机处理,该函数必须在里面,被循环调用,而且调用频率得比较快才(越快越好)以便及时处理各种事务。注意,MX_USB_HOST_Process函数仅在U盘识别阶段需要频繁反复调用,但是当U盘被识别后,剩下操作(U盘读写),都可以由USB中断处理。 
-=== 2. 时钟函数 ===+=== 2. 用户处理函数 ===
 <code c> <code c>
-void HAL_SYSTICK_Callback(void)  ​+static ​void USBH_UserProcess  ​(USBH_HandleTypeDef *phost, uint8_t id)  ​
 {  ​ {  ​
-    ​//​中断时间1ms, ​ +    ​int i,​j;  ​ 
-static int counter = 0;   +    static ​FRESULT res;   
- +    unsigned char write_buffer[512]; ​  
-    if((counter ​++ % 250) == 0){   +    unsigned char read_buffer[512]; ​  
-        ​systick.second_flag = 1     +    unsigned ​int counter;   
 +  switch(id) ​  
 +  {   
 +  case HOST_USER_SELECT_CONFIGURATION: ​  
 +  break;  
 +  case HOST_USER_DISCONNECTION: ​  
 +  Appli_state ​APPLICATION_DISCONNECT;   
 +  ​break; ​  
 +  case HOST_USER_CLASS_ACTIVE:​  
 +//​f_mount ​  
 +    res = f_mount(&​fatfs,"​0:",​1);  ​ 
 +    if(res != RES_OK){ ​  
 +        USBH_UsrLog("​\r\nf_mount error!"​); ​  
 +        return; ​  
 +    }else{ ​  
 +        USBH_UsrLog("​\r\nf_mount successful!"​); ​  
 +    }      
 +    //​f_open ​  
 +    for(i = 0; i < 512 ; i ++)write_buffer[i] ​i % 256;   
 +    res f_open(&​file,"​0:/​test.txt",​FA_READ | FA_WRITE | FA_OPEN_ALWAYS); ​  
 +    if(res != RES_OK){   
 +        ​USBH_UsrLog("​f_open error!"​)  
 +        return; ​  
 +    }else{ ​  
 +        USBH_UsrLog("​f_open successful!"​);  ​
     }  ​     }  ​
-+    ​//​f_lseek ​  
- +    ​res ​f_lseek(&file,0)  
-</code> +    if(res !RES_OK){   
-  * 通过时钟函数计时,定时向主机发送数据 +        ​USBH_UsrLog("​f_lseek error!"​);     
-=== 3. usb驱动文件修改 ===  +        ​return; ​       
-  * 因为hal库中的驱动没有对hid设备接收函数的处理,需要修改usbd_hid.c文件。主要是添加USBD_HID_DataOut函数,增加对从主机发送的数据接收功能。 +    }else{   
-<code c> +        ​USBH_UsrLog("​f_lseek successful!"​);  ​
-static uint8_t ​ USBD_HID_DataOut ​(USBD_HandleTypeDef *pdev   +
-                              uint8_t epnum  +
-  +
-    if(epnum == HID_EPOUT_ADDR){   +
-        ​usb_receive_counter = USBD_GetRxCount(pdev,epnum);   +
-        ​if(pdev->​dev_state == USBD_STATE_CONFIGURED){   +
-            ​usb_receive_flag = 1;   +
-  USBD_LL_PrepareReceive(pdev,​HID_EPOUT_ADDR,​usb_receive_buffer,​HID_EPOUT_SIZE);   +
-        }  +
     }  ​     }  ​
-  return ​USBD_OK;   +    //​f_write ​  
-+    res = f_write(&​file,​write_buffer,​512,&​counter); ​  
 +    if(res != RES_OK || counter != 512){   
 +        USBH_UsrLog("​f_write error!"​); ​  
 +        return; ​       
 +    }else{ ​  
 +        USBH_UsrLog("​f_write successful!"​); ​  
 +    } //​f_lseek ​  
 +    res = f_lseek(&​file,​0); ​  
 +    if(res != RES_OK){ ​  
 +        USBH_UsrLog("​f_lseek error!"​); ​  
 +        return; ​  
 +    }else{ ​  
 +        USBH_UsrLog("​f_lseek successful!"​); ​  
 +    }  
 +//​f_read ​  
 +    res = f_read(&​file,​read_buffer,​512,&​counter); ​  ​ 
 +    if(res != RES_OK || counter != 512){   
 +return; ​    
 +  }else{ ​  
 +        ​USBH_UsrLog("​f_read successful!"​); ​  
 +    ​  
 +    f_close(&​file); ​  
 +    USBH_UsrLog("​read data:"​); ​  
 +    for(i = 0;i < 32;​i++){ ​  
 +        for(j = 0; j < 16; j ++)   
 +            USBH_UsrLog("​%02X ",​read_buffer[i*16+j]); ​  
 +    }   
 +    memset(read_buffer,​0,​sizeof(read_buffer)); ​  
 +  break; ​  
 +  case HOST_USER_CONNECTION: ​  
 +  Appli_state = APPLICATION_START; ​  
 +  break; ​  
 +  default: ​  
 +  break; ​  
 +  }   
 +}  ​
  
 </​code>​ </​code>​
-  * 修改USBD_HID_Init函数,增加USBD_LL_OpenEP函数语句与USBD_LL_PrepareReceive函数语句保证相应功能初始化+ 
 +=== 3. 打印函数 ​===  
 +  * USBH自带打印输出但是需要向串口4打印输出需要修改相应的打印输出参数在打印调试输出之前需要打开USBH_DEBUG。打开方式参照iCore3_CubeMX教程二十_USBH_MSC或在usbh_conf.h中将宏定义USBH_DEBUG_LEVEL改为
 <code c> <code c>
-/* Open Ep Out */   +  ​#define USBH_DEBUG_LEVEL ​     1U 
-    USBD_LL_OpenEP(pdev,​ HID_EPOUT_ADDR,​ USBD_EP_TYPE_INTR,​ HID_EPOUT_SIZE); ​  ​ +
-    /* Prepare Out endpoint to receive next packet */   +
-    USBD_LL_PrepareReceive(pdev,​ HID_EPOUT_ADDR,​ usb_receive_buffer,​ HID_EPOUT_SIZE); ​+
 </​code>​ </​code>​
-  * 在usbd_hid.h中添加对EPOUT参数地址与大小的定义+  * 打开USBH_DEBUG后,需将打印信息输出到串口4,即将打印信息修改为
 <code c> <code c>
-#define HID_EPOUT_ADDR ​                             0x01   +#if (USBH_DEBUG_LEVEL > 0U)   
-#​define ​HID_EPOUT_SIZE ​                             0x40  +#​define  ​USBH_UsrLog(...)   uart4.printf(__VA_ARGS__);​\ ​  
-</​code>​ +                            uart4.printf("​\r\n"​);  ​ 
-  * 利用上位机hid.exe与iCore3通讯,HID设备的描述符需要进行修改,以便可以与上位机软件进行通讯。主要是对usbd_desc.c 设备描述符与usbd_hid.c配置描述符进行修改。这些描述符决定了HID设备的类型与定义,上位机需要根据这些描述符发出相应的指令控制。直接将程序中的usbd_hid.c文件替换为例程文件的usbd_hid.c。在usbd_desc.c中需要修改USBD_HS_DeviceDesc中的相应描述配置,将宏定义中的一些参数进行修改,即可实现hid描述符的修改。 +#else   
-<code c> +#​define ​USBH_UsrLog(...) do {} while (0)   
-#define USBD_VID ​    ​0x483 ​  +#endif   
-#​define ​USBD_LANGID_STRING ​    ​1033 ​  +   
-#define USBD_MANUFACTURER_STRING ​    "​Gingko" ​  +#if (USBH_DEBUG_LEVEL > 1U)   
-#define USBD_PID_HS ​    ​0x5720 ​  +   
-#​define ​USBD_PRODUCT_STRING_HS ​    "iCore3 in HS mode" ​  +#​define ​ ​USBH_ErrLog(...) do { \   
-#​define ​USBD_SERIALNUMBER_STRING_HS ​    "​00000000001A" ​  +                            uart4.printf("ERROR: ​") ; \   
-#​define ​USBD_CONFIGURATION_STRING_HS ​    "HID Config" ​  +                            uart4.printf(__VA_ARGS__);​ \   
-#define USBD_INTERFACE_STRING_HS ​    "HID Interface" ​  +#​define ​USBH_ErrLog(...) do {} while (0)   
-#define USB_SIZ_BOS_DESC ​           0x0C +#​endif ​    
 +#if (USBH_DEBUG_LEVEL > 2U)   
 +#​define ​ ​USBH_DbgLog(...) ​  do { \   
 +                            uart4.printf("DEBUG : ") ; \   
 +                            ​uart4.printf(__VA_ARGS__);​ \   
 +                            uart4.printf("\r\n"); \   
 +} while (0)   
 +#else   
 </​code>​ </​code>​
 +  * 即可正常向串口4打印调试信息。
 +
 ==== 五、 实验步骤 ==== ==== 五、 实验步骤 ====
   - 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连);   - 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连);
-  - 跳线帽插在USBOTG; +  - 跳线帽插在USB_UART; 
-  - 把iCore3(USB_OTG)通过Micro USB线与计算机相连,为iCore3供电; +  - 把iCore3(USB_UART)通过Micro USB线与计算机相连,为iCore3供电; 
-  - 打开Keil MDK开发环境,并打开本实验工程; +  - 把USB_OTG通过Micor USB线与U盘或者读卡器相连,向此存储设备写入文件; 
-  - 烧写程序到iCore3; +  - 打开Keil MDK 开发环境,并打开本实验工程; 
-  - 也可以进入Debug模式,单步运行或设置断点验证程序逻辑; +  - 打开PuTTY串口中断(注:PuTTY使用方法见附录); 
-  - 打开usb_hid.exe进行验证+  - 烧写程序到iCore3; 
 +  - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。
  
 ==== 六、 实验现象 ==== ==== 六、 实验现象 ====
-  * 点击测试软件的LED控制按钮iCore3上的LED灯的颜色状态将发生变化,点击校准时间,将用电脑系统的时间校准iCore3的部RTC按下iCore3上的ARM-KEY,​按键状态栏将显示按键的状态(如下图示)。 +  * 打开串口终端可以显示操作过程操作完成后可以通过电脑查看U盘是否操作成功,成功后U盘新建一个test.txt文件。 
-{{ :icore3:icore3_arm_hal_19_3.png?direct |}}+{{ :​icore3:​icore3_arm_hal_20_3.png?​direct |}} 
 + 
 +**附录:** 
 +**PuTTY使用方法:** 
 +  * 1、iCore3供电后打开计算机——属性——设备管理器——端口,查看iCore3所占用的COM口; 
 +{{ :icore3:icore3_arm_hal_20_4.png?direct |}} 
 +  * 2、打开PuTTY; 
 +{{ :​icore3:​icore3_arm_hal_20_5.png?​direct |}} 
 +  * 3、烧写程序验证 
  
icore3_arm_hal_20.1587115690.txt.gz · 最后更改: 2020/04/17 17:28 由 fmj