打印
[STM32F1]

用STM32CUBE生成虚拟串口

[复制链接]
2305|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lvyong6105|  楼主 | 2016-9-17 20:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我总是班门弄斧,前两天还在问虚拟串口的问题,今天初步鼓捣出来了,就急忙写了稿件,与大家分享。
由于现在的PC机大多都没有串口了,但PC机上的很多应用程序却使用串口,为了让PC机与STM32处理器进行通信,可以让STM32处理器,以串行方式与外界进行通信,再用CH340等芯片,实现USB转串口的功能,实现虚拟串口。不过这样做需要额外的芯片和相关电路,不很理想。
利用STM32处理器自身的USB功能,就可以实现虚拟串口。由于USB是一个很复杂的东西,所对应的代码很多,如果采用操作寄存器或标准库的方式,都要编写很多代码,也容易出错,而采用STM32CUBE就方便多了。
首先要利用STM32CUBE,选择芯片,比如芯片型号为STM32F103ZET6,如下图所示:
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA2D8.tmp.jpg
然后在Pinout选项页中,先选择“RCC”项,按下图设置:
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA2E9.tmp.jpg
再选择USB”选项,按下图设置:
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA2EA.tmp.jpg
这一步的最后再选择USB_DEBICE”,按下图设置:
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA2FA.tmp.jpg
下面要设置时钟,进入Clock Configuration”选项页,按下图设置:
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA2FB.tmp.jpg
请注意:上图的设置必须保障给USB模块的时钟信号是精准的48MHz,不允许有偏差。
然后进行工程设置,点击菜单项PorjectSettings...”,这时将弹出一个对话框窗口如下:
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA31B.tmp.jpg
在该对话框窗口上,输入工程名、工程存放的文件夹、所用的开发工具之后,点击OK”按键,关闭该对话框。
最后点击菜单项PorjectGenerate Code”,生成工程。本人用的开发工具是IAR,打开该工程,如下图所示:
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA32C.tmp.jpg
这个工程已经包含了不少文件,建立了基本的程序框架和初始化代码,只要进一步添加应用程序代码就可以了。下面将围绕虚拟串口进一步编写程序:
在这个工程中,有一个usbd_cdc_if.c”文件,进行USB虚拟串口进行数据的发送和接收时,首先要在usbd_cdc_if.c文件中修改“APP_RX_DATA_SIZE”、“APP_TX_DATA_SIZE”两个宏,它们用于数据的接收和发送缓冲区的大小;然后要声明一个结构体(并初始化),其代码如下:
USBD_CDC_LineCodingTypeDef LineCoding =
{
        115200,                /*baud rate*/
        0x00,                /*stop bits - 1*/
        0x00,                /*parity - none*/
        0x08,                /*nb. of bits 8*/
};
这段代码用于指示串口的基本设置。
在该文件的CDC_Control_FS”函数中,在“CDC_SET_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;
这样之后,就可以使用虚拟串口了!
当需要发送数据时,先将要发送的数据放入一个数组中(假设该数组名为a,要发送的n个字节),然后用如下代码就可以发送数据:
CDC_Transmit_FS(a, n);
如果还需要读取上位机传来的数据,要修改usbd_cdc_if.c文件中的CDC_Receive_FS函数,该函数原本为:
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(hUsbDevice_0, &Buf[0]);
  USBD_CDC_ReceivePacket(hUsbDevice_0);
  return (USBD_OK);
  /* USER CODE END 6 */
}
该函数在收到数据时,将被系统调用,它的两个参数分别指向接收缓冲区和接收到的数据字节长度。显然我们可以编写一段代码,将接收到的数据送到应用程序指定的内存区,比如进行如下修改:
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  uint8_t i;
  USBD_CDC_SetRxBuffer(hUsbDevice_0, &Buf[0]);
  USBD_CDC_ReceivePacket(hUsbDevice_0);
  for(i = 0; i < *Len; i++)
    app_rx_buf = Buf;//将收到的数据转移到app_rx_buf数组中
  rx_f = TRUE;//将收到数据标志位置位,用以通知应用程序
  return (USBD_OK);
  /* USER CODE END 6 */
}
这样就可以进行数据的上传和下传了。

沙发
nstel| | 2016-9-17 22:48 | 只看该作者
file:///C:\Users\lvy\AppData\Local\Temp\ksohtml\wpsA2D8.tmp.jpg这些图片都看不到。能不能上传看看呢?

使用特权

评论回复
板凳
zxmxx| | 2016-9-18 09:01 | 只看该作者
学习了

使用特权

评论回复
地板
panjun10| | 2016-9-19 11:33 | 只看该作者
我想知道 有没有发送完成,接收完成的中断?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

18

主题

30

帖子

0

粉丝