stm32f1串口初始化步骤(F7水星开发板资料连载第五十六章)
1)实验平台:正点原子水星 STM32F4/F7 开发板
2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码 手册 视频下载地址:http://www.openedv.com/thread-13912-1-1.html
第五十六章 USB 虚拟串口(Slave)实验
上一章我们向大家介绍了如何利用 STM32F7 的 USB 接口来做一个 USB 声卡,本章我们将
利用 STM32F7 的 USB 来做一个虚拟串口(VCP)。本章分为如下几个部分:
56.1 USB 虚拟串口简介
56.2 硬件设计
56.3 软件设计
56.4 下载验证
56.1 USB 虚拟串口简介
USB 虚拟串口,简称 VCP,是 Virtual COM Port 的简写,它是利用 USB 的 CDC 类来实现
的一种通信接口。
我们可以利用 STM32 自带的 USB 功能,来实现一个 USB 虚拟串口,从而通过 USB,实
现电脑与 STM32 的数据互传。上位机无需编写专门的 USB 程序,只需要一个串口调试助手即
可调试,非常实用。
同上一章一样,我们直接移植官方的 USB VCP 例程,官方例程路径:8,STM32 参考资料
→STM32 USB 学习资料→STM32_USB-Host-Device_Lib_V2.2.0→Project→USB_Devic
e_Examples→VCP,该例程采用 USB CDC 类来实现,利用 STM32 的 USB 接口,实现一个 USB
转串口的功能。
56.2 硬件设计
本章实验功能简介:本实验利用 STM32 自带的 USB 功能,连接电脑 USB,虚拟出一个 USB
串口,实现电脑和开发板的数据通信。本例程功能完全同实验 3(串口通信实验),只不过串
口变成了 STM32 的 USB 虚拟串口。当 USB 连接电脑(USB 线插入 USB_SLAVE 接口),开
发板将通过 USB 和电脑建立连接,并虚拟出一个串口(注意:需要先安装:光盘\6,软件资料\1,
软件\STM32 USB 虚拟串口驱动\VCP_V1.4.0_Setup.exe 这个驱动软件),USB 和电脑连接成
功后,DS1 常亮。
在找到虚拟串口后,即可打开串口调试助手,实现同实验 3 一样的功能,即:STM32 通
过 USB 虚拟串口和上位机对话,STM32 在收到上位机发过来的字符串(以回车换行结束)后,
原原本本的返回给上位机。下载后,DS0 闪烁,提示程序在运行,同时每隔一定时间,通过
USB 虚拟串口输出一段信息到电脑。
所要用到的硬件资源如下:
1) 指示灯 DS0 、DS1
2) 串口
3) LCD 模块
4) USB SLAVE 接口
这几个部分,在之前的实例中都已经介绍过了,我们在此就不多说了。这里再次提醒大家,
P10 的连接,要通过跳线帽连接 PA11 和 D-以及 PA12 和 D 。
56.3 软件设计
本章,我们在第三十章 IIC 实验(实验 25)的基础上修改,先打开实验 25 的工程,在
HARDWARE 文件夹所在文件夹下新建一个 USB 的文件夹,同上一章一样,对照官方 VCP 例子,将相关文件拷贝到 USB 文件夹下。
然后,我们在工程里面去掉一些不必要的代码,并添加 USB 相关代码,最终得到如图 56.3.1
所示的工程:
图 63.3.1 USB 虚拟串口工程截图
可以看到,USB 部分代码,同上一章的在结构上是一模一样的,只是.c 文件稍微有些变化。
同样,我们移植需要修改的代码,就是 USB_APP 里面的这四个.c 文件了。
其中 usb_bsp.c 和 usbd_usr.c 的代码,和上一章基本一样,可以用上一章的代码直接替换即
可正常使用。
usb_desc.c 代码,同上一章不一样,上一章描述符是大容量存储设备,本章变成了 USB 声
卡了,所以直接用 ST 官方的就行。
最后 usbd_cdc_vcp.c,这里面的代码,是重点要修改的,修改后代码如下:
//USB 虚拟串口相关配置参数
LINE_CODING linecoding =
{
115200,
//波特率
0x00, //停止位,默认 1 位
0x00, //校验位,默认无
0x08
//数据位,默认 8 位
};
u8 USART_PRINTF_Buffer[USB_USART_REC_LEN]; //usb_printf 发送缓冲区
//用类似串口 1 接收数据的方法,来处理 USB 虚拟串口接收到的数据.
u8 USB_USART_RX_BUF[USB_USART_REC_LEN];
//接收缓冲,最大 USART_REC_LEN 个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到 0x0d
//bit13~0, 接收到的有效字节数目
u16 USB_USART_RX_STA=0;
//接收状态标记
extern uint8_t APP_Rx_Buffer [];
//虚拟串口发送缓冲区(发给电脑)
extern uint32_t APP_Rx_ptr_in;
//虚拟串口接收缓冲区(接收来自电脑的数据)
//虚拟串口配置函数(供 USB 内核调用)
CDC_IF_Prop_TypeDef VCP_fops =
{
VCP_Init,
VCP_DeInit,
VCP_Ctrl,
VCP_DataTx,
VCP_DataRx
};
//初始化 VCP
//返回值:USBD_OK
uint16_t VCP_Init(void)
{
return USBD_OK;
}
//复位 VCP
//返回值:USBD_OK
uint16_t VCP_DeInit(void)
{
return USBD_OK;
}
//控制 VCP 的设置
//buf:命令数据缓冲区/参数保存缓冲区
//len:数据长度
//返回值:USBD_OK
uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
{
switch (Cmd)
{
case SEND_ENCAPSULATED_COMMAND:break;
case GET_ENCAPSULATED_RESPONSE:break;
case SET_COMM_FEATURE:break;
case GET_COMM_FEATURE:break;
case CLEAR_COMM_FEATURE:break;
case SET_LINE_CODING:
linecoding.bitrate = (uint32_t)(Buf[0] | \
(Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24));
linecoding.format = Buf[4];
linecoding.paritytype = Buf[5];
linecoding.datatype = Buf[6];
//打印配置参数
printf("linecoding.format:%d\r\n",linecoding.format);
printf("linecoding.paritytype:%d\r\n",linecoding.paritytype);
printf("linecoding.datatype:%d\r\n",linecoding.datatype);
printf("linecoding.bitrate:%d\r\n",linecoding.bitrate);
break;
case GET_LINE_CODING:
Buf[0] = (uint8_t)(linecoding.bitrate);
Buf[1] = (uint8_t)(linecoding.bitrate >> 8);
Buf[2] = (uint8_t)(linecoding.bitrate >> 16);
Buf[3] = (uint8_t)(linecoding.bitrate >> 24);
Buf[4] = linecoding.format;
Buf[5] = linecoding.paritytype;
Buf[6] = linecoding.datatype;
break;
case SET_CONTROL_LINE_STATE:break;
case SEND_BREAK:break;
default:break;
}
return USBD_OK;
}
//发送一个字节给虚拟串口(发给电脑)
//data:要发送的数据
//返回值:USBD_OK
uint16_t VCP_DataTx (uint8_t data)
{
APP_Rx_Buffer[APP_Rx_ptr_in]=data;
//写入发送 buf
APP_Rx_ptr_in ;
//写位置加 1
if(APP_Rx_ptr_in==APP_RX_DATA_SIZE)
//超过 buf 大小了,归零.
{
APP_Rx_ptr_in = 0;
}
return USBD_OK;
}
//处理从 USB 虚拟串口接收到的数据
//databuffer:数据缓存区
//Nb_bytes:接收到的字节数.
//返回值:USBD_OK
uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
{
u8 i;
u8 res;
for(i=0;i<Len;i )
{
res=Buf[i];
if((USB_USART_RX_STA&0x8000)==0)
//接收未完成
{
if(USB_USART_RX_STA&0x4000)
//接收到了 0x0d
{
if(res!=0x0a)USB_USART_RX_STA=0;//接收错误,重新开始
else USB_USART_RX_STA|=0x8000; //接收完成了
}else //还没收到 0X0D
{
if(res==0x0d)USB_USART_RX_STA|=0x4000;
else
{
USB_USART_RX_BUF[USB_USART_RX_STA&0X3FFF]=res;
USB_USART_RX_STA ;
if(USB_USART_RX_STA>(USB_USART_REC_LEN-1))\
USB_USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
return USBD_OK;
}
//usb 虚拟串口,printf 函数
//确保一次发送数据不超 USB_USART_REC_LEN 字节
void usb_printf(char* fmt,...)
{
u16 i,j;
va_list ap;
va_start(ap,fmt);
vsprintf((char*)USART_PRINTF_Buffer,fmt,ap);
va_end(ap);
i=strlen((const char*)USART_PRINTF_Buffer);//此次发送数据的长度
for(j=0;j<i;j )//循环发送数据
{
VCP_DataTx(USART_PRINTF_Buffer[j]);
}
}
此部分总共 6 个函数,其中前 5 个函数,用于初始化 VCP_fops 结构体,给 USB 内核
调用,以实现相关功能。接下来我们分别介绍这几个函数。
VCP_Init 用于初始化 VCP,在初始化的时候由 USB 内核调用,这里我们无需任何操作,
所以直接范围 USBD_OK 即可。
VCP_DeInit 用于复位 VCP,我们用不到,所以直接返回 USBD_OK 即可。
VCP_Ctrl 用于控制 VCP 的相关参数,根据 cmd 的不同,执行不同的操作,这里主要用到
SET_LINE_CODING 命令,该命令用于设置 VCP 的相关参数,比如波特率、数据类型(位数)、
校验类型(奇偶校验)等,保存在 linecoding 结构体里面,在需要的时候,应用程序可以读取
linecoding 结构体里面的参数,以获得当前 VCP 的相关信息。
VCP_DataTx 用于发送一个字节的数据给 VCP,应用程序每调用一次该函数,就可以发送
一个字节给 VCP,由 VCP 通过 USB 传输给电脑,实现 VCP 的数据发送。
VCP_DataRx 用于 VCP 的数据接收,当 STM32 的 USB 接收到电脑端串口发送过来的数据
时,由 USB 内核程序调用该函数,实现 VCP 的数据接收。我们只需要在该函数里面,将接收
到的数据,保存起来即可,接收的原理同第八章(实验 3 串口通信实验)完全一样。
usb_printf 用于实现和普通串口一样的 printf 操作,该函数将数据格式化输出到 USB VCP,
功能完全同 printf,方便大家使用。
USB VCP 相关代码,就给大家介绍到这里,详细的介绍,请大家参考:CD00289278.pdf
这个文档。
最后在 main.c 里面,我们修改 main 函数如下:
USB_OTG_CORE_HANDLE USB_OTG_dev;
extern vu8 bDeviceState;
//USB 连接 情况
int main(void)
{
u16 t;
u16 len;
u16 times=0;
u8 usbstatus=0;
Cache_Enable(); //打开 L1-Cache
HAL_Init();
//初始化 HAL 库
Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz
delay_init(216); //延时初始化
uart_init(115200);
//串口初始化
LED_Init(); //初始化 LED
KEY_Init(); //初始化按键
SDRAM_Init(); //初始化 SDRAM
LCD_Init();
//初始化 LCD
W25QXX_Init();
//初始化 W25Q256
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7");
LCD_ShowString(30,70,200,16,16,"USB Virtual USART TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2016/8/10");
LCD_ShowString(30,130,200,16,16,"USB Connecting...");//提示 USB 开始连接
USBD_Init(&USB_OTG_dev,USB_OTG_FS_CORE_ID,&USR_desc,
&USBD_CDC_cb,&USR_cb);
while(1)
{
if(usbstatus!=bDeviceState)//USB 连接状态发生了改变.
{
usbstatus=bDeviceState;//记录新的状态
if(usbstatus==1)
{
POINT_COLOR=BLUE;
LCD_ShowString(30,130,200,16,16,"USB Connected ");//提示连接成功
LED1(0);//DS1 亮
}else
{
POINT_COLOR=RED;
LCD_ShowString(30,130,200,16,16,"USB disConnected ");//提示 USB 断开
LED1(1);//DS1 灭
}
}
if(USB_USART_RX_STA&0x8000)
{
len=USB_USART_RX_STA&0x3FFF;//得到此次接收到的数据长度
usb_printf("\r\n 您发送的消息为:%d\r\n\r\n",len);
for(t=0;t<len;t )
{
VCP_DataTx(USB_USART_RX_BUF[t]);//以字节方式,发送给 USB
}
usb_printf("\r\n\r\n");//插入换行
USB_USART_RX_STA=0;
}else
{
times ;
if(timesP00==0)
{
usb_printf("\r\n 水星 STM32F4/F7 开发板 USB 虚拟串口实验\r\n");
usb_printf("正点原子@ALIENTEK\r\n\r\n");
}
if(times 0==0)usb_printf("请输入数据,以回车键结束\r\n");
if(times0==0)LED0_Toggle;//闪烁 LED,提示系统正在运行.
delay_ms(10);
}
}
}
此部分代码比较简单,同上一章一样定义了 USB_OTG_dev 结构体,然后通过 USBD_Init
初始化 USB,不过本章实现的是 USB 虚拟串口的功能。然后在死循环里面轮询 USB 状态并检
查是否接收到数据,如果接收到了数据,则通过 VCP_DataTx 将数据通过 VCP 原原本本的返回
给电脑端串口调试助手。
其他部分我们就不详细介绍了,软件设计部分就为大家介绍到这里。
56.4 下载验证
本例程的测试,需要在电脑上先安装 ST 提供的 USB 虚拟串口驱动软件,该软件路径:光
盘→6,软件资料→1,软件→STM32 USB 虚拟串口驱动→VCP_V1.4.0_Setup.exe,双击安装即
可。
然后,在代码编译成功之后,我们下载代码到水星 STM32 开发板上,然后将 USB 数据线,
插入 USB_SLAVE 口,连接电脑和开发板(注意:不是插 USB_232 端口!),此时电脑会提示
找到新硬件,并自动安装驱动。不过,如果自动安装不成功(有惊叹号),如图 56.4.1 所示:
图 56.4.1 自动安装失败
此时,我们可手动选择驱动(以 WIN7 为例),进行安装,在如图 63.4.1 所示的条目上面,
右键→更新驱动程序软件→浏览计算机以查找驱动程序软件→浏览,选择 STM32 虚拟串口的驱
动的路径为:C:\Program Files (x86)\STMicroelectronics\Software\Virtual comport driver\WIN7,然
后点击下一步,即可完成安装。安装完成后,可以看到设备管理器里面多出了一个 STM32 的虚拟串口,如图 56.4.2 所示:
图 56.4.2 发现 STM32 USB 虚拟串口
如图 56.4.2,STM32 通过 USB 虚拟的串口,被电脑识别了,端口号为:COM15(可变),
字符串名字为:STMicroelectronics Virtual COM Port(固定)。此时,开发板的 DS1 常亮,同时,
开发板的 LCD 显示 USB Connected,如图 56.4.3 所示:
图 56.4.3 USB 虚拟串口连接成功
然后我们打开 XCOM,选择 COM15(需根据自己的电脑识别到的串口号选择),并打开串
口(注意:波特率可以随意设置),就可以进行测试了,如图 56.4.4 所示:
图 56.4.4 STM32 虚拟串口通信测试
可以看到,我们的串口调试助手,收到了来自 STM32 开发板的数据,同时,按发送按钮
(串口助手必须勾选:发送新行),也可以收到电脑发送给 STM32 的数据(原样返回),说明
我们的实验是成功的。实验现象同第八章完全一样。
至此,USB 虚拟串口实验就完成了,通过本实验,我们就可以利用 STM32 的 USB,直接
和电脑进行数据互传了,具有广泛的应用前景。
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com