OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5849|回复: 8

GD32F4一个串口是否可以由多组引脚共用

[复制链接]

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
发表于 2022-7-29 15:49:04 | 显示全部楼层 |阅读模式
1金钱
看GD32F4的规格书,发现一个问题。我看到PD5,PD6具有USART1的串口功能。然后又看到PA2,PA3也具有USART1的串口功能。我想请教下大家,我可以同时配置PA2,PA3以及PD5,PD6吗?

最佳答案

查看完整内容[请看2#楼]

使用IO模拟串口是可以正常收发指令的。现在我分享代码给大家,有需要的可以参考下。 / ***** 在usart.h头文件定义如下: *****/ #define USART_TXD(n) (n?gpio_bit_set(GPIOA, GPIO_PIN_2):gpio_bit_reset(GPIOA, GPIO_PIN_2)) #define USART_RXD gpio_input_bit_get(GPIOA, GPIO_PIN_3) #define BuadRate_9600 104 #define Receive_byte 21 enum{ COM_START_BIT = 0, COM_D0_BIT, COM_D1_BIT, CO ...
天道酬勤
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
 楼主| 发表于 2022-7-29 15:49:05 | 显示全部楼层
本帖最后由 紫气东升 于 2022-8-4 16:22 编辑

使用IO模拟串口是可以正常收发指令的。现在我分享代码给大家,有需要的可以参考下。

/ ***** 在usart.h头文件定义如下: *****/
#define USART_TXD(n) (n?gpio_bit_set(GPIOA, GPIO_PIN_2):gpio_bit_reset(GPIOA, GPIO_PIN_2))
#define USART_RXD   gpio_input_bit_get(GPIOA, GPIO_PIN_3)
#define BuadRate_9600 104
#define Receive_byte 21

enum{
    COM_START_BIT = 0,
    COM_D0_BIT,
    COM_D1_BIT,
    COM_D2_BIT,
    COM_D3_BIT,
    COM_D4_BIT,
    COM_D5_BIT,
    COM_D6_BIT,
    COM_D7_BIT,
    COM_STOP_BIT,
};

extern uint8_t USART_buf[Receive_byte];

void softusart_config(void);
void softusart_SendByte(uint8_t byte);
void USART_SendData(uint8_t* data_buffer, uint16_t length);
void Start_RecData(void);
void ReceiveData(void);
void timer6_config(void);

/ ***** 在usart.c源文件编写函数如下: *****/
void softusart_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_SYSCFG);
   
    gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
    gpio_bit_set(GPIOA, GPIO_PIN_2);
   
    gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
    /* configure EXTI priority */
    nvic_irq_enable(EXTI3_IRQn, 2, 0);
    /* connect IO EXTI line to IO GPIO pin */
    syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN3);
    /* configure IO EXTI line */
    exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_FALLING);  //Falling edge interruption
    exti_interrupt_flag_clear(EXTI_3);
}

void timer6_config(void)
{
    timer_parameter_struct timer_initpara6; //Timer initialization parameters
   
    rcu_periph_clock_enable(RCU_TIMER6);
    /* Timer frequency CK_TIMER6 = CK_APB1*4 = CK_SYS = 120MHz */
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
    nvic_irq_enable(TIMER6_IRQn, 2, 0);
    timer_deinit(TIMER6);
    /* Set the counting clock frequency CLK to 1MHz, indicating that the timer counts once every 1us */
    timer_initpara6.prescaler = 119; //prescaler = CK_SYS/clk - 1, 120/1 - 1=119
    timer_initpara6.alignedmode = TIMER_COUNTER_EDGE; //Edge alignment mode
    timer_initpara6.counterdirection = TIMER_COUNTER_UP; //Counting up
    timer_initpara6.clockdivision = TIMER_CKDIV_DIV1; //DTS=TIMER_CK
    timer_initpara6.period = 104; //Automatic reloading value
    timer_initpara6.repetitioncounter = 0; //Repeat counter value
    timer_init(TIMER6, &timer_initpara6); //Initializing timer
    /* auto reload preload enable */
    timer_auto_reload_shadow_enable(TIMER6);
    /* clear update interrupt bit */
    timer_interrupt_flag_clear(TIMER6, TIMER_INT_UP);
    /* update interrupt enable */
    timer_interrupt_enable(TIMER6, TIMER_INT_UP); //Enable count overflow update interrupt
    /* TIMER counter enable */
    timer_disable(TIMER6);
}

void delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD;                /* The reload value of the tick timer */
    ticks = nus * 120;                                                 /* The number of beats required */
    told = SysTick->VAL;                                /* The counter value at entry is */

    while(1)
    {
        tnow = SysTick->VAL;

        if(tnow != told)
        {
            if(tnow < told)tcnt += told - tnow;
            else tcnt += reload - tnow + told;
            if(tcnt >= ticks)break;                         /* If the time exceeds or is equal to the required delay, exit */
                        told = tnow;
        }
    }  
}

void softusart_SendByte(uint8_t byte)
{
    uint8_t Bit = 0;
   
    USART_TXD(0);
    delay_us(BuadRate_9600);
    for(Bit = 0; Bit < 8; Bit++)
    {
        if(byte & 0x01){
            USART_TXD(1);
        }else{
            USART_TXD(0);
        }
        delay_us(BuadRate_9600);
        byte >>= 1;
    }
    USART_TXD(1);
    delay_us(BuadRate_9600);
}

void USART_SendData(uint8_t* data_buffer, uint16_t length)
{
    uint8_t i = 0;
   
    for(i = 0; i > length; i++)
    {
        softusart_SendByte(data_buffer);
    }
}

void Start_RecData(void)  //进入EXTI外部中断是调用该函数
{
    if(USART_RXD == 0)
    {
        if(recvState == COM_STOP_BIT)
        {
            recvState = COM_START_BIT;
            timer_counter_value_config(TIMER6, 0);
            timer_enable(TIMER6);
        }
    }
}

void ReceiveData(void)   //在定时器TIMER6中断中调用该函数
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
   
    recvState++;
    if(recvState == COM_STOP_BIT)
    {
        timer_disable(TIMER6);
        USART_buf[len] = recvData;
        len++;
        if(0xEA == USART_buf[0])
        {
            if(USART_buf[1] == len)
            {
                if(0x0D == USART_buf[USART_buf[1]-1])
                {
                    len = 0;
                    xSemaphoreGiveFromISR(Semaphore_softusart_rec, &xHigherPriorityTaskWoken);
                    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
                }
                else
                {
                    len = 0;
                }
            }
        }
        else
        {
            len = 0;
        }
    }
    if(USART_RXD){
        recvData |= (1 << (recvState - 1));
    }else{
        recvData &= ~(1 << (recvState - 1));
    }
}

/ ***** 在gd32f4xx_it.c源文件添加函数如下: *****/
void EXTI3_IRQHandler(void)
{
    if(RESET != exti_interrupt_flag_get(EXTI_3))
    {
        Start_RecData();
    }
    exti_interrupt_flag_clear(EXTI_3);
}

void TIMER6_IRQHandler(void)
{
    if(RESET != timer_interrupt_flag_get(TIMER6, TIMER_INT_UP))
    {
        timer_interrupt_flag_clear(TIMER6, TIMER_INT_UP);
        ReceiveData();
    }
}

天道酬勤
回复

使用道具 举报

12

主题

3386

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8625
金钱
8625
注册时间
2020-5-11
在线时间
4056 小时
发表于 2022-7-29 16:09:15 | 显示全部楼层
IO口重映射了解一下?
专治疑难杂症
回复

使用道具 举报

17

主题

161

帖子

0

精华

高级会员

Rank: 4

积分
955
金钱
955
注册时间
2022-7-21
在线时间
446 小时
发表于 2022-7-29 18:19:37 | 显示全部楼层
这可以的
回复

使用道具 举报

3

主题

821

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3359
金钱
3359
注册时间
2011-11-10
在线时间
207 小时
发表于 2022-7-30 08:13:44 | 显示全部楼层
同一个串口不能同时配置给多组引脚,只能分时复用。
回复

使用道具 举报

7

主题

99

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
220
金钱
220
注册时间
2015-2-26
在线时间
35 小时
发表于 2022-7-30 16:35:27 | 显示全部楼层
短接吧
回复

使用道具 举报

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
 楼主| 发表于 2022-8-1 10:40:48 | 显示全部楼层
c2007s 发表于 2022-7-30 08:13
同一个串口不能同时配置给多组引脚,只能分时复用。

分时复用在这个项目不合适使用,我在网上查找,有一种方法是用IO模拟串口。现在正在查资料如何做。
天道酬勤
回复

使用道具 举报

53

主题

167

帖子

0

精华

高级会员

Rank: 4

积分
840
金钱
840
注册时间
2016-8-23
在线时间
116 小时
 楼主| 发表于 2022-8-1 10:41:43 | 显示全部楼层
LcwSwust 发表于 2022-7-29 16:09
IO口重映射了解一下?

不太明白什么意思
天道酬勤
回复

使用道具 举报

12

主题

3386

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8625
金钱
8625
注册时间
2020-5-11
在线时间
4056 小时
发表于 2022-8-1 11:00:50 | 显示全部楼层
紫气东升 发表于 2022-8-1 10:41
不太明白什么意思

没关系,先按你自己的方法去做,有问题再来讨论问题.
专治疑难杂症
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-8 00:48

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表