GD32E230单片机串口中断 M0内核

一、开发背景

因为疫情的原因,导致stm32的价格上涨,且货期也不稳定。所以需要从国内寻找新的芯片厂商,经过多家对比,最终选择了GD的单片机,之前使用的是stm32f031系列芯片,在GD的代理商引导下选择了GD32E230单片机,可以与stm32f031 pin to pin 兼容,之前准备直接用ST的代码直接烧录使用,但是存在一些问题,索性使用GD的库直接重写代码。后面的博文会持续更新GD的各种外设使用。此次开篇先来一个基础的USART配置和使用,涉及到串口的接收中断和发送。

二、串口配置

GPIO引脚配置

GD的API函数和ST略有差异,但是配置过程基本相同。
首先配置GPIO,包括时钟和IO口配置。
PA8为RS485使能引脚。
PA9和PA10是USART0,相当于STM32的USART1。

void com_gpio_init(void)
{
    
    
    /* enable COM GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOA);

    /* connect port to USARTx_Tx */
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9);

    /* connect port to USARTx_Rx */
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_9);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_10);
	
	gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
	
	GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_8;
	GPIO_BC(GPIOA) = (uint32_t)GPIO_PIN_8;
}

串口配置

同样是使能串口,配置串口的相关参数。

void com_usart_init(void)
{
    
    
    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART0);

    /* USART configure */
    usart_deinit(USART0);
    usart_baudrate_set(USART0,2500000U);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);

    usart_enable(USART0);
}

串口中断配置

串口中断的配置只需要一个API函数,相当简单。nvic_irq_enable(USART0_IRQn, 0);
下面是中断服务函数,被屏蔽的代码为直接操作寄存器,加快代码的速度,因为我的项目对串口的速度要求较高,看我的波特率就知道了2.5M的波特率。
串口接收数据进入中断后首先获取USART中断标志位状态,通过usart_interrupt_flag_get(EVAL_COM, USART_INT_FLAG_RBNE)判断。然后用数组接收串口数据,判断数据是否是0x1A,符合条件进入if函数。判断串口数据接收标志位是否为RESET,然后通过函数发送数据,发送完失能串口中断,以便下一次进入中断,这里和st的库函数处理方法有所不同。我在测试的时候想用usart_flag_clear()函数清除掉中断标志位,但是在手册里没有清除中断标志位的选项,GD是采用失能串口中断的方式退出中断。

void USART0_IRQHandler(void)
{
    
    
//		if(RESET != (USART_STAT(USART0)&0x00000010)) 
//		{
    
    
//			 GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_8;
//			 receiver_buffer[0] = (uint16_t)(GET_BITS(USART_RDATA(USART0), 0U, 8U));
//			 USART_REG_VAL(USART0, USART_INT_TBE) |= BIT(USART_BIT_POS(USART_INT_TBE));
//			 
//		}
//		
//		if(RESET != (USART_STAT(USART0)&0x00000040)) 
//		{
    
    
//			USART_TDATA(USART0) = (USART_TDATA_TDATA & transmitter_buffer[txcount++]);	 
//			if(txcount == transfersize){
    
    
//				USART_REG_VAL(USART0, USART_INT_TBE) &= ~BIT(USART_BIT_POS(USART_INT_TBE));
//				GPIO_BC(GPIOA) = (uint32_t)GPIO_PIN_8;
//				txcount = 0 ;
//        }
//		}
	
	
	  if(RESET != usart_interrupt_flag_get(EVAL_COM, USART_INT_FLAG_RBNE)){
    
    
        /* receive data */
		  
			receiver_buffer[0] = usart_data_receive(EVAL_COM);
		  usart_interrupt_enable(EVAL_COM, USART_INT_TBE);
		  if(receiver_buffer[0] == 0x1A)
		  {
    
    		
			/* transmit data */
			gpio_bit_set(GPIOA,GPIO_PIN_8);
			while(usart_flag_get(USART0,USART_FLAG_TC)==RESET);
			usart_data_transmit(EVAL_COM, transmitter_buffer[4]);
			while(usart_flag_get(USART0,USART_FLAG_TC)==RESET);
			gpio_bit_reset(GPIOA,GPIO_PIN_8);
//			usart_flag_clear(USART0,USART_FLAG_TC);
			usart_interrupt_disable(EVAL_COM, USART_INT_TBE);
		  }		
    }
}

主函数

主函数就非常简单,配置串口中断,初始化时钟和串口,使能串口中断。

int main(void)
{
    
    
    /* 串口中断配置*/
    nvic_irq_enable(USART0_IRQn, 0);
     systick_config() ;
    /* 初始化串口 */
    com_gpio_init();//GPIO初始化
    com_usart_init();//串口初始化 
	printf("please test Usart recevie transfersize\n") ;
	delay_1ms(300) ;
    usart_interrupt_enable(USART0, USART_INT_RBNE);  
    while (1);
	}

三、运行结果

在这里插入图片描述
发送1A,返回transmitter_buffer[4]的值。
GD的库因为不熟悉,刚用起来有点费劲,但是用过一次就会发现比ST的要简单和方便,代码集成度更高,用起来代码更简单。单片机的性能也进行过测试,怎么说呢,对标比较:更快,更强,更便宜。希望国产芯片越来越强。

猜你喜欢

转载自blog.csdn.net/dy_ngmm/article/details/108345627
今日推荐