STM32
直播中

刘刚

7年用户 1039经验值
私信 关注
[问答]

请教大神STM32F103C8开发板上的虚拟串口该怎样去移植呢

请教大神STM32F103C8开发板上的虚拟串口该怎样去移植呢?

回帖(1)

严晶鲁

2021-12-8 14:17:38
1 虚拟串口移植




  • 项目新建 USB 文件夹,将USB 驱动拷贝过来










  • 从官方案例的 src,inc拷贝以下文件






2 添加分组和头文件




  • 新建分组










  • 添加头文件目录






  3 修改 platform_config.h




  • 去掉红色框部分,添加如图的头文件















  • 注释掉这里






4 修改 hw_config.c

先编译



  • 注释掉 #include "stm32_it.h"
  • 添加如下的头文件


#include "u***_lib.h"
#include "u***_prop.h"
#include "u***_desc.h"
#include "u***_istr.h"
#include "hw_config.h"
#include "u***_pwr.h"
#include "usart.h"
#include "string.h"
#include "stdarg.h"
#include "stdio.h"

  • 去掉




  • 添加


_u***_usart_fifo uu_txfifo; // u***串口发送FIFO结构体,在 hw_config.h 定义
u8 USART_PRINTF_Buffer[USB_USART_REC_LEN]; // u*** printf 发送缓冲区
u8 USB_USART_RX_BUF[USB_USART_REC_LEN]; // 接收缓冲区


//接收状态
// bit15--接收完成标志
// bit14--接收到 0x0d
// bit13~0--接收到的有效字节的数目
u16 USB_USART_RX_STA = 0;
extern LINE_CODING linecoding; // u***虚拟串口配置信息(波特率、位数等),u***_prop.c 定义



  


  • hw_config.h 添加


#define USB_USART_TXFIFO_SIZE        1024 // USB虚拟串口发送FIFO大小
#define USB_USART_REC_LEN                        200 // 接收缓冲区的最大字节


//定义一个USB USART FIFO 结构体
typedef struct
{
        u8 buffer[USB_USART_TXFIFO_SIZE];
        vu16 writeptr; // 写指针
        vu16 readptr; // 读指针
}_u***_usart_fifo;


extern _u***_usart_fifo uu_txfifo;

  • 删除 void Set_System(void) 函数
  • 添加函数


void USBWakeUp_IRQHandler(void)
{
        EXTI_ClearITPendingBit(EXTI_Line18); // 清除 USB 唤醒中断挂起位
}


// USB 中断处理
void USB_LP_CAN1_RX0_IRQHandler(void)
{
        USB_Istr();
}



  • 修改 void Enter_LowPowerMode(void) 函数


void Set_USBClock(void)
{
  /* Select USBCLK source */
  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); // USB-48MHz
  /* Enable the USB clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
}



  • 修改 void Leave_LowPowerMode(void) 函数


void Leave_LowPowerMode(void)
{
  DEVICE_INFO *pInfo = &Device_Info;


        printf("leave low power modern");
  /* Set the device state to the correct state */
  if (pInfo->Current_Configuration != 0)
  {
    /* Device configured */
    bDeviceState = CONFIGURED;
  }
  else
  {
    bDeviceState = ATTACHED;
  }
  
  /*Enable SystemCoreClock*/
  //SystemInit();
}



  • 修改 void USB_Interrupts_Config(void) 函数


void USB_Interrupts_Config(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;
       
        EXTI_ClearITPendingBit(EXTI_Line18);// 开启线 18 中断
       
        EXTI_InitStructure.EXTI_Line = EXTI_Line18;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
       
        //enable u*** interrupt
        NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; //组2,优先级次之
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
       
        // enable u*** wake-up interrupt
        NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn; // 组2,优先级最高
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_Init(&NVIC_InitStructure);
       
}



  • 修改 void USB_Cable_Config (FunctionalState NewState) 函数


// NewState: DISABLE,不上拉; ENABLE,上拉;
void USB_Cable_Config (FunctionalState NewState)
{
        if(NewState != DISABLE)
                printf("u*** pull up enablern");
        else
                printf("u*** pull up disablern");
}



  • 删除 void USART_Config_Default(void) 函数
  • 添加 USB_Port_Set(u8 enable) 函数


void USB_Port_Set(u8 enable)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
       
        if(enable)
        {
                _SetCNTR(_GetCNTR() & (~(1<<1))); // 退出断电模式
        }else{
                _SetCNTR(_GetCNTR() | (1<<1)); // 断电模式
                GPIOA -> CRH &= 0xFFF00FFF;
                GPIOA -> CRH |= 0x00033000;
                PAout(12) = 0;
        }
}



  • 修改 bool USART_Config(void) 函数


// USB COM 口的配置信息打印
bool USART_Config(void)
{
        uu_txfifo.readptr = 0; // 清空读指针
        uu_txfifo.writeptr = 0;
        USB_USART_RX_STA = 0;
       
        printf("linecoding.format: %drn",linecoding.format);
        printf("linecoding.paritytype: %drn",linecoding.paritytype);
        printf("linecoding.datatype: %drn",linecoding.datatype);
        printf("linecoding.bitrate: %drn",linecoding.bitrate);
       
        return (TRUE);
}



  • 修改 void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes) 函数


// 处理从 USB 虚拟串口接收到的数据
void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes)
{
        u8 i;
        u8 res;
        for(i = 0;i < Nb_bytes; i++)
        {
                res = data_buffer;
                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; // 标记接收到了 0x0d
                                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;// 错误,重传
                                }
                        }
                }
        }
}


  • 删除 Handle_USBAsynchXfer 和 USART_To_USB_Send_Data 这两个函数;
  • 新增 USB_USART_SendData 函数,用于虚拟串口发送一个字节数据到 USB(实际上只是写到了发送 FIFO,最终还是由 EP1_IN_Callback 函数实现输出给 USB)

void USB_USART_SendData(u8 data)
{
        uu_txfifo.buffer[uu_txfifo.writeptr] = data;
        uu_txfifo.writeptr++;
        if(uu_txfifo.writeptr == USB_USART_TXFIFO_SIZE)
        {
                uu_txfifo.writeptr = 0;
        }
}

  • 删除 IntToUnicode 函数前面的 static, 在 hw_config.h 中声明这个函数
  • 新增 u***_printf 函数,实现 USB 虚拟串口的 printf


// USB 虚拟串口 printf 函数
// 确保一次发送数据不超过 USB_USART_REC_LEN 字节
void u***_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         {
                USB_USART_SendData(USART_PRINTF_Buffer[j]);
        }
}
举报

更多回帖

×
20
完善资料,
赚取积分