zanjun 发表于 2026-1-9 10:37:56

USB-CDC虚拟串口,和传统串口

程序需要单片机的串口1,兼容2种方式,不需要同时

1、通过USB有线和计算机通讯
2、串口通过蓝牙模块,无线和计算机通讯
是不是,程序中调用usb_init(),串口1就作为USB虚拟串口,否则就可以作为传统串口用


DebugLab 发表于 2026-1-9 11:15:29

USB只能使用P30、P31,所以只能复用串口1
打开USB,关闭串口,IO设置高阻使用USB
关闭USB,打开串口(包括波特率发生器),P30设置准双向+4K上拉,P31设置推挽使用串口

zanjun 发表于 2026-1-12 10:58:08

DebugLab 发表于 2026-1-9 11:15
USB只能使用P30、P31,所以只能复用串口1
打开USB,关闭串口,IO设置高阻使用USB
关闭USB,打开串口(包括 ...

谢谢回复,打开USB,就是调用usb_init()?

zanjun 发表于 2026-1-15 15:04:03

zanjun 发表于 2026-1-12 10:58
谢谢回复,打开USB,就是调用usb_init()?
使用一个IO口,上电时判断高低电平,高电平程序使用USB通讯,低电平使用传统串口
使用传统串口下载程序,试了传统串口通讯,没有问题
可USB通讯,系统不能识别出USB-CDC


bit Detect_Ext_Port(void)
{
      P33 = 1;
      Delay1ms(1);
      if (P33 == 1) return(1);
      return(0);
}

void Init_COMM(void)
{
      //串口1,与PC通讯,蓝牙
      P_SW1 &= B00111111;                //串口1在p3.0 p3.1
      PCON &= B00111111;                //速度不加倍               
      SCON = B01010000;                        //串口1,模式1,8位数据,可变波特率
      AUXR |= B00000001;                //串口1选择定时器2为波特率发生器
      AUXR |= B00000100;                //定时器2时钟为Fosc,即1T,
      AUXR &= B11110111;                //T2定时方式
      T2L = 0xD8;                                                //设定定时初值,250000,晶振40MHz
      T2H = 0xFF;                        
      AUXR |= B00010000;      //启动定时器2,T2固定16位自动重装

      //SBUF
      RI = 0;
      TI = 0;
      REN = 1;                                                      //开放串口1接收
      ES = 1;                                                                //串口1中断允许
      //IP.4 IPH.4优先级
      //0k
      EA = 1;
}

void UART1_Routine(void) interrupt 4
{
unsigned char temp;

      if (RI == 0)      return;

      temp = SBUF;
      bb = temp;
      RI = 0;
}

void Send_Byte_COM1(unsigned char chr)
{
      TI = 0;
      TB8 = 0;
NOP2();
      SBUF = chr;
      while(TI == 0);
      TI = 0;
}


void main()
{
unsigned int aa, i;
      
      bb=0;
      Delay1ms(2000);

   
      P_SW2 |= 0x80;
   
    P0M1 = 0x00;   P0M0 = 0x00;
    P1M1 = 0x00;   P1M0 = 0x00;
    P2M1 = 0x00;   P2M0 = 0x00;
    P3M1 = 0x00;   P3M0 = 0x00;
    P4M1 = 0x00;   P4M0 = 0x00;
    P5M1 = 0x00;   P5M0 = 0x00;
    P6M1 = 0x00;   P6M0 = 0x00;
    P7M1 = 0x00;   P7M0 = 0x00;
               
      P3M1 = B00001000;      //I/O口3模式控制器1,初始值=高阻输入,
      P3M0 = B00000000;
      P3PU = B00001000;      //p33高阻输入,内部4.2k上拉
   
      USB_Flag = Detect_Ext_Port();
      
      if (USB_Flag==1)
      {
                P34 = 0;
                Delay1ms(200);
                P34 = 1;
                Delay1ms(200);
                P34 = 0;

                usb_init();                //USB CDC 接口配置
      }
      if (USB_Flag==0)
      {
                P3M1 = B00000000;      //I/O口3模式控制器1,初始值=高阻输入,
                P3M0 = B00000010; //准双向口不能接上拉??
               
                Init_COMM();               
                Delay1ms(100);
      
                Send_Byte_COM1('1');
                Send_Byte_COM1('2');
                Send_Byte_COM1('3');
                Send_Byte_COM1('4');
                Send_Byte_COM1('5');
                Send_Byte_COM1('6');
               
                P34 = 0;
                Delay1ms(200);
                P34 = 1;
                Delay1ms(200);
                P34 = 0;
                Delay1ms(200);
                P34 = 1;
      }               


      EA = 1;
      
      //可有可无???可以主动发数据了
      //if(DeviceState!=DEVSTATE_CONFIGURED);      //如果USB配置没有完成,等待

      
      
      aa=0x30;

      while (1)
      {
                if (bb > 0)
                {
                        Send_Byte_COM1(bb);
                        P34 = ~P34;
                        bb = 0;
                }

                if (bUsbOutReady)
                {
                        if (UsbOutBuffer == '1')
                        {
                              ff = 1;
                        }else
                        if (UsbOutBuffer == '2')
                        {
                              ff = 0;
                              CDC_Buffer=0x36;
                              CDC_Buffer=0x37;
                              CDC_Buffer=0x38;
                              CDC_Buffer=0x39;
                              CDC_Buffer=0x41;
                              CDC_Buffer=0x42;
                              P36 = 0;
                              USB_SendData(CDC_Buffer,9);//22us,每字节2.5us,每秒400k字节
                              P36 = 1;
                        }else
                        {
                              USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
                        }
                        usb_OUT_done();//当前包的数据处理完成
                }            
               
                if (ff == 1)
                {
                        CDC_Buffer=0x55;
                        CDC_Buffer=0xAA;
                        CDC_Buffer=0x30;
                        CDC_Buffer=0x31;
                        CDC_Buffer=0x32;
                        CDC_Buffer=0x33;
                        CDC_Buffer=0x34;
                        CDC_Buffer=0x35;
                        CDC_Buffer=0x0D;
               
                        P36 = 0;
                        USB_SendData(CDC_Buffer,9);
                        P36 = 1;
                }
      }
}


使用传统串口下载如下程序,也不能识别USB


void main()
{
    P_SW2 |= 0x80;
   
    P0M1 = 0x00;   P0M0 = 0x00;
    P1M1 = 0x00;   P1M0 = 0x00;
    P2M1 = 0x00;   P2M0 = 0x00;
    P3M1 = 0x00;   P3M0 = 0x00;
    P4M1 = 0x00;   P4M0 = 0x00;
    P5M1 = 0x00;   P5M0 = 0x00;
    P6M1 = 0x00;   P6M0 = 0x00;
    P7M1 = 0x00;   P7M0 = 0x00;
   
    usb_init();                                     //USB CDC 接口配置
   
    EA = 1;

    while (1)
    {
      if (bUsbOutReady)
      {
            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            
            usb_OUT_done();
      }
    }
}


神农鼎 发表于 2026-1-16 09:51:44













#include"stc8h.h"                //头文件不分大小写,但关键字分大小写
#include"ai_usb.h"        //USB库和USB虚拟设备的头文件

voidmain(void)
{
        P_SW2 |= 0x80;                                //允许访问扩展的特殊寄存器,XFR

                                                                //32位8051需要使用下面3句进行初始化
//        EAXFR = 1;                                        //允许访问扩展的特殊寄存器,XFR
//        WTST = 0;                                        //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
//        CKCON = 0;                                        //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间

        P0M0 = 0x00; P0M1 = 0x00;        //初始化P0口为准双向口模式
        P1M0 = 0x00; P1M1 = 0x00;         //初始化P1口为准双向口模式
        P2M0 = 0x00; P2M1 = 0x00;         //初始化P2口为准双向口模式
        P3M0 = 0x00; P3M1 = 0x00;         //初始化P3口为准双向口模式
        P4M0 = 0x00; P4M1 = 0x00;         //初始化P4口为准双向口模式
        P5M0 = 0x00; P5M1 = 0x00;         //初始化P5口为准双向口模式

        usb_init();
        //初始化USB模块,并且会将【P3.0,P3.1】初始化为高阻输入,不影响USB【D-,D+】通讯
        EA = 1;                //使能总中断

        while (1)
        {
                printf_usb("Hello World !\r\n");
                //\r是回车,并跳到行首,\n是换行,就是换到下一行;\r\n不要交换次序
        }
}


推荐优先看的 printf_usb()及usb不停电下载演示视频 - 学习打卡区 ,为集中维护,一个学习专题只发一个贴持续跟贴 国芯人工智能技术交流网站 - AI32位8051交流社区

页: [1]
查看完整版本: USB-CDC虚拟串口,和传统串口