5. Printf implementation and DMA implementation of USART0
[Copy link]
This post was last edited by sonicfirr on 2022-2-9 21:09
The following GD32L233C-START special review:
1. Unboxing review https://bbs.eeworld.com.cn/thread-1192788-1-1.html
2. GD32L233C-START environment construction https://bbs.eeworld.com.cn/thread-1193053-1-1.html
3. Lighting case and extension https://bbs.eeworld.com.cn/thread-1193183-1-1.html
4. Analysis of Demo Project https://bbs.eeworld.com.cn/thread-1193279-1-1.html
I worked on a demo last night, then fell asleep. I'll post one tonight.
1. Back up a project
When I was teaching, I was used to writing all the cases of a course in one project. This was convenient to use (and also provided good service to the students). I brought this habit here.
In addition, the download link of GD official website is mentioned again: http://www.gd32mcu.com/cn/download/0?kw=GD32L2. The firmware library provided here contains demos of all interfaces.
2. Case code
1) First create a system header file and put other header file connections and test function declarations here.
#ifndef _AITA_SYS_H
#define _AITA_SYS_H
#include "gd32l23x.h"
#include "systick.h"
#include "gd32l233c_start.h"
#include <stdio.h>
#include <string.h>
extern uint8_t rx_buffer[256];
extern uint32_t nbr_data_to_read;
extern volatile uint32_t rx_counter;
#define AITA_EASYSHIELD_EN 1 //开启EasySheild扩展板,即增加多个LED的驱动
void aita_InitBSP(void);
void aita_InitLED(void);
void aita_InitUSART(void);
void aita_Flash(void);
void aita_RGB(void);
void aita_TestUSART(void);
void aita_InitDMAForU0(void);
#endif
2) The code of main.c is divided into several sections and is complete from top to bottom. The code for lighting the lamp is in the previous review post, so I won’t write it here.
//by author. DMA测试的定义和printf重定向
#include "aita_sys.h"
//DMA USART0 发送和接收寄存器地址
#define USART0_RDATA_ADDRESS (&USART_RDATA(USART0))
#define USART0_TDATA_ADDRESS (&USART_TDATA(USART0))
#define ARRAYNUM(arr_nanme) (uint32_t)(sizeof(arr_nanme) / sizeof(*(arr_nanme)))
//DMA USART0 测试用到的内存缓存
__IO FlagStatus g_transfer_complete = RESET;
uint8_t rxbuffer[10];
uint8_t txbuffer[] = "\n\rUSART DMA interrupt receive and transmit example, please input 10 bytes:\n\r";
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(EVAL_COM, (uint8_t) ch);
while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
return ch;
}
//by author. main函数之前做的功能写成了三个测试函数,aita_TestUSART()是串口收发的测试(非DMA方式)
//现在启用的是DMA收发的过程
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void) {
aita_InitBSP();
//aita_Flash();
//aita_RGB();
//aita_TestUSART();
/* waiting for the transfer to complete*/
while(RESET == g_transfer_complete) {
}
g_transfer_complete = RESET;
/* waiting for the transfer to complete*/
while(RESET == g_transfer_complete) {
}
printf("\n\r%s\n\r", rxbuffer);
while(1) {
}
}
//by author. 初始化部分
void aita_InitBSP(void) {
systick_config();
aita_InitLED();
aita_InitUSART();
aita_InitDMAForU0();
}
//by author. GPIO控制LED初始化和串口初始化(目前开启DMA,所以注释了后两句)
//串口初始化代码gd_eval_com_init(),Demo中写在了gd32l233c_start.c
void aita_InitLED(void) {
gd_eval_led_init(LED1);
gd_eval_led_init(LED2);
gd_eval_led_init(LED3);
gd_eval_led_init(LED4);
#if AITA_EASYSHIELD_EN
rcu_periph_clock_enable(RCU_GPIOB);
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_12 | GPIO_PIN_15 | GPIO_PIN_0);
gpio_output_options_set(
GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,
GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_12 | GPIO_PIN_15 | GPIO_PIN_0);
gpio_bit_reset(GPIOB, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_12 | GPIO_PIN_15 | GPIO_PIN_0);
#endif
}
void aita_InitUSART(void) {
/* configure EVAL_COM */
gd_eval_com_init(EVAL_COM);
/* USART interrupt configuration */
//nvic_irq_enable(USART0_IRQn, 0);
/* enable EVAL_COM receive interrupt */
//usart_interrupt_enable(EVAL_COM, USART_INT_RBNE);
}
//by author. 从固件库Demo移植过来,Demo中使用了U1,这里改成板子上的U0
//另外,这里本人分析L233提供了一个DMA矩阵,包含7个通道,应该是外设可以映射到任意通道来使用
//原Demo U1口使用了DMA_CH0和DMA_CH1,我改成U0口也可以使用
void aita_InitDMAForU0(void) {
dma_parameter_struct dma_init_struct;
/* enable DMA clock */
rcu_periph_clock_enable(RCU_DMA);
/*configure DMA interrupt*/
nvic_irq_enable(DMA_Channel0_IRQn, 0);
nvic_irq_enable(DMA_Channel1_IRQn, 0);
/* initialize DMA channel 0 */
dma_deinit(DMA_CH0);
dma_struct_para_init(&dma_init_struct);
dma_init_struct.request = DMA_REQUEST_USART0_TX;
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
dma_init_struct.memory_addr = (uint32_t)txbuffer;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = ARRAYNUM(txbuffer);
dma_init_struct.periph_addr = (uint32_t)USART0_TDATA_ADDRESS;
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA_CH0, &dma_init_struct);
/* configure DMA mode */
dma_circulation_disable(DMA_CH0);
dma_memory_to_memory_disable(DMA_CH0);
/* disable the DMAMUX_MUXCH0 synchronization mode */
dmamux_synchronization_disable(DMAMUX_MUXCH0);
/* USART DMA enable for transmission and reception */
usart_dma_transmit_config(USART0, USART_DENT_ENABLE);
/* enable DMA channel 0 transfer complete interrupt */
dma_interrupt_enable(DMA_CH0, DMA_INT_FTF);
/* enable DMA channel 0 */
dma_channel_enable(DMA_CH0);
/* initialize DMA channel 1 */
dma_deinit(DMA_CH1);
dma_struct_para_init(&dma_init_struct);
dma_init_struct.request = DMA_REQUEST_USART0_RX;
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)rxbuffer;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = ARRAYNUM(rxbuffer);
dma_init_struct.periph_addr = (uint32_t)USART0_RDATA_ADDRESS;
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA_CH1, &dma_init_struct);
/* configure DMA mode */
dma_circulation_disable(DMA_CH1);
dma_memory_to_memory_disable(DMA_CH1);
/* disable the DMAMUX_MUXCH1 synchronization mode */
dmamux_synchronization_disable(DMAMUX_MUXCH1);
/* USART DMA enable for reception */
usart_dma_receive_config(USART0, USART_DENR_ENABLE);
/* enable DMA channel 1 transfer complete interrupt */
dma_interrupt_enable(DMA_CH1, DMA_INT_FTF);
/* enable DMA channel 1 */
dma_channel_enable(DMA_CH1);
}
//by author. 非DMA方式的U0收发测试,开启了接收中断
void aita_TestUSART(void) {
uint16_t i=0;
while(1) {
if(rx_counter > 0) {
printf("get msg: \r\n%s\r\n", rx_buffer);
rx_counter = 0;
memset(rx_buffer, 0, 256);
}
if(i++ >= 500) {
i = 0;
printf("Hello from GD32L233C-START!\r\n");
}
delay_1ms(10);
}
}
3) Interrupt function——gd32l23x_it.c
//by author. 以下是文件修改和新增部分
//原U0接收中断,是接收固定数量字节,然后就关闭接收中断(注释掉部分)
//DMA中断暂时从固件库案例粘贴过来,没有做修改,测试功能也是案例中的发送一句话,并接收10个字节
#define BUFFER_SIZE 256
uint8_t rx_buffer[BUFFER_SIZE];
uint32_t nbr_data_to_read = BUFFER_SIZE;
volatile uint32_t rx_counter = 0;
/*!
\brief this function handles USART0 exception
\param[in] none
\param[out] none
\retval none
*/
void USART0_IRQHandler(void)
{
if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) {
/* read one byte from the receive data register */
rx_buffer[rx_counter++] = (uint8_t)usart_data_receive(USART0);
// if(rx_counter >= nbr_data_to_read) {
// /* disable the USART0 receive interrupt */
// usart_interrupt_disable(USART0, USART_INT_RBNE);
// }
}
}
extern FlagStatus g_transfer_complete;
/*!
\brief this function handles DMA_Channel0_IRQHandler interrupt
\param[in] none
\param[out] none
\retval none
*/
void DMA_Channel0_IRQHandler(void)
{
if(RESET != dma_interrupt_flag_get(DMA_CH0, DMA_INT_FLAG_FTF)){
dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FLAG_G);
g_transfer_complete = SET;
}
}
/*!
\brief this function handles DMA_Channel1_IRQHandler interrupt
\param[in] none
\param[out] none
\retval none
*/
void DMA_Channel1_IRQHandler(void)
{
if(RESET != dma_interrupt_flag_get(DMA_CH1, DMA_INT_FLAG_FTF)){
dma_interrupt_flag_clear(DMA_CH1, DMA_INT_FLAG_G);
g_transfer_complete = SET;
}
}
3. Test results
Friends in need can download my case and put it in "..\GD32L233C-START\GD32L233C_START_Demo_Suites\Projects".
|