### Configure DMA Transfers and Interrupts Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Provides functions for memory-to-memory and memory-to-peripheral DMA transfers, along with an interrupt handler example. ```c #include "gd32f4xx_dma.h" /* Initialize DMA for memory-to-memory transfer */ void dma_mem_to_mem_init(uint32_t *src, uint32_t *dst, uint32_t count) { dma_single_data_parameter_struct dma_init_struct; /* Reset DMA channel */ dma_deinit(DMA1, DMA_CH0); /* Configure DMA parameters */ dma_init_struct.periph_addr = (uint32_t)src; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_ENABLE; dma_init_struct.memory0_addr = (uint32_t)dst; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_32BIT; dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE; dma_init_struct.direction = DMA_MEMORY_TO_MEMORY; dma_init_struct.number = count; dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; dma_single_data_mode_init(DMA1, DMA_CH0, &dma_init_struct); /* Enable DMA transfer complete interrupt */ dma_interrupt_enable(DMA1, DMA_CH0, DMA_CHXCTL_FTFIE); /* Enable DMA channel */ dma_channel_enable(DMA1, DMA_CH0); } /* Configure DMA for USART transmission */ void dma_usart_tx_init(uint32_t usart_periph, uint8_t *buffer, uint32_t length) { dma_single_data_parameter_struct dma_init_struct; /* USART0 TX uses DMA1 Channel 7, subperipheral 4 */ dma_deinit(DMA1, DMA_CH7); dma_init_struct.periph_addr = (uint32_t)(&USART_DATA(usart_periph)); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.memory0_addr = (uint32_t)buffer; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT; dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE; dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; dma_init_struct.number = length; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_single_data_mode_init(DMA1, DMA_CH7, &dma_init_struct); dma_channel_subperipheral_select(DMA1, DMA_CH7, DMA_SUBPERI4); /* Enable USART DMA transmit */ usart_dma_transmit_config(usart_periph, USART_DENT_ENABLE); dma_channel_enable(DMA1, DMA_CH7); } /* DMA interrupt handler */ void DMA1_Channel0_IRQHandler(void) { if(dma_interrupt_flag_get(DMA1, DMA_CH0, DMA_INT_FLAG_FTF)) { /* Transfer complete */ dma_interrupt_flag_clear(DMA1, DMA_CH0, DMA_INT_FLAG_FTF); /* Handle completion */ } } ``` -------------------------------- ### Read ADC Value from Configured Channel Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Reads the converted ADC value from the specified peripheral. This function starts a software-triggered conversion and waits for its completion. Ensure the ADC is initialized before calling this function. ```c /* Read ADC value from configured channel */ uint16_t adc_read_value(uint32_t adc_periph) { /* Start conversion */ adc_software_trigger_enable(adc_periph, ADC_REGULAR_CHANNEL); /* Wait for conversion complete */ while(!adc_flag_get(adc_periph, ADC_FLAG_EOC)); /* Clear flag and return result */ adc_flag_clear(adc_periph, ADC_FLAG_EOC); return adc_regular_data_read(adc_periph); } ``` -------------------------------- ### Initialize and Use SPI Communication Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Demonstrates SPI master mode initialization using a parameter structure and functions for byte-wise and buffer-based data transfers. The SPI peripheral must be enabled after configuration. ```c #include "gd32f4xx_spi.h" /* Initialize SPI0 as master, 8-bit, mode 0 */ void spi0_master_init(void) { spi_parameter_struct spi_init_struct; /* Reset SPI peripheral */ spi_i2s_deinit(SPI0); /* Initialize SPI parameter structure with defaults */ spi_struct_para_init(&spi_init_struct); /* Configure SPI parameters */ spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; spi_init_struct.device_mode = SPI_MASTER; spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; /* Mode 0 */ spi_init_struct.nss = SPI_NSS_SOFT; spi_init_struct.prescale = SPI_PSC_8; /* Clock / 8 */ spi_init_struct.endian = SPI_ENDIAN_MSB; spi_init(SPI0, &spi_init_struct); /* Enable SPI */ spi_enable(SPI0); } /* SPI transmit and receive a byte */ uint8_t spi_transfer_byte(uint32_t spi_periph, uint8_t data) { /* Wait until transmit buffer empty */ while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); spi_i2s_data_transmit(spi_periph, data); /* Wait until receive buffer not empty */ while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)); return (uint8_t)spi_i2s_data_receive(spi_periph); } /* SPI transmit buffer */ void spi_transmit_buffer(uint32_t spi_periph, uint8_t *buffer, uint32_t length) { for(uint32_t i = 0; i < length; i++) { while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)); spi_i2s_data_transmit(spi_periph, buffer[i]); } /* Wait for transmission complete */ while(SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TRANS)); } ``` -------------------------------- ### Initialize and Manage USB CDC Device Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Demonstrates USB device stack initialization, endpoint data transfer, and connection management. ```c #include "usbd_core.h" #include "cdc_acm_core.h" usb_core_driver usb_cdc_dev; /* Initialize USB CDC device */ void usb_cdc_init(void) { /* Initialize USB device stack with CDC class */ usbd_init(&usb_cdc_dev, USB_CORE_ENUM_FS, /* Full-speed core */ &cdc_desc, /* Device descriptors */ &cdc_class); /* CDC class driver */ /* Connect USB device */ usbd_connect(&usb_cdc_dev); } /* USB endpoint operations */ void usb_data_transfer(void) { uint8_t tx_buffer[64] = "Hello USB!\r\n"; uint8_t rx_buffer[64]; /* Send data on endpoint */ usbd_ep_send(&usb_cdc_dev, CDC_DATA_IN_EP, tx_buffer, 12); /* Prepare to receive data on endpoint */ usbd_ep_recev(&usb_cdc_dev, CDC_DATA_OUT_EP, rx_buffer, 64); /* Get received data length */ uint16_t rx_count = usbd_rxcount_get(&usb_cdc_dev, CDC_DATA_OUT_EP & 0x7F); /* Stall/unstall endpoint for error handling */ usbd_ep_stall(&usb_cdc_dev, CDC_DATA_IN_EP); usbd_ep_stall_clear(&usb_cdc_dev, CDC_DATA_IN_EP); /* Flush endpoint FIFO */ usbd_fifo_flush(&usb_cdc_dev, CDC_DATA_IN_EP); } /* Disconnect USB device */ void usb_device_disconnect(void) { usbd_disconnect(&usb_cdc_dev); } ``` -------------------------------- ### Initialize TIMER0 for PWM Output Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Configures TIMER0 to generate PWM signals on channel 0. Ensure the timer clock is set appropriately for the desired frequency and duty cycle. ```c #include "gd32f4xx_timer.h" /* Initialize TIMER0 for PWM output on channel 0 */ void timer0_pwm_init(uint32_t frequency, uint32_t duty_cycle) { timer_parameter_struct timer_initpara; timer_oc_parameter_struct timer_ocinitpara; /* Reset timer */ timer_deinit(TIMER0); /* TIMER0 configuration for PWM */ timer_struct_para_init(&timer_initpara); timer_initpara.prescaler = 167; /* 168MHz / 168 = 1MHz */ timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = (1000000 / frequency) - 1; /* Auto-reload value */ timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.repetitioncounter = 0; timer_init(TIMER0, &timer_initpara); /* Channel 0 PWM configuration */ timer_channel_output_struct_para_init(&timer_ocinitpara); timer_ocinitpara.outputstate = TIMER_CCX_ENABLE; timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE; timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocinitpara); /* Set PWM mode and duty cycle */ timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0); timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, (timer_initpara.period * duty_cycle) / 100); timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_ENABLE); /* Enable auto-reload preload */ timer_auto_reload_shadow_enable(TIMER0); /* Enable primary output (required for advanced timers) */ timer_primary_output_config(TIMER0, ENABLE); /* Enable timer */ timer_enable(TIMER0); } ``` -------------------------------- ### Configure and Handle External Interrupts Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Initializes PA0 as an interrupt source and provides an interrupt handler to toggle an LED on PA5 upon a falling edge trigger. ```c #include "gd32f4xx_exti.h" #include "gd32f4xx_syscfg.h" /* Configure PA0 as external interrupt source (button) */ void exti_button_init(void) { /* Enable SYSCFG clock */ rcu_periph_clock_enable(RCU_SYSCFG); /* Configure PA0 as input with pull-up */ gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0); /* Connect EXTI line 0 to PA0 */ syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN0); /* Configure EXTI line 0 */ exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING); exti_interrupt_flag_clear(EXTI_0); /* Enable EXTI0 interrupt in NVIC */ nvic_irq_enable(EXTI0_IRQn, 2, 0); } /* EXTI0 interrupt handler */ void EXTI0_IRQHandler(void) { if(exti_interrupt_flag_get(EXTI_0) != RESET) { exti_interrupt_flag_clear(EXTI_0); /* Handle button press */ gpio_bit_toggle(GPIOA, GPIO_PIN_5); /* Toggle LED */ } } ``` -------------------------------- ### Configure GPIO Pins for Various Modes Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Configures GPIO pins for output, input with pull-up, alternate function (e.g., USART), and analog input. Includes setting output options like push-pull and speed, and performing GPIO output/input operations. Use pin locking to prevent accidental changes. ```c #include "gd32f4xx_gpio.h" /* Configure GPIO pins for various purposes */ void gpio_configuration(void) { /* Reset GPIO port to default state */ gpio_deinit(GPIOA); /* Configure PA5 as output (LED) - push-pull, no pull resistor, 50MHz */ gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_5); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5); /* Configure PA0 as input with pull-up (button) */ gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0); /* Configure PA9/PA10 as USART0 TX/RX (alternate function) */ gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9 | GPIO_PIN_10); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9 | GPIO_PIN_10); gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9 | GPIO_PIN_10); /* Configure PA4 as analog input (ADC) */ gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4); /* GPIO output operations */ gpio_bit_set(GPIOA, GPIO_PIN_5); /* Set pin high */ gpio_bit_reset(GPIOA, GPIO_PIN_5); /* Set pin low */ gpio_bit_toggle(GPIOA, GPIO_PIN_5); /* Toggle pin state */ gpio_bit_write(GPIOA, GPIO_PIN_5, SET); /* Write specific state */ gpio_port_write(GPIOA, 0x00FF); /* Write to entire port */ /* GPIO input operations */ FlagStatus pin_state = gpio_input_bit_get(GPIOA, GPIO_PIN_0); uint16_t port_state = gpio_input_port_get(GPIOA); /* Lock GPIO configuration to prevent accidental changes */ gpio_pin_lock(GPIOA, GPIO_PIN_5); } ``` -------------------------------- ### Initialize ADC0 for Single Channel Conversion Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Configures ADC0 for a single channel conversion. Ensure ADC clock and resolution are set appropriately for your application. This function enables the ADC and performs calibration. ```c #include "gd32f4xx_adc.h" /* Initialize ADC0 for single channel conversion */ void adc0_single_channel_init(void) { /* Reset ADC */ adc_deinit(); /* Configure ADC clock - APB2 / 4 */ adc_clock_config(ADC_ADCCK_PCLK2_DIV4); /* Configure ADC mode */ adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT); /* Configure ADC resolution */ adc_resolution_config(ADC0, ADC_RESOLUTION_12B); /* Configure ADC data alignment */ adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); /* Configure scan mode - single channel */ adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE); adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE); /* Configure regular channel */ adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1); adc_regular_channel_config(ADC0, 0, ADC_CHANNEL_4, ADC_SAMPLETIME_56); /* Configure external trigger - software trigger */ adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE); /* Enable ADC */ adc_enable(ADC0); /* Wait for ADC stabilization */ for(uint32_t i = 0; i < 0xFFFF; i++); /* Calibrate ADC */ adc_calibration_enable(ADC0); } ``` -------------------------------- ### Configure Timer for Periodic Interrupt Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Initializes a timer peripheral to generate periodic interrupts. The prescaler and period should be set to achieve the desired interrupt frequency. ```c /* Configure timer for periodic interrupt */ void timer_periodic_interrupt_init(uint32_t timer_periph, uint32_t period_ms) { timer_parameter_struct timer_initpara; timer_deinit(timer_periph); timer_struct_para_init(&timer_initpara); timer_initpara.prescaler = 8399; /* 84MHz / 8400 = 10kHz */ timer_initpara.period = (10 * period_ms) - 1; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_init(timer_periph, &timer_initpara); /* Enable update interrupt */ timer_interrupt_enable(timer_periph, TIMER_INT_UP); timer_enable(timer_periph); } ``` -------------------------------- ### Configure ADC for Multi-Channel Scan with DMA Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Sets up ADC0 for multi-channel scanning with DMA transfers. This function configures the DMA controller to transfer ADC conversion results to a buffer. Ensure the buffer is large enough to hold all channel data. ```c /* Configure ADC for multi-channel scan with DMA */ void adc_multi_channel_dma_init(uint16_t *buffer, uint8_t num_channels) { /* Configure DMA for ADC */ dma_single_data_parameter_struct dma_init_struct; dma_deinit(DMA1, DMA_CH0); dma_init_struct.periph_addr = (uint32_t)(&ADC_RDATA(ADC0)); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.memory0_addr = (uint32_t)buffer; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_16BIT; dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_ENABLE; dma_init_struct.direction = DMA_PERIPH_TO_MEMORY; dma_init_struct.number = num_channels; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_single_data_mode_init(DMA1, DMA_CH0, &dma_init_struct); dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0); dma_channel_enable(DMA1, DMA_CH0); /* Configure ADC with scan mode and DMA */ adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE); adc_dma_request_after_last_enable(ADC0); adc_dma_mode_enable(ADC0); /* Start continuous conversion */ adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); } ``` -------------------------------- ### Initialize and Operate I2C Master Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Provides functions to initialize the I2C peripheral and perform master-mode read and write operations. Ensure the peripheral clock is configured before calling initialization. ```c #include "gd32f4xx_i2c.h" #define I2C_SPEED 400000U /* 400kHz Fast mode */ #define I2C_SLAVE_ADDRESS7 0xA0 /* Example EEPROM address */ /* Initialize I2C0 as master */ void i2c0_master_init(void) { /* Reset I2C */ i2c_deinit(I2C0); /* Configure I2C clock */ i2c_clock_config(I2C0, I2C_SPEED, I2C_DTCY_2); /* Configure I2C mode */ i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); /* Enable I2C */ i2c_enable(I2C0); /* Enable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_ENABLE); } /* I2C write data to slave device */ void i2c_master_write(uint32_t i2c_periph, uint8_t slave_addr, uint8_t *data, uint32_t length) { /* Wait until I2C bus is idle */ while(i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY)); /* Generate START condition */ i2c_start_on_bus(i2c_periph); while(!i2c_flag_get(i2c_periph, I2C_FLAG_SBSEND)); /* Send slave address with write bit */ i2c_master_addressing(i2c_periph, slave_addr, I2C_TRANSMITTER); while(!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND)); i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND); /* Transmit data */ for(uint32_t i = 0; i < length; i++) { while(!i2c_flag_get(i2c_periph, I2C_FLAG_TBE)); i2c_data_transmit(i2c_periph, data[i]); } /* Wait for last byte transmitted */ while(!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)); /* Generate STOP condition */ i2c_stop_on_bus(i2c_periph); while(I2C_CTL0(i2c_periph) & I2C_CTL0_STOP); } /* I2C read data from slave device */ void i2c_master_read(uint32_t i2c_periph, uint8_t slave_addr, uint8_t *data, uint32_t length) { /* Wait until I2C bus is idle */ while(i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY)); /* Enable acknowledge */ i2c_ack_config(i2c_periph, I2C_ACK_ENABLE); /* Generate START condition */ i2c_start_on_bus(i2c_periph); while(!i2c_flag_get(i2c_periph, I2C_FLAG_SBSEND)); /* Send slave address with read bit */ i2c_master_addressing(i2c_periph, slave_addr, I2C_RECEIVER); while(!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND)); i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND); /* Receive data */ for(uint32_t i = 0; i < length; i++) { if(i == length - 1) { /* Disable ACK before receiving last byte */ i2c_ack_config(i2c_periph, I2C_ACK_DISABLE); } while(!i2c_flag_get(i2c_periph, I2C_FLAG_RBNE)); data[i] = i2c_data_receive(i2c_periph); } /* Generate STOP condition */ i2c_stop_on_bus(i2c_periph); while(I2C_CTL0(i2c_periph) & I2C_CTL0_STOP); } ``` -------------------------------- ### Enable Peripheral Clocks with RCU Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Enables clocks for various peripherals like GPIO, USART, SPI, Timer, ADC, DMA, and I2C. Also demonstrates how to reset and disable a peripheral's reset state. Ensure clocks are enabled before using any peripheral. ```c #include "gd32f4xx_rcu.h" /* Enable peripheral clocks before using GPIO, USART, SPI, etc. */ void system_clock_init(void) { /* Enable GPIO port clocks */ rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_GPIOC); /* Enable USART0 clock */ rcu_periph_clock_enable(RCU_USART0); /* Enable SPI0 clock */ rcu_periph_clock_enable(RCU_SPI0); /* Enable Timer0 clock */ rcu_periph_clock_enable(RCU_TIMER0); /* Enable ADC0 clock */ rcu_periph_clock_enable(RCU_ADC0); /* Enable DMA0 clock */ rcu_periph_clock_enable(RCU_DMA0); /* Enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); /* Reset a peripheral if needed */ rcu_periph_reset_enable(RCU_USART0RST); rcu_periph_reset_disable(RCU_USART0RST); } ``` -------------------------------- ### Initialize and Use USART Communication Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Provides functions for USART initialization, byte/string transmission, polling-based reception, and an interrupt handler template. Ensure the peripheral clock is enabled before calling initialization functions. ```c #include "gd32f4xx_usart.h" /* Initialize USART0 for 115200 baud, 8N1 */ void usart0_init(void) { /* Reset USART */ usart_deinit(USART0); /* Configure USART parameters */ usart_baudrate_set(USART0, 115200U); usart_word_length_set(USART0, USART_WL_8BIT); usart_stop_bit_set(USART0, USART_STB_1BIT); usart_parity_config(USART0, USART_PM_NONE); usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); /* Enable transmitter and receiver */ usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); /* Enable USART */ usart_enable(USART0); } /* Transmit a single byte */ void usart_send_byte(uint32_t usart_periph, uint8_t data) { /* Wait until transmit buffer is empty */ while(RESET == usart_flag_get(usart_periph, USART_FLAG_TBE)); usart_data_transmit(usart_periph, data); } /* Transmit a string */ void usart_send_string(uint32_t usart_periph, const char *str) { while(*str) { usart_send_byte(usart_periph, *str++); } /* Wait for transmission complete */ while(RESET == usart_flag_get(usart_periph, USART_FLAG_TC)); } /* Receive a byte with polling */ uint8_t usart_receive_byte(uint32_t usart_periph) { /* Wait until receive buffer not empty */ while(RESET == usart_flag_get(usart_periph, USART_FLAG_RBNE)); return (uint8_t)usart_data_receive(usart_periph); } /* USART interrupt-driven receive handler */ void USART0_IRQHandler(void) { if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) { uint8_t received = (uint8_t)usart_data_receive(USART0); /* Process received byte */ } if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_TBE)) { /* Transmit buffer empty - send next byte */ usart_interrupt_flag_clear(USART0, USART_INT_FLAG_TBE); } } ``` -------------------------------- ### Update PWM Duty Cycle at Runtime Source: https://context7.com/communitygd32cores/gd32firmware/llms.txt Dynamically changes the PWM duty cycle for a specified timer channel. Ensure the timer is already initialized and enabled. ```c /* Update PWM duty cycle at runtime */ void timer_update_duty_cycle(uint32_t timer_periph, uint16_t channel, uint32_t duty_percent) { uint32_t period = TIMER_CAR(timer_periph); uint32_t pulse = (period * duty_percent) / 100; timer_channel_output_pulse_value_config(timer_periph, channel, pulse); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.