用户工具

站点工具


icore3_arm_hal_21

这是本文档旧的修订版!


银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
技术论坛http://www.eeschool.org
版本 日期 作者 修改内容
V1.0 2020-04-18 gingko 初次建立






STM32CubeMX教程二十一——虚拟串口

1. 新建工程:在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR  2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各种查找方式,可以选择芯片内核、型号等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32F407IGTx。  3. 配置RCC,使用外部时钟源  4. 配置调试引脚  5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output  6. 引脚模式配置  7. 配置USB_OTG_HS  8. 配置USB_Device  9. 打开USB中断  10. 时钟源设置,选择外部高速时钟源,配置为最大主频  11. 工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK5

12. 点击Code Generator,进行进一步配置

  • Copy all used libraries into the project folder
  • 将HAL库的所有.C和.H都复制到所建工程中
    • 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便
    • 缺点:体积大,编译时间很长
  • Copy only the necessary library files
  • 只复制所需要的.C和.H(推荐)
    • 优点:体积相对小,编译时间短,并且工程可复制拷贝
    • 缺点:新增外设时需要重新用STM32CubeMX导入
  • Add necessary library files as reference in the toolchain project configuration file
  • 不复制文件,直接从软件包存放位置导入.C和.H
    • 优点:体积小,比较节约硬盘空间
    • 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径

自行选择方式即可

13. 然后点击GENERATE CODE 创建工程  创建成功,打开工程。





STM32CubeMX教程二十一——虚拟串口

一、 实验目的与意义

  1. 了解STM32 USB SLAVE结构。
  2. 了解STM32 USB SLAVE特征。
  3. 掌握STM32 HAL库中USB SLAVE的配置方法。
  4. 掌握USB SLAVE VCP使用方法。
  5. 掌握Keil MDK集成开发环境使用方法。

二、 实验设备及平台

  1. iCore3 双核心板。点击购买
  2. JLINK(或相同功能)仿真器。点击购买
  3. Micro USB线缆。
  4. Keil MDK 开发平台。
  5. STM32CubeMX开发平台。
  6. 装有WIN XP(及更高版本)系统的计算机。

三、 实验原理

1、USB_VCP设备

  • USB_VCP是属于USB_CDC类设备中的一种,是通过USB接口虚拟串口实现串口通讯的功能。
    • USB虚拟串口,简称VCP,是Virtual COM Port的简写,它是利用USB的CDC类来实现的一种通信接口。
    • USB虚拟串口属于USB通信设备类。在物理层通过USB总线,采用虚拟串口的方式为主机提供一个物理串口。在系统内部,USB控制器提供了一个批量传输IN端点和一个批量传输的OUT端点,用于数据的接收和发送,模拟串口的RX和TX线。另外USB控制器还提供中断IN端点,发送当前串口的状态,实现对串口传输的控制。串口设备的数据,由系统的串口采集,在芯片内完成USB包的封装,通过USB总线上传至主机,再由相应的串口应用程序进行处理。对用户来说,看到的是基于串口的数据采集和传输,而实际上实现的是基于USB协议包的数据传输。
    • 我们可以利用STM32自带的USB功能,来实现一个USB虚拟串口,从而通过USB,实现电脑与STM32的数据互传。上位机无需编写专门的USB程序,只需要一个串口调试助手即可调试,非常实用。
    • 本实验利用STM32自带的USB功能,连接电脑USB,虚拟出一个USB串口,实现电脑和开发板的数据通信。

2、USB_CDC

  • USB2.0标准下定义了很多子类,有音频类,CDC类,HID,打印,大容量存储类,HUB,智能卡等等,这些在usb.org官网上有具体的定义,这里主要介绍通信类CDC。CDC(Communication Device Class)类是USB2.0标准下的一个子类,定义了通信相关设备的抽象集合。

 USB的CDC类是USB通信设备类(Communication Device Class)的简称。CDC类是USB组织定义的一类专门给各种通信设备(电信通信设备和中速网络通信设备)使用的USB子类。根据CDC类所针对通信设备的不同,CDC类又被分成以下不同的模型:USB传统纯电话业务(POTS)模型,USBISDN模型和USB网络模型,其中USB传统纯电话业务模型又可分为直线控制模型(Direct Line Control Model)、抽象模型、电话模型。虚拟串口就属于USB传统纯电话业务模型下的抽象控制模型。  USB CDC类的通信部分主要包含三部分:枚举过程、虚拟串口操作和数据通信。其中虚拟串口操作部分并不一定强制需要,因为若跳过这些虚拟串口的操作,实际上USB依然是可以通信的。之所以会有虚拟串口操作,主要是我们通常使用PC作为Host端,在PC端使用一个串口工具来与其进行通信,PC端的对应驱动将其虚拟成一个普通串口,这样一来,可以方便PC端软件通过操作串口的方式来与其进行通信,但实际上,Host端与Device端物理上是通过USB总线来进行通信的,与串口没有关系,这一虚拟化过程,起决定性作用的是对应驱动,包含如何将每一条具体的虚拟串口操作对应到实际上的USB操作。需要注意的是,Host端与Device端的USB通信速率并不受所谓的串口波特率影响,它就是标准的USB2.0全速(12Mbps)速度,实际速率取决于总线的实际使用率、驱动访问USB外设有效速率(两边)以及外部环境对通信本身造成的干扰率等因素组成。  CDC类软件框架

3、USB MSC Device

  • 我们所关注的U盘,就是所谓的MSC设备,大容量存储设备。
  • U盘的功能,就是数据存储。而对应的数据传输,用的是USB中的Bulk Transfer。

4、USB MSC相关的协议

  • USB MSC Bulk-Only (BBB) Transport
  • 如上所述,Bulk-only是USB设备端,此处的U盘和USB Host端,即普通PC,之间信息交换的协议。Bulk Only Transport,也被简称为BOT。
  • USB MSC USB Attached SCSI Protocol (UASP)
  • “Attached”顾名思义,是附在某个上面的,此处即附在SCSI协议的上面的,即SCSI协议的补充部分。
  • UASP规范,定义了关于如何在USB 2.0和USB 3.0中,UAS的传输标准是如何实现的,并且给出了一些范例和一些推荐的做法。

  • 如上图,我们U盘实现的功能,主要就是数据的读写,而Device和Host之间的数据通信,主要有两种:
    • CBI:主要用于Floppy设备,所以新的设备,都很少用此协议
    • BOT:Bulk-Only Transport,也称BBB(Bulk/Bulk/Bulk),而对于BOT/BBB来说,对其提高USB总线利用率,提高了USB速度后,就是对应的UASP协议,故此处称UASP为BOT的增强版的协议。

5、USBH_MSC实验介绍

  • 硬件框架图:

  • USBH_MSC实验是用STM32F407的USB接口实现iCore3作为主机对U盘(即USB大容量存储器)实现读/写操作并通过串口打印到电脑上并显示的实验。
  • 实验内容:
    • 通过cube MX库提供的代码来实现STM32对U盘或者读卡器等大容量USB存储设备的读写操作,本实验是向存储设备中新建一个名为test.txt的文件,并向文件中写入数据,待写入成功后,读出文件的内容,并通过终端显示出来。

四、 实验程序

1. 主函数

int main(void)  
{  
  HAL_Init();  
  SystemClock_Config();  
  MX_GPIO_Init();  
  MX_UART4_Init();  
  MX_FATFS_Init();  
  MX_USB_HOST_Init();  
  uart4.printf("\x0c");
  uart4.printf("\033[1;32;40m");   
  uart4.printf("\r\nHello, I am iCore3.\r\n");      
  while (1)  
  {  
    MX_USB_HOST_Process();  
    LED_RED_ON;  
  }  
} 
  • 对于USB主机,需要调用一个重要函数MX_USB_HOST_Process,该函数用于实现USB主机通信的核心状态机处理,该函数必须在主函数里面,被循环调用,而且调用频率得比较快才行(越快越好),以便及时处理各种事务。注意,MX_USB_HOST_Process函数仅在U盘识别阶段,需要频繁反复调用,但是当U盘被识别后,剩下的操作(U盘读写),都可以由USB中断处理。

2. 用户处理函数

static void USBH_UserProcess  (USBH_HandleTypeDef *phost, uint8_t id)  
{  
    int i,j;  
    static FRESULT res;  
    unsigned char write_buffer[512];  
    unsigned char read_buffer[512];  
    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);  
    if(res != RES_OK){  
        USBH_UsrLog("f_lseek error!");    
        return;       
    }else{  
        USBH_UsrLog("f_lseek successful!");  
    }  
    //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;  
  }  
}

3. 打印函数

  • USBH自带打印输出,但是需要向串口4打印输出,需要修改相应的打印输出参数。在打印调试输出之前需要打开USBH_DEBUG。打开方式参照iCore3_CubeMX教程二十_USBH_MSC或在usbh_conf.h中将宏定义USBH_DEBUG_LEVEL改为
  #define USBH_DEBUG_LEVEL      1U 
  • 打开USBH_DEBUG后,需将打印信息输出到串口4,即将打印信息修改为
#if (USBH_DEBUG_LEVEL > 0U)  
#define  USBH_UsrLog(...)   uart4.printf(__VA_ARGS__);\  
                            uart4.printf("\r\n");  
#else  
#define USBH_UsrLog(...) do {} while (0)  
#endif  
 
#if (USBH_DEBUG_LEVEL > 1U)  
 
#define  USBH_ErrLog(...) do { \  
                            uart4.printf("ERROR: ") ; \  
                            uart4.printf(__VA_ARGS__); \  
#define USBH_ErrLog(...) do {} while (0)  
#endif    
#if (USBH_DEBUG_LEVEL > 2U)  
#define  USBH_DbgLog(...)   do { \  
                            uart4.printf("DEBUG : ") ; \  
                            uart4.printf(__VA_ARGS__); \  
                            uart4.printf("\r\n"); \  
} while (0)  
#else
  • 即可正常向串口4打印调试信息。

五、 实验步骤

  1. 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连);
  2. 将跳线帽插在USB_UART;
  3. 把iCore3(USB_UART)通过Micro USB线与计算机相连,为iCore3供电;
  4. 把USB_OTG通过Micor USB线与U盘或者读卡器相连,向此存储设备写入文件;
  5. 打开Keil MDK 开发环境,并打开本实验工程;
  6. 打开PuTTY串口中断(注:PuTTY使用方法见附录);
  7. 烧写程序到iCore3上;
  8. 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。

六、 实验现象

  • 打开串口终端可以显示操作过程,操作完成后可以通过电脑查看U盘是否操作成功,成功后U盘内新建一个test.txt文件。

附录: PuTTY使用方法:

  • 1、iCore3供电后,打开计算机——属性——设备管理器——端口,查看iCore3所占用的COM口;

  • 2、打开PuTTY;

  • 3、烧写程序验证
icore3_arm_hal_21.1587202240.txt.gz · 最后更改: 2020/04/18 17:30 由 fmj