一、开发背景
因为疫情的原因,导致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,U); 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的要简单和方便,代码集成度更高,用起来代码更简单。单片机的性能也进行过测试,怎么说呢,对标比较:更快,更强,更便宜。希望国产芯片越来越强。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/40892.html