### Touch Detection Example (C) Source: https://context7.com/openwch/ch32x035/llms.txt Demonstrates a complete example of using the TouchKey peripheral for touch detection. It initializes the system, TouchKey, and performs calibration. Then, it enters an infinite loop continuously reading touch values and comparing them against the calibrated baseline to detect touches and releases, printing status messages via UART. ```c void TouchKey_Example(void) { u16 touch_value; u8 touch_detected = 0; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); TouchKey_Init(); TouchKey_Calibrate(); while(1) { touch_value = TouchKey_Read(ADC_Channel_2); // Detect touch (value decreases when touched) if(touch_baseline - touch_value > TOUCH_THRESHOLD) { if(!touch_detected) { touch_detected = 1; printf("Touch detected! Value: %d\r\n", touch_value); } } else { if(touch_detected) { touch_detected = 0; printf("Touch released\r\n"); } } Delay_Ms(50); } } ``` -------------------------------- ### Example: Generate 1KHz PWM with Dynamic Duty Cycle (C) Source: https://context7.com/openwch/ch32x035/llms.txt Demonstrates generating a 1KHz PWM signal with a 50% duty cycle and dynamically adjusting it in a loop. This example requires the system core clock to be updated and a delay function to be initialized. The PWM frequency and duty cycle are calculated based on the system clock. ```c // Generate 1KHz PWM with 50% duty cycle at 48MHz system clock void PWM_Example(void) { SystemCoreClockUpdate(); Delay_Init(); // Period = 1000, Prescaler = 48-1 = 47 // PWM frequency = 48MHz / (48 * 1000) = 1KHz // Pulse = 500 for 50% duty cycle TIM1_PWM_Init(1000, 48-1, 500); while(1) { // Dynamically adjust duty cycle for(u16 duty = 0; duty <= 1000; duty += 10) { TIM_SetCompare1(TIM1, duty); Delay_Ms(50); } } } ``` -------------------------------- ### Read Encoder Position and Speed Example (C) Source: https://context7.com/openwch/ch32x035/llms.txt An example function demonstrating how to read encoder data to calculate absolute position and speed. It initializes the system, configures the encoder interface, and then enters a loop to periodically read the current position and calculate the speed based on the change in position. Dependencies include system clock updates, delay functions, and UART printing. ```c void Encoder_Read_Example(void) { int32_t position, speed; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); TIM2_Encoder_Init(); while(1) { Delay_Ms(100); // Calculate absolute position position = circle * ENCODER_PPR + TIM2->CNT; // Calculate speed (pulses per 100ms) speed = position - (precircle * ENCODER_PPR + precnt); precircle = circle; precnt = TIM2->CNT; printf("Position: %d pulses, Speed: %d pulses/100ms\r\n", position, speed); } } ``` -------------------------------- ### Example: PIOC Accelerated I2C EEPROM Access in C Source: https://context7.com/openwch/ch32x035/llms.txt Demonstrates how to use the PIOC to perform I2C read and write operations on an EEPROM. It initializes the system, PIOC, and UART for output, then performs a write to the EEPROM followed by a read operation, printing the results to the console. ```c // Example usage: PIOC-accelerated I2C EEPROM access void PIOC_EEPROM_Example(void) { uint8_t write_data[] = "PIOC I2C"; uint8_t read_data[20] = {0}; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); PIOC_IIC_Init(); printf("PIOC I2C Example\r\n"); // Write to EEPROM at address 0x00 PIOC_IIC_Write(0xA0, write_data, sizeof(write_data)); Delay_Ms(10); // Read back PIOC_IIC_Read(0xA0, read_data, sizeof(write_data)); printf("Read: %s\r\n", read_data); } ``` -------------------------------- ### CH32x035 External Interrupt Routine (EXTI0) Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt An example routine demonstrating the configuration and handling of external interrupts on pin EXTI0 for the CH32x035 MCU. This allows event-driven responses. ```c // EXTI0 external interrupt routine content placeholder ``` -------------------------------- ### Configure ADC with DMA for Continuous Sampling - CH32X035 C Source: https://context7.com/openwch/ch32x035/llms.txt Sets up an ADC (ADC1) on a specified channel (PA1) to perform continuous sampling using DMA. The sampled data is stored in a buffer (`ADC_Buffer`) for later processing. This example requires `debug.h` for delay functions and includes configurations for ADC, GPIO, and DMA peripherals. ```c #include "debug.h" #define SAMPLE_SIZE 1024 u16 ADC_Buffer[SAMPLE_SIZE]; void DMA_ADC_Init(void) { ADC_InitTypeDef ADC_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0}; DMA_InitTypeDef DMA_InitStructure = {0}; // Enable peripheral clocks RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Configure PA1 as analog input GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // Configure ADC ADC_DeInit(ADC1); ADC_CLKConfig(ADC1, ADC_CLK_Div6); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); // Configure DMA for ADC DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->RDATAR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_Buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = SAMPLE_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); // Enable and start conversion ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_11Cycles); ADC_SoftwareStartConvCmd(ADC1, ENABLE); // Wait for completion Delay_Ms(50); ADC_SoftwareStartConvCmd(ADC1, DISABLE); // Process samples for(u16 i = 0; i < SAMPLE_SIZE; i++) { printf("%04d\r\n", ADC_Buffer[i]); } } ``` -------------------------------- ### SPI DMA Transfer Setup (C) Source: https://context7.com/openwch/ch32x035/llms.txt Configures and enables DMA channels for SPI transmit (TX) and receive (RX) operations in full-duplex mode. This allows for high-speed data transfer without CPU intervention. Requires DMA and SPI HAL libraries. ```c void SPI_DMA_Transfer(void) { DMA_InitTypeDef DMA_InitStructure = {0}; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA for TX DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DATAR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)TxData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel3, &DMA_InitStructure); // DMA for RX DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DATAR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)RxData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_Init(DMA1_Channel2, &DMA_InitStructure); // Enable DMA SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE); DMA_Cmd(DMA1_Channel3, ENABLE); DMA_Cmd(DMA1_Channel2, ENABLE); // Wait for completion while(!DMA_GetFlagStatus(DMA1_FLAG_TC3)); while(!DMA_GetFlagStatus(DMA1_FLAG_TC2)); } ``` -------------------------------- ### Configure OPA2 as Voltage Follower Source: https://context7.com/openwch/ch32x035/llms.txt Initializes and configures the OPA2 operational amplifier to operate in a voltage follower configuration. This setup requires specific GPIO pin configurations for the positive input and feedback, and sets the output to a designated IO pin. The OPA is then enabled for operation. ```c #include "debug.h" void OPA2_Voltage_Follower_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; OPA_InitTypeDef OPA_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Configure OPA2 pins: CHP0 (PA7 - positive input), CHN1 (PA5 - feedback) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // Configure OPA2 as voltage follower OPA_InitStructure.OPA_NUM = OPA2; OPA_InitStructure.PSEL = CHP0; // Positive input from PA7 OPA_InitStructure.NSEL = CHN0; // Negative feedback OPA_InitStructure.Mode = OUT_IO_OUT0; // Output to PA4 OPA_Init(&OPA_InitStructure); OPA_Cmd(OPA2, ENABLE); } ``` -------------------------------- ### Calibrate TouchKey Baseline (C) Source: https://context7.com/openwch/ch32x035/llms.txt Calibrates the baseline touch value for the TouchKey sensor. It reads the ADC channel multiple times (16 samples) with a small delay between each reading to get an average value. This baseline is used later to detect touch events by comparing current readings against it. ```c void TouchKey_Calibrate(void) { u32 sum = 0; // Average 16 samples for baseline for(u8 i = 0; i < 16; i++) { sum += TouchKey_Read(ADC_Channel_2); Delay_Ms(10); } touch_baseline = sum / 16; printf("TouchKey baseline: %d\r\n", touch_baseline); } ``` -------------------------------- ### CH32x035 Startup and Core System Files Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Provides the startup file and core system header files for the CH32x035 MCU. These are essential for initializing the microcontroller and its core system functionalities. ```assembly startup_ch32x035.S ``` ```c // Core system header file content placeholder ``` -------------------------------- ### USB PD Sink Initialization and Main Loop (C) Source: https://context7.com/openwch/ch32x035/llms.txt This C code snippet demonstrates the initialization of a 1ms timer for system timing and the main loop for USB Power Delivery (PD) Sink operations on the CH32X035. It includes PD peripheral initialization, timer configuration, and the core logic for PD detection and main protocol processing. The code relies on the 'debug.h' and 'PD_Process.h' headers for peripheral and PD-specific functions. ```c #include "debug.h" #include "PD_Process.h" void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); volatile UINT8 Tim_Ms_Cnt = 0x00; void TIM1_Init_1ms(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); // Configure for 1ms tick at 48MHz TIM_TimeBaseStructure.TIM_Period = 999; TIM_TimeBaseStructure.TIM_Prescaler = 48 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); TIM_Cmd(TIM1, ENABLE); } void TIM1_UP_IRQHandler(void) { if(TIM_GetITStatus(TIM1, TIM_IT_Update)) { Tim_Ms_Cnt++; TIM_ClearITPendingBit(TIM1, TIM_IT_Update); } } int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(921600); printf("SystemClk:%d\r\n", SystemCoreClock); printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID()); printf("PD SNK TEST\r\n"); // Initialize PD peripheral PD_Init(); TIM1_Init_1ms(); // Main PD processing loop while(1) { // Calculate timing delta TIM_ITConfig(TIM1, TIM_IT_Update, DISABLE); Tmr_Ms_Dlt = Tim_Ms_Cnt - Tmr_Ms_Cnt_Last; Tmr_Ms_Cnt_Last = Tim_Ms_Cnt; TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); // PD detection every 4ms PD_Ctl.Det_Timer += Tmr_Ms_Dlt; if(PD_Ctl.Det_Timer > 4) { PD_Ctl.Det_Timer = 0; PD_Det_Proc(); // Handle PD detection state machine } // Main PD protocol processing PD_Main_Proc(); } } // To request different voltage, modify PDO_Request() in PD_Process.c: // PDO_Request(PDO_INDEX_1); // 5V // PDO_Request(PDO_INDEX_2); // 9V // PDO_Request(PDO_INDEX_3); // 12V // PDO_Request(PDO_INDEX_4); // 15V // PDO_Request(PDO_INDEX_5); // 20V ``` -------------------------------- ### Initialize TIM2 for Encoder Interface (C) Source: https://context7.com/openwch/ch32x035/llms.txt Initializes the TIM2 peripheral to function as a quadrature encoder interface. This involves configuring GPIO pins for encoder signals, setting up the timer for encoder mode, and enabling update interrupts for multi-turn tracking. Dependencies include the microcontroller's peripheral clock and GPIO configuration libraries. ```c #include "debug.h" #define ENCODER_PPR 80 // Pulses per revolution volatile int circle = 0, precircle = 0; volatile uint16_t precnt = 0; volatile uint32_t time = 0; void TIM2_Encoder_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0}; TIM_ICInitTypeDef TIM_ICInitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // Configure encoder inputs: PA0 (TI1), PA1 (TI2) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // Timer configuration TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_Period = ENCODER_PPR; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // Encoder interface mode: both edges on TI1 and TI2 TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); // Input capture filter TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.ICFilter = 10; TIM_ICInit(TIM2, &TIM_ICInitStructure); // Overflow interrupt for multi-turn tracking NVIC_InitStructure.NVIC_IRQChannel = TIM2_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_Cmd(TIM2, ENABLE); } ``` -------------------------------- ### CH32X035 DMA Memory-to-Memory Transfer Initialization (C) Source: https://context7.com/openwch/ch32x035/llms.txt Initializes the DMA controller for a memory-to-memory transfer on the CH32X035. It configures source and destination buffers, DMA channel parameters, and waits for the transfer to complete, followed by data verification. Requires debug.h and CH32X035 peripheral libraries. ```c #include "debug.h" #define BUFFER_SIZE 1024 u32 src_buffer[BUFFER_SIZE]; u32 dst_buffer[BUFFER_SIZE]; void DMA_Memory_to_Memory_Init(void) { DMA_InitTypeDef DMA_InitStructure = {0}; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Initialize source data for(u16 i = 0; i < BUFFER_SIZE; i++) { src_buffer[i] = i; dst_buffer[i] = 0; } // Configure DMA for memory-to-memory transfer DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)src_buffer; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)dst_buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); // Wait for transfer complete while(!DMA_GetFlagStatus(DMA1_FLAG_TC1)); printf("DMA Transfer Complete\r\n"); // Verify data u8 error = 0; for(u16 i = 0; i < BUFFER_SIZE; i++) { if(src_buffer[i] != dst_buffer[i]) { error = 1; printf("Error at index %d: src=%d, dst=%d\r\n", i, src_buffer[i], dst_buffer[i]); break; } } if(!error) printf("Data verification successful!\r\n"); } ``` -------------------------------- ### SPI Master Initialization (C) Source: https://context7.com/openwch/ch32x035/llms.txt Initializes the SPI peripheral in master mode for full-duplex communication. Configures GPIO pins for SCK, MISO, and MOSI, and sets SPI parameters such as data size, clock polarity/phase, and baud rate. Requires HAL library for STM32/CH32 MCUs. ```c #include "debug.h" #include "string.h" #define SPI_MODE HOST_MODE // or SLAVE_MODE #define BUFFER_SIZE 18 u16 TxData[BUFFER_SIZE] = {0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x2121, 0x2222, 0x2323, 0x2424, 0x2525, 0x2626}; u16 RxData[BUFFER_SIZE]; void SPI_Master_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; SPI_InitTypeDef SPI_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); // Master: SCK (PA5) - output, MISO (PA6) - input, MOSI (PA7) - output GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // SPI configuration SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); } ``` -------------------------------- ### CH32x035 HarmonyOS LiteOS Migration Routine Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Contains routines for migrating and running the HarmonyOS LiteOS real-time operating system on the CH32x035 MCU. Enables advanced embedded OS features. ```c // LiteOS_m HarmonyOS migration routine content placeholder ``` -------------------------------- ### CH32x035 Boot Flash as User Flash Routine Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt A routine demonstrating how to utilize the Boot Flash memory as User Flash on the CH32x035 MCU. This might be used for specific bootloader or application configurations. ```c // Boot Flash used for user flash routine content placeholder ``` -------------------------------- ### Initialize and Communicate with I2C EEPROM in C Source: https://context7.com/openwch/ch32x035/llms.txt Configures and uses the I2C1 peripheral to communicate with an external I2C EEPROM. It includes functions for initializing the I2C bus, writing a byte to the EEPROM, and reading a byte from it. Requires the 'debug.h' header and standard microcontroller peripheral libraries. ```c #include "debug.h" #define EEPROM_ADDRESS 0xA0 const u8 WriteData[] = "CH32X035 I2C TEST"; void I2C_EEPROM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; I2C_InitTypeDef I2C_InitStructure = {0}; // Enable clocks RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // Configure I2C1 pins: SCL (PA10), SDA (PA11) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // Configure I2C I2C_InitStructure.I2C_ClockSpeed = 100000; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); } void I2C_WriteByte(u8 addr, u8 data) { // Start condition while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // Send device address (write) I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // Send memory address I2C_SendData(I2C1, addr); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // Send data I2C_SendData(I2C1, data); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // Stop condition I2C_GenerateSTOP(I2C1, ENABLE); Delay_Ms(5); // EEPROM write cycle time } u8 I2C_ReadByte(u8 addr) { u8 data; // Start + Device Address + Memory Address I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, addr); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // Restart + Device Address (read) I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // Disable ACK for last byte I2C_AcknowledgeConfig(I2C1,DISABLE); I2C_GenerateSTOP(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); data = I2C_ReceiveData(I2C1); I2C_AcknowledgeConfig(I2C1, ENABLE); return data; } ``` -------------------------------- ### CH32x035 FreeRTOS Migration Routines Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Provides routines for migrating and running the FreeRTOS real-time operating system on the CH32x035 MCU. This enables multitasking capabilities. ```c // FreeRTOS core migration routines content placeholder ``` -------------------------------- ### Configure OPA1 as Programmable Gain Amplifier (PGA) Source: https://context7.com/openwch/ch32x035/llms.txt Initializes and configures the OPA1 operational amplifier for Programmable Gain Amplifier (PGA) applications. This involves setting up the OPA with specified positive and negative input selections and an output mode. The gain is typically configured externally using resistors, and the OPA is then enabled. ```c // For PGA (Programmable Gain Amplifier) configuration: void OPA1_PGA_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; OPA_InitTypeDef OPA_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); OPA_InitStructure.OPA_NUM = OPA1; OPA_InitStructure.PSEL = CHP1; OPA_InitStructure.NSEL = CHN1; OPA_InitStructure.Mode = OUT_IO_OUT1; OPA_Init(&OPA_InitStructure); // Configure gain using external resistors OPA_Cmd(OPA1, ENABLE); } ``` -------------------------------- ### Read OPA Output with ADC Source: https://context7.com/openwch/ch32x035/llms.txt Demonstrates how to read the output of an operational amplifier (configured as a voltage follower) using the Analog-to-Digital Converter (ADC). This involves initializing the OPA, configuring the ADC peripheral and GPIO pin for analog input, and continuously reading the converted value to display the amplified signal voltage. ```c #include "debug.h" void OPA_ADC_Example(void) { ADC_InitTypeDef ADC_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0}; u16 adc_value; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); // Initialize OPA2 as voltage follower (PA7 input -> PA4 output) OPA2_Voltage_Follower_Init(); // Configure ADC to read OPA output on PA4 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_DeInit(ADC1); ADC_CLKConfig(ADC1, ADC_CLK_Div6); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); // Read amplified signal while(1) { ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_11Cycles); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); adc_value = ADC_GetConversionValue(ADC1); printf("OPA Output: %d (%.2fV)\r\n", adc_value, adc_value * 3.3 / 4096); Delay_Ms(500); } } ``` -------------------------------- ### CH32x035 Peripheral Driver Routines Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Basic driver source and header files for controlling the peripherals of the CH32x035 MCU. These files enable interaction with hardware components. ```c // Basic peripheral driver source/header file content placeholder ``` -------------------------------- ### Configure TIM1 for PWM Output (C) Source: https://context7.com/openwch/ch32x035/llms.txt Initializes Timer 1 for Pulse Width Modulation (PWM) output. It configures the timer period, prescaler, and initial pulse width. This function requires the system clock to be configured and GPIO pins to be set as alternate function push-pull outputs. ```c #include "debug.h" void TIM1_PWM_Init(u16 period, u16 prescaler, u16 pulse) { GPIO_InitTypeDef GPIO_InitStructure = {0}; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0}; TIM_OCInitTypeDef TIM_OCInitStructure = {0}; // Enable clocks RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE); // Configure PA8 as TIM1_CH1 output GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // Timer base configuration TIM_TimeBaseStructure.TIM_Period = period; TIM_TimeBaseStructure.TIM_Prescaler = prescaler; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // PWM mode configuration TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = pulse; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM1, ENABLE); TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_Cmd(TIM1, ENABLE); } ``` -------------------------------- ### Initialize TouchKey Peripheral (C) Source: https://context7.com/openwch/ch32x035/llms.txt Initializes the TouchKey capacitive sensing peripheral on the CH32X035. This function configures a GPIO pin as an analog input for the ADC and sets up the ADC itself for touch sensing, including charge/discharge timing. It enables the TouchKey module via a specific control register. ```c #include "debug.h" #define TOUCH_THRESHOLD 100 u16 touch_baseline = 0; void TouchKey_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; ADC_InitTypeDef ADC_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); // Configure PA2 as touch input GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // ADC configuration for TouchKey ADC_CLKConfig(ADC1, ADC_CLK_Div6); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); // Enable TouchKey module (bit 24 of CTLR1) TKey1->CTLR1 |= (1 << 24); } ``` -------------------------------- ### Configure and Toggle GPIO Output - CH32X035 C Source: https://context7.com/openwch/ch32x035/llms.txt Demonstrates how to configure a GPIO pin (PA0) as a push-pull output and toggle its state periodically. This function utilizes the STM32-style HAL structure provided by the SDK. It assumes the availability of `debug.h` for delay functions and GPIO/RCC configurations. ```c #include "debug.h" void GPIO_Toggle_Example(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; u8 toggle_state = 0; // Enable GPIOA clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Configure PA0 as push-pull output at 50MHz GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // Toggle PA0 every 500ms while(1) { Delay_Ms(500); GPIO_WriteBit(GPIOA, GPIO_Pin_0, (toggle_state == 0) ? (toggle_state = Bit_SET) : (toggle_state = Bit_RESET)); } } // Available GPIO modes: // GPIO_Mode_AIN - Analog input // GPIO_Mode_IN_FLOATING - Floating input // GPIO_Mode_IPD - Input pull-down (only PA0-PA15, PC16-PC17) // GPIO_Mode_IPU - Input pull-up // GPIO_Mode_Out_PP - Push-pull output // GPIO_Mode_AF_PP - Alternate function push-pull ``` -------------------------------- ### CH32x035 IAP Upgrade Routines (USB/UART) Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt In-Application Programming (IAP) upgrade routines for the CH32x035 MCU, including USB and UART interfaces. Also includes tools for Hex to Bin conversion. ```c // USB+UART IAP routine content placeholder ``` ```script // Hex to Bin tool and IAP upgrade tool usage placeholder ``` -------------------------------- ### Initialize and Use USART1 for Serial Debugging in C Source: https://context7.com/openwch/ch32x035/llms.txt Configures and utilizes USART1 for serial communication, primarily for debugging purposes. It sets up the serial port with a specified baud rate and includes functions to print system information and periodic messages. Requires the 'debug.h' header and standard microcontroller peripheral libraries. ```c #include "debug.h" int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); Delay_Init(); // Initialize USART1 on PB10 at 115200 baud USART_Printf_Init(115200); // Print system information printf("SystemClk:%d\r\n", SystemCoreClock); printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID()); printf("CH32X035 USART Example\r\n"); while(1) { printf("Running...\r\n"); Delay_Ms(1000); } } // For custom USART configuration: void USART_Custom_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; USART_InitTypeDef USART_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 921600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } ``` -------------------------------- ### CH32x035 1-Wire WS2812 and DS1820 Control Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Routines for controlling WS2812 LEDs and DS1820 temperature sensors using the 1-Wire protocol on the CH32x035 MCU. Includes assembly and batch files for compilation. ```assembly PIOC_INC.ASM RGB1W.ASM ``` ```batch RGB1W.BAT ``` ```text RGB1W.BIN RGB1W.LST RGB1W_inc.h ``` -------------------------------- ### CH32x035 WS2812 LED Control via SPI/PWM Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt An application routine demonstrating how to operate WS2812 LEDs using SPI or PWM on the CH32x035 MCU. This is useful for addressable LED control. ```c // WS2812 LED via SPI/PWM routine content placeholder ``` -------------------------------- ### Initialize PIOC for I2C Communication in C Source: https://context7.com/openwch/ch32x035/llms.txt Initializes the PIOC peripheral for I2C communication. It configures GPIO pins for SCL and SDA, loads the I2C bytecode into PIOC memory, and sets up the necessary interrupts. This function prepares the PIOC to act as an I2C master or slave. ```c #include "debug.h" #include "string.h" #define HOST_MODE 0 #define SLAVE_MODE 1 #define I2C_MODE HOST_MODE // PIOC I2C bytecode (hardware accelerated I2C protocol) __attribute__((aligned(16))) const unsigned char PIOC_IIC_CODE[] = { 0x00,0x00,0xE2,0x61,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x30,0x00,0x03,0x70,0x00,0x00,0x03,0x70,0x00,0x00,0x03,0x70,0x00,0x00, // ... (full bytecode array provided in example) }; volatile uint8_t PIOC_IIC_FLAG = 0; volatile uint16_t PIOC_IIC_RemainLEN = 0; uint8_t rx_buffer[100] = {0}; void PIOC_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void PIOC_IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PIOC, ENABLE); // Configure PC18 (SCL), PC19 (SDA) for PIOC I2C GPIO_InitStructure.GPIO_Pin = GPIO_Pin_18 | GPIO_Pin_19; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); // Load PIOC bytecode PIOC_SFR->SYS_CFG_CTRL0 = 0xFF; PIOC_SFR->SYS_CFG_CTRL1 = 0; uint32_t *src = (uint32_t *)PIOC_IIC_CODE; volatile uint32_t *dst = (volatile uint32_t *)PIOC_MEM; for(uint16_t i = 0; i < sizeof(PIOC_IIC_CODE) / 4; i++) { dst[i] = src[i]; } // Configure interrupt NVIC_InitTypeDef NVIC_InitStructure = {0}; NVIC_InitStructure.NVIC_IRQChannel = PIOC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // Start PIOC execution PIOC->D8_SYS_CFG = (1 << 7) | (1 << 4); // Enable and start } ``` -------------------------------- ### CH32x035 PIOC Simulated UART Routines Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Routines for simulating UART communication using the PIOC (Programmable Input/Output Controller) on the CH32x035 MCU. Includes assembly and batch files for compilation. ```assembly PIOC_INC.ASM PIOC_UART.ASM ``` ```batch PIOC_UART.BAT ``` ```text PIOC_UART.BIN PIOC_UART.LST PIOC_UART_inc.h ``` -------------------------------- ### CH32x035 Debugging Routines Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Contains source and header files for delay functions and UART debugging. These are used for timing control and serial communication for debugging purposes. ```c // Delay function and UART debugging source/header file content placeholder ``` -------------------------------- ### CH32x035 Independent Watchdog Routine (IWDG) Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt A routine demonstrating the configuration and usage of the Independent Watchdog Timer (IWDG) on the CH32x035 MCU. Helps in system recovery from hangs. ```c // Independent Watchdog routine content placeholder ``` -------------------------------- ### CH32x035 PIOC I2C Routines Source: https://github.com/openwch/ch32x035/blob/main/EVT/CH32X035_List_EN.txt Placeholder for routines related to I2C communication using the PIOC (Programmable Input/Output Controller) on the CH32x035 MCU. ```c // PIOC_IIC routines content placeholder ```