├── .cproject ├── .gitattributes ├── .gitignore ├── .project ├── LICENSE ├── README.md ├── USBCompositeDevice.uvopt ├── USBCompositeDevice.uvproj ├── bootloader.c ├── bootloader.h ├── ch554_conf.c ├── ch554_conf.h ├── ch554_platform.h ├── delay.c ├── delay.h ├── host ├── .gitignore ├── CH554_CDC_BusBridge.sln ├── CH554_CDC_BusBridge.vcxproj ├── CH554_CDC_BusBridge.vcxproj.filters ├── Makefile ├── flash25.c ├── flash25.h ├── main.c ├── rikka.png ├── rs232.c ├── rs232.h ├── spi.c └── spi.h ├── i2c.c ├── i2c.h ├── include ├── ch554.h ├── ch554_datatypes.h └── ch554_usb.h ├── keilc51 ├── CH554.H └── CH554.INC ├── main.c ├── spi.c ├── spi.h ├── usb_cdc.c ├── usb_cdc.h ├── usb_desc.c ├── usb_desc.h ├── usb_endp.c ├── usb_endp.h ├── usb_ep0.c ├── usb_it.c └── usb_string_desc.c /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 29 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | # Keil 55 | Listings/ 56 | Objects/ 57 | *.build_log.htm 58 | *.uvgui.* 59 | 60 | # Eclipse SDCC 61 | .settings/ 62 | Release/ 63 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | USB_CDC 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 24 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 rikka0w0 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CH554 USB CDC 2 | 3 | This demo emulates a USB CDC, which is equivalent to a UART port. (本演示程序模拟了一个USB CDC设备, 可以当作串口使用): 4 | 5 | Author(作者): Rikka0w0 (小六花) 6 | Original Author(原作者): rgwan (Zhiyuan Wan) 7 | 8 | * `keilc51\CH554.H`, `Delay.C` and `Delay.h` comes from official CH554 demo (WCH), the USB MSD implementation is inspired by the USB MSD demo for STM32 (ST). 9 | (`keilc51\CH554.H`, `Delay.C`和`Delay.h`是从WCH官方的示例代码里提取的,U盘部分程序参考了STM32的USB MSD示例) 10 | * All file in folder `includes` comes from Github repository [Blinkinlabs's ch554_sdcc](https://github.com/Blinkinlabs/ch554_sdcc). 11 | (`includes`文件夹中的文件是从[Blinkinlabs's ch554_sdcc](https://github.com/Blinkinlabs/ch554_sdcc)里复制的) 12 | * Compiler/IDE: Keil uVersion & SDCC. (编译器/开发环境:Keil 礦ision和SDCC) 13 | * A Wiki page describes how to setup SDCC on Windows and Linux. (Wiki中会介绍如何在Windows和Linux上搭建SDCC编译环境) 14 | * Feel free to use this demo as the template/start of a open-source or non-commercial project, modifying source code and republishing is allowed. 15 | (对于开源项目和非商业项目,可以是用本演示代码作为起点或者模板,作者允许修改并重新发布这份代码) 16 | * However you __MUST__ contact the author for permission prior to use this demo for commercial purposes. 17 | (__如果用于商业目的的话,必须提前得到作者的允许__) 18 | 19 | # Hardware Setup(硬件配置): 20 | * The hardware is based on the minimal circuit setup of CH554 21 | (硬件基于CH554的最小系统) 22 | * Chip is directly powered by Vbus, which is approximately 5V 23 | (芯片直接由Vbus驱动,大约是5V) 24 | * P1.5 = I2C SDA, P1.4 = I2C SCL, defined in `i2c.c`, each pin is pull-up by a 1k resistor to 5V. 25 | (I2C引脚定义在`i2c.c`里面,每个脚都要一个1k的上拉电阻,上拉到5V) 26 | * Pin 1 to pin 4 of 24LC512 are connected to ground, Pin 8 connect to 5V, Pin5 is I2C SDA and Pin6 is I2C SCL, Pin7 is floating. 27 | (24LC512 EEPROM的1到4脚都接地,8脚连接5V,5脚对应I2C SDA,6脚对应I2C SCL,七脚悬空) 28 | 29 | 30 | # Capabilities(能做到什么): 31 | ## USB Mass Storage Device (USB大容量储存设备) 32 | * Emulate a 512Kib I2C EEPROM 24LC512 as a 64KB USB Drive 33 | (用512Kib的I2C总线EEPROM 24LC512模拟了一个64KB的U盘) 34 | * Read, write, delete and format operations are fully supported. 35 | (完全支持各种读写删除还有格式化操作) 36 | * Support safe media ejection in Windows, Linux and Mac OS X 37 | (在Windows, Linux和Mac OS X上支持安全弹出介质) 38 | * Use USB Endpoint 3 IN and OUT, Interface 2, Bulk-only transfer 39 | (使用了端点3的IN和OUT,2号接口,BOT传输) 40 | ## USB Keyboard (USB键盘) 41 | * Simulate key press and release, and send them to the host. 42 | (可以模拟键盘按键操作并发往主机) 43 | * Use USB Endpoint 1 IN, Interface 1, Interrupt transfer 44 | (使用了端点2的IN,1号接口, 中断传输) 45 | ## USB Vendor-Define HID (厂商自定义的USB HID设备) 46 | * Exchange data (receive and send) with host, up to 64 bytes each time 47 | (可以和主机交换数据,每次最多64字节) 48 | * Use USB Endpoint 2 IN, Interface 0, Interrupt transfer 49 | (使用了端点2的IN, 0号接口,中断传输) 50 | ## UART (串口) 51 | * UART0, no function re-mapping (0号串口,没有io重映射) 52 | * Exchange data (receive and send) with host (可以和主机交换数据) 53 | * Support printf (支持printf) 54 | ## I2C 55 | * CH55x does not have built-in I2C peripheral (CH55x系列木有内置I2C通信外设) 56 | * Implement and emulate a I2C peripheral with GPIO (用GPIO来模拟I2C总线通信) 57 | 58 | # File Structure(文件结构): 59 | ## main.c 60 | * void main(void) {} 61 | * USB Device Interrupt Entry(USB设备中断函数入口) 62 | ## Delay.c Delay.h 63 | * Delay (延时函数) 64 | ## ch554_platform.h 65 | * Define uint8_t, uint32_t e.t.c (定义uint8_t, uint32_t等等标准类型) 66 | * Handle the difference between Keil C51 and SDCC 67 | (处理Keil C51和SDCC编译器之间的差异) 68 | * `U16B0` returns the lowest byte of a 16-bit integer, regardless of endian, similar defination for `U16B1`, `U32B0` e.t.c 69 | (`U16B0`会返回一个16位整数的低字节,与端无关,`U16B1`, `U32B0`等也是类似功能) 70 | * `U16_XBig` converts a big-endian 16-bit integer to fit the local endian, vise versa, similar defination for `U16_XLittle`, `U32_XBig` and `U32_XLittle`. 71 | (`U16_XBig`用于将一个大端储存的16位数转换成当前的端方式,也可以用于反向转换,`U16_XLittle`, `U32_XBig`和`U32_XLittle`的作用类似) 72 | * Instead of using `sbit led=P1^1`, use `SBIT(var, port, bin)` to declare a bit variable, for example, `SBIT(led, GPIO1, 1)`, this facilitates compilation under different compilers. 73 | (最好用`SBIT(var, port, bin)`来声明位变量,比如`SBIT(led, GPIO1, 1)`来代替`sbit led=P1^1`,这样有助于在不同编译器下编译程序) 74 | ## ch554_conf.c ch554_conf.h 75 | * Configure system clock (配置系统时钟) 76 | * Initialize USB Device (初始化USB设备) 77 | * Initialize UART0 (初始化串口0) 78 | * Set system clock frequency and UART0 baud rate in ch554_conf.h 79 | (在ch554_conf.h里设置系统时钟频率和UART0的波特率) 80 | ## i2c.c i2c.h 81 | * Emulate a I2C bus host with GPIO (用GPIO来模拟一个I2C总线主机) 82 | * `I2C_DELAY(void)` controls the I2C clock frequency 83 | * `I2C_WriteByte()` sends the data byte in `I2C_Buf` to I2C bus and return the ACK status in bit 0 of `I2C_Buf` then release the I2C bus, 84 | 0 means ACK and 1 means NACK. 85 | (`I2C_WriteByte()`会把`I2C_Buf`里的一个字节发送到I2C总线上并在`I2C_Buf`的最低位返回ACK的状态然后释放I2C总线,0为ACK,1为NACK) 86 | * `I2C_ReadByte(void)` reads a byte from I2C bus and store it in `I2C_Buf`. 87 | (`I2C_ReadByte(void)`从I2C总线上读一个字节然后放在`I2C_Buf`里面) 88 | ## usb_it.c 89 | * USB interrupt service routine (USB中断处理函数) 90 | * Handle USB bus reset/suspend/wakeup (处理USB总线重置/挂起/唤醒) 91 | * Dispatch incoming requests to EndPoint service functions (把主机发来的请求分发给端点的处理函数) 92 | ## usb_endp.h 93 | * Declear EndPoint buffers (声明端点的缓存) 94 | * Toggle certain EndPoint service function (开启或者关闭相关的端点处理函数) 95 | ## usb_endp.c 96 | * Define EndPoint buffers (定义端点的缓存以及大小) 97 | * `USB_EP_HALT_SET(ep)` and `USB_EP_HALT_CLEAR(ep)` stall or restore an EndPoint as the host requests 98 | (`USB_EP_HALT_SET(ep)`和`USB_EP_HALT_CLEAR(ep)`根据主机请求挂起stall或者恢复端点) 99 | * Optionally, add your EndPoint service functions here (如果愿意可以把USB的端点处理函数放在这里) 100 | ## usb_ep0.c 101 | * Contain service routine for EndPoint 0 SETUP/IN/OUT 102 | (包含端点0的SETUP/IN/OUT事务的处理函数) 103 | * Handle requests sent by host during enumeration phase 104 | (在枚举的时候负责回应主机的请求) 105 | ## usb_desc.h 106 | * Define the total length of Config Descriptor, including Interface Descriptor e.t.c (定义配置描述符的总大小,包含接口描述符等) 107 | * Define the total number of String Descriptor (定义字符描述符的数量) 108 | * Define length of HID Report Descriptors (定义各种HID报告描述符的大小) 109 | ## usb_desc.c 110 | * Define Device Descriptor (定义设备描述符) 111 | * Define Configuration Descriptor and Interface Descriptor (定义配置和接口描述符) 112 | ## usb_string_desc.c 113 | * Define custom String Descriptors (定义自定义的字符描述符) 114 | * String Descriptor 0 is reserved for language configuration (0号字符描述符是为语言标识保留的) 115 | 116 | # Notes: 117 | * The only difference between CH554 and CH552 is that, CH552 only supports USB device mode while CH554 can also be programmed as a Host. 118 | So this demo may work on CH552 as well. (CH552只能作为USB的设备,而CH554还可以作为USB主机,这是两种芯片唯一的区别。因此本Demo可能也能在CH552上正常工作) 119 | * 8051 systems including CH554 is big-endian while x86 and ARM processors are little-endian. 120 | (8051系统包括CH554是大端存储的,即数据的高位放在低内存地址中,而x86和ARM处理器都是小端存储的) 121 | * USB packets are little-endian, keep this in mind! 122 | (USB包都是小端的,特别需要注意!) 123 | * SDCC requires that all interrupt service functions must be written inside the same .c file containing `void main(void)`, 124 | otherwise SDCC can not find them. According to official SDCC documentation, it's not a bug but a feature. Keil C51 doesn't have this limitaion. 125 | (SDCC要求中断处理函数必须和main函数放在一个.c文件中,否则SDCC没办法找到这些函数。根据SDCC官方文档,这是一个特性不算Bug,Keil C51编译器没有这种限制) -------------------------------------------------------------------------------- /USBCompositeDevice.uvopt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.0 5 | 6 |
### uVision Project, (C) Keil Software
7 | 8 | 9 | *.c 10 | *.s*; *.src; *.a* 11 | *.obj 12 | *.lib 13 | *.txt; *.h; *.inc 14 | *.plm 15 | *.cpp 16 | 0 17 | 18 | 19 | 20 | 0 21 | 0 22 | 23 | 24 | 25 | Target 1 26 | 0x0 27 | MCS-51 28 | 29 | 24000000 30 | 31 | 1 32 | 1 33 | 1 34 | 0 35 | 0 36 | 37 | 38 | 0 39 | 65535 40 | 0 41 | 0 42 | 0 43 | 44 | 45 | 120 46 | 65 47 | 8 48 | .\Listings\ 49 | 50 | 51 | 1 52 | 1 53 | 1 54 | 0 55 | 1 56 | 1 57 | 0 58 | 1 59 | 0 60 | 0 61 | 0 62 | 0 63 | 64 | 65 | 1 66 | 1 67 | 1 68 | 1 69 | 1 70 | 1 71 | 1 72 | 0 73 | 0 74 | 75 | 76 | 1 77 | 0 78 | 1 79 | 80 | 255 81 | 82 | 83 | 0 84 | Data Sheet 85 | DATASHTS\SST\SST89C5X.PDF 86 | 87 | 88 | 89 | 1 90 | 0 91 | 1 92 | 1 93 | 1 94 | 1 95 | 1 96 | 1 97 | 1 98 | 1 99 | 0 100 | 1 101 | 1 102 | 1 103 | 0 104 | 1 105 | 1 106 | 1 107 | 1 108 | 0 109 | 0 110 | -1 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 0 126 | DLGDP51 127 | (98=-1,-1,-1,-1,0)(82=-1,-1,-1,-1,0)(83=-1,-1,-1,-1,0)(84=-1,-1,-1,-1,0)(85=-1,-1,-1,-1,0)(3003=-1,-1,-1,-1,0)(91=-1,-1,-1,-1,0)(92=-1,-1,-1,-1,0)(93=-1,-1,-1,-1,0) 128 | 129 | 130 | 131 | 132 | 0 133 | 134 | 135 | 0 136 | 1 137 | 1 138 | 0 139 | 0 140 | 0 141 | 0 142 | 1 143 | 0 144 | 0 145 | 0 146 | 0 147 | 0 148 | 0 149 | 0 150 | 0 151 | 0 152 | 0 153 | 0 154 | 0 155 | 0 156 | 0 157 | 0 158 | 0 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Source Group 1 167 | 1 168 | 0 169 | 0 170 | 0 171 | 172 | 1 173 | 1 174 | 1 175 | 0 176 | 0 177 | 0 178 | 0 179 | .\usb_ep0.c 180 | usb_ep0.c 181 | 0 182 | 0 183 | 184 | 185 | 1 186 | 2 187 | 1 188 | 0 189 | 0 190 | 0 191 | 0 192 | .\usb_desc.c 193 | usb_desc.c 194 | 0 195 | 0 196 | 197 | 198 | 1 199 | 3 200 | 1 201 | 0 202 | 0 203 | 0 204 | 0 205 | .\usb_it.c 206 | usb_it.c 207 | 0 208 | 0 209 | 210 | 211 | 1 212 | 4 213 | 1 214 | 0 215 | 0 216 | 0 217 | 0 218 | .\usb_endp.c 219 | usb_endp.c 220 | 0 221 | 0 222 | 223 | 224 | 1 225 | 5 226 | 1 227 | 0 228 | 0 229 | 0 230 | 0 231 | .\usb_string_desc.c 232 | usb_string_desc.c 233 | 0 234 | 0 235 | 236 | 237 | 1 238 | 6 239 | 1 240 | 0 241 | 0 242 | 0 243 | 0 244 | .\i2c.c 245 | i2c.c 246 | 0 247 | 0 248 | 249 | 250 | 1 251 | 7 252 | 1 253 | 0 254 | 0 255 | 0 256 | 0 257 | .\ch554_conf.c 258 | ch554_conf.c 259 | 0 260 | 0 261 | 262 | 263 | 1 264 | 8 265 | 1 266 | 0 267 | 0 268 | 0 269 | 0 270 | .\main.c 271 | main.c 272 | 0 273 | 0 274 | 275 | 276 | 1 277 | 9 278 | 1 279 | 0 280 | 0 281 | 0 282 | 0 283 | .\bootloader.c 284 | bootloader.c 285 | 0 286 | 0 287 | 288 | 289 | 1 290 | 10 291 | 1 292 | 0 293 | 0 294 | 0 295 | 0 296 | .\delay.c 297 | delay.c 298 | 0 299 | 0 300 | 301 | 302 | 1 303 | 11 304 | 1 305 | 0 306 | 0 307 | 0 308 | 0 309 | .\usb_cdc.c 310 | usb_cdc.c 311 | 0 312 | 0 313 | 314 | 315 | 1 316 | 12 317 | 1 318 | 0 319 | 0 320 | 0 321 | 0 322 | .\spi.c 323 | spi.c 324 | 0 325 | 0 326 | 327 | 328 | 329 |
330 | -------------------------------------------------------------------------------- /USBCompositeDevice.uvproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1.1 5 | 6 |
### uVision Project, (C) Keil Software
7 | 8 | 9 | 10 | Target 1 11 | 0x0 12 | MCS-51 13 | 14 | 15 | SST89C54 16 | SST 17 | IRAM(0-0xFF) IROM(0-0x3FFF) CLOCK(33000000) 18 | 19 | "LIB\STARTUP.A51" ("Standard 8051 Startup Code") 20 | 21 | 2932 22 | REG52.H 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 0 34 | 0 35 | 36 | 37 | 38 | 39 | 40 | 41 | 0 42 | 0 43 | 0 44 | 0 45 | 1 46 | 47 | .\Objects\ 48 | USBCompositeDevice 49 | 1 50 | 0 51 | 1 52 | 1 53 | 1 54 | .\Listings\ 55 | 0 56 | 0 57 | 0 58 | 59 | 0 60 | 0 61 | 62 | 63 | 0 64 | 0 65 | 0 66 | 0 67 | 68 | 69 | 0 70 | 0 71 | 72 | 73 | 0 74 | 0 75 | 0 76 | 0 77 | 78 | 79 | 0 80 | 0 81 | 82 | 83 | 0 84 | 0 85 | 86 | 0 87 | 88 | 89 | 90 | 0 91 | 0 92 | 0 93 | 0 94 | 0 95 | 1 96 | 0 97 | 0 98 | 0 99 | 0 100 | 3 101 | 102 | 103 | 1 104 | 65535 105 | 106 | 107 | S8051.DLL 108 | 109 | DP51.DLL 110 | -pSST5X 111 | S8051.DLL 112 | 113 | TP51.DLL 114 | -pSST5X 115 | 116 | 117 | 118 | 0 119 | 0 120 | 0 121 | 0 122 | 16 123 | 124 | 125 | 1 126 | 1 127 | 1 128 | 1 129 | 1 130 | 1 131 | 1 132 | 1 133 | 0 134 | 1 135 | 136 | 137 | 0 138 | 1 139 | 0 140 | 1 141 | 1 142 | 1 143 | 0 144 | 1 145 | 1 146 | 1 147 | 148 | 0 149 | -1 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 1 169 | 0 170 | 0 171 | 0 172 | 0 173 | -1 174 | 175 | 0 176 | 177 | "" () 178 | 179 | 180 | 181 | 182 | 0 183 | 184 | 185 | 186 | 0 187 | 0 188 | 2 189 | 0 190 | 0 191 | 0 192 | 0 193 | 0 194 | 0 195 | 1 196 | 0 197 | 1 198 | 0 199 | 0 200 | 0 201 | 0 202 | 0 203 | 0 204 | 0 205 | 0 206 | 0 207 | 0 208 | 0 209 | 0 210 | 0 211 | 0 212 | 0 213 | 0 214 | 0 215 | 0 216 | 0 217 | 0 218 | 0 219 | 0 220 | 0 221 | 0 222 | 0 223 | 0 224 | 0 225 | 0 226 | 0 227 | 228 | 229 | 0 230 | 0x0 231 | 0xffff 232 | 233 | 234 | 0 235 | 0x0 236 | 0x0 237 | 238 | 239 | 0 240 | 0x0 241 | 0x0 242 | 243 | 244 | 0 245 | 0x0 246 | 0x0 247 | 248 | 249 | 0 250 | 0x0 251 | 0x0 252 | 253 | 254 | 0 255 | 0x0 256 | 0x0 257 | 258 | 259 | 0 260 | 0x0 261 | 0x0 262 | 263 | 264 | 0 265 | 0x0 266 | 0x0 267 | 268 | 269 | 1 270 | 0x0 271 | 0x4000 272 | 273 | 274 | 0 275 | 0x0 276 | 0x100 277 | 278 | 279 | 0 280 | 0x0 281 | 0x0 282 | 283 | 284 | 0 285 | 0x0 286 | 0x0 287 | 288 | 289 | 0 290 | 0x0 291 | 0x0 292 | 293 | 294 | 295 | 296 | 0 297 | 0 298 | 1 299 | 0 300 | 1 301 | 3 302 | 8 303 | 2 304 | 1 305 | 1 306 | 0 307 | 0 308 | 309 | 310 | CLOCK_FREQ_24 311 | 312 | 313 | 314 | 315 | 316 | 0 317 | 1 318 | 0 319 | 0 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 0 329 | 0 330 | 1 331 | 0 332 | 2 333 | 1 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | Source Group 1 363 | 364 | 365 | usb_ep0.c 366 | 1 367 | .\usb_ep0.c 368 | 369 | 370 | usb_desc.c 371 | 1 372 | .\usb_desc.c 373 | 374 | 375 | usb_it.c 376 | 1 377 | .\usb_it.c 378 | 379 | 380 | usb_endp.c 381 | 1 382 | .\usb_endp.c 383 | 384 | 385 | usb_string_desc.c 386 | 1 387 | .\usb_string_desc.c 388 | 389 | 390 | i2c.c 391 | 1 392 | .\i2c.c 393 | 394 | 395 | ch554_conf.c 396 | 1 397 | .\ch554_conf.c 398 | 399 | 400 | main.c 401 | 1 402 | .\main.c 403 | 404 | 405 | bootloader.c 406 | 1 407 | .\bootloader.c 408 | 409 | 410 | 2 411 | 0 412 | 0 413 | 0 414 | 0 415 | 2 416 | 2 417 | 1 418 | 1 419 | 2 420 | 11 421 | 422 | 423 | 1 424 | 65535 425 | 426 | 427 | 428 | 2 429 | 2 430 | 2 431 | 2 432 | 2 433 | 8 434 | 10 435 | 3 436 | 2 437 | 2 438 | 2 439 | 0 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | delay.c 452 | 1 453 | .\delay.c 454 | 455 | 456 | usb_cdc.c 457 | 1 458 | .\usb_cdc.c 459 | 460 | 461 | spi.c 462 | 1 463 | .\spi.c 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 |
472 | -------------------------------------------------------------------------------- /bootloader.c: -------------------------------------------------------------------------------- 1 | #include "bootloader.h" 2 | #include "delay.h" 3 | #include "ch554_platform.h" 4 | 5 | void JumpToBootloader(void) { 6 | USB_INT_EN = 0; 7 | USB_CTRL = 0x06; 8 | 9 | mDelaymS(100); 10 | 11 | EA = 0;/* Disable all interrupts */ 12 | 13 | #ifdef __SDCC 14 | __asm 15 | LJMP BOOT_ADDR /* Jump to bootloader */ 16 | __endasm; 17 | #endif 18 | 19 | #ifdef __C51__ 20 | #pragma asm 21 | LJMP BOOT_ADDR /* Jump to bootloader */ 22 | #pragma endasm 23 | #endif 24 | 25 | while(1); 26 | } 27 | -------------------------------------------------------------------------------- /bootloader.h: -------------------------------------------------------------------------------- 1 | #ifndef __BOOTLOADER_H 2 | #define __BOOTLOADER_H 3 | 4 | #define BOOT_ADDR 0x3800 5 | 6 | void JumpToBootloader(void); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /ch554_conf.c: -------------------------------------------------------------------------------- 1 | #include "Delay.H" 2 | #include "ch554_platform.h" 3 | 4 | #include "usb_desc.h" 5 | #include "usb_endp.h" 6 | #include "i2c.h" 7 | #include "spi.h" 8 | 9 | 10 | void ConfigSysClock() { 11 | //SAFE_MOD = 0x55; 12 | //SAFE_MOD = 0xAA; 13 | //CLOCK_CFG |= bOSC_EN_XT; // Enable External Crystal 14 | //CLOCK_CFG &= ~bOSC_EN_INT; // Disable External Crystal 15 | 16 | // Enters `safe mode` for next 13 to 23 CPU clock cycles 17 | SAFE_MOD = 0x55; 18 | SAFE_MOD = 0xAA; 19 | 20 | #if defined CLOCK_FREQ_32 21 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz 22 | #elif defined CLOCK_FREQ_24 23 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz 24 | #elif defined CLOCK_FREQ_16 25 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz 26 | #elif defined CLOCK_FREQ_12 27 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz 28 | #elif defined CLOCK_FREQ_6 29 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz 30 | #elif defined CLOCK_FREQ_3 31 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz 32 | #elif defined CLOCK_FREQ_P750 33 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz 34 | #elif defined CLOCK_FREQ_P1875 35 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5KHz 36 | #else 37 | #error "Clock frequency is not configured!" 38 | #endif 39 | 40 | SAFE_MOD = 0x00; 41 | } 42 | 43 | void USBDevice_Init() { 44 | IE_USB = 0; // Disable USB interrupt (for setup) 45 | USB_CTRL = 0x00; // Device mode, Full speed(12Mbps), Disable pull up(Invisible to host), Reset stuff 46 | //UDEV_CTRL = bUD_PD_DIS; //Disable DP/DN pull down resistor 47 | 48 | //Configure Endpoint 0 49 | UEP0_DMA_L = (uint8_t) Ep0Buffer; // Address of Endpoint 0 buffer 50 | // bUEP4_RX_EN and bUEP4_TX_EN controls both Endpoint 0 and 4, refer to table 16.3.2 51 | UEP4_1_MOD &= ~(bUEP4_RX_EN | bUEP4_TX_EN); // EP0 64-byte buffer 52 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; // SETUP/OUT -> ACK, IN -> NAK 53 | 54 | //Configure Endpoint 1 55 | UEP1_DMA_L = (uint8_t) Ep1Buffer; // Address of Endpoint 1 buffer 56 | //UEP4_1_MOD = UEP4_1_MOD & ~bUEP1_BUF_MOD | bUEP1_TX_EN; 57 | UEP4_1_MOD &=~bUEP1_BUF_MOD; //See table 16.3.3 58 | UEP4_1_MOD |= bUEP1_TX_EN; // EP1 Tx only, 64 bytes of buffer 59 | // Enable DATA0/DATA1 toggling, Reply NAK for IN transactions 60 | UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK; 61 | 62 | //Configure Endpoint 2 63 | UEP2_DMA_L = (uint8_t) Ep2Buffer; // Address of Endpoint 2 buffer 64 | //UEP2_3_MOD = UEP2_3_MOD & ~bUEP2_BUF_MOD | bUEP2_TX_EN; 65 | UEP2_3_MOD &=~bUEP2_BUF_MOD; // Disable Endpoint2 buffer mode 66 | UEP2_3_MOD |= bUEP2_TX_EN; // Enable Endpoint2 Tx 67 | UEP2_3_MOD |= bUEP2_RX_EN; // Enable Endpoint2 Rx 68 | // Enable DATA0/DATA1 toggling, Reply NAK for IN transactions, ACK for OUT transactions 69 | UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; 70 | 71 | // Setup interrupts 72 | USB_INT_FG = 0xFF; // Clear interrupt flags 73 | // Generate a interrupt when USB bus suspend | transfer complete | bus reset 74 | USB_INT_EN = bUIE_SUSPEND | bUIE_TRANSFER | bUIE_BUS_RST; 75 | IE_USB = 1; //Enable USB interrupt 76 | 77 | 78 | // Get ready for enumeration 79 | USB_DEV_AD = 0x00; //Set USB address to 0, get ready for enumeration 80 | // Connect pull up resistor | While handling interrup, reply NAK t if flag is set | Enable DMA 81 | USB_CTRL = bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; 82 | UDEV_CTRL |= bUD_PORT_EN; // Enable USB Port 83 | 84 | // Reset all tx length to 0 85 | UEP1_T_LEN = 0; 86 | UEP2_T_LEN = 0; 87 | } 88 | 89 | void UART0_Init(void) { 90 | uint32_t x; 91 | uint8_t x2; 92 | 93 | SM0 = 0; 94 | SM1 = 1; 95 | SM2 = 0; // UART0 Mode 0 96 | 97 | // Use Timer1 as the baud rate generator 98 | RCLK = 0; 99 | TCLK = 0; 100 | PCON |= SMOD; 101 | x = 10 * FREQ_SYS / UART0_BUAD / 16; 102 | x2 = x % 10; 103 | x /= 10; 104 | if ( x2 >= 5 ) x ++; // Round 105 | 106 | TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1; // Timer1: 8-bit auto reload 107 | T2MOD = T2MOD | bTMR_CLK | bT1_CLK; // Select input clock for Timer1 108 | TH1 = 0-x; 109 | TR1 = 1; // Start Timer1 110 | TI = 1; 111 | REN = 1; // Enable UART1 112 | } 113 | 114 | void CH554_Init(void) { 115 | ConfigSysClock(); 116 | mDelaymS(5); // Wait until the internal crystal becomes stable 117 | 118 | //UART0_Init(); 119 | I2C_Init(); 120 | SPI_SetMasterMode3(); 121 | SPI_SetMasterIOFloat(); 122 | SPI_SetClockDivider(4); 123 | 124 | USBDevice_Init(); 125 | 126 | EA = 1; 127 | } 128 | 129 | //void putchar(char c) { 130 | // while (!TI) /* assumes UART is initialized */ 131 | // ; 132 | // TI = 0; 133 | // SBUF = c; 134 | //} 135 | // 136 | //char getchar() { 137 | // while(!RI); /* assumes UART is initialized */ 138 | // RI = 0; 139 | // return SBUF; 140 | //} 141 | 142 | //void putchar(char data); 143 | //char getchar(); 144 | -------------------------------------------------------------------------------- /ch554_conf.h: -------------------------------------------------------------------------------- 1 | #ifndef __CH554_CONF_H__ 2 | #define __CH554_CONF_H__ 3 | 4 | #define UART0_BUAD 57600 5 | 6 | //#define CLOCK_FREQ_32 7 | //#define CLOCK_FREQ_24 8 | //#define CLOCK_FREQ_16 9 | //#define CLOCK_FREQ_12 10 | //#define CLOCK_FREQ_6 11 | //#define CLOCK_FREQ_3 12 | //#define CLOCK_FREQ_P750 13 | //#define CLOCK_FREQ_P1875 14 | 15 | #ifdef CLOCK_FREQ_32 16 | #define FREQ_SYS 32000000 17 | #endif 18 | #ifdef CLOCK_FREQ_24 19 | #define FREQ_SYS 24000000 20 | #endif 21 | #ifdef CLOCK_FREQ_16 22 | #define FREQ_SYS 16000000 23 | #endif 24 | #ifdef CLOCK_FREQ_12 25 | #define FREQ_SYS 12000000 26 | #endif 27 | #ifdef CLOCK_FREQ_6 28 | #define FREQ_SYS 6000000 29 | #endif 30 | #ifdef CLOCK_FREQ_3 31 | #define FREQ_SYS 3000000 32 | #endif 33 | #ifdef CLOCK_FREQ_P750 34 | #define FREQ_SYS 750000 35 | #endif 36 | #ifdef CLOCK_FREQ_P1875 37 | #define FREQ_SYS 187500 38 | #endif 39 | 40 | 41 | void CH554_Init(void); 42 | 43 | // Interrupt Handlers 44 | void USBInterrupt(void); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /ch554_platform.h: -------------------------------------------------------------------------------- 1 | #ifndef __PLATFORM 2 | #define __PLATFORM 3 | 4 | #if defined (SDCC) || defined (__SDCC) 5 | #ifndef __SDCC 6 | #define __SDCC 7 | #endif 8 | 9 | // Use GCC defined standard types 10 | #include 11 | // SDCC is little-endian 12 | #define __LITTLE_ENDIAN 13 | 14 | // Define Keil C51 specified derivatives 15 | #define xdata __xdata 16 | #define idata __idata 17 | #define code __code 18 | #define interrupt __interrupt 19 | 20 | #define xdatabuf(addr, name, sz) __xdata __at(addr) uint8_t name[sz] 21 | #define extern_xdatabuf(addr, name) extern __xdata __at(addr) uint8_t name[] 22 | #elif defined (__C51__) || defined (__CX51__) 23 | #ifndef __C51__ 24 | #define __C51__ 25 | #endif 26 | 27 | // Define standard types 28 | #ifndef bool 29 | typedef bit bool; 30 | #endif 31 | 32 | #ifndef uint8_t 33 | typedef unsigned char uint8_t; 34 | #endif 35 | 36 | #ifndef int8_t 37 | typedef signed char int8_t; 38 | #endif 39 | 40 | #ifndef uint16_t 41 | typedef unsigned short uint16_t; 42 | #endif 43 | 44 | #ifndef int16_t 45 | typedef signed short int16_t; 46 | #endif 47 | 48 | #ifndef uint32_t 49 | typedef unsigned long uint32_t; 50 | #endif 51 | 52 | #ifndef int32_t 53 | typedef signed long int32_t; 54 | #endif 55 | 56 | // Keil C51 is big-endian 57 | #define __BIG_ENDIAN 58 | 59 | // SDCC style SBIT 60 | #define SBIT(var, port, pin) sbit var = port^pin 61 | 62 | #define xdatabuf(addr, name, sz) xdata uint8_t name[sz] _at_ addr 63 | #define extern_xdatabuf(addr, name) extern xdata uint8_t name[] 64 | #else 65 | #error "Unsupported compiler!" 66 | #endif 67 | 68 | #if defined __BIG_ENDIAN 69 | // uint16_t 70 | #define U16B0(u) (((uint8_t*)&u)[1]) 71 | #define U16B1(u) (((uint8_t*)&u)[0]) 72 | // uint32_t 73 | #define U32B0(u) (((uint8_t*)&u)[3]) 74 | #define U32B1(u) (((uint8_t*)&u)[2]) 75 | #define U32B2(u) (((uint8_t*)&u)[1]) 76 | #define U32B3(u) (((uint8_t*)&u)[0]) 77 | 78 | #define U16_XBig(dstAddr, srcAddr) { \ 79 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \ 80 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \ 81 | } 82 | 83 | #define U16_XLittle(dstAddr, srcAddr) { \ 84 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[1]; \ 85 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[0]; \ 86 | } 87 | 88 | #define U32_XBig(dstAddr, srcAddr) { \ 89 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \ 90 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \ 91 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[2]; \ 92 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[3]; \ 93 | } 94 | 95 | #define U32_XLittle(dstAddr, srcAddr) { \ 96 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[3]; \ 97 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[2]; \ 98 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[1]; \ 99 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[0]; \ 100 | } 101 | #elif defined __LITTLE_ENDIAN 102 | // uint16_t 103 | #define U16B0(u) (((uint8_t*)&u)[0]) 104 | #define U16B1(u) (((uint8_t*)&u)[1]) 105 | // uint32_t 106 | #define U32B0(u) (((uint8_t*)&u)[0]) 107 | #define U32B1(u) (((uint8_t*)&u)[1]) 108 | #define U32B2(u) (((uint8_t*)&u)[2]) 109 | #define U32B3(u) (((uint8_t*)&u)[3]) 110 | 111 | #define U16_XBig(dstAddr, srcAddr) { \ 112 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[1]; \ 113 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[0]; \ 114 | } 115 | 116 | #define U16_XLittle(dstAddr, srcAddr) { \ 117 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \ 118 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \ 119 | } 120 | 121 | #define U32_XBig(dstAddr, srcAddr) { \ 122 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[3]; \ 123 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[2]; \ 124 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[1]; \ 125 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[0]; \ 126 | } 127 | 128 | #define U32_XLittle(dstAddr, srcAddr) { \ 129 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \ 130 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \ 131 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[2]; \ 132 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[3]; \ 133 | } 134 | #else 135 | #error "Little-Endian or Big-Endian?" 136 | #endif 137 | 138 | 139 | #endif // __PLATFORM 140 | 141 | 142 | 143 | #define GPIO1 0x90 144 | #define GPIO2 0xA0 145 | #define GPIO3 0xB0 146 | 147 | 148 | 149 | #include "ch554_conf.H" 150 | 151 | #ifdef __SDCC 152 | #include "include\ch554.h" 153 | #include "include\ch554_usb.h" 154 | #endif 155 | 156 | #ifdef __C51__ 157 | #include "keilc51\ch554.h" 158 | #endif 159 | -------------------------------------------------------------------------------- /delay.c: -------------------------------------------------------------------------------- 1 | #include "Delay.H" 2 | #include "ch554_platform.h" 3 | 4 | void mDelayuS(uint16_t n ) { 5 | #ifdef CLOCK_CFG 6 | #if CLOCK_CFG <= 6000000 7 | n >>= 2; 8 | #endif 9 | #if CLOCK_CFG <= 3000000 10 | n >>= 2; 11 | #endif 12 | #if CLOCK_CFG <= 750000 13 | n >>= 4; 14 | #endif 15 | #endif 16 | while ( n ) { 17 | ++ SAFE_MOD; 18 | #ifdef CLOCK_CFG 19 | #if CLOCK_CFG >= 14000000 20 | ++ SAFE_MOD; 21 | #endif 22 | #if CLOCK_CFG >= 16000000 23 | ++ SAFE_MOD; 24 | #endif 25 | #if CLOCK_CFG >= 18000000 26 | ++ SAFE_MOD; 27 | #endif 28 | #if CLOCK_CFG >= 20000000 29 | ++ SAFE_MOD; 30 | #endif 31 | #if CLOCK_CFG >= 22000000 32 | ++ SAFE_MOD; 33 | #endif 34 | #if CLOCK_CFG >= 24000000 35 | ++ SAFE_MOD; 36 | #endif 37 | #if CLOCK_CFG >= 26000000 38 | ++ SAFE_MOD; 39 | #endif 40 | #if CLOCK_CFG >= 28000000 41 | ++ SAFE_MOD; 42 | #endif 43 | #if CLOCK_CFG >= 30000000 44 | ++ SAFE_MOD; 45 | #endif 46 | #if CLOCK_CFG >= 32000000 47 | ++ SAFE_MOD; 48 | #endif 49 | #endif 50 | -- n; 51 | } 52 | } 53 | 54 | void mDelaymS(uint16_t n ) { 55 | while ( n ) { 56 | #ifdef DELAY_MS_HW 57 | while ( ( TKEY_CTRL & bTKC_IF ) == 0 ); 58 | while ( TKEY_CTRL & bTKC_IF ); 59 | #else 60 | mDelayuS(1000); 61 | #endif 62 | -- n; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /delay.h: -------------------------------------------------------------------------------- 1 | #ifndef __DELAY_H__ 2 | #define __DELAY_H__ 3 | 4 | #include "ch554_platform.h" 5 | 6 | void mDelayuS(uint16_t n ); 7 | void mDelaymS(uint16_t n ); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /host/.gitignore: -------------------------------------------------------------------------------- 1 | #Visual Studio files 2 | *.[Oo]bj 3 | *.user 4 | *.aps 5 | *.pch 6 | *.vspscc 7 | *.vssscc 8 | *_i.c 9 | *_p.c 10 | *.ncb 11 | *.suo 12 | *.tlb 13 | *.tlh 14 | *.bak 15 | *.[Cc]ache 16 | *.ilk 17 | *.log 18 | *.sbr 19 | *.sdf 20 | *.opensdf 21 | *.unsuccessfulbuild 22 | ipch/ 23 | obj/ 24 | [Ll]ib 25 | [Bb]in 26 | [Dd]ebug*/ 27 | [Rr]elease*/ 28 | Ankh.NoLoad 29 | *.VC.db 30 | 31 | #GCC files 32 | *.o 33 | *.d 34 | *.res 35 | *.dll 36 | *.a 37 | 38 | #Visual Studio Code files 39 | .vscode/ -------------------------------------------------------------------------------- /host/CH554_CDC_BusBridge.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.6 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CH554_CDC_BusBridge", "CH554_CDC_BusBridge.vcxproj", "{600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x64.ActiveCfg = Debug|x64 17 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x64.Build.0 = Debug|x64 18 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x86.ActiveCfg = Debug|Win32 19 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x86.Build.0 = Debug|Win32 20 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x64.ActiveCfg = Release|x64 21 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x64.Build.0 = Release|x64 22 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x86.ActiveCfg = Release|Win32 23 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /host/CH554_CDC_BusBridge.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D} 24 | Win32Proj 25 | CH554_CDC_BusBridge 26 | 7.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141_xp 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141_xp 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141_xp 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141_xp 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | $(SolutionDir)$(Platform)\$(Configuration)\ 76 | $(Platform)\$(Configuration)\ 77 | 78 | 79 | true 80 | 81 | 82 | false 83 | $(SolutionDir)$(Platform)\$(Configuration)\ 84 | $(Platform)\$(Configuration)\ 85 | 86 | 87 | false 88 | 89 | 90 | 91 | 92 | 93 | Level3 94 | Disabled 95 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 96 | 97 | 98 | Console 99 | 100 | 101 | 102 | 103 | 104 | 105 | Level3 106 | Disabled 107 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | 109 | 110 | Console 111 | 112 | 113 | 114 | 115 | Level3 116 | 117 | 118 | MaxSpeed 119 | true 120 | true 121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | 123 | 124 | Console 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | Level3 132 | 133 | 134 | MaxSpeed 135 | true 136 | true 137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 138 | 139 | 140 | Console 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /host/CH554_CDC_BusBridge.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | -------------------------------------------------------------------------------- /host/Makefile: -------------------------------------------------------------------------------- 1 | test: main.o spi.o rs232.o flash25.o 2 | cc -o main main.o rs232.o spi.o flash25.o 3 | 4 | main.o: main.c 5 | cc $(CFLAGS) -c main.c -o main.o 6 | flash25.o: flash25.c flash25.h 7 | cc $(CFLAGS) -c flash25.c -o flash25.o 8 | spi.o: spi.c spi.h 9 | cc $(CFLAGS) -c spi.c -o spi.o 10 | rs232.o: rs232.c rs232.h 11 | cc $(CFLAGS) -c rs232.c -o rs232.o 12 | 13 | clean: 14 | rm *.o main 15 | -------------------------------------------------------------------------------- /host/flash25.c: -------------------------------------------------------------------------------- 1 | #include "flash25.h" 2 | #include "spi.h" 3 | #include "rs232.h" 4 | 5 | #include 6 | 7 | uint32_t SPI_Flash25_ReadID(HCOM hCom) { 8 | uint8_t cmd = FLASH25_CMD_RDID; 9 | uint8_t id[3] = { 0 }; 10 | SPI_Write(hCom, &cmd, 1, SPI_NO_STOP); 11 | SPI_Read(hCom, &id, 3, SPI_STOP_AFTER); 12 | 13 | return (id[2] << 16) | (id[1] << 8) | id[0]; 14 | } 15 | 16 | void SPI_Flash25_WriteEnable(HCOM hCom) { 17 | unsigned char cmd = FLASH25_CMD_WREN; 18 | SPI_Write(hCom, &cmd, 1, SPI_STOP_AFTER); 19 | } 20 | 21 | void SPI_Flash25_WaitForWriteEnd(HCOM hCom) { 22 | uint8_t temp = FLASH25_CMD_RDSR; 23 | SPI_Write(hCom, &temp, 1, SPI_NO_STOP); 24 | 25 | /* Loop as long as the memory is busy with a write cycle */ 26 | do { 27 | /* Send a dummy byte to generate the clock needed by the FLASH 28 | and put the value of the status register in FLASH_Status variable */ 29 | SPI_Read(hCom, &temp, 1, SPI_NO_STOP); 30 | 31 | } while (temp & FLASH25_FLAG_WIP); 32 | 33 | // Set CS to high 34 | SPI_CS(hCom, 1); 35 | } 36 | 37 | static void SPI_Flash25_PageWrite(HCOM hCom, uint8_t* buf, uint32_t addr, uint32_t count) { 38 | /* Enable the write access to the FLASH */ 39 | SPI_Flash25_WriteEnable(hCom); 40 | 41 | unsigned char header[4] = { 0 }; 42 | header[0] = FLASH25_CMD_WRITE; 43 | header[1] = (addr & 0xFF0000) >> 16; 44 | header[2] = (addr & 0xFF00) >> 8; 45 | header[3] = addr & 0xFF; 46 | 47 | SPI_Write(hCom, header, 4, SPI_NO_STOP); 48 | SPI_Write(hCom, buf, count, SPI_STOP_AFTER); 49 | 50 | /* Wait the end of Flash writing */ 51 | SPI_Flash25_WaitForWriteEnd(hCom); 52 | } 53 | 54 | void SPI_Flash25_BufferWrite(HCOM hCom, uint8_t* buf, uint32_t addr, uint32_t page_size, uint32_t count) { 55 | uint32_t page_count = 0, byte_remaining = 0, offset = 0, byte_to_boundary = 0; 56 | 57 | offset = addr % page_size; 58 | byte_to_boundary = page_size - offset; 59 | page_count = count / page_size; 60 | byte_remaining = count % page_size; 61 | 62 | if (offset == 0) { /* addr is page_size aligned */ 63 | if (page_count == 0) { /* byte_to_boundary < page_size */ 64 | SPI_Flash25_PageWrite(hCom, buf, addr, count); 65 | } else { /* byte_to_boundary > page_size */ 66 | while (page_count--) { 67 | SPI_Flash25_PageWrite(hCom, buf, addr, page_size); 68 | addr += page_size; 69 | buf += page_size; 70 | } 71 | 72 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_remaining); 73 | } 74 | } else { /* addr is not page_size aligned */ 75 | if (page_count == 0) { /* byte_to_boundary < page_size */ 76 | if (byte_remaining > byte_to_boundary) { /* (byte_to_boundary + addr) > page_size */ 77 | byte_remaining -= byte_to_boundary; 78 | 79 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_to_boundary); 80 | addr += byte_to_boundary; 81 | buf += byte_to_boundary; 82 | 83 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_remaining); 84 | } else { 85 | SPI_Flash25_PageWrite(hCom, buf, addr, count); 86 | } 87 | } else { /* more than 1 page */ 88 | count -= byte_to_boundary; 89 | page_count = count / page_size; 90 | byte_remaining = count % page_size; 91 | 92 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_to_boundary); 93 | addr += byte_to_boundary; 94 | buf += byte_to_boundary; 95 | 96 | while (page_count--) { 97 | SPI_Flash25_PageWrite(hCom, buf, addr, page_size); 98 | addr += page_size; 99 | buf += page_size; 100 | } 101 | 102 | if (byte_remaining != 0) { 103 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_remaining); 104 | } 105 | } 106 | } 107 | } 108 | 109 | void SPI_Flash25_BufferRead(HCOM hCom, uint8_t* pBuffer, uint32_t ReadAddr, uint32_t NumByteToRead) { 110 | uint8_t header[4]; 111 | header[0] = FLASH25_CMD_READ; 112 | header[1] = (ReadAddr & 0xFF0000) >> 16; 113 | header[2] = (ReadAddr & 0xFF00) >> 8; 114 | header[3] = ReadAddr & 0xFF; 115 | 116 | SPI_Write(hCom, header, 4, SPI_NO_STOP); 117 | SPI_Read(hCom, pBuffer, NumByteToRead, SPI_STOP_AFTER); 118 | } 119 | 120 | void SPI_Flash25_SectorErase(HCOM hCom, uint32_t SectorAddr) { 121 | /* Send write enable instruction */ 122 | SPI_Flash25_WriteEnable(hCom); 123 | 124 | uint8_t header[4]; 125 | header[0] = FLASH25_CMD_SE; 126 | header[1] = (SectorAddr & 0xFF0000) >> 16; 127 | header[2] = (SectorAddr & 0xFF00) >> 8; 128 | header[3] = SectorAddr & 0xFF; 129 | 130 | SPI_Write(hCom, header, 4, SPI_STOP_AFTER); 131 | 132 | /* Wait the end of Flash writing */ 133 | SPI_Flash25_WaitForWriteEnd(hCom); 134 | } 135 | 136 | void SPI_Flash25_BulkErase(HCOM hCom) { 137 | /* Send write enable instruction */ 138 | SPI_Flash25_WriteEnable(hCom); 139 | 140 | unsigned char cmd = FLASH25_CMD_BE; 141 | SPI_Write(hCom, &cmd, 1, SPI_STOP_AFTER); 142 | 143 | /* Wait the end of Flash writing */ 144 | SPI_Flash25_WaitForWriteEnd(hCom); 145 | } -------------------------------------------------------------------------------- /host/flash25.h: -------------------------------------------------------------------------------- 1 | #ifndef __FLASH25_H 2 | #define __FLASH25_H 3 | 4 | #include "rs232.h" 5 | #include 6 | 7 | #define FLASH25_CMD_WRITE 0x02 /* Write to Memory instruction */ 8 | #define FLASH25_CMD_WRSR 0x01 /* Write Status Register instruction */ 9 | #define FLASH25_CMD_WREN 0x06 /* Write enable instruction */ 10 | 11 | #define FLASH25_CMD_READ 0x03 /* Read from Memory instruction */ 12 | #define FLASH25_CMD_RDSR 0x05 /* Read Status Register instruction */ 13 | #define FLASH25_CMD_RDID 0x9F /* Read identification */ 14 | #define FLASH25_CMD_SE 0xD8 /* Sector Erase instruction */ 15 | #define FLASH25_CMD_BE 0xC7 /* Bulk Erase instruction */ 16 | 17 | #define FLASH25_FLAG_WIP 0x01 /* Write In Progress (WIP) flag */ 18 | 19 | uint32_t SPI_Flash25_ReadID(HCOM hCom); 20 | void SPI_Flash25_WriteEnable(HCOM hCom); 21 | void SPI_Flash25_WaitForWriteEnd(HCOM hCom); 22 | void SPI_Flash25_BufferWrite(HCOM hCom, uint8_t* pBuffer, uint32_t WriteAddr, uint32_t page_size, uint32_t NumByteToWrite); 23 | void SPI_Flash25_BufferRead(HCOM hCom, uint8_t* pBuffer, uint32_t ReadAddr, uint32_t NumByteToRead); 24 | void SPI_Flash25_SectorErase(HCOM hCom, uint32_t SectorAddr); 25 | void SPI_Flash25_BulkErase(HCOM hCom); 26 | 27 | #endif // !__FLASH25_H 28 | -------------------------------------------------------------------------------- /host/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "rs232.h" 4 | #include "spi.h" 5 | #include "flash25.h" 6 | 7 | int main(int argc, const char** argv) { 8 | #ifndef _WIN32 9 | printf("WARNING: Linux users should disable modemmanager to make this program work properly!\n E.g. sudo apt-get purge modemmanager\n"); 10 | #endif 11 | 12 | if (argc < 2) { 13 | printf("RS232 port is not specified, on Linux, normally it should be /dev/ttyACM0, on Windows it should be something like COM8. \n"); 14 | return EXIT_FAILURE; 15 | } 16 | 17 | const char* portName = argv[1]; 18 | HCOM hCom = RS232_Open(portName); 19 | //Set the buffer size 20 | if (RS232_IS_INVALID(hCom)) { 21 | printf("Unable to open port %s \n", portName); 22 | return EXIT_FAILURE; 23 | } 24 | RS232_Config(hCom, 115200, RS232_CONFIG_DEFAULT); 25 | 26 | // Pull up CS to terminate any pending SPI operation 27 | SPI_CS(hCom, 1); 28 | printf("Chip ID = %x\n", SPI_Flash25_ReadID(hCom)); 29 | unsigned char* src = (unsigned char*)malloc(0x200000); 30 | FILE *file = fopen("rikka.png", "rb"); 31 | fseek(file, 0L, SEEK_END); 32 | long src_len = ftell(file); 33 | rewind(file); 34 | fread(src, src_len, 1, file); 35 | fclose(file); 36 | 37 | printf("File size = %ld\n", src_len); 38 | SPI_Flash25_BulkErase(hCom); 39 | printf("Chip Erased\n"); 40 | SPI_Flash25_BufferWrite(hCom, src, 0, 256, src_len); 41 | printf("Writing done!\n"); 42 | 43 | unsigned char* dst = (unsigned char*)malloc(0x200000); 44 | SPI_Flash25_BufferRead(hCom, dst, 0, src_len); 45 | printf("Reading done!\n"); 46 | 47 | for (int i = 0; i < src_len; i++) { 48 | if (src[i] != dst[i]) { 49 | printf("diff %d\n", i); 50 | } 51 | } 52 | 53 | RS232_Close(hCom); 54 | 55 | system("pause"); 56 | return 0; 57 | } -------------------------------------------------------------------------------- /host/rikka.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/host/rikka.png -------------------------------------------------------------------------------- /host/rs232.c: -------------------------------------------------------------------------------- 1 | #include "rs232.h" 2 | 3 | ssize_t RS232_ReadLine(HCOM hCom, char *buffer, size_t count) { 4 | size_t received = 0; 5 | ssize_t n = 0; 6 | char sbuf; 7 | 8 | do { 9 | n = RS232_Read(hCom, &sbuf, 1); 10 | 11 | if (n == -1) 12 | return -1; 13 | 14 | buffer[received] = sbuf; 15 | received += n; 16 | } while (sbuf != '\n' && (received + 2) < count); 17 | 18 | if (buffer[received - 2] == '\r') 19 | received--; 20 | buffer[received] = '\0'; 21 | return received; 22 | } 23 | 24 | #ifdef _WIN32 25 | HCOM RS232_Open(const unsigned char* name) { 26 | HCOM hCom = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL); 27 | 28 | return hCom; 29 | } 30 | 31 | void RS232_Config(HCOM hCom, speed_t baud, unsigned char config) { 32 | DCB dcb = { 0 }; 33 | GetCommState(hCom, &dcb); 34 | 35 | dcb.BaudRate = baud; 36 | 37 | switch (config & RS232_CONFIG_CS_MASK) { 38 | case RS232_CONFIG_CS5: 39 | dcb.ByteSize = 5; 40 | break; 41 | case RS232_CONFIG_CS6: 42 | dcb.ByteSize = 6; 43 | break; 44 | case RS232_CONFIG_CS7: 45 | dcb.ByteSize = 7; 46 | break; 47 | case RS232_CONFIG_CS8: 48 | default: 49 | dcb.ByteSize = 8; 50 | break; 51 | } 52 | 53 | switch (config & RS232_CONFIG_PARITY_MASK) { 54 | case RS232_CONFIG_PARITY_EVEN: 55 | dcb.ByteSize = EVENPARITY; 56 | break; 57 | case RS232_CONFIG_PARITY_ODD: 58 | dcb.Parity = ODDPARITY; 59 | break; 60 | case RS232_CONFIG_PARITY_NO: 61 | default: 62 | dcb.Parity = NOPARITY; 63 | break; 64 | } 65 | 66 | dcb.StopBits = (config & RS232_CONFIG_STOPBIT_2) ? TWOSTOPBITS : ONESTOPBIT; 67 | dcb.fOutxCtsFlow = 0; 68 | dcb.fOutxDsrFlow = 0; 69 | dcb.fDsrSensitivity = 0; 70 | dcb.fDtrControl = DTR_CONTROL_DISABLE; 71 | dcb.fRtsControl = RTS_CONTROL_DISABLE; 72 | 73 | SetCommState(hCom, &dcb); 74 | } 75 | 76 | ssize_t RS232_Write(HCOM hCom, const void* buf, size_t count) { 77 | DWORD written = 0; 78 | if (WriteFile(hCom, buf, count, &written, NULL) == FALSE) { 79 | return -1; // Error 80 | } else { 81 | return written; 82 | } 83 | } 84 | 85 | ssize_t RS232_Read(HCOM hCom, void *buf, size_t count) { 86 | DWORD read = 0; 87 | if (ReadFile(hCom, buf, count, &read, NULL) == FALSE) { 88 | return -1; // Error 89 | } else { 90 | return read; 91 | } 92 | } 93 | 94 | void RS232_RTS_Set(HCOM hCom) { 95 | EscapeCommFunction(hCom, SETRTS); 96 | } 97 | 98 | void RS232_RTS_Clr(HCOM hCom) { 99 | EscapeCommFunction(hCom, CLRRTS); 100 | } 101 | 102 | void RS232_DTR_Set(HCOM hCom) { 103 | EscapeCommFunction(hCom, SETDTR); 104 | } 105 | 106 | void RS232_DTR_Clr(HCOM hCom) { 107 | EscapeCommFunction(hCom, CLRDTR); 108 | } 109 | 110 | void RS232_Close(HCOM hCom) { 111 | CloseHandle(hCom); 112 | } 113 | 114 | int RS232_CTS(HCOM hCom) { 115 | DWORD flags; 116 | GetCommModemStatus(hCom, &flags); 117 | return (flags & MS_CTS_ON) ? 1 : 0; 118 | } 119 | 120 | int RS232_DSR(HCOM hCom) { 121 | DWORD flags; 122 | GetCommModemStatus(hCom, &flags); 123 | return (flags & MS_DSR_ON) ? 1 : 0; 124 | } 125 | #else 126 | HCOM RS232_Open(const unsigned char* name) { 127 | return open(name, O_RDWR | O_NOCTTY); 128 | } 129 | 130 | void RS232_Config(HCOM fd, speed_t baud, unsigned char config) { 131 | struct termios options; 132 | int baudr; 133 | tcgetattr(fd, &options); 134 | 135 | switch (baud) { 136 | case 50: 137 | baudr = B50; 138 | break; 139 | case 75: 140 | baudr = B75; 141 | break; 142 | case 110: 143 | baudr = B110; 144 | break; 145 | case 134: 146 | baudr = B134; 147 | break; 148 | case 150: 149 | baudr = B150; 150 | break; 151 | case 200: 152 | baudr = B200; 153 | break; 154 | case 300: 155 | baudr = B300; 156 | break; 157 | case 600: 158 | baudr = B600; 159 | break; 160 | case 1200: 161 | baudr = B1200; 162 | break; 163 | case 1800: 164 | baudr = B1800; 165 | break; 166 | case 2400: 167 | baudr = B2400; 168 | break; 169 | case 4800: 170 | baudr = B4800; 171 | break; 172 | case 9600: 173 | baudr = B9600; 174 | break; 175 | case 19200: 176 | baudr = B19200; 177 | break; 178 | case 38400: 179 | baudr = B38400; 180 | break; 181 | case 57600: 182 | baudr = B57600; 183 | break; 184 | case 115200: 185 | baudr = B115200; 186 | break; 187 | case 230400: 188 | baudr = B230400; 189 | break; 190 | case 460800: 191 | baudr = B460800; 192 | break; 193 | case 500000: 194 | baudr = B500000; 195 | break; 196 | case 576000: 197 | baudr = B576000; 198 | break; 199 | case 921600: 200 | baudr = B921600; 201 | break; 202 | case 1000000: 203 | baudr = B1000000; 204 | break; 205 | case 1152000: 206 | baudr = B1152000; 207 | break; 208 | case 1500000: 209 | baudr = B1500000; 210 | break; 211 | case 2000000: 212 | baudr = B2000000; 213 | break; 214 | case 2500000: 215 | baudr = B2500000; 216 | break; 217 | case 3000000: 218 | baudr = B3000000; 219 | break; 220 | case 3500000: 221 | baudr = B3500000; 222 | break; 223 | case 4000000: 224 | baudr = B4000000; 225 | break; 226 | default: 227 | baudr = B1152000; 228 | break; 229 | } 230 | cfsetispeed(&options, baudr); 231 | cfsetospeed(&options, baudr); 232 | 233 | options.c_cflag &= ~CSIZE; 234 | switch (config & RS232_CONFIG_CS_MASK) { 235 | case RS232_CONFIG_CS5: 236 | options.c_cflag |= CS5; 237 | break; 238 | case RS232_CONFIG_CS6: 239 | options.c_cflag |= CS6; 240 | break; 241 | case RS232_CONFIG_CS7: 242 | options.c_cflag |= CS7; 243 | break; 244 | case RS232_CONFIG_CS8: 245 | default: 246 | options.c_cflag |= CS8; 247 | break; 248 | } 249 | 250 | switch (config & RS232_CONFIG_PARITY_MASK) { 251 | case RS232_CONFIG_PARITY_EVEN: 252 | options.c_cflag |= PARENB; 253 | options.c_cflag &= ~PARODD; 254 | break; 255 | case RS232_CONFIG_PARITY_ODD: 256 | options.c_cflag |= PARENB; 257 | options.c_cflag |= PARODD; 258 | break; 259 | case RS232_CONFIG_PARITY_NO: 260 | default: 261 | options.c_cflag &= ~PARENB; 262 | break; 263 | } 264 | 265 | if (config & RS232_CONFIG_STOPBIT_2) { 266 | options.c_cflag |= CSTOPB; 267 | } else { 268 | options.c_cflag &= ~CSTOPB; 269 | } 270 | 271 | options.c_cflag &= ~CRTSCTS; 272 | options.c_cflag |= CREAD | CLOCAL; 273 | 274 | // Put the serial port in raw mode, similar to cfmakeraw 275 | options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); 276 | options.c_oflag &= ~OPOST; 277 | options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 278 | tcsetattr(fd, TCSANOW, &options); 279 | } 280 | 281 | ssize_t RS232_Write(HCOM fd, const void* buf, size_t count) { 282 | return write(fd, buf, count); 283 | } 284 | 285 | ssize_t RS232_Read(HCOM fd, void *buf, size_t count) { 286 | return read(fd, buf, count); 287 | } 288 | 289 | void RS232_RTS_Set(HCOM fd) { 290 | int RTS_flag = TIOCM_RTS; 291 | ioctl(fd, TIOCMBIS, &RTS_flag); 292 | } 293 | 294 | void RS232_RTS_Clr(HCOM fd) { 295 | int RTS_flag = TIOCM_RTS; 296 | ioctl(fd, TIOCMBIC, &RTS_flag); 297 | } 298 | 299 | void RS232_DTR_Set(HCOM fd) { 300 | int DTR_flag = TIOCM_DTR; 301 | ioctl(fd, TIOCMBIS, &DTR_flag); 302 | } 303 | 304 | void RS232_DTR_Clr(HCOM fd) { 305 | int DTR_flag = TIOCM_DTR; 306 | ioctl(fd, TIOCMBIC, &DTR_flag); 307 | } 308 | 309 | int RS232_CTS(HCOM fd) { 310 | int flags; 311 | ioctl(fd, TIOCMGET, &flags); 312 | return (flags & TIOCM_CTS) ? 1 : 0; 313 | } 314 | 315 | int RS232_DSR(HCOM fd) { 316 | int flags; 317 | ioctl(fd, TIOCMGET, &flags); 318 | return (flags & TIOCM_DSR) ? 1 : 0; 319 | } 320 | 321 | void RS232_Close(HCOM hCom) { 322 | close(hCom); 323 | } 324 | #endif 325 | 326 | 327 | -------------------------------------------------------------------------------- /host/rs232.h: -------------------------------------------------------------------------------- 1 | #ifndef __RS232_H 2 | #define __RS232_H 3 | 4 | #define RS232_CONFIG_STOPBIT_2 0x40 5 | #define RS232_CONFIG_STOPBIT_1 0x00 6 | 7 | #define RS232_CONFIG_PARITY_MASK 0x30 8 | #define RS232_CONFIG_PARITY_EVEN 0x20 9 | #define RS232_CONFIG_PARITY_ODD 0x10 10 | #define RS232_CONFIG_PARITY_NO 0x00 11 | 12 | #define RS232_CONFIG_CS_MASK 0x0F 13 | #define RS232_CONFIG_CS8 8 14 | #define RS232_CONFIG_CS7 7 15 | #define RS232_CONFIG_CS6 6 16 | #define RS232_CONFIG_CS5 5 17 | 18 | #define RS232_CONFIG_DEFAULT (RS232_CONFIG_CS8 | RS232_CONFIG_PARITY_NO | RS232_CONFIG_STOPBIT_1) 19 | 20 | #ifdef _WIN32 21 | #include 22 | typedef SSIZE_T ssize_t; 23 | typedef unsigned int speed_t; 24 | typedef void* HCOM; 25 | #define RS232_IS_INVALID(hCom) (hCom == INVALID_HANDLE_VALUE) 26 | #else 27 | #include /* File Control Definitions */ 28 | #include /* POSIX Terminal Control Definitions */ 29 | #include /* UNIX Standard Definitions */ 30 | #include /* ERROR Number Definitions */ 31 | #include /* ioctl() */ 32 | 33 | typedef int HCOM; 34 | #define RS232_IS_INVALID(hCom) (hCom == -1) 35 | #endif 36 | 37 | // Valid bauds: 110, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400 38 | // 57600, 115200, 128000, 256000, 500000, 1000000 39 | 40 | HCOM RS232_Open(const unsigned char* name); 41 | void RS232_Config(HCOM hCom, speed_t baud, unsigned char config); 42 | ssize_t RS232_Write(HCOM hCom, const void* buf, size_t count); 43 | ssize_t RS232_Read(HCOM hCom, void *buf, size_t count); 44 | ssize_t RS232_ReadLine(HCOM hCom, char *buffer, size_t count); 45 | void RS232_RTS_Set(HCOM hCom); 46 | void RS232_RTS_Clr(HCOM hCom); 47 | void RS232_DTR_Set(HCOM hCom); 48 | void RS232_DTR_Clr(HCOM hCom); 49 | int RS232_CTS(HCOM hCom); 50 | int RS232_DSR(HCOM hCom); 51 | void RS232_Close(HCOM hCom); 52 | 53 | #endif // !__RS232_H 54 | -------------------------------------------------------------------------------- /host/spi.c: -------------------------------------------------------------------------------- 1 | #include "spi.h" 2 | #include "rs232.h" 3 | 4 | #include 5 | 6 | #define SPI_SEGMENT_MAXLEN 32 7 | #define SPI_REPLY_MAXLEN 32 8 | 9 | int SPI_Write(HCOM hCom, const void* buf, size_t count, char flag) { 10 | char rx_buf[SPI_REPLY_MAXLEN]; 11 | const char* tx_buf = (char*)buf; 12 | unsigned char header[2]; 13 | header[0] = 'S'; 14 | header[1] = SPI_SEGMENT_MAXLEN | SPI_NO_STOP; 15 | 16 | while (count > SPI_SEGMENT_MAXLEN) { 17 | if (RS232_Write(hCom, header, 2) == -1) 18 | goto err; 19 | 20 | if (RS232_Write(hCom, tx_buf, SPI_SEGMENT_MAXLEN) == -1) 21 | goto err; 22 | 23 | if (RS232_ReadLine(hCom, rx_buf, SPI_REPLY_MAXLEN) == -1) 24 | goto err; 25 | 26 | if (!strcmp(rx_buf, "OK")) 27 | goto err; 28 | 29 | tx_buf += SPI_SEGMENT_MAXLEN; 30 | count -= SPI_SEGMENT_MAXLEN; 31 | } 32 | 33 | if (count > 0) { 34 | if (flag & SPI_NO_STOP) { 35 | header[1] = count | SPI_NO_STOP; 36 | } else { 37 | header[1] = count; 38 | } 39 | 40 | if (RS232_Write(hCom, header, 2) == -1) 41 | goto err; 42 | 43 | if (RS232_Write(hCom, tx_buf, count) == -1) 44 | goto err; 45 | 46 | if (RS232_ReadLine(hCom, rx_buf, SPI_REPLY_MAXLEN) == -1) 47 | goto err; 48 | 49 | if (!strcmp(rx_buf, "OK")) 50 | goto err; 51 | } 52 | 53 | return 0; 54 | err: 55 | return -1; 56 | } 57 | 58 | int SPI_Read(HCOM hCom, void* buf, size_t count, char flag) { 59 | char* rx_buf = (char*)buf; 60 | unsigned char header[2]; 61 | size_t read; 62 | header[0] = 'G'; 63 | header[1] = SPI_SEGMENT_MAXLEN | SPI_NO_STOP; 64 | 65 | while (count > SPI_SEGMENT_MAXLEN) { 66 | if (RS232_Write(hCom, header, 2) == -1) 67 | goto err; 68 | 69 | read = 0; 70 | do { 71 | size_t rs232_read_ret = RS232_Read(hCom, rx_buf, SPI_SEGMENT_MAXLEN - read); 72 | if (rs232_read_ret == -1) 73 | goto err; 74 | read += rs232_read_ret; 75 | rx_buf += rs232_read_ret; 76 | } while (read < SPI_SEGMENT_MAXLEN); 77 | 78 | count -= SPI_SEGMENT_MAXLEN; 79 | } 80 | 81 | if (count > 0) { 82 | if (flag & SPI_NO_STOP) { 83 | header[1] = count | SPI_NO_STOP; 84 | } else { 85 | header[1] = count; 86 | } 87 | 88 | if (RS232_Write(hCom, header, 2) == -1) 89 | goto err; 90 | 91 | read = 0; 92 | do { 93 | size_t rs232_read_ret = RS232_Read(hCom, rx_buf, count); 94 | if (rs232_read_ret == -1) 95 | goto err; 96 | read += rs232_read_ret; 97 | rx_buf += rs232_read_ret; 98 | } while (read < count); 99 | 100 | return 0; 101 | } 102 | 103 | return 0; 104 | err: 105 | return -1; 106 | } 107 | 108 | int SPI_CS(HCOM hCom, unsigned char val) { 109 | unsigned char header[2]; 110 | if (val) { 111 | header[0] = 'G'; 112 | header[1] = 0; 113 | } else { 114 | header[0] = 'S'; 115 | header[1] = 0; 116 | } 117 | 118 | return (RS232_Write(hCom, header, 2) == -1) ? -1 : 0; 119 | } 120 | -------------------------------------------------------------------------------- /host/spi.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPI_H 2 | #define __SPI_H 3 | 4 | #include "rs232.h" 5 | 6 | // SPI_Write and SPI_Read flags 7 | #define SPI_NO_STOP 0x80 /* After this transmission, CS remains low */ 8 | #define SPI_STOP_AFTER 0x00 /* After this transmission, CS will be set to high */ 9 | 10 | /* Write bytes from to SPI device */ 11 | int SPI_Write(HCOM hCom, const void* buf, size_t count, char flag); 12 | /* Read bytes from SPI device to */ 13 | int SPI_Read(HCOM hCom, void* buf, size_t count, char flag); 14 | /* Set the level of CS, normally you don't need this! */ 15 | int SPI_CS(HCOM hCom, unsigned char val); 16 | 17 | #endif // !__SPI_H 18 | -------------------------------------------------------------------------------- /i2c.c: -------------------------------------------------------------------------------- 1 | #include "i2c.h" 2 | #include "ch554_platform.h" 3 | 4 | xdata uint8_t I2C_Buf; 5 | 6 | SBIT(sda_pin, 0x90, 7); 7 | SBIT(scl_pin, 0x90, 6); 8 | //sbit sda_pin = P1^5; 9 | //sbit scl_pin = P1^4; 10 | 11 | #define I2C_SDA() (sda_pin==1) 12 | #define I2C_SDA_H() {sda_pin = 1;} 13 | #define I2C_SDA_L() {sda_pin = 0;} 14 | #define I2C_SCL_H() {scl_pin = 1;} 15 | #define I2C_SCL_L() {scl_pin = 0;} 16 | 17 | void I2C_DELAY(void) { 18 | uint8_t i; 19 | for (i=0; i<7; i++); // Frequency control 20 | } 21 | 22 | void I2C_Init(void) { 23 | I2C_SDA_H(); 24 | I2C_DELAY(); 25 | I2C_SCL_H(); 26 | I2C_DELAY(); 27 | } 28 | 29 | // Generate a I2C start sequence 30 | void I2C_Send_Start(void) { 31 | // I2C_SCL = H, I2C_SDA = H 32 | I2C_SDA_H(); 33 | I2C_DELAY(); 34 | I2C_SCL_H(); 35 | I2C_DELAY(); 36 | I2C_SDA_L(); 37 | I2C_DELAY(); 38 | I2C_SCL_L(); 39 | I2C_DELAY(); 40 | // I2C_SCL = L, I2C_SDA = L 41 | } 42 | 43 | // Write a byte (stored in I2C_Buf) to I2C bus and return the ACK status in I2C_Buf 44 | // xxxx xxx(ACK bit) 45 | // ACK bit = 0 -> ACK received 46 | // ACK bit = 1 -> NACK received 47 | void I2C_WriteByte(void) { 48 | // I2C_SCL = L 49 | if (I2C_Buf & 0x80) {I2C_SDA_H();} else {I2C_SDA_L();} 50 | I2C_DELAY(); 51 | I2C_SCL_H(); 52 | I2C_DELAY(); 53 | I2C_SCL_L(); 54 | I2C_DELAY(); 55 | 56 | if (I2C_Buf & 0x40) {I2C_SDA_H();} else {I2C_SDA_L();} 57 | I2C_DELAY(); 58 | I2C_SCL_H(); 59 | I2C_DELAY(); 60 | I2C_SCL_L(); 61 | I2C_DELAY(); 62 | 63 | if (I2C_Buf & 0x20) {I2C_SDA_H();} else {I2C_SDA_L();} 64 | I2C_DELAY(); 65 | I2C_SCL_H(); 66 | I2C_DELAY(); 67 | I2C_SCL_L(); 68 | I2C_DELAY(); 69 | 70 | if (I2C_Buf & 0x10) {I2C_SDA_H();} else {I2C_SDA_L();} 71 | I2C_DELAY(); 72 | I2C_SCL_H(); 73 | I2C_DELAY(); 74 | I2C_SCL_L(); 75 | I2C_DELAY(); 76 | 77 | if (I2C_Buf & 0x08) {I2C_SDA_H();} else {I2C_SDA_L();} 78 | I2C_DELAY(); 79 | I2C_SCL_H(); 80 | I2C_DELAY(); 81 | I2C_SCL_L(); 82 | I2C_DELAY(); 83 | 84 | if (I2C_Buf & 0x04) {I2C_SDA_H();} else {I2C_SDA_L();} 85 | I2C_DELAY(); 86 | I2C_SCL_H(); 87 | I2C_DELAY(); 88 | I2C_SCL_L(); 89 | I2C_DELAY(); 90 | 91 | if (I2C_Buf & 0x02) {I2C_SDA_H();} else {I2C_SDA_L();} 92 | I2C_DELAY(); 93 | I2C_SCL_H(); 94 | I2C_DELAY(); 95 | I2C_SCL_L(); 96 | I2C_DELAY(); 97 | 98 | if (I2C_Buf & 0x01) {I2C_SDA_H();} else {I2C_SDA_L();} 99 | I2C_DELAY(); 100 | I2C_SCL_H(); 101 | I2C_DELAY(); 102 | I2C_SCL_L(); 103 | I2C_DELAY(); 104 | 105 | I2C_SDA_H(); 106 | I2C_DELAY(); 107 | 108 | // Check ACK bit 109 | // I2C_SCL = L 110 | I2C_SCL_H(); 111 | I2C_DELAY(); 112 | 113 | I2C_Buf = 0; 114 | if (I2C_SDA()) 115 | I2C_Buf = 1; 116 | 117 | I2C_SCL_L(); 118 | I2C_DELAY(); 119 | } 120 | 121 | // Read a byte from I2C bus and store the result into I2C_Buf 122 | void I2C_ReadByte(void) { 123 | I2C_Buf = 0; 124 | 125 | // I2C_SCL = L 126 | I2C_SDA_H(); //Master release the bus 127 | I2C_DELAY(); 128 | 129 | I2C_SCL_H(); 130 | I2C_DELAY(); 131 | if (I2C_SDA()) 132 | I2C_Buf |= 0x80; 133 | I2C_SCL_L(); 134 | I2C_DELAY(); 135 | 136 | 137 | I2C_SCL_H(); 138 | I2C_DELAY(); 139 | if (I2C_SDA()) 140 | I2C_Buf |= 0x40; 141 | I2C_SCL_L(); 142 | I2C_DELAY(); 143 | 144 | I2C_SCL_H(); 145 | I2C_DELAY(); 146 | if (I2C_SDA()) 147 | I2C_Buf |= 0x20; 148 | I2C_SCL_L(); 149 | I2C_DELAY(); 150 | 151 | I2C_SCL_H(); 152 | I2C_DELAY(); 153 | if (I2C_SDA()) 154 | I2C_Buf |= 0x10; 155 | I2C_SCL_L(); 156 | I2C_DELAY(); 157 | 158 | I2C_SCL_H(); 159 | I2C_DELAY(); 160 | if (I2C_SDA()) 161 | I2C_Buf |= 0x08; 162 | I2C_SCL_L(); 163 | I2C_DELAY(); 164 | 165 | I2C_SCL_H(); 166 | I2C_DELAY(); 167 | if (I2C_SDA()) 168 | I2C_Buf |= 0x04; 169 | I2C_SCL_L(); 170 | I2C_DELAY(); 171 | 172 | I2C_SCL_H(); 173 | I2C_DELAY(); 174 | if (I2C_SDA()) 175 | I2C_Buf |= 0x02; 176 | I2C_SCL_L(); 177 | I2C_DELAY(); 178 | 179 | I2C_SCL_H(); 180 | I2C_DELAY(); 181 | if (I2C_SDA()) 182 | I2C_Buf |= 0x01; 183 | I2C_SCL_L(); 184 | I2C_DELAY(); 185 | } 186 | 187 | // Send a ACK to I2C bus 188 | void I2C_Send_ACK(void) { 189 | // I2C_SCL = L 190 | I2C_SDA_L(); 191 | I2C_DELAY(); 192 | I2C_SCL_H(); 193 | I2C_DELAY(); 194 | I2C_SCL_L(); 195 | I2C_DELAY(); 196 | } 197 | 198 | // Send a NACK to I2C bus 199 | void I2C_Send_NACK(void) { 200 | // I2C_SCL = L 201 | I2C_SDA_H(); 202 | I2C_DELAY(); 203 | I2C_SCL_H(); 204 | I2C_DELAY(); 205 | I2C_SCL_L(); 206 | I2C_DELAY(); 207 | } 208 | 209 | // Generate a I2C stop condition, release the bus 210 | void I2C_Send_Stop(void) { 211 | // I2C_SCL = L, I2C_SDA = H 212 | I2C_SDA_L(); 213 | I2C_DELAY(); 214 | I2C_SCL_H(); 215 | I2C_DELAY(); 216 | I2C_SDA_H(); //Master release the bus 217 | I2C_DELAY(); 218 | } 219 | -------------------------------------------------------------------------------- /i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef __I2C_H 2 | #define __I2C_H 3 | 4 | #include "ch554_platform.h" 5 | 6 | extern xdata uint8_t I2C_Buf; 7 | 8 | void I2C_Init(void); 9 | 10 | // Generate a I2C start sequence 11 | void I2C_Send_Start(void); 12 | // Write a byte (stored in I2C_Buf) to I2C bus and return the ACK status in I2C_Buf 13 | // xxxx xxx(ACK bit) 14 | // ACK bit = 0 -> ACK received 15 | // ACK bit = 1 -> NACK received 16 | void I2C_WriteByte(); 17 | 18 | // Read a byte from I2C bus and store the result into I2C_Buf 19 | void I2C_ReadByte(void); 20 | // Send a ACK to I2C bus 21 | void I2C_Send_ACK(void); 22 | // Send a NACK to I2C bus 23 | void I2C_Send_NACK(void); 24 | 25 | // Generate a I2C stop condition, release the bus 26 | void I2C_Send_Stop(void); 27 | 28 | #endif -------------------------------------------------------------------------------- /include/ch554.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | CH554.H 3 | Header file for CH554 microcontrollers. 4 | **************************************** 5 | ** Copyright (C) W.ch 1999-2014 ** 6 | ** Web: http://wch.cn ** 7 | **************************************** 8 | --------------------------------------------------------------------------*/ 9 | 10 | #ifndef __CH554_H__ 11 | #define __CH554_H__ 12 | 13 | #include 14 | 15 | /*----- SFR --------------------------------------------------------------*/ 16 | /* sbit are bit addressable, others are byte addressable */ 17 | 18 | /* System Registers */ 19 | SFR(PSW, 0xD0); // program status word 20 | SBIT(CY, 0xD0, 7); // carry flag 21 | SBIT(AC, 0xD0, 6); // auxiliary carry flag 22 | SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0 23 | SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit 24 | SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit 25 | #define MASK_PSW_RS 0x18 // bit mask of register R0-R7 bank selection 26 | // RS1 & RS0: register R0-R7 bank selection 27 | // 00 - bank 0, R0-R7 @ address 0x00-0x07 28 | // 01 - bank 1, R0-R7 @ address 0x08-0x0F 29 | // 10 - bank 2, R0-R7 @ address 0x10-0x17 30 | // 11 - bank 3, R0-R7 @ address 0x18-0x1F 31 | SBIT(OV, 0xD0, 2); // overflow flag 32 | SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1 33 | SBIT(P, 0xD0, 0); // ReadOnly: parity flag 34 | SFR(ACC, 0xE0); // accumulator 35 | SFR(B, 0xF0); // general purpose register B 36 | SFR(SP, 0x81); // stack pointer 37 | //sfr16 DPTR = 0x82; // DPTR pointer, little-endian 38 | SFR(DPL, 0x82); // data pointer low 39 | SFR(DPH, 0x83); // data pointer high 40 | SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode 41 | //sfr CHIP_ID = 0xA1; // ReadOnly: reading chip ID 42 | #define CHIP_ID SAFE_MOD 43 | SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode 44 | #define bBOOT_LOAD 0x20 // ReadOnly: boot loader status for discriminating BootLoader or Application: set 1 by power on reset, clear 0 by software reset 45 | #define bSW_RESET 0x10 // software reset bit, auto clear by hardware 46 | #define bCODE_WE 0x08 // enable flash-ROM (include code & Data-Flash) being program or erasing: 0=writing protect, 1=enable program and erase 47 | #define bDATA_WE 0x04 // enable Data-Flash (flash-ROM data area) being program or erasing: 0=writing protect, 1=enable program and erase 48 | #define bLDO3V3_OFF 0x02 // disable 5V->3.3V LDO: 0=enable LDO for USB and internal oscillator under 5V power, 1=disable LDO, V33 pin input external 3.3V power 49 | #define bWDOG_EN 0x01 // enable watch-dog reset if watch-dog timer overflow: 0=as timer only, 1=enable reset if timer overflow 50 | 51 | /* Clock and Sleep and Power Registers */ 52 | SFR(PCON, 0x87); // power control and reset flag 53 | #define SMOD 0x80 // baud rate selection for UART0 mode 1/2/3: 0=slow(Fsys/128 @mode2, TF1/32 @mode1/3, no effect for TF2), 54 | // 1=fast(Fsys/32 @mode2, TF1/16 @mode1/3, no effect for TF2) 55 | #define bRST_FLAG1 0x20 // ReadOnly: recent reset flag high bit 56 | #define bRST_FLAG0 0x10 // ReadOnly: recent reset flag low bit 57 | #define MASK_RST_FLAG 0x30 // ReadOnly: bit mask of recent reset flag 58 | #define RST_FLAG_SW 0x00 59 | #define RST_FLAG_POR 0x10 60 | #define RST_FLAG_WDOG 0x20 61 | #define RST_FLAG_PIN 0x30 62 | // bPC_RST_FLAG1 & bPC_RST_FLAG0: recent reset flag 63 | // 00 - software reset, by bSW_RESET=1 @(bBOOT_LOAD=0 or bWDOG_EN=1) 64 | // 01 - power on reset 65 | // 10 - watch-dog timer overflow reset 66 | // 11 - external input manual reset by RST pin 67 | #define GF1 0x08 // general purpose flag bit 1 68 | #define GF0 0x04 // general purpose flag bit 0 69 | #define PD 0x02 // power-down enable bit, auto clear by wake-up hardware 70 | SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode 71 | #define bOSC_EN_INT 0x80 // internal oscillator enable and original clock selection: 1=enable & select internal clock, 0=disable & select external clock 72 | #define bOSC_EN_XT 0x40 // external oscillator enable, need quartz crystal or ceramic resonator between XI and XO pins 73 | #define bWDOG_IF_TO 0x20 // ReadOnly: watch-dog timer overflow interrupt flag, cleared by reload watch-dog count or auto cleared when MCU enter interrupt routine 74 | #define bROM_CLK_FAST 0x10 // flash-ROM clock frequency selection: 0=normal(for Fosc>=16MHz), 1=fast(for Fosc<16MHz) 75 | #define bRST 0x08 // ReadOnly: pin RST input 76 | #define bT2EX_ 0x08 // alternate pin for T2EX 77 | #define bCAP2_ 0x08 // alternate pin for CAP2 78 | #define MASK_SYS_CK_SEL 0x07 // bit mask of system clock Fsys selection 79 | /* 80 | Fxt = 24MHz(8MHz~25MHz for non-USB application), from external oscillator @XI&XO 81 | Fosc = bOSC_EN_INT ? 24MHz : Fxt 82 | Fpll = Fosc * 4 => 96MHz (32MHz~100MHz for non-USB application) 83 | Fusb4x = Fpll / 2 => 48MHz (Fixed) 84 | MASK_SYS_CK_SEL[2] [1] [0] 85 | Fsys = Fpll/3 = 32MHz: 1 1 1 86 | Fsys = Fpll/4 = 24MHz: 1 1 0 87 | Fsys = Fpll/6 = 16MHz: 1 0 1 88 | Fsys = Fpll/8 = 12MHz: 1 0 0 89 | Fsys = Fpll/16 = 6MHz: 0 1 1 90 | Fsys = Fpll/32 = 3MHz: 0 1 0 91 | Fsys = Fpll/128 = 750KHz: 0 0 1 92 | Fsys = Fpll/512 =187.5KHz: 0 0 0 93 | */ 94 | SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode 95 | #define bWAK_BY_USB 0x80 // enable wake-up by USB event 96 | #define bWAK_RXD1_LO 0x40 // enable wake-up by RXD1 low level 97 | #define bWAK_P1_5_LO 0x20 // enable wake-up by pin P1.5 low level 98 | #define bWAK_P1_4_LO 0x10 // enable wake-up by pin P1.4 low level 99 | #define bWAK_P1_3_LO 0x08 // enable wake-up by pin P1.3 low level 100 | #define bWAK_RST_HI 0x04 // enable wake-up by pin RST high level 101 | #define bWAK_P3_2E_3L 0x02 // enable wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level 102 | #define bWAK_RXD0_LO 0x01 // enable wake-up by RXD0 low level 103 | SFR(RESET_KEEP, 0xFE); // value keeper during reset 104 | SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536 105 | 106 | /* Interrupt Registers */ 107 | SFR(IE, 0xA8); // interrupt enable 108 | SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0 109 | SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable 110 | SBIT(ET2, 0xA8, 5); // enable timer2 interrupt 111 | SBIT(ES, 0xA8, 4); // enable UART0 interrupt 112 | SBIT(ET1, 0xA8, 3); // enable timer1 interrupt 113 | SBIT(EX1, 0xA8, 2); // enable external interrupt INT1 114 | SBIT(ET0, 0xA8, 1); // enable timer0 interrupt 115 | SBIT(EX0, 0xA8, 0); // enable external interrupt INT0 116 | SFR(IP, 0xB8); // interrupt priority and current priority 117 | SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag 118 | SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag 119 | // PH_FLAG & PL_FLAG: current interrupt priority 120 | // 00 - no interrupt now 121 | // 01 - low level priority interrupt action now 122 | // 10 - high level priority interrupt action now 123 | // 11 - unknown error 124 | SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level 125 | SBIT(PS, 0xB8, 4); // UART0 interrupt priority level 126 | SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level 127 | SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level 128 | SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level 129 | SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level 130 | SFR(IE_EX, 0xE8); // extend interrupt enable 131 | SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt 132 | SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt 133 | SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt 134 | SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt 135 | SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt 136 | SBIT(IE_USB, 0xE8, 2); // enable USB interrupt 137 | SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt 138 | SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt 139 | SFR(IP_EX, 0xE9); // extend interrupt priority 140 | #define bIP_LEVEL 0x80 // ReadOnly: current interrupt nested level: 0=no interrupt or two levels, 1=one level 141 | #define bIP_GPIO 0x40 // GPIO input interrupt priority level 142 | #define bIP_PWMX 0x20 // PWM1/2 interrupt priority level 143 | #define bIP_UART1 0x10 // UART1 interrupt priority level 144 | #define bIP_ADC 0x08 // ADC interrupt priority level 145 | #define bIP_USB 0x04 // USB interrupt priority level 146 | #define bIP_TKEY 0x02 // touch-key timer interrupt priority level 147 | #define bIP_SPI0 0x01 // SPI0 interrupt priority level 148 | SFR(GPIO_IE, 0xC7); // GPIO interrupt enable 149 | #define bIE_IO_EDGE 0x80 // enable GPIO edge interrupt: 0=low/high level, 1=falling/rising edge 150 | #define bIE_RXD1_LO 0x40 // enable interrupt by RXD1 low level / falling edge 151 | #define bIE_P1_5_LO 0x20 // enable interrupt by pin P1.5 low level / falling edge 152 | #define bIE_P1_4_LO 0x10 // enable interrupt by pin P1.4 low level / falling edge 153 | #define bIE_P1_3_LO 0x08 // enable interrupt by pin P1.3 low level / falling edge 154 | #define bIE_RST_HI 0x04 // enable interrupt by pin RST high level / rising edge 155 | #define bIE_P3_1_LO 0x02 // enable interrupt by pin P3.1 low level / falling edge 156 | #define bIE_RXD0_LO 0x01 // enable interrupt by RXD0 low level / falling edge 157 | 158 | /* FlashROM and Data-Flash Registers */ 159 | SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian 160 | SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM 161 | SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM 162 | SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian 163 | SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing 164 | SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing 165 | SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control 166 | #define ROM_CMD_WRITE 0x9A // WriteOnly: flash-ROM word or Data-Flash byte write operation command 167 | #define ROM_CMD_READ 0x8E // WriteOnly: Data-Flash byte read operation command 168 | //sfr ROM_STATUS = 0x86; // ReadOnly: flash-ROM status 169 | #define ROM_STATUS ROM_CTRL 170 | #define bROM_ADDR_OK 0x40 // ReadOnly: flash-ROM writing operation address valid flag, can be reviewed before or after operation: 0=invalid parameter, 1=address valid 171 | #define bROM_CMD_ERR 0x02 // ReadOnly: flash-ROM operation command error flag: 0=command accepted, 1=unknown command 172 | 173 | /* Port Registers */ 174 | SFR(P1, 0x90); // port 1 input & output 175 | SBIT(SCK, 0x90, 7); // serial clock for SPI0 176 | SBIT(TXD1, 0x90, 7); // TXD output for UART1 177 | SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key 178 | SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0 179 | SBIT(RXD1, 0x90, 6); // RXD input for UART1 180 | SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key 181 | SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0 182 | SBIT(PWM1, 0x90, 5); // PWM output for PWM1 183 | SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key 184 | SBIT(UCC2, 0x90, 5); // CC2 for USB type-C 185 | SBIT(AIN2, 0x90, 5); // AIN2 for ADC 186 | SBIT(T2_, 0x90, 4); // alternate pin for T2 187 | SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1 188 | SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0 189 | SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key 190 | SBIT(UCC1, 0x90, 4); // CC1 for USB type-C 191 | SBIT(AIN1, 0x90, 4); // AIN1 for ADC 192 | SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0 193 | SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0 194 | SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture 195 | SBIT(CAP2, 0x90, 1); // capture2 input for timer2 196 | SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key 197 | SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C 198 | SBIT(AIN0, 0x90, 1); // AIN0 for ADC 199 | SBIT(T2, 0x90, 0); // external count input 200 | SBIT(CAP1, 0x90, 0); // capture1 input for timer2 201 | SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key 202 | SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain 203 | SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain 204 | // Pn_MOD_OC & Pn_DIR_PU: pin input & output configuration for Pn (n=1/3) 205 | // 0 0: float input only, without pullup resistance 206 | // 0 1: push-pull output, strong driving high level and low level 207 | // 1 0: open-drain output and input without pullup resistance 208 | // 1 1: quasi-bidirectional (standard 8051 mode), open-drain output and input with pullup resistance, just driving high level strongly for 2 clocks if turning output level from low to high 209 | #define bSCK 0x80 // serial clock for SPI0 210 | #define bTXD1 0x80 // TXD output for UART1 211 | #define bMISO 0x40 // master serial data input or slave serial data output for SPI0 212 | #define bRXD1 0x40 // RXD input for UART1 213 | #define bMOSI 0x20 // master serial data output or slave serial data input for SPI0 214 | #define bPWM1 0x20 // PWM output for PWM1 215 | #define bUCC2 0x20 // CC2 for USB type-C 216 | #define bAIN2 0x20 // AIN2 for ADC 217 | #define bT2_ 0x10 // alternate pin for T2 218 | #define bCAP1_ 0x10 // alternate pin for CAP1 219 | #define bSCS 0x10 // slave chip-selection input for SPI0 220 | #define bUCC1 0x10 // CC1 for USB type-C 221 | #define bAIN1 0x10 // AIN1 for ADC 222 | #define bTXD_ 0x08 // alternate pin for TXD of UART0 223 | #define bRXD_ 0x04 // alternate pin for RXD of UART0 224 | #define bT2EX 0x02 // external trigger input for timer2 reload & capture 225 | #define bCAP2 bT2EX // capture2 input for timer2 226 | #define bVBUS2 0x02 // VBUS2 for USB type-C 227 | #define bAIN0 0x02 // AIN0 for ADC 228 | #define bT2 0x01 // external count input or clock output for timer2 229 | #define bCAP1 bT2 // capture1 input for timer2 230 | SFR(P2, 0xA0); // port 2 231 | SFR(P3, 0xB0); // port 3 input & output 232 | SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input 233 | SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input 234 | SBIT(T1, 0xB0, 5); // external count input for timer1 235 | SBIT(PWM2, 0xB0, 4); // PWM output for PWM2 236 | SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1 237 | SBIT(T0, 0xB0, 4); // external count input for timer0 238 | SBIT(INT1, 0xB0, 3); // external interrupt 1 input 239 | SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1 240 | SBIT(INT0, 0xB0, 2); // external interrupt 0 input 241 | SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C 242 | SBIT(AIN3, 0xB0, 2); // AIN3 for ADC 243 | SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2 244 | SBIT(TXD, 0xB0, 1); // TXD output for UART0 245 | SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1 246 | SBIT(RXD, 0xB0, 0); // RXD input for UART0 247 | SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain 248 | SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain 249 | #define bUDM 0x80 // ReadOnly: pin UDM input 250 | #define bUDP 0x40 // ReadOnly: pin UDP input 251 | #define bT1 0x20 // external count input for timer1 252 | #define bPWM2 0x10 // PWM output for PWM2 253 | #define bRXD1_ 0x10 // alternate pin for RXD1 254 | #define bT0 0x10 // external count input for timer0 255 | #define bINT1 0x08 // external interrupt 1 input 256 | #define bTXD1_ 0x04 // alternate pin for TXD1 257 | #define bINT0 0x04 // external interrupt 0 input 258 | #define bVBUS1 0x04 // VBUS1 for USB type-C 259 | #define bAIN3 0x04 // AIN3 for ADC 260 | #define bPWM2_ 0x02 // alternate pin for PWM2 261 | #define bTXD 0x02 // TXD output for UART0 262 | #define bPWM1_ 0x01 // alternate pin for PWM1 263 | #define bRXD 0x01 // RXD input for UART0 264 | SFR(PIN_FUNC, 0xC6); // pin function selection 265 | #define bUSB_IO_EN 0x80 // USB UDP/UDM I/O pin enable: 0=P3.6/P3.7 as GPIO, 1=P3.6/P3.7 as USB 266 | #define bIO_INT_ACT 0x40 // ReadOnly: GPIO interrupt request action status 267 | #define bUART1_PIN_X 0x20 // UART1 alternate pin enable: 0=RXD1/TXD1 on P1.6/P1.7, 1=RXD1/TXD1 on P3.4/P3.2 268 | #define bUART0_PIN_X 0x10 // UART0 alternate pin enable: 0=RXD0/TXD0 on P3.0/P3.1, 1=RXD0/TXD0 on P1.2/P1.3 269 | #define bPWM2_PIN_X 0x08 // PWM2 alternate pin enable: 0=PWM2 on P3.4, 1=PWM2 on P3.1 270 | #define bPWM1_PIN_X 0x04 // PWM1 alternate pin enable: 0=PWM1 on P1.5, 1=PWM1 on P3.0 271 | #define bT2EX_PIN_X 0x02 // T2EX/CAP2 alternate pin enable: 0=T2EX/CAP2 on P1.1, 1=T2EX/CAP2 on RST 272 | #define bT2_PIN_X 0x01 // T2/CAP1 alternate pin enable: 0=T2/CAP1 on P1.1, 1=T2/CAP1 on P1.4 273 | SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting 274 | #define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmittal status 275 | #define bUART0_RX 0x40 // ReadOnly: indicate UART0 receiving status 276 | #define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status 277 | #define GF2 0x08 // general purpose flag bit 2 278 | #define bDPTR_AUTO_INC 0x04 // enable DPTR auto increase if finished MOVX_@DPTR instruction 279 | #define DPS 0x01 // dual DPTR selection: 0=DPTR0 selected, 1=DPTR1 selected 280 | 281 | /* Timer0/1 Registers */ 282 | SFR(TCON, 0x88); // timer 0/1 control and external interrupt control 283 | SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine 284 | SBIT(TR1, 0x88, 6); // timer1 run enable 285 | SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine 286 | SBIT(TR0, 0x88, 4); // timer0 run enable 287 | SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine 288 | SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action 289 | SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine 290 | SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action 291 | SFR(TMOD, 0x89); // timer 0/1 mode 292 | #define bT1_GATE 0x80 // gate control of timer1: 0=timer1 run enable while TR1=1, 1=timer1 run enable while P3.3 (INT1) pin is high and TR1=1 293 | #define bT1_CT 0x40 // counter or timer mode selection for timer1: 0=timer, use internal clock, 1=counter, use P3.5 (T1) pin falling edge as clock 294 | #define bT1_M1 0x20 // timer1 mode high bit 295 | #define bT1_M0 0x10 // timer1 mode low bit 296 | #define MASK_T1_MOD 0x30 // bit mask of timer1 mode 297 | // bT1_M1 & bT1_M0: timer1 mode 298 | // 00: mode 0, 13-bit timer or counter by cascaded TH1 and lower 5 bits of TL1, the upper 3 bits of TL1 are ignored 299 | // 01: mode 1, 16-bit timer or counter by cascaded TH1 and TL1 300 | // 10: mode 2, TL1 operates as 8-bit timer or counter, and TH1 provide initial value for TL1 auto-reload 301 | // 11: mode 3, stop timer1 302 | #define bT0_GATE 0x08 // gate control of timer0: 0=timer0 run enable while TR0=1, 1=timer0 run enable while P3.2 (INT0) pin is high and TR0=1 303 | #define bT0_CT 0x04 // counter or timer mode selection for timer0: 0=timer, use internal clock, 1=counter, use P3.4 (T0) pin falling edge as clock 304 | #define bT0_M1 0x02 // timer0 mode high bit 305 | #define bT0_M0 0x01 // timer0 mode low bit 306 | #define MASK_T0_MOD 0x03 // bit mask of timer0 mode 307 | // bT0_M1 & bT0_M0: timer0 mode 308 | // 00: mode 0, 13-bit timer or counter by cascaded TH0 and lower 5 bits of TL0, the upper 3 bits of TL0 are ignored 309 | // 01: mode 1, 16-bit timer or counter by cascaded TH0 and TL0 310 | // 10: mode 2, TL0 operates as 8-bit timer or counter, and TH0 provide initial value for TL0 auto-reload 311 | // 11: mode 3, TL0 is 8-bit timer or counter controlled by standard timer0 bits, TH0 is 8-bit timer using TF1 and controlled by TR1, timer1 run enable if it is not mode 3 312 | SFR(TL0, 0x8A); // low byte of timer 0 count 313 | SFR(TL1, 0x8B); // low byte of timer 1 count 314 | SFR(TH0, 0x8C); // high byte of timer 0 count 315 | SFR(TH1, 0x8D); // high byte of timer 1 count 316 | 317 | /* UART0 Registers */ 318 | SFR(SCON, 0x98); // UART0 control (serial port control) 319 | SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data 320 | SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable 321 | // SM0 & SM1: UART0 mode 322 | // 00 - mode 0, shift Register, baud rate fixed at: Fsys/12 323 | // 01 - mode 1, 8-bit UART, baud rate = variable by timer1 or timer2 overflow rate 324 | // 10 - mode 2, 9-bit UART, baud rate fixed at: Fsys/128@SMOD=0, Fsys/32@SMOD=1 325 | // 11 - mode 3, 9-bit UART, baud rate = variable by timer1 or timer2 overflow rate 326 | SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3 327 | #define MASK_UART0_MOD 0xE0 // bit mask of UART0 mode 328 | SBIT(REN, 0x98, 4); // enable UART0 receiving 329 | SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3 330 | SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1 331 | SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear 332 | SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear 333 | SFR(SBUF, 0x99); // UART0 data buffer: reading for receiving, writing for transmittal 334 | 335 | /* Timer2/Capture2 Registers */ 336 | SFR(T2CON, 0xC8); // timer 2 control 337 | SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1 338 | SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear 339 | SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear 340 | SBIT(RCLK, 0xC8, 5); // selection UART0 receiving clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse 341 | SBIT(TCLK, 0xC8, 4); // selection UART0 transmittal clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse 342 | SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge 343 | SBIT(TR2, 0xC8, 2); // timer2 run enable 344 | SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge 345 | SBIT(CP_RL2, 0xC8, 0); // timer2 function selection (force 0 if RCLK=1 or TCLK=1): 0=timer and auto reload if count overflow or T2EX edge, 1=capture by T2EX edge 346 | SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode 347 | #define bTMR_CLK 0x80 // fastest internal clock mode for timer 0/1/2 under faster clock mode: 0=use divided clock, 1=use original Fsys as clock without dividing 348 | #define bT2_CLK 0x40 // timer2 internal clock frequency selection: 0=standard clock, Fsys/12 for timer mode, Fsys/4 for UART0 clock mode, 349 | // 1=faster clock, Fsys/4 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for timer mode, Fsys/2 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for UART0 clock mode 350 | #define bT1_CLK 0x20 // timer1 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1 351 | #define bT0_CLK 0x10 // timer0 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1 352 | #define bT2_CAP_M1 0x08 // timer2 capture mode high bit 353 | #define bT2_CAP_M0 0x04 // timer2 capture mode low bit 354 | // bT2_CAP_M1 & bT2_CAP_M0: timer2 capture point selection 355 | // x0: from falling edge to falling edge 356 | // 01: from any edge to any edge (level changing) 357 | // 11: from rising edge to rising edge 358 | #define T2OE 0x02 // enable timer2 generated clock output: 0=disable output, 1=enable clock output at T2 pin, frequency = TF2/2 359 | #define bT2_CAP1_EN 0x01 // enable T2 trigger function for capture 1 of timer2 if RCLK=0 & TCLK=0 & CP_RL2=1 & C_T2=0 & T2OE=0 360 | SFR16(RCAP2, 0xCA); // reload & capture value, little-endian 361 | SFR(RCAP2L, 0xCA); // low byte of reload & capture value 362 | SFR(RCAP2H, 0xCB); // high byte of reload & capture value 363 | SFR16(T2COUNT, 0xCC); // counter, little-endian 364 | SFR(TL2, 0xCC); // low byte of timer 2 count 365 | SFR(TH2, 0xCD); // high byte of timer 2 count 366 | SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2 367 | SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2 368 | SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2 369 | 370 | /* PWM1/2 Registers */ 371 | SFR(PWM_DATA2, 0x9B); // PWM data for PWM2 372 | SFR(PWM_DATA1, 0x9C); // PWM data for PWM1 373 | SFR(PWM_CTRL, 0x9D); // PWM 1/2 control 374 | #define bPWM_IE_END 0x80 // enable interrupt for PWM mode cycle end 375 | #define bPWM2_POLAR 0x40 // PWM2 output polarity: 0=default low and high action, 1=default high and low action 376 | #define bPWM1_POLAR 0x20 // PWM1 output polarity: 0=default low and high action, 1=default high and low action 377 | #define bPWM_IF_END 0x10 // interrupt flag for cycle end, write 1 to clear or write PWM_CYCLE or load new data to clear 378 | #define bPWM2_OUT_EN 0x08 // PWM2 output enable 379 | #define bPWM1_OUT_EN 0x04 // PWM1 output enable 380 | #define bPWM_CLR_ALL 0x02 // force clear FIFO and count of PWM1/2 381 | SFR(PWM_CK_SE, 0x9E); // clock divisor setting 382 | 383 | /* SPI0/Master0/Slave Registers */ 384 | SFR(SPI0_STAT, 0xF8); // SPI 0 status 385 | SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0 386 | SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear 387 | SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear 388 | SBIT(S0_IF_BYTE, 0xF8, 4); // interrupt flag for a byte data exchanged, direct bit address clear or write 1 to clear or accessing FIFO to clear if bS0_AUTO_IF=1 389 | SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status 390 | SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0 391 | SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0 392 | SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receiving, writing for transmittal 393 | SFR(SPI0_CTRL, 0xFA); // SPI 0 control 394 | #define bS0_MISO_OE 0x80 // SPI0 MISO output enable 395 | #define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable 396 | #define bS0_SCK_OE 0x20 // SPI0 SCK output enable 397 | #define bS0_DATA_DIR 0x10 // SPI0 data direction: 0=out(master_write), 1=in(master_read) 398 | #define bS0_MST_CLK 0x08 // SPI0 master clock mode: 0=mode 0 with default low, 1=mode 3 with default high 399 | #define bS0_2_WIRE 0x04 // enable SPI0 two wire mode: 0=3 wire (SCK+MOSI+MISO), 1=2 wire (SCK+MISO) 400 | #define bS0_CLR_ALL 0x02 // force clear FIFO and count of SPI0 401 | #define bS0_AUTO_IF 0x01 // enable FIFO accessing to auto clear S0_IF_BYTE interrupt flag 402 | SFR(SPI0_CK_SE, 0xFB); // clock divisor setting 403 | //sfr SPI0_S_PRE = 0xFB; // preset value for SPI slave 404 | #define SPI0_S_PRE SPI0_CK_SE 405 | SFR(SPI0_SETUP, 0xFC); // SPI 0 setup 406 | #define bS0_MODE_SLV 0x80 // SPI0 slave mode: 0=master, 1=slave 407 | #define bS0_IE_FIFO_OV 0x40 // enable interrupt for slave mode FIFO overflow 408 | #define bS0_IE_FIRST 0x20 // enable interrupt for first byte received for SPI0 slave mode 409 | #define bS0_IE_BYTE 0x10 // enable interrupt for a byte received 410 | #define bS0_BIT_ORDER 0x08 // SPI0 bit data order: 0=MSB first, 1=LSB first 411 | #define bS0_SLV_SELT 0x02 // ReadOnly: SPI0 slave mode chip selected status: 0=unselected, 1=selected 412 | #define bS0_SLV_PRELOAD 0x01 // ReadOnly: SPI0 slave mode data pre-loading status just after chip-selection 413 | 414 | /* UART1 Registers */ 415 | SFR(SCON1, 0xC0); // UART1 control (serial port control) 416 | SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data 417 | SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1)) 418 | SBIT(U1REN, 0xC0, 4); // enable UART1 receiving 419 | SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode 420 | SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode 421 | SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear 422 | SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear 423 | SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receiving, writing for transmittal 424 | SFR(SBAUD1, 0xC2); // UART1 baud rate setting 425 | 426 | /* ADC and comparator Registers */ 427 | SFR(ADC_CTRL, 0x80); // ADC control 428 | SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input 429 | SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear 430 | SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear 431 | SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished 432 | SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3 433 | SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit 434 | SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit 435 | // ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection 436 | // 00: AIN0(P1.1) 437 | // 01: AIN1(P1.4) 438 | // 10: AIN2(P1.5) 439 | // 11: AIN3(P3.2) 440 | SFR(ADC_CFG, 0x9A); // ADC config 441 | #define bADC_EN 0x08 // control ADC power: 0=shut down ADC, 1=enable power for ADC 442 | #define bCMP_EN 0x04 // control comparator power: 0=shut down comparator, 1=enable power for comparator 443 | #define bADC_CLK 0x01 // ADC clock frequency selection: 0=slow clock, 384 Fosc cycles for each ADC, 1=fast clock, 96 Fosc cycles for each ADC 444 | SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data 445 | 446 | /* Touch-key timer Registers */ 447 | SFR(TKEY_CTRL, 0xC3); // touch-key control 448 | #define bTKC_IF 0x80 // ReadOnly: interrupt flag for touch-key timer, cleared by writing touch-key control or auto cleared when start touch-key checking 449 | #define bTKC_2MS 0x10 // touch-key timer cycle selection: 0=1mS, 1=2mS 450 | #define bTKC_CHAN2 0x04 // touch-key channel selection high bit 451 | #define bTKC_CHAN1 0x02 // touch-key channel selection middle bit 452 | #define bTKC_CHAN0 0x01 // touch-key channel selection low bit 453 | // bTKC_CHAN2 & bTKC_CHAN1 & bTKC_CHAN0: touch-key channel selection 454 | // 000: disable touch-key 455 | // 001: TIN0(P1.0) 456 | // 010: TIN1(P1.1) 457 | // 011: TIN2(P1.4) 458 | // 100: TIN3(P1.5) 459 | // 101: TIN4(P1.6) 460 | // 110: TIN5(P1.7) 461 | // 111: enable touch-key but disable all channel 462 | SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian 463 | SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data 464 | SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data 465 | #define bTKD_CHG 0x80 // ReadOnly: indicate control changed, current data maybe invalid 466 | 467 | /* USB/Host/Device Registers */ 468 | SFR(USB_C_CTRL, 0x91); // USB type-C control 469 | #define bVBUS2_PD_EN 0x80 // USB VBUS2 10K pulldown resistance: 0=disable, 1=enable pullup 470 | #define bUCC2_PD_EN 0x40 // USB CC2 5.1K pulldown resistance: 0=disable, 1=enable pulldown 471 | #define bUCC2_PU1_EN 0x20 // USB CC2 pullup resistance control high bit 472 | #define bUCC2_PU0_EN 0x10 // USB CC2 pullup resistance control low bit 473 | #define bVBUS1_PD_EN 0x08 // USB VBUS1 10K pulldown resistance: 0=disable, 1=enable pullup 474 | #define bUCC1_PD_EN 0x04 // USB CC1 5.1K pulldown resistance: 0=disable, 1=enable pulldown 475 | #define bUCC1_PU1_EN 0x02 // USB CC1 pullup resistance control high bit 476 | #define bUCC1_PU0_EN 0x01 // USB CC1 pullup resistance control low bit 477 | // bUCC?_PU1_EN & bUCC?_PU0_EN: USB CC pullup resistance selection 478 | // 00: disable pullup resistance 479 | // 01: enable 56K pullup resistance for default USB power 480 | // 10: enable 22K pullup resistance for 1.5A USB power 481 | // 11: enable 10K pullup resistance for 3A USB power 482 | SFR(UDEV_CTRL, 0xD1); // USB device physical port control 483 | #define bUD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable 484 | #define bUD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level 485 | #define bUD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level 486 | #define bUD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed 487 | #define bUD_GP_BIT 0x02 // general purpose bit 488 | #define bUD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable 489 | //sfr UHOST_CTRL = 0xD1; // USB host physical port control 490 | #define UHOST_CTRL UDEV_CTRL 491 | #define bUH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable 492 | #define bUH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level 493 | #define bUH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level 494 | #define bUH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed 495 | #define bUH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset 496 | #define bUH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached 497 | SFR(UEP1_CTRL, 0xD2); // endpoint 1 control 498 | #define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 499 | #define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 500 | #define bUEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle 501 | #define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT) 502 | #define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT) 503 | #define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT) 504 | #define UEP_R_RES_ACK 0x00 505 | #define UEP_R_RES_TOUT 0x04 506 | #define UEP_R_RES_NAK 0x08 507 | #define UEP_R_RES_STALL 0x0C 508 | // bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receiving (OUT) 509 | // 00: ACK (ready) 510 | // 01: no response, time out to host, for non-zero endpoint isochronous transactions 511 | // 10: NAK (busy) 512 | // 11: STALL (error) 513 | #define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN) 514 | #define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN) 515 | #define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN) 516 | #define UEP_T_RES_ACK 0x00 517 | #define UEP_T_RES_TOUT 0x01 518 | #define UEP_T_RES_NAK 0x02 519 | #define UEP_T_RES_STALL 0x03 520 | // bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) 521 | // 00: DATA0 or DATA1 then expecting ACK (ready) 522 | // 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions 523 | // 10: NAK (busy) 524 | // 11: STALL (error) 525 | SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmittal length 526 | SFR(UEP2_CTRL, 0xD4); // endpoint 2 control 527 | SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmittal length 528 | SFR(UEP3_CTRL, 0xD6); // endpoint 3 control 529 | SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmittal length 530 | SFR(USB_INT_FG, 0xD8); // USB interrupt flag 531 | SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received 532 | SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK 533 | SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status 534 | SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear 535 | SBIT(UIF_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear 536 | SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear 537 | SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear 538 | SBIT(UIF_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear 539 | SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear 540 | SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status 541 | #define bUIS_IS_NAK 0x80 // ReadOnly: indicate current USB transfer is NAK received for USB device mode 542 | #define bUIS_TOG_OK 0x40 // ReadOnly: indicate current USB transfer toggle is OK 543 | #define bUIS_TOKEN1 0x20 // ReadOnly: current token PID code bit 1 received for USB device mode 544 | #define bUIS_TOKEN0 0x10 // ReadOnly: current token PID code bit 0 received for USB device mode 545 | #define MASK_UIS_TOKEN 0x30 // ReadOnly: bit mask of current token PID code received for USB device mode 546 | #define UIS_TOKEN_OUT 0x00 547 | #define UIS_TOKEN_SOF 0x10 548 | #define UIS_TOKEN_IN 0x20 549 | #define UIS_TOKEN_SETUP 0x30 550 | // bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode 551 | // 00: OUT token PID received 552 | // 01: SOF token PID received 553 | // 10: IN token PID received 554 | // 11: SETUP token PID received 555 | #define MASK_UIS_ENDP 0x0F // ReadOnly: bit mask of current transfer endpoint number for USB device mode 556 | #define MASK_UIS_H_RES 0x0F // ReadOnly: bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received 557 | SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status 558 | #define bUMS_SOF_PRES 0x80 // ReadOnly: indicate host SOF timer presage status 559 | #define bUMS_SOF_ACT 0x40 // ReadOnly: indicate host SOF timer action status for USB host 560 | #define bUMS_SIE_FREE 0x20 // ReadOnly: indicate USB SIE free status 561 | #define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receiving FIFO ready status (not empty) 562 | #define bUMS_BUS_RESET 0x08 // ReadOnly: indicate USB bus reset status 563 | #define bUMS_SUSPEND 0x04 // ReadOnly: indicate USB suspend status 564 | #define bUMS_DM_LEVEL 0x02 // ReadOnly: indicate UDM level saved at device attached to USB host 565 | #define bUMS_DEV_ATTACH 0x01 // ReadOnly: indicate device attached status on USB host 566 | SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receiving length 567 | SFR(UEP0_CTRL, 0xDC); // endpoint 0 control 568 | SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmittal length 569 | SFR(UEP4_CTRL, 0xDE); // endpoint 4 control 570 | SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmittal length 571 | SFR(USB_INT_EN, 0xE1); // USB interrupt enable 572 | #define bUIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode 573 | #define bUIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode 574 | #define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow 575 | #define bUIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode 576 | #define bUIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event 577 | #define bUIE_TRANSFER 0x02 // enable interrupt for USB transfer completion 578 | #define bUIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode 579 | #define bUIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode 580 | SFR(USB_CTRL, 0xE2); // USB base control 581 | #define bUC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode 582 | #define bUC_LOW_SPEED 0x40 // enable USB low speed: 0=full speed, 1=low speed 583 | #define bUC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable 584 | #define bUC_SYS_CTRL1 0x20 // USB system control high bit 585 | #define bUC_SYS_CTRL0 0x10 // USB system control low bit 586 | #define MASK_UC_SYS_CTRL 0x30 // bit mask of USB system control 587 | // bUC_HOST_MODE & bUC_SYS_CTRL1 & bUC_SYS_CTRL0: USB system control 588 | // 0 00: disable USB device and disable internal pullup resistance 589 | // 0 01: enable USB device and disable internal pullup resistance, need external pullup resistance 590 | // 0 1x: enable USB device and enable internal pullup resistance 591 | // 1 00: enable USB host and normal status 592 | // 1 01: enable USB host and force UDP/UDM output SE0 state 593 | // 1 10: enable USB host and force UDP/UDM output J state 594 | // 1 11: enable USB host and force UDP/UDM output resume or K state 595 | #define bUC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid 596 | #define bUC_RESET_SIE 0x04 // force reset USB SIE, need software clear 597 | #define bUC_CLR_ALL 0x02 // force clear FIFO and count of USB 598 | #define bUC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB 599 | SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address 600 | #define bUDA_GP_BIT 0x80 // general purpose bit 601 | #define MASK_USB_ADDR 0x7F // bit mask for USB device address 602 | SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian 603 | SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte 604 | SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte 605 | SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian 606 | SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte 607 | SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte 608 | SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode 609 | #define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT) 610 | #define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN) 611 | #define bUEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1 612 | // bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA 613 | // 0 0 x: disable endpoint and disable buffer 614 | // 1 0 0: 64 bytes buffer for receiving (OUT endpoint) 615 | // 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes 616 | // 0 1 0: 64 bytes buffer for transmittal (IN endpoint) 617 | // 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes 618 | // 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes 619 | // 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes 620 | #define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT) 621 | #define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN) 622 | // bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA 623 | // 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) 624 | // 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes 625 | // 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes 626 | // 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) 627 | // + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes 628 | SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode 629 | #define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT) 630 | #define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN) 631 | #define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3 632 | #define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT) 633 | #define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN) 634 | #define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2 635 | SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian 636 | SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte 637 | SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte 638 | SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian 639 | SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte 640 | SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte 641 | //sfr UH_SETUP = 0xD2; // host aux setup 642 | #define UH_SETUP UEP1_CTRL 643 | #define bUH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub 644 | #define bUH_SOF_EN 0x40 // USB host automatic SOF enable 645 | //sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control 646 | #define UH_RX_CTRL UEP2_CTRL 647 | #define bUH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1 648 | #define bUH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle 649 | #define bUH_R_RES 0x04 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions 650 | //sfr UH_EP_PID = 0xD5; // host endpoint and token PID, lower 4 bits for endpoint number, upper 4 bits for token PID 651 | #define UH_EP_PID UEP2_T_LEN 652 | #define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer 653 | #define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer 654 | //sfr UH_TX_CTRL = 0xD6; // host transmittal endpoint control 655 | #define UH_TX_CTRL UEP3_CTRL 656 | #define bUH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1 657 | #define bUH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle 658 | #define bUH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions 659 | //sfr UH_TX_LEN = 0xD7; // host transmittal endpoint transmittal length 660 | #define UH_TX_LEN UEP3_T_LEN 661 | //sfr UH_EP_MOD = 0xEB; // host endpoint mode 662 | #define UH_EP_MOD UEP2_3_MOD 663 | #define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal 664 | #define bUH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint 665 | // bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA 666 | // 0 x: disable endpoint and disable buffer 667 | // 1 0: 64 bytes buffer for transmittal (OUT endpoint) 668 | // 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes 669 | #define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving 670 | #define bUH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint 671 | // bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA 672 | // 0 x: disable endpoint and disable buffer 673 | // 1 0: 64 bytes buffer for receiving (IN endpoint) 674 | // 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes 675 | //sfr16 UH_RX_DMA = 0xE4; // host rx endpoint buffer start address, little-endian 676 | #define UH_RX_DMA UEP2_DMA 677 | //sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte 678 | #define UH_RX_DMA_L UEP2_DMA_L 679 | //sfr UH_RX_DMA_H = 0xE5; // host rx endpoint buffer start address high byte 680 | #define UH_RX_DMA_H UEP2_DMA_H 681 | //sfr16 UH_TX_DMA = 0xE6; // host tx endpoint buffer start address, little-endian 682 | #define UH_TX_DMA UEP3_DMA 683 | //sfr UH_TX_DMA_L = 0xE6; // host tx endpoint buffer start address low byte 684 | #define UH_TX_DMA_L UEP3_DMA_L 685 | //sfr UH_TX_DMA_H = 0xE7; // host tx endpoint buffer start address high byte 686 | #define UH_TX_DMA_H UEP3_DMA_H 687 | 688 | /*----- XDATA: xRAM ------------------------------------------*/ 689 | 690 | #define XDATA_RAM_SIZE 0x0400 // size of expanded xRAM, xdata SRAM embedded chip 691 | 692 | /*----- Reference Information --------------------------------------------*/ 693 | #define ID_CH554 0x54 // chip ID 694 | 695 | /* Interrupt routine address and interrupt number */ 696 | #define INT_ADDR_INT0 0x0003 // interrupt vector address for INT0 697 | #define INT_ADDR_TMR0 0x000B // interrupt vector address for timer0 698 | #define INT_ADDR_INT1 0x0013 // interrupt vector address for INT1 699 | #define INT_ADDR_TMR1 0x001B // interrupt vector address for timer1 700 | #define INT_ADDR_UART0 0x0023 // interrupt vector address for UART0 701 | #define INT_ADDR_TMR2 0x002B // interrupt vector address for timer2 702 | #define INT_ADDR_SPI0 0x0033 // interrupt vector address for SPI0 703 | #define INT_ADDR_TKEY 0x003B // interrupt vector address for touch-key timer 704 | #define INT_ADDR_USB 0x0043 // interrupt vector address for USB 705 | #define INT_ADDR_ADC 0x004B // interrupt vector address for ADC 706 | #define INT_ADDR_UART1 0x0053 // interrupt vector address for UART1 707 | #define INT_ADDR_PWMX 0x005B // interrupt vector address for PWM1/2 708 | #define INT_ADDR_GPIO 0x0063 // interrupt vector address for GPIO 709 | #define INT_ADDR_WDOG 0x006B // interrupt vector address for watch-dog timer 710 | #define INT_NO_INT0 0 // interrupt number for INT0 711 | #define INT_NO_TMR0 1 // interrupt number for timer0 712 | #define INT_NO_INT1 2 // interrupt number for INT1 713 | #define INT_NO_TMR1 3 // interrupt number for timer1 714 | #define INT_NO_UART0 4 // interrupt number for UART0 715 | #define INT_NO_TMR2 5 // interrupt number for timer2 716 | #define INT_NO_SPI0 6 // interrupt number for SPI0 717 | #define INT_NO_TKEY 7 // interrupt number for touch-key timer 718 | #define INT_NO_USB 8 // interrupt number for USB 719 | #define INT_NO_ADC 9 // interrupt number for ADC 720 | #define INT_NO_UART1 10 // interrupt number for UART1 721 | #define INT_NO_PWMX 11 // interrupt number for PWM1/2 722 | #define INT_NO_GPIO 12 // interrupt number for GPIO 723 | #define INT_NO_WDOG 13 // interrupt number for watch-dog timer 724 | 725 | /* Special Program Space */ 726 | #define DATA_FLASH_ADDR 0xC000 // start address of Data-Flash 727 | #define BOOT_LOAD_ADDR 0x3800 // start address of boot loader program 728 | #define ROM_CFG_ADDR 0x3FF8 // chip configuration information address 729 | #define ROM_CHIP_ID_HX 0x3FFA // chip ID number highest byte (only low byte valid) 730 | #define ROM_CHIP_ID_LO 0x3FFC // chip ID number low word 731 | #define ROM_CHIP_ID_HI 0x3FFE // chip ID number high word 732 | 733 | /* 734 | New Instruction: MOVX @DPTR1,A 735 | Instruction Code: 0xA5 736 | Instruction Cycle: 1 737 | Instruction Operation: 738 | step-1. write ACC @DPTR1 into xdata SRAM embedded chip 739 | step-2. increase DPTR1 740 | ASM example: 741 | INC XBUS_AUX 742 | MOV DPTR,#TARGET_ADDR ;DPTR1 743 | DEC XBUS_AUX 744 | MOV DPTR,#SOURCE_ADDR ;DPTR0 745 | MOV R7,#xxH 746 | LOOP: MOVX A,@DPTR ;DPTR0 747 | INC DPTR ;DPTR0, if need 748 | DB 0A5H ;MOVX @DPTR1,A & INC DPTR1 749 | DJNZ R7,LOOP 750 | */ 751 | 752 | #endif // __CH554_H__ 753 | -------------------------------------------------------------------------------- /include/ch554_datatypes.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | CH554.H 3 | Header file for CH554 microcontrollers. 4 | **************************************** 5 | ** Copyright (C) W.ch 1999-2014 ** 6 | ** Web: http://wch.cn ** 7 | **************************************** 8 | --------------------------------------------------------------------------*/ 9 | 10 | #ifndef __BASE_TYPE__ 11 | #define __BASE_TYPE__ 12 | 13 | /*----- constant and type define -----------------------------------------*/ 14 | 15 | #ifndef TRUE 16 | #define TRUE 1 17 | #define FALSE 0 18 | #endif 19 | #ifndef NULL 20 | #define NULL 0 21 | #endif 22 | 23 | #ifndef BOOL 24 | typedef bit BOOL; 25 | #endif 26 | #ifndef UINT8 27 | typedef unsigned char UINT8; 28 | #endif 29 | #ifndef UINT16 30 | typedef unsigned short UINT16; 31 | #endif 32 | #ifndef UINT32 33 | typedef unsigned long UINT32; 34 | #endif 35 | #ifndef UINT8D 36 | typedef unsigned char data UINT8D; 37 | #endif 38 | #ifndef UINT16D 39 | typedef unsigned short data UINT16D; 40 | #endif 41 | #ifndef UINT32D 42 | typedef unsigned long data UINT32D; 43 | #endif 44 | #ifndef UINT8I 45 | typedef unsigned char idata UINT8I; 46 | #endif 47 | #ifndef UINT16I 48 | typedef unsigned short idata UINT16I; 49 | #endif 50 | #ifndef UINT32I 51 | typedef unsigned long idata UINT32I; 52 | #endif 53 | #ifndef UINT8X 54 | typedef unsigned char xdata UINT8X; 55 | #endif 56 | #ifndef UINT16X 57 | typedef unsigned short xdata UINT16X; 58 | #endif 59 | #ifndef UINT32X 60 | typedef unsigned long xdata UINT32X; 61 | #endif 62 | #ifndef UINT8V 63 | typedef unsigned char volatile UINT8V; 64 | #endif 65 | #ifndef UINT8DV 66 | typedef unsigned char volatile data UINT8DV; 67 | #endif 68 | #ifndef UINT8XV 69 | typedef unsigned char volatile xdata UINT8XV; 70 | #endif 71 | #ifndef UINT8PV 72 | typedef unsigned char volatile pdata UINT8PV; 73 | #endif 74 | #ifndef UINT8C 75 | typedef const unsigned char code UINT8C; 76 | #endif 77 | #ifndef PUINT8 78 | typedef unsigned char *PUINT8; 79 | #endif 80 | #ifndef PUINT16 81 | typedef unsigned short *PUINT16; 82 | #endif 83 | #ifndef PUINT32 84 | typedef unsigned long *PUINT32; 85 | #endif 86 | #ifndef PUINT8I 87 | typedef unsigned char idata *PUINT8I; 88 | #endif 89 | #ifndef PUINT16I 90 | typedef unsigned short idata *PUINT16I; 91 | #endif 92 | #ifndef PUINT32I 93 | typedef unsigned long idata *PUINT32I; 94 | #endif 95 | #ifndef PUINT8X 96 | typedef unsigned char xdata *PUINT8X; 97 | #endif 98 | #ifndef PUINT16X 99 | typedef unsigned short xdata *PUINT16X; 100 | #endif 101 | #ifndef PUINT32X 102 | typedef unsigned long xdata *PUINT32X; 103 | #endif 104 | #ifndef PUINT8V 105 | typedef unsigned char volatile *PUINT8V; 106 | #endif 107 | #ifndef PUINT8DV 108 | typedef unsigned char volatile data *PUINT8DV; 109 | #endif 110 | #ifndef PUINT8XV 111 | typedef unsigned char volatile xdata *PUINT8XV; 112 | #endif 113 | #ifndef PUINT8PV 114 | typedef unsigned char volatile pdata *PUINT8PV; 115 | #endif 116 | #ifndef PUINT8C 117 | typedef const unsigned char code *PUINT8C; 118 | #endif 119 | 120 | #ifndef STRUCT_OFFSET 121 | #define STRUCT_OFFSET( s, m ) ( (UINT8)( & (((s) *)0) -> (m) ) ) /* get the offset address for a member of a structure */ 122 | #endif 123 | 124 | #endif // __BASE_TYPE__ 125 | -------------------------------------------------------------------------------- /include/ch554_usb.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/include/ch554_usb.h -------------------------------------------------------------------------------- /keilc51/CH554.H: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/keilc51/CH554.H -------------------------------------------------------------------------------- /keilc51/CH554.INC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/keilc51/CH554.INC -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include "Delay.H" 2 | #include "usb_cdc.h" 3 | 4 | #include "ch554_platform.h" 5 | 6 | void main(void) { 7 | CDC_InitBaud(); 8 | CH554_Init(); 9 | 10 | while(1) { 11 | CDC_USB_Poll(); 12 | CDC_UART_Poll(); 13 | }; 14 | } 15 | 16 | /* 17 | * According to SDCC specification, interrupt handlers MUST be placed within the file which contains 18 | * the void main(void) function, otherwise SDCC won't be able to recognize it. It's not a bug but a feature. 19 | * If you know how to fix this, please let me know. 20 | */ 21 | void USBInterruptEntry(void) interrupt INT_NO_USB { 22 | USBInterrupt(); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /spi.c: -------------------------------------------------------------------------------- 1 | #include "spi.h" 2 | 3 | #include "ch554_platform.h" 4 | 5 | void SPI_SetMasterMode0(void) { 6 | SPI0_SETUP = 0; // Master, MSB first 7 | SPI0_CTRL = 0x60; // Mode 0 8 | } 9 | 10 | void SPI_SetMasterMode3(void) { 11 | SPI0_SETUP = 0; // Master, MSB first 12 | SPI0_CTRL = 0x68; // Mode 3 13 | } 14 | 15 | void SPI_SetMasterIO(void) { 16 | P1_MOD_OC &= 0x0F; 17 | P1_DIR_PU |= 0xB0; // SCS,MOSI,SCK push-pull 18 | P1_DIR_PU &= 0xBF; // MISO floating 19 | } 20 | 21 | void SPI_SetMasterIOFloat(void) { 22 | P1_MOD_OC |= 0xF0; 23 | P1_DIR_PU &= 0x0F; // SCS,MOSI,SCK,MISO floating, no pull-up 24 | } 25 | 26 | uint8_t SPI_MasterData(uint8_t dat) { 27 | SPI0_DATA = dat; 28 | while(S0_FREE == 0); 29 | return SPI0_DATA; 30 | } 31 | -------------------------------------------------------------------------------- /spi.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPI_H_ 2 | #define __SPI_H_ 3 | 4 | #include "ch554_platform.h" 5 | 6 | #define SPI_SetCS(cs) (SCS = cs) 7 | #define SPI_SetClockDivider(n) (SPI0_CK_SE = n) 8 | 9 | void SPI_SetMasterMode0(void); 10 | void SPI_SetMasterMode3(void); 11 | void SPI_SetMasterIO(void); 12 | void SPI_SetMasterIOFloat(void); 13 | uint8_t SPI_MasterData(uint8_t dat); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /usb_cdc.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/usb_cdc.c -------------------------------------------------------------------------------- /usb_cdc.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_CDC_H 2 | #define __USB_CDC_H 3 | 4 | #include "ch554_platform.h" 5 | 6 | // CDC bRequests: 7 | // bmRequestType = 0xA1 8 | #define SERIAL_STATE 0x20 9 | #define GET_LINE_CODING 0X21 // This request allows the host to find out the currently configured line coding. 10 | // bmRequestType = 21 11 | #define SET_LINE_CODING 0X20 // Configures DTE rate, stop-bits, parity, and number-of-character 12 | #define SET_CONTROL_LINE_STATE 0X22 // This request generates RS-232/V.24 style control signals. 13 | #define SEND_BREAK 0x23 14 | 15 | // CDC Rx state machine 16 | #define CDC_STATE_IDLE 0 17 | #define CDC_STATE_I2C_TXSTART 1 18 | #define CDC_STATE_I2C_TXING 2 19 | #define CDC_STATE_I2C_RXSTART 3 20 | #define CDC_STATE_I2C_RXING 4 21 | #define CDC_STATE_SPI_TXSTART 5 22 | #define CDC_STATE_SPI_TXING 6 23 | #define CDC_STATE_SPI_RXING 7 24 | #define CDC_STATE_SPI_TEST 8 25 | 26 | #define CDC_FLAG_NOSTOP 0x80 27 | 28 | 29 | #define LINECODING_ADDR 0xCA 30 | #define LINECODING_SIZE 7 31 | extern_xdatabuf(LINECODING_ADDR, LineCoding); 32 | extern uint32_t CDC_Baud; 33 | 34 | 35 | #define CDC_PUTCHARBUF_LEN 64 36 | 37 | void CDC_InitBaud(void); 38 | void CDC_SetBaud(void); 39 | void CDC_USB_Poll(void); 40 | void CDC_UART_Poll(void); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /usb_desc.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/usb_desc.c -------------------------------------------------------------------------------- /usb_desc.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_DESC_H 2 | #define __USB_DESC_H 3 | 4 | #include "ch554_platform.h" 5 | 6 | // Note: to make the code more structural and human-readable, ideas have been borrowed from: 7 | // https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/f4/stm32f4-discovery/usb_midi/usbmidi.c#L259 8 | // https://github.com/libopencm3/libopencm3/blob/master/include/libopencm3/usb/usbstd.h 9 | 10 | #ifdef __SDCC 11 | #define USB_UINT8(name, val) .name = val 12 | // A Helper to set a 16-bit field in USB descriptors, USB int16s are little-endian (Except USB Attached SCSI) 13 | #define USB_UINT16(name, leVal) .name##L = leVal&0xFF, .name##H = (leVal>>8)&0xFF 14 | #elif defined __C51__ 15 | #define USB_UINT8(name,val) val 16 | #define USB_UINT16(name, leVal) leVal&0xFF, (leVal>>8)&0xFF 17 | #endif 18 | 19 | // USB Descriptors 20 | typedef struct _USB_DEVICE_DESCR usb_device_descriptor; 21 | #define USB_DESCSIZE_DEVICE sizeof(usb_device_descriptor) 22 | typedef struct _USB_CONFIG_DESCR usb_config_descriptor_header; 23 | #define USB_DESCSIZE_CONFIG sizeof(usb_config_descriptor) 24 | 25 | //typedef struct usb_config_descriptor_st { 26 | // usb_config_descriptor_header header; 27 | //} usb_config_descriptor; 28 | 29 | 30 | #define USB_INTERFACES 2 31 | 32 | // Common USB Descriptors 33 | 34 | #define USB_DESCSIZE_CONFIG_H 0 35 | #define USB_DESCSIZE_CONFIG_L 75 // Actual size of your CfgDesc, set according to your configuration 36 | // Device Descriptor 37 | extern code const usb_device_descriptor DevDesc; 38 | //extern code const uint8_t DevDesc[]; 39 | // Configuration Descriptor, Interface Descriptors, Endpoint Descriptors and ... 40 | extern code const uint8_t CfgDesc[]; 41 | // String Descriptors 42 | #define USB_STRINGDESC_COUNT 4 // Number of String Descriptors available 43 | extern code const uint8_t* StringDescs[]; 44 | 45 | #endif /* __USB_DESC_H */ 46 | -------------------------------------------------------------------------------- /usb_endp.c: -------------------------------------------------------------------------------- 1 | #include "usb_endp.h" 2 | #include "usb_cdc.h" 3 | 4 | #include "ch554_platform.h" 5 | 6 | #define MAX_PACKET_SIZE 64 7 | 8 | // The buffer (Tx and Rx) must have an even address, size: 64 (0x42) 9 | xdatabuf(EP1_ADDR, Ep1Buffer, 64); 10 | // The buffer (Tx and Rx) must have an even address, size: 128 (0x84) 11 | xdatabuf(EP2_ADDR, Ep2Buffer, EP2_SIZE + EP2_SIZE); // Rx + Tx 12 | 13 | uint8_t USB_EP_HALT_SET(uint8_t ep) { 14 | switch (ep) { 15 | case 0x82: 16 | UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL; 17 | return 0; 18 | case 0x02: 19 | UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL; 20 | return 0; 21 | case 0x83: 22 | UEP3_CTRL = UEP3_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL; 23 | return 0; 24 | case 0x03: 25 | UEP3_CTRL = UEP3_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL; 26 | return 0; 27 | case 0x81: 28 | UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL; 29 | return 0; 30 | default: 31 | return 0xFF; 32 | } 33 | } 34 | 35 | uint8_t USB_EP_HALT_CLEAR(uint8_t ep) { 36 | switch (ep) 37 | { 38 | case 0x82: 39 | UEP2_CTRL = UEP2_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES) | UEP_T_RES_NAK; 40 | return 0; 41 | case 0x02: 42 | UEP2_CTRL = UEP2_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES) | UEP_R_RES_ACK; 43 | return 0; 44 | case 0x83: 45 | UEP3_CTRL = UEP3_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES) | UEP_T_RES_NAK; 46 | return 0; 47 | case 0x03: 48 | UEP3_CTRL = UEP3_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES) | UEP_R_RES_ACK; 49 | return 0; 50 | case 0x81: 51 | UEP1_CTRL = UEP1_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES) | UEP_T_RES_NAK; 52 | return 0; 53 | default: 54 | return 0xFF; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /usb_endp.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_ENDP_H 2 | #define __USB_ENDP_H 3 | 4 | #include "ch554_platform.h" 5 | uint8_t USB_EP_HALT_SET(uint8_t ep); 6 | uint8_t USB_EP_HALT_CLEAR(uint8_t ep); 7 | 8 | // EP0 9 | #define EP0_ADDR 0x0000 10 | extern_xdatabuf(EP0_ADDR, Ep0Buffer); 11 | void USB_EP0_SETUP(void); 12 | void USB_EP0_IN(void); 13 | void USB_EP0_OUT(void); 14 | 15 | // EP1 16 | #define EP1_ADDR 0x000A 17 | extern_xdatabuf(EP1_ADDR, Ep1Buffer); 18 | void USB_EP1_IN(void); 19 | 20 | // EP2 21 | #define EP2_ADDR 0x004A 22 | extern_xdatabuf(EP2_ADDR, Ep2Buffer); 23 | #define EP2_SIZE 64 24 | #define EP2_RX_BUF (Ep2Buffer) 25 | #define EP2_TX_BUF (Ep2Buffer + EP2_SIZE) 26 | void USB_EP2_IN(void); 27 | void USB_EP2_OUT(void); 28 | 29 | void NOP_Process(void); 30 | 31 | // Out 32 | #define EP0_OUT_Callback USB_EP0_OUT 33 | #define EP1_OUT_Callback NOP_Process 34 | #define EP2_OUT_Callback USB_EP2_OUT 35 | #define EP3_OUT_Callback NOP_Process 36 | #define EP4_OUT_Callback NOP_Process 37 | 38 | // SOF 39 | #define EP0_SOF_Callback NOP_Process 40 | #define EP1_SOF_Callback NOP_Process 41 | #define EP2_SOF_Callback NOP_Process 42 | #define EP3_SOF_Callback NOP_Process 43 | #define EP4_SOF_Callback NOP_Process 44 | 45 | // IN 46 | #define EP0_IN_Callback USB_EP0_IN 47 | #define EP1_IN_Callback USB_EP1_IN 48 | #define EP2_IN_Callback USB_EP2_IN 49 | #define EP3_IN_Callback NOP_Process 50 | #define EP4_IN_Callback NOP_Process 51 | 52 | // SETUP 53 | #define EP0_SETUP_Callback USB_EP0_SETUP 54 | #define EP1_SETUP_Callback NOP_Process 55 | #define EP2_SETUP_Callback NOP_Process 56 | #define EP3_SETUP_Callback NOP_Process 57 | #define EP4_SETUP_Callback NOP_Process 58 | 59 | #endif /*__USB_ENDP_H*/ 60 | -------------------------------------------------------------------------------- /usb_ep0.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/usb_ep0.c -------------------------------------------------------------------------------- /usb_it.c: -------------------------------------------------------------------------------- 1 | #include "ch554_platform.h" 2 | #include "usb_desc.h" 3 | #include "usb_endp.h" 4 | 5 | void NOP_Process(void) {} 6 | 7 | // See CH554 datasheet page 42 8 | code const void (*pEndPoint_OUT_CallBack[])(void) = 9 | { 10 | EP0_OUT_Callback, 11 | EP1_OUT_Callback, 12 | EP2_OUT_Callback, 13 | EP3_OUT_Callback, 14 | EP4_OUT_Callback, 15 | }; 16 | 17 | code const void (*pEndPoint_SOF_CallBack[])(void) = 18 | { 19 | EP0_SOF_Callback, 20 | EP1_SOF_Callback, 21 | EP2_SOF_Callback, 22 | EP3_SOF_Callback, 23 | EP4_SOF_Callback, 24 | }; 25 | 26 | code const void (*pEndPoint_IN_CallBack[])(void) = 27 | { 28 | EP0_IN_Callback, 29 | EP1_IN_Callback, 30 | EP2_IN_Callback, 31 | EP3_IN_Callback, 32 | EP4_IN_Callback, 33 | }; 34 | 35 | code const void (*pEndPoint_SETUP_CallBack[])(void) = 36 | { 37 | EP0_SETUP_Callback, 38 | EP1_SETUP_Callback, 39 | EP2_SETUP_Callback, 40 | EP3_SETUP_Callback, 41 | EP4_SETUP_Callback, 42 | }; 43 | 44 | void USBInterrupt(void) { 45 | if(UIF_TRANSFER) { 46 | // Dispatch to service functions 47 | switch (USB_INT_ST & MASK_UIS_TOKEN) { 48 | case UIS_TOKEN_OUT: 49 | (*pEndPoint_OUT_CallBack[USB_INT_ST & MASK_UIS_ENDP])(); 50 | break; 51 | case UIS_TOKEN_SOF: 52 | (*pEndPoint_SOF_CallBack[USB_INT_ST & MASK_UIS_ENDP])(); 53 | break; 54 | case UIS_TOKEN_IN: 55 | (*pEndPoint_IN_CallBack[USB_INT_ST & MASK_UIS_ENDP])(); 56 | break; 57 | case UIS_TOKEN_SETUP: 58 | (*pEndPoint_SETUP_CallBack[USB_INT_ST & MASK_UIS_ENDP])(); 59 | break; 60 | } 61 | 62 | UIF_TRANSFER = 0; // Clear interrupt flag 63 | } 64 | 65 | // Device mode USB bus reset 66 | if(UIF_BUS_RST) { 67 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; 68 | UEP1_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK; 69 | UEP2_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK; 70 | UEP3_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK; 71 | USB_DEV_AD = 0x00; 72 | UIF_SUSPEND = 0; 73 | UIF_TRANSFER = 0; 74 | UIF_BUS_RST = 0; // Clear interrupt flag 75 | } 76 | 77 | // USB bus suspend / wake up 78 | if (UIF_SUSPEND) { 79 | UIF_SUSPEND = 0; 80 | if ( USB_MIS_ST & bUMS_SUSPEND ) { // Suspend 81 | 82 | // while ( XBUS_AUX & bUART0_TX ); // Wait for Tx 83 | // SAFE_MOD = 0x55; 84 | // SAFE_MOD = 0xAA; 85 | // WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO; // Wake up by USB or RxD0 86 | // PCON |= PD; // Chip sleep 87 | // SAFE_MOD = 0x55; 88 | // SAFE_MOD = 0xAA; 89 | // WAKE_CTRL = 0x00; 90 | 91 | } else { // Unexpected interrupt, not supposed to happen ! 92 | USB_INT_FG = 0xFF; // Clear interrupt flag 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /usb_string_desc.c: -------------------------------------------------------------------------------- 1 | #include "ch554_platform.h" 2 | #include "usb_desc.h" 3 | 4 | // Language Descriptor 5 | code const uint8_t LangDesc[] = { 6 | 4, 0x03, // Length = 4 bytes, String Descriptor (0x03) 7 | 0x09, 0x04 // 0x0409 English - United States 8 | }; 9 | 10 | // String Descriptors: 11 | 12 | code const uint8_t DevName1[] = { 13 | 20, 0x03, // Length = 20 bytes, String Descriptor (0x03) 14 | 'C', 0, 'H', 0, '5', 0, '5', 0, '4', 0, ' ', 0, 'C', 0, 'D', 0, 'C', 0 15 | }; 16 | 17 | code const uint8_t ProductName[] = { 18 | 38, 0x03, // Length = 38 bytes, String Descriptor (0x03) 19 | 'R', 0, 'i', 0, 'k', 0, 'k', 0, 'a', 0, '`', 0, 's', 0, ' ', 0, 'C', 0, 'H', 0, '5', 0, '5', 0, '4', 0, ' ', 0, 'D', 0, 'e', 0, 'm', 0, 'o', 0 20 | }; 21 | 22 | code const uint8_t ManuName[] = { 23 | 18, 0x03, // Length = 18 bytes, String Descriptor (0x03) 24 | 'R', 0, 'i', 0, 'k', 0, 'k', 0, 'a', 0, '0', 0, 'w', 0, '0', 0 25 | }; 26 | 27 | code const uint8_t* StringDescs[USB_STRINGDESC_COUNT] = { 28 | LangDesc, // 0 (If you want to support string descriptors, you must have this!) 29 | ProductName, // 1 30 | ManuName, // 2 31 | DevName1 // 3 32 | }; 33 | --------------------------------------------------------------------------------