Git Product home page Git Product logo

ch55xduino's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ch55xduino's Issues

Timers with the Arduino IDE

Hey,
I am facing some trouble with the Timers in the Arduino IDE. When working with the CH55xTool my Code works, but with the Arduino IDE, it does not. However, I would like to use some of your libraries for example for printing into the Serial Monitor. Below there is an example code, that I could not get to run. It would be really nice if you could tell me what the problem is.

#define LED_PIN 7

SBIT(LED, 0x90, LED_PIN);
int counter = 0;
/**
SFR(TMOD,  0x89);  // timer 0/1 mode
SFR(TH0,  0x8C);  // high byte of timer 0 count
SFR(TL0,  0x8A);  // low byte of timer 0 count
SBIT(TR0,  0x88, 4); // timer0 run enable
SBIT(ET0,  0xA8, 1); // enable timer0 interrupt
SBIT(EA,  0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0
**/
void setup() {
    //CfgFsys(); <-- from ch554.h
    // Configure pin 1.7 as GPIO output
    P1_DIR_PU &= 0x0C;
    P1_MOD_OC = P1_MOD_OC & ~(1<<LED_PIN);
    P1_DIR_PU = P1_DIR_PU |  (1<<LED_PIN);

      // Init
   TMOD = 0x11;       // set Timers to 16-Bit Mode
   TH0 = 0;           // Reset High-Byte
   TL0 = 0;           // Reset Low-Byte
   TR0 = 1;          
                      // wird jetzt TH0:TL0 um 1 hochgezählt
   ET0 = 1;           // Activate Timer 0 Interrupt
   EA  = 1;           //Activate Globle Interrupt

}
void loop()
{
  //do something with the counter
}
#pragma NOOVERLAY
void Timer0(void) __interrupt (INT_NO_TMR0)
{
        counter = counter + 1;
        LED = !LED;
        TH0 = 0;  // reset of High-Byte
        TL0 = 0;  // reset of Low-Byte
}

Can I make a combined HID for keyboard and mouse?

I found a sample program for the keyboard HID, so I understood it. I looked for a sample program for the mouse, but there was none.
Please let me know if you have a sample program that is easy to understand.
Thank you very much.

DTR Line problem

`/*
UsbSerialAdaptor
A simple example turns CH552 to a serial adaptor,
relaying data between USB serial and Serial0.
Baudrate of Serial0 is determined by USB serial's rate.
created 2020
by Deqing Sun for use with CH55xduino
This example code is in the public domain.
*/

#define RTS_LINE 11
#define DTR_LINE 33

extern __xdata uint8_t LineCoding[]; //lineCoding of CDC is located in this array
extern __xdata uint8_t controlLineState;
__xdata uint32_t oldBaudRate = 9600;
__xdata uint8_t oldLineState = 1;

void setup() {
Serial0_begin(9600);
pinMode(RTS_LINE, OUTPUT);
pinMode(DTR_LINE, OUTPUT);
}

void loop() {
while (USBSerial_available()) {
char serialChar = USBSerial_read();
Serial0_write(serialChar);
}
while (Serial0_available()) {
char serialChar = Serial0_read();
USBSerial_write(serialChar);
}

__xdata uint32_t currentBaudRate = *((__xdata uint32_t *)LineCoding); //both linecoding and sdcc are little-endian
__xdata uint8_t currentLineState = controlLineState; //both linecoding and sdcc are little-endian

if (oldBaudRate != currentBaudRate) {
oldBaudRate = currentBaudRate;
Serial0_begin(currentBaudRate);
}

if (oldLineState != currentLineState) {
oldLineState = currentLineState;
digitalWrite (RTS_LINE ,!((currentLineState & 0x02) == 0x02));
digitalWrite (DTR_LINE ,!((currentLineState & 0x01) == 0x01));
}
}`

When DTR line go UP the microcontroller stop writing to the serial console. Im trying to use this microcontroller as a serial programmer for the ESP8266 and ESP 32.

I think that the problem is in the file USBCDC.c

CMSIS-DAP example fails on Win7

I've tried both with a CH552 and a CH551 module.
After power cycling the module, windows detects it, but under device status, the device status is "device cannot start (Code 10)"
The UsbSerialAdaptor example works fine.

CH552 CMISIS DAP

Hi @DeqingSun

First of all thank you for your work

I am triying your code for CMISIS DAP with CH552, but but I can't see the usb port of the device, is there any reference that it should appear?

Thanks

No support for Linux x64

I tried to install ch55xduino on Arduino IDE under a Linux 64bits, I got the following error:

"Tool MCS51Tools is not available for your operating system"

Any chance to add some Linux support?

USB MIDI?

So... I've been playing around with the CH551 and I'm trying to create a MIDI device.

I have tried to port (to CH55Xduino) and compile some code that is on github but using SDCC directly. This is the code that I have tried to compile, and i can compile it and upload it to the IC. But the device is not detected by the computer:

Maybe a little help here?

 
/********************************** (C) COPYRIGHT *******************************
* File Name    : main.c
* Author    : Zhiyuan Wan
* License   : MIT
* Version   : V1.0
* Date      : 2018/03/27
* Description   : CH55x做USB-MIDI桥。使用UAC-MIDI协议。此实例是一个简单的回环设备。
*******************************************************************************/



#include "include/ch554.h"
#include "include/ch554_usb.h"

__xdata __at (0x0000) uint8_t  Ep0Buffer[DEFAULT_ENDP0_SIZE];    //端点0 OUT&IN缓冲区,必须是偶地址
__xdata __at (0x0040) uint8_t  Ep1Buffer[DEFAULT_ENDP1_SIZE];    //端点1上传缓冲区
__xdata __at (0x0080) uint8_t  Ep2Buffer[2*MAX_PACKET_SIZE];  //端点2 IN & OUT缓冲区,必须是偶地址

uint16_t SetupLen;
uint8_t   SetupReq,Count,UsbConfig;
const uint8_t *  pDescr;                             //USB配置标志
USB_SETUP_REQ   SetupReqBuf;                           //暂存Setup包
#define UsbSetupBuf  ((PUSB_SETUP_REQ)Ep0Buffer)

/*设备描述符*/
__code uint8_t DevDesc[] = {  
        0x12,0x01,0x10,0x01,
        0x00,0x00,0x00,DEFAULT_ENDP0_SIZE, /* Define it in interface level */
        0x86,0x1a,0x22,0x57,0x00,0x01,0x01,0x02,0x03, /* VID PID bString */
        0x01
         };
        
__code uint8_t CfgDesc[] ={
  0x09,0x02,sizeof(CfgDesc) & 0xff,sizeof(CfgDesc) >> 8,
  0x02,0x01,0x00,0x80,0x32,      //配置描述符(两个接口)
  //以下为接口0(音频接口)描述符
  0x09,0x04,0x00,0x00,0x00,0x01,0x01,0x00,0x00, // USB Audio Class 描述,无端点
  //以下为功能描述符
  0x09,0x24,0x01,0x00,0x01,0x09,0x00,0x01,0x01, //功能描述符,长度大端
  //以下为接口1(MIDI接口描述符)
  0x09,0x04,0x01,0x00,0x02,0x01,0x03,0x00,0x00,
  //功能描述符
  0x07,0x24,0x01,0x00,0x01,0x25,0x00,
  //IN-JACK
  0x06,0x24,0x02,0x01,0x01,0x00,
  0x06,0x24,0x02,0x02,0x02,0x00,
  //OUT-JACK
  0x09,0x24,0x03,0x01,0x03,0x01,0x02,0x01,0x00,
  0x09,0x24,0x03,0x02,0x04,0x01,0x01,0x01,0x00,
  //以下为两个端点的描述符
  0x07,0x05,0x02,0x02,0x40,0x00,0x00,
  0x05,0x25,0x01,0x01,0x01, /* EMB MIDI JACK = 1, AssocJACKID=1, OUT */
  0x07,0x05,0x82,0x02,0x40,0x00,0x00,
  0x05,0x25,0x01,0x01,0x03 /* EMB MIDI JACK = 1, AssocJACKID=3, IN */
  
};
/*字符串描述符*/
unsigned char  __code LangDes[]={0x04,0x03,0x09,0x04};       //语言描述符
unsigned char  __code SerDes[]={                 //序列号字符串描述符
          0x14,0x03,
          '2',0x00,'0',0x00,'1',0x00,'8',0x00,'-',0x00,
          '3',0x00,'-',0x00,
          '2',0x00,'7',0x00
                 };
unsigned char  __code Prod_Des[]={                //产品字符串描述符
          0x14,0x03,
          'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00,'M',0x00,
          'I',0x00,'D',0x00,'I',0x00,
                 };
unsigned char  __code Manuf_Des[]={
  0x0A,0x03,
  0x5F,0x6c,0xCF,0x82,0x81,0x6c,0x52,0x60,
};

//MIDI参数


#define MIDI_REV_LEN  64         //串口接收缓冲区大小
__idata uint8_t Receive_Midi_Buf[MIDI_REV_LEN];   //串口接收缓冲区
volatile __idata uint8_t Midi_Input_Point = 0;   //循环缓冲区写入指针,总线复位需要初始化为0
volatile __idata uint8_t Midi_Output_Point = 0;  //循环缓冲区取出指针,总线复位需要初始化为0
volatile __idata uint8_t MidiByteCount = 0;   //当前缓冲区剩余待取字节数


volatile __idata uint8_t USBByteCount = 0;    //代表USB端点接收到的数据
volatile __idata uint8_t USBBufOutPoint = 0;  //取数据指针

volatile __idata uint8_t UpPoint2_Busy  = 0;   //上传端点是否忙标志


/*******************************************************************************
* Function Name  : USBDeviceCfg()
* Description : USB设备模式配置
* Input     : None
* Output     : None
* Return     : None
*******************************************************************************/
void USBDeviceCfg()
{
  USB_CTRL = 0x00;                               //清空USB控制寄存器
  USB_CTRL &= ~bUC_HOST_MODE;                       //该位为选择设备模式
  USB_CTRL |=  bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN;         //USB设备和内部上拉使能,在中断期间中断标志未清除前自动返回NAK
  USB_DEV_AD = 0x00;                             //设备地址初始化
  //   USB_CTRL |= bUC_LOW_SPEED;
  //   UDEV_CTRL |= bUD_LOW_SPEED;                        //选择低速1.5M模式
  USB_CTRL &= ~bUC_LOW_SPEED;
  UDEV_CTRL &= ~bUD_LOW_SPEED;                       //选择全速12M模式,默认方式
  UDEV_CTRL = bUD_PD_DIS;  // 禁止DP/DM下拉电阻
  UDEV_CTRL |= bUD_PORT_EN;                         //使能物理端口
}
/*******************************************************************************
* Function Name  : USBDeviceIntCfg()
* Description : USB设备模式中断初始化
* Input     : None
* Output     : None
* Return     : None
*******************************************************************************/
void USBDeviceIntCfg()
{
  USB_INT_EN |= bUIE_SUSPEND;                        //使能设备挂起中断
  USB_INT_EN |= bUIE_TRANSFER;                        //使能USB传输完成中断
  USB_INT_EN |= bUIE_BUS_RST;                        //使能设备模式USB总线复位中断
  USB_INT_FG |= 0x1F;                            //清中断标志
  IE_USB = 1;                                //使能USB中断
  EA = 1;                                  //允许单片机中断
}
/*******************************************************************************
* Function Name  : USBDeviceEndPointCfg()
* Description : USB设备模式端点配置,模拟兼容HID设备,除了端点0的控制传输,还包括端点2批量上下传
* Input     : None
* Output     : None
* Return     : None
*******************************************************************************/
void USBDeviceEndPointCfg()
{
  UEP1_DMA = (uint16_t) Ep1Buffer;                            //端点1 发送数据传输地址
  UEP2_DMA = (uint16_t) Ep2Buffer;                            //端点2 IN数据传输地址
  UEP2_3_MOD = 0xCC;                             //端点2/3 单缓冲收发使能
  UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;    //端点2自动翻转同步标志位,IN事务返回NAK,OUT返回ACK

  UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK;        //端点1自动翻转同步标志位,IN事务返回NAK
  UEP0_DMA = (uint16_t) Ep0Buffer;                            //端点0数据传输地址
  UEP4_1_MOD = 0X40;                             //端点1上传缓冲区;端点0单64字节收发缓冲区
  UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;        //手动翻转,OUT事务返回ACK,IN事务返回NAK
}

/*******************************************************************************
* Function Name  : DeviceInterrupt()
* Description : CH55xUSB中断处理函数
*******************************************************************************/
void DeviceInterrupt(void) __interrupt (INT_NO_USB)            //USB中断服务程序,使用寄存器组1
{
  uint16_t len;
  if(UIF_TRANSFER)                              //USB传输完成标志
  {
    switch (USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP))
    {
    case UIS_TOKEN_IN | 1:                          //endpoint 1# 端点中断上传
      UEP1_T_LEN = 0;
      UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK;      //默认应答NAK
      break;
    case UIS_TOKEN_IN | 2:                          //endpoint 2# 端点批量上传
    {
      UEP2_T_LEN = 0;                         //预使用发送长度一定要清空
      UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK;      //默认应答NAK
      UpPoint2_Busy = 0;                          //清除忙标志
    }
      break;
    case UIS_TOKEN_OUT | 2:                      //endpoint 3# 端点批量下传
      if ( U_TOG_OK )                          // 不同步的数据包将丢弃
      {
        USBByteCount = USB_RX_LEN;
        USBBufOutPoint = 0;                      //取数据指针复位
        UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK;    //收到一包数据就NAK,主函数处理完,由主函数修改响应方式
      }
      break;
    case UIS_TOKEN_SETUP | 0:                       //SETUP事务
      len = USB_RX_LEN;
      if(len == (sizeof(USB_SETUP_REQ)))
      {
        SetupLen = ((uint16_t)UsbSetupBuf->wLengthH<<8) | (UsbSetupBuf->wLengthL);
        len = 0;                            // 默认为成功并且上传0长度
        SetupReq = UsbSetupBuf->bRequest;
        if ( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )//非标准请求
        {
          switch( SetupReq )
          {
          
          default:
            len = 0xFF;                                    /*命令不支持*/
            break;
          }
        }
        else                               //标准请求
        {
          switch(SetupReq)                       //请求码
          {
          case USB_GET_DESCRIPTOR:
            switch(UsbSetupBuf->wValueH)
            {
            case 1:                            //设备描述符
              pDescr = DevDesc;                    //把设备描述符送到要发送的缓冲区
              len = sizeof(DevDesc);
              break;
            case 2:                           //配置描述符
              pDescr = CfgDesc;                     //把设备描述符送到要发送的缓冲区
              len = sizeof(CfgDesc);
              break;
            case 3:
              if(UsbSetupBuf->wValueL == 0)
              {
                pDescr = LangDes;
                len = sizeof(LangDes);
              }
              else if(UsbSetupBuf->wValueL == 1)
              {
                pDescr = Manuf_Des;
                len = sizeof(Manuf_Des);
              }
              else if(UsbSetupBuf->wValueL == 2)
              {
                pDescr = Prod_Des;
                len = sizeof(Prod_Des);
              }
              else
              {
                pDescr = SerDes;
                len = sizeof(SerDes);
              }
              break;
            default:
              len = 0xff;                       //不支持的命令或者出错
              break;
            }
            if ( SetupLen > len )
            {
              SetupLen = len; //限制总长度
            }
            len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen;             //本次传输长度
            memcpy(Ep0Buffer,pDescr,len);                 //加载上传数据
            SetupLen -= len;
            pDescr += len;
            break;
          case USB_SET_ADDRESS:
            SetupLen = UsbSetupBuf->wValueL;                //暂存USB设备地址
            break;
          case USB_GET_CONFIGURATION:
            Ep0Buffer[0] = UsbConfig;
            if ( SetupLen >= 1 )
            {
              len = 1;
            }
            break;
          case USB_SET_CONFIGURATION:
            UsbConfig = UsbSetupBuf->wValueL;
            break;
          case USB_GET_INTERFACE:
            break;
          case USB_CLEAR_FEATURE:                     //Clear Feature
            if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE )          /* 清除设备 */
            {
              if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 )
              {
                if( CfgDesc[ 7 ] & 0x20 )
                {
                  /* 唤醒 */
                }
                else
                {
                  len = 0xFF;                   /* 操作失败 */
                }
              }
              else
              {
                len = 0xFF;                     /* 操作失败 */
              }
            }
            else if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )// 端点
            {
              switch( UsbSetupBuf->wIndexL )
              {
              case 0x83:
                UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
                break;
              case 0x03:
                UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
                break;
              case 0x82:
                UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
                break;
              case 0x02:
                UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
                break;
              case 0x81:
                UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
                break;
              case 0x01:
                UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
                break;
              default:
                len = 0xFF;                    // 不支持的端点
                break;
              }
            }
            else
            {
              len = 0xFF;                       // 不是端点不支持
            }
            break;
          case USB_SET_FEATURE:                     /* Set Feature */
            if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE )          /* 设置设备 */
            {
              if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 )
              {
                if( CfgDesc[ 7 ] & 0x20 )
                {
                  /* 休眠 */
#ifdef DE_PRINTF
                  printf( "suspend\r\n" );                               //睡眠状态
#endif
                  while ( XBUS_AUX & bUART0_TX )
                  {
                    ; //等待发送完成
                  }
                  SAFE_MOD = 0x55;
                  SAFE_MOD = 0xAA;
                  WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO;            //USB或者RXD0/1有信号时可被唤醒
                  PCON |= PD;                                //睡眠
                  SAFE_MOD = 0x55;
                  SAFE_MOD = 0xAA;
                  WAKE_CTRL = 0x00;
                }
                else
                {
                  len = 0xFF;                   /* 操作失败 */
                }
              }
              else
              {
                len = 0xFF;                     /* 操作失败 */
              }
            }
            else if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_ENDP )      /* 设置端点 */
            {
              if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x00 )
              {
                switch( ( ( uint16_t )UsbSetupBuf->wIndexH << 8 ) | UsbSetupBuf->wIndexL )
                {
                case 0x83:
                  UEP3_CTRL = UEP3_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* 设置端点3 IN STALL */
                  break;
                case 0x03:
                  UEP3_CTRL = UEP3_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;/* 设置端点3 OUT Stall */
                  break;
                case 0x82:
                  UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* 设置端点2 IN STALL */
                  break;
                case 0x02:
                  UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;/* 设置端点2 OUT Stall */
                  break;
                case 0x81:
                  UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* 设置端点1 IN STALL */
                  break;
                case 0x01:
                  UEP1_CTRL = UEP1_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;/* 设置端点1 OUT Stall */
                default:
                  len = 0xFF;                 /* 操作失败 */
                  break;
                }
              }
              else
              {
                len = 0xFF;                   /* 操作失败 */
              }
            }
            else
            {
              len = 0xFF;                     /* 操作失败 */
            }
            break;
          case USB_GET_STATUS:
            Ep0Buffer[0] = 0x00;
            Ep0Buffer[1] = 0x00;
            if ( SetupLen >= 2 )
            {
              len = 2;
            }
            else
            {
              len = SetupLen;
            }
            break;
          default:
            len = 0xff;                         //操作失败
            break;
          }
        }
      }
      else
      {
        len = 0xff;                            //包长度错误
      }
      if(len == 0xff)
      {
        SetupReq = 0xFF;
        UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL;//STALL
      }
      else if(len <= DEFAULT_ENDP0_SIZE)                             //上传数据或者状态阶段返回0长度包
      {
        UEP0_T_LEN = len;
        UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//默认数据包是DATA1,返回应答ACK
      }
      else
      {
        UEP0_T_LEN = 0;  //虽然尚未到状态阶段,但是提前预置上传0长度数据包以防主机提前进入状态阶段
        UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//默认数据包是DATA1,返回应答ACK
      }
      break;
    case UIS_TOKEN_IN | 0:                            //endpoint0 IN
      switch(SetupReq)
      {
      case USB_GET_DESCRIPTOR:
        len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen;                //本次传输长度
        memcpy( Ep0Buffer, pDescr, len );                  //加载上传数据
        SetupLen -= len;
        pDescr += len;
        UEP0_T_LEN = len;
        UEP0_CTRL ^= bUEP_T_TOG;                       //同步标志位翻转
        break;
      case USB_SET_ADDRESS:
        USB_DEV_AD = USB_DEV_AD & bUDA_GP_BIT | SetupLen;
        UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
        break;
      default:
        UEP0_T_LEN = 0;                           //状态阶段完成中断或者是强制上传0长度数据包结束控制传输
        UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
        break;
      }
      break;
    case UIS_TOKEN_OUT | 0:  // endpoint0 OUT
      /*if(SetupReq ==SET_LINE_CODING)  //设置串口属性
      {
        if( U_TOG_OK )
        {
        //  memcpy(LineCoding,UsbSetupBuf,USB_RX_LEN);
        //  Config_Uart1(LineCoding);
          UEP0_T_LEN = 0;
          UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_ACK;  // 准备上传0包
        }
      }
      else
      {*/
        UEP0_T_LEN = 0;
        UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_ACK;  //状态阶段,对IN响应NAK
      //}
      break;



    default:
      break;
    }
    UIF_TRANSFER = 0;                              //写0清空中断
  }
  if(UIF_BUS_RST)                                //设备模式USB总线复位中断
  {
#ifdef DE_PRINTF
    printf( "reset\r\n" );                               //睡眠状态
#endif
    UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
    UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK;
    UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;
    USB_DEV_AD = 0x00;
    UIF_SUSPEND = 0;
    UIF_TRANSFER = 0;
    UIF_BUS_RST = 0;                               //清中断标志
    Midi_Input_Point = 0;   //循环缓冲区输入指针
    Midi_Output_Point = 0;  //循环缓冲区读出指针
    MidiByteCount = 0;    //当前缓冲区剩余待取字节数
    USBByteCount = 0;    //USB端点收到的长度
    UsbConfig = 0;      //清除配置值
    UpPoint2_Busy = 0;
  }
  if (UIF_SUSPEND)                                 //USB总线挂起/唤醒完成
  {
    UIF_SUSPEND = 0;
    if ( USB_MIS_ST & bUMS_SUSPEND )                       //挂起
    {
#ifdef DE_PRINTF
      printf( "suspend\r\n" );                               //睡眠状态
#endif
      while ( XBUS_AUX & bUART0_TX )
      {
        ; //等待发送完成
      }
      SAFE_MOD = 0x55;
      SAFE_MOD = 0xAA;
      WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO;            //USB或者RXD0/1有信号时可被唤醒
      PCON |= PD;                                //睡眠
      SAFE_MOD = 0x55;
      SAFE_MOD = 0xAA;
      WAKE_CTRL = 0x00;
    }
  }
  else {                                       //意外的中断,不可能发生的情况
    USB_INT_FG = 0xFF;                               //清中断标志

  }
}
/*******************************************************************************
* Function Name  : Uart1_ISR()
* Description : 串口接收中断函数,实现循环缓冲接收
*******************************************************************************/
#if 0
void Uart1_ISR(void) __interrupt (INT_NO_UART1)
{
  if(U1RI)   //收到数据
  {
    Receive_Uart_Buf[Uart_Input_Point++] = SBUF1;
    UartByteCount++;          //当前缓冲区剩余待取字节数
    if(Uart_Input_Point>=UART_REV_LEN)
      Uart_Input_Point = 0;      //写入指针
    U1RI =0;
  }

}
#endif

//主函数
void main1()
{
  uint8_t length = 0;
  uint8_t Midi_Timeout = 0;
  Serial0_begin(9600);

#ifdef DE_PRINTF
  printf("start ...\r\n");
#endif
  
  USBDeviceCfg();
  USBDeviceEndPointCfg();                        //端点配置
  USBDeviceIntCfg();                          //中断初始化
  UEP0_T_LEN = 0;
  UEP1_T_LEN = 0;                            //预使用发送长度一定要清空
  UEP2_T_LEN = 0;                            //预使用发送长度一定要清空

  while(1)
  {
    if(UsbConfig)
    {
      if(USBByteCount)   //USB接收端点有数据
      {
        //CH554UART1SendByte(Ep2Buffer[USBBufOutPoint++]);
        //USBByteCount--;
        //if(USBByteCount==0)
        memcpy(Receive_Midi_Buf, Ep2Buffer, USBByteCount);
        #ifdef DE_PRINTF
        printf("R=%d, %02x %02x %02x %02x\r\n", USBByteCount, Receive_Midi_Buf[0], Receive_Midi_Buf[1], Receive_Midi_Buf[2], Receive_Midi_Buf[3]);
        #endif
        
        UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK;
        length = USBByteCount;
        USBByteCount = 0;

      }
      if(MidiByteCount)
        Midi_Timeout++;
      if(!UpPoint2_Busy)   //端点不繁忙(空闲后的第一包数据,只用作触发上传)
      {
        //length = MidiByteCount;
        if(length>0)
        {
          /*if(length>39 || Midi_Timeout>100)
          {
            Midi_Timeout = 0;
            if(Midi_Output_Point+length>UART_REV_LEN)
              length = UART_REV_LEN-Midi_Output_Point;
            MidiByteCount -= length;*/
                        //Midi_Output_Point+=length;
            //if(Midi_Output_Point>=UART_REV_LEN)
            //  Midi_Output_Point = 0;
            //写上传端点
            memcpy(Ep2Buffer+MAX_PACKET_SIZE, Receive_Midi_Buf, length); //环回MIDI设备
            UEP2_T_LEN = length;                //预使用发送长度一定要清空
            UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK;     //应答ACK
            UpPoint2_Busy = 1;
            length = 0;
          //}
        }
      }
    }
  }
}

void setup(){
  
}

void loop(){
  main1();
}

USB DTR RTS lines in UsbSerialAdaptor example

I think that this module would be a great addition to other microcontrollers that not have USB stack. But for some microcontrollers like the ESP8266 or the ESP32 we need those lines.
So.... Here is the code:

/*
  UsbSerialAdaptor
  A simple example turns CH552 to a serial adaptor, 
  relaying data between USB serial and Serial0.
  Baudrate of Serial0 is determined by USB serial's rate.
  created 2020
  by Deqing Sun for use with CH55xduino
  This example code is in the public domain.
*/

#define RTS_LINE 11
#define DTR_LINE 33

extern __xdata uint8_t LineCoding[]; //lineCoding of CDC is located in this array
extern __xdata uint8_t controlLineState;
__xdata uint32_t oldBaudRate = 9600;
__xdata uint8_t oldLineState = 0;

void setup() {
  Serial0_begin(9600);
  pinMode(RTS_LINE, OUTPUT);
  pinMode(DTR_LINE, OUTPUT);
}

void loop() {
  while (USBSerial_available()) {
    char serialChar = USBSerial_read();
    Serial0_write(serialChar);
  }
  while (Serial0_available()) {
    char serialChar = Serial0_read();
    USBSerial_write(serialChar);
  }

  __xdata uint32_t currentBaudRate = *((__xdata uint32_t *)LineCoding); //both linecoding and sdcc are little-endian
  __xdata uint8_t currentLineState = controlLineState; //both linecoding and sdcc are little-endian

  if (oldBaudRate != currentBaudRate) {
    oldBaudRate = currentBaudRate;
    Serial0_begin(currentBaudRate);
  }

  if (oldLineState != currentLineState) {
    oldLineState = currentLineState;
    digitalWrite (RTS_LINE ,((currentLineState & 0x02) == 0x02));
    digitalWrite (DTR_LINE ,((currentLineState & 0x01) == 0x01));
  }
}

add 16/24Mhz F_CPU option

I just did some testing with a CH552 running at 3V3, and running at 24MHz is unstable; it seems to run for a few ms after changing the PLL, then it hangs. At 16MHz, it's fine. I had been running the MCU at 5V for a few months and never encountered problems with 24MHz.
The datasheet has some contradictory information about what speeds are supported at what voltages, but given the first chip I tested at 3V3 doesn't work at 24MHz, I think it is worth adding the option to choose 16/24Mhz.

set bLDO3V3_OFF when 3V3/16M is chosen?

Although it doesn't seem to cause any problems leaving the LDO enabled when VCC and V33 are connected to a 3.3V supply, the datasheet does recommend it be set. This could be done at the same time as the clock frequency is initialized, while the MCU is in safe mode.

add option to disable CDC serial

The Arduino Blink sketch compiles to 5333 bytes of flash, and about 4kB of that seems to be the CDC serial code. Using ch554_sdcc, examples/blink compiles to 700 bytes. By leaving out the UART code in debug.c, I reduced it to 232 bytes.

I realize that without the CDC serial code, a manual power cycle into boot mode would be required before uploading new code. I'm hoping there is a way to leave the device in DFU, while still running the user code. Some investigation into how the bootloader works would be required.

I cannot write from the ArduinoIDE.

When you press the Write button, the ArduinoIDE will display an error.


CH55x Programmer by VNPro


Load file as hex

Loaded 4388 bytes between: 0000 to 1151

Found no CH55x USB
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

image

image

image

Are the settings correct? Is there anything else I can do?

Accessing BOD settings

We have having some trouble with the CH552 chips, programmed via the Arduino IDE, becoming unstable if the supply voltage drops too much, rather than reverting to a consistent off state. Does anyone contributing on here know if there are BOD settings that might be accessible via a future update? Thanks!

Uploading a code via UART

Hi, I have to have the possibility to upload a code via UART.
Does do you mean enter in bootload mode to access as a function 0xF400 address of the CH559 chip or something else? I tried it in this way, but without any success.
Thank you in advance.

shift registers problem

I wanted to use a CH552 and a seven-segment display using a 74hc595 shift registers.
On stm8s103f3p6 (sduino) it works fine, but ch552 doesn't even compile.
I get errors:

warning 112: function 'shiftOut' implicit declaration
warning 112: function 'shiftOut' implicit declaration
error 101: too many parameters 
error 101: too many parameters 

2021-03-28_18-08-55

If I drop these two lines with "shiftOut", the sketch will compile successfully.

CH559 Port 4 "OC" mode

I have configured the pins on Port 4 as output to use I2C devices with them. Port 4 has a drive limit:

bP4_DRV - P4 port output drive capability selection, this bit is 0 to select the drive current 5mA level. This bit is 1 to select the drive current 20mA level

At default 0 this seems safe for the attached devices. It might be a usable workaround.

WinUSB driver for on-chip boot loader mode.

Just would like to check if anyone have any further success with installing Window's WinUSB driver with CH55x on chip boot loader mode.

The reason I am still "stubborn" on staying with WinUSB instead of libUSB is because Chrome's WebUSB only works with WinUSB driver (Correct me if I am wrong).

Thank you.

USB problems on XPSP2

This implementation of CDC (and others) has a problem with incomplete handlers in XPSP2.

Application of KB943198-v2 and KB945436 and the use of Zadig_xp-2.2 to install the Serial (CDC) driver makes it all work.

And yes, some of us are still supporting XPSP2!

CH552T upload problems

When I tried to upload a blink demo to a CH552T chip, I got:

------------------------------------------------------------------
CH55x Programmer by VNPro
------------------------------------------------------------------
Load file as hex
   Loaded 4393 bytes between: 0000 to 1156
Not support

2021-03-30 203417

(failed to upload the project)

But with the same code, CH551G and CH522G works just fine.

Then I export the hex file and upload it by WCHISPTool, and it works.

Maybe it's a VNPro compatible problem?

USB CDC 串口收发信息问题,接收无反应

您好,在阿莫论坛看到您的帖子,这段时间也在测试这个小板子,想请教一个问题

调试步骤:
结合usb文件夹内案例和触摸感应例程,想用电脑接收触摸的编号
烧录后电脑可以识别为usb串行设备(COMxx)的方式
然后用一个usb转串口设备(profilic)连接p3.0和p3.1,gnd,使用两个串口助手互发信息模拟发送和接收

结果:
板子对应的cdc串口调试助手发送信息,profilic可以收到信息,profilic发送的信息,CDC对应串口助手没有反应

求教:
usb cdc编程接收板子信息,比如C#直接使用serialPort类,怎么接收?还是usbCDC例程设置问题?

代码:
#ifndef USER_USB_RAM
#error "This example needs to be compiled with a USER USB setting"
#endif

#include "src/userUsbCdc/USBCDC.h"

#include <TouchKey.h>
#define LED_BUILTIN 32

__xdata uint32_t oldBaudRate = 9600;

#define Rec_Long 64
__xdata char recvStr[Rec_Long], serialStr[Rec_Long];
uint8_t recvStrPtr = 0,serialPtr = 0;

void setup() {
USBInit();
Serial0_begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
TouchKey_begin( (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) );
}

void loop() {
TouchKey_Process();
uint8_t touchResult = TouchKey_Get();
if (touchResult) {
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
for (uint8_t i = 0; i < 6; i++) {
USBSerial_print_s("TIN");
USBSerial_print_i(i);
if (touchResult & (1 << i)) {
USBSerial_print_s(" X ");
} else {
USBSerial_print_s(" _ ");
}
}
USBSerial_println();

while (USBSerial_available()) {
char serialChar = USBSerial_read();

if (recvStrPtr < Rec_Long) {
  recvStr[recvStrPtr] = serialChar;
  recvStrPtr++;
}

}

if (recvStrPtr > 0) {
Serial0_print_s("From UsbCDC:");
Serial0_println_s(recvStr);
recvStrPtr = 0;
memset(recvStr, '\0', sizeof(recvStr));
}

while (Serial0_available()) {
char serialChar = Serial0_read();

if (serialPtr < Rec_Long) {
  serialStr[serialPtr] = serialChar;
  serialPtr++;
}

}

if (serialPtr > 0) {
USBSerial_print_s("From Serial:");
USBSerial_println_s(serialStr);
serialPtr = 0;
memset(serialStr, '\0', sizeof(serialStr));
}
}

Uart0 can't work with 115200 baud rate after chosen clock source as 16Mh (internal), 3.3v or 5V

Hi,

I find my board(CH554, 3.3V power) Uart0 does not work when the baudrate is set as 115200 and clock source as "16Mh (internal), 3.3v or 5V." But it works well with 9600 with "clock source as 16Mh (internal), 3.3v or 5". And I use another board(CH552) with 5V power, it has same issue. In this way, I confirm it's not caused by power.

I use a FT232 USB to serial convertor as a sender. Its TXD is connected to P3.0(Pin10). And here is a simple code which will send the data got from Uart0 to USB port.

`
#ifndef USER_USB_RAM
#error "This example needs to be compiled with a USER USB setting"
#endif

#include "src/userUsbCdc/USBCDC.h"

void setup() {
USBInit();
Serial0_begin(115200);
}

void loop() {
while (Serial0_available()) {
char serialChar = Serial0_read();
USBSerial_write(serialChar);
USBSerial_flush();
}

}`

Could you please check it?

Thanks.

Z.t

How to Disable Reset Input Pin

I want to Disable RST pin, so the status of that pin will not reset the chip
I have made a mistake on a pcb that I use RST pin to control a LED, now I want to use pin 1.7 instead by shorting P1.7 and RST with solder bridge, but by doing that, the chip hang on reset
thanks for help

consider uint16_t for timer0 and millis

https://github.com/DeqingSun/ch55xduino/blob/ch55xduino/ch55xduino/ch55x/cores/ch55xduino/main.c#L33

In my Arduino core for AVR, I used uint16_t to save on code size and interrupt time. 65.5 seconds for delay() would likely be fine for any programs using ch55xduino.

An even more efficient way of implementing it would be to dedicate one of the 4 register banks for ISRs (a common technique in 8051 programming), and dedicate two of the registers to the counter.

enhancement: add CH551

It has 10kB of flash available according to the specs, though my testing reveals 12kB usable. It only has 512B of xRAM, no ADC, and one UART. Adding a board or MCU option for the CH551 would make ch55xduino more foolproof for newbies that don't understand the differences between the different devices.

CMSIS-DAP very slow

The speed control is of little use, since the bit-bang SWD code is so slow, it can't go any faster than 1/60th of the system clock. With a CH552 running at 16MHz, the SWD frequency was ~260kHz, even though I chose a 1MHz clock. I can think of a few ways to improve performance.

  1. Use the SPI peripheral on P1.7 & P1.5. The SPI clock can run at 1/2 the CPU clock. I'm not sure if it can send less than 8 bits, so the ACK sequence may still have to be bit-banged.
  2. Optimize the bit-bang code for maximum speed. I tried defining SW_WRITE_BITS as SWD = (bits)&1; SWK = 0; SWK = 1;, and measured the speed at ~1.25MHz. I'm not aware of any devices that can't handle a clock of at least 1.33MHz (8MHz/6 for some STM32 devices). Lower clock rates could still be supported by modifying the PLL. 6MHz, the lowest for full-speed USB operation, would give a SWD clock of 400-500kHz.
  3. Change the bit-bang timing to use a busy loop. nop + djnz reg gives a reliable delay that is a multiple of 6 cycles. Since SWD data is latched after the rising edge of SWCLK, the delay would only be needed after SWK = 1. This could support speeds from 10kHz to 1MHz.

The slow speeds is most noticeable during uploads. So far I've only tested with small programs of a few kB, but for people using large programs on devices with >64kB of flash, faster SWD speeds should make a big difference. Without buffered HID requests, the maximum USB data throughput will be less than 32KB/s. With bit-banged SWD communications at 1MHz, there should be enough CPU cycles left to get a system throughput of 20-30KB/s.

CMSIS_DAP unreliable

With a CH552 running at 16MHz and 3V3 supply, I was getting ACK failures using a STM32F0 target. When I attached my scope probes to the SWDCLK & SWDIO lines, it would work intermittently. When I looked at the capture, I could see the clock phase is wrong. It appears the code was copied from the DAPLink template, which itself is wrong.
ARMmbed/DAPLink#764

I fixed the SW_ macros in SW_DP.c, but it seems more bugs as I'm getting a transfer fault and the SWDIO is being left low instead of high.

Use type-generic macros

According to the README:

There is no free C++ compiler for MCS51 chip, we can not use polymorph functions. So you can not expect the compiler will choose a function according to the parameter's type.

C11 adds _Generic for this purpose. Here's a trivial example: https://godbolt.org/z/Yv8sznf3v

However, this currently can't be used for print due to an SDCC bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.