OpenEdv-开源电子网

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

使用 STM32F1串口4 DMA收发

[复制链接]

13

主题

49

帖子

0

精华

高级会员

Rank: 4

积分
542
金钱
542
注册时间
2017-10-17
在线时间
118 小时
发表于 2024-1-9 15:23:41 | 显示全部楼层 |阅读模式
/*
* hal_USART4_stm32f1.c

*/

#include "hal_usart.h"
#include "stm32f10x.h"
#include "bsp.h"
#include <string.h>


static uint8_t USART4_RxBuffer[0x100];
static uint8_t USART4_TxBuffer[0x100];

static uint32_t USART4_ReadIndex = 0;



/**
* &#65533;&#65533;&#700;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;
*/
void USART4_Init(void)
{
    /**
     * 1.&#65533;&#65533;&#700;&#65533;&#65533;&#689;&#65533;&#65533;
     */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1|RCC_AHBPeriph_DMA2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);


    /**
     * 2.&#65533;&#65533;&#700;&#65533;&#65533;IO
     */
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Configure USART4 Rx as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* Configure USART4 Tx as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);


    /**
     * 3.&#65533;&#65533;&#700;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;
     */
    USART_InitTypeDef USART_InitStructure;

    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    /* Configure USARTy */
    USART_Init(UART4, &USART_InitStructure);
    USART_ITConfig(UART4, USART_IT_IDLE, ENABLE);

    /**
     * 4.&#65533;&#65533;&#700;&#65533;&#65533;DMA
     */
    DMA_InitTypeDef DMA_InitStructure;

    DMA_DeInit(DMA2_Channel3);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(UART4->DR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&USART4_RxBuffer[0];
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = sizeof(USART4_RxBuffer);
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // &#65533;&#65533;&#65533;&#65533;DMA&#65533;&#65533;&#65533;&#65533;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA2_Channel3, &DMA_InitStructure);
    USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);
    DMA_Cmd(DMA2_Channel3, ENABLE);


    DMA_DeInit(DMA2_Channel5);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(UART4->DR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&USART4_TxBuffer[0];
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = sizeof(USART4_TxBuffer);
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA2_Channel5, &DMA_InitStructure);
    USART_DMACmd(UART4, USART_DMAReq_Tx, ENABLE);
    DMA_ITConfig(DMA2_Channel5, DMA_IT_TC, ENABLE);

    USART_Cmd(UART4, ENABLE);


    /**
     * 5.&#65533;&#65533;&#700;&#65533;&#65533;&#65533;ж&#65533;&#1013;&#883;
     */
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Enable the USART4 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Enable the DMA1_Channel2 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel4_5_IRQn; //TX
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

}




/**
*
* @param buffer
* @param length
* @return
*/
uint32_t USART4_Send(void* buffer, uint32_t length)
{
    uint32_t send_length;

    if( length > sizeof(USART4_TxBuffer) )
    {
        send_length = sizeof(USART4_TxBuffer);
    }
    else
    {
        send_length = length;
    }

    memcpy(USART4_TxBuffer, buffer, send_length);
    DMA_Cmd(DMA2_Channel5, DISABLE);
    DMA_SetCurrDataCounter(DMA2_Channel5, send_length);
    DMA_Cmd(DMA2_Channel5, ENABLE);

    return send_length;
}



static USART_SendDoneISR SendDoneISR4 = 0;

/**
*
* @param isr
*/
void USART4_SetSendDoneISR       (USART_SendDoneISR isr)
{
    SendDoneISR4 = isr;
}



/**
*
* @param buffer
* @param max_length
* @return
*/
uint32_t USART4_Recv(uint8_t* buffer, uint32_t max_length)
{
    uint32_t recv_length;
    uint32_t write_index;

    write_index = sizeof(USART4_RxBuffer) - DMA_GetCurrDataCounter(DMA2_Channel3);
    recv_length = 0;

    while( (write_index - USART4_ReadIndex) != 0 ) // &#65533;&#65533;&#65533;&#65533;&#65533;
    {
        buffer[recv_length] = USART4_RxBuffer[USART4_ReadIndex];
        recv_length ++;
        USART4_ReadIndex ++;

        if( USART4_ReadIndex == sizeof(USART4_RxBuffer) )
        {
            USART4_ReadIndex = 0;
        }

        if( recv_length == max_length )
        {
            break;
        }
    }

    return recv_length;
}



uint32_t USART4_DataAvailable(void)
{
    uint32_t filled_length;
    uint32_t write_index;

    write_index = sizeof(USART4_RxBuffer) - DMA_GetCurrDataCounter(DMA2_Channel3);

    if( USART4_ReadIndex > write_index )
    {
        filled_length = (sizeof(USART4_RxBuffer) - USART4_ReadIndex) + write_index;
    }
    else
    {
        filled_length = write_index - USART4_ReadIndex;
    }


    return filled_length;
}



uint32_t USART4_Flush(void)
{
    uint32_t flush_length;
    uint32_t write_index;

    write_index = sizeof(USART4_RxBuffer) - DMA_GetCurrDataCounter(DMA2_Channel3);

    if( USART4_ReadIndex > write_index )
    {
        flush_length = (sizeof(USART4_RxBuffer) - USART4_ReadIndex) + write_index;
    }
    else
    {
        flush_length = write_index - USART4_ReadIndex;
    }

    USART4_ReadIndex = write_index;

    return flush_length;
}




static USART_RecvTimeoutISR RecvTimeoutISR4 = 0;

/**
*
* @param isr
*/
void USART4_SetRecvTimeoutISR    (USART_RecvTimeoutISR isr)
{
    RecvTimeoutISR4 = isr;
}



void UART4_IRQHandler(void)
{
//    uint16_t recv;
//    SYS_EnterInt();

    if(USART_GetITStatus(UART4, USART_IT_IDLE) != RESET)//&#65533;&#65533;&#65533;&#1407;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#938;&#65533;&#65533;&#689;
    {
//        recv =
        USART_ReceiveData(UART4);

        if( RecvTimeoutISR4 != 0 )
        {
            RecvTimeoutISR4();
        }

        USART_ClearITPendingBit(UART4, USART_IT_IDLE);
    }


//    SYS_ExitInt();
}



void DMA2_Channel4_5_IRQHandler(void)
{
//    SYS_EnterInt();

    if ( DMA_GetITStatus(DMA2_IT_TC5) )
    {
        if( SendDoneISR4 != 0 )
        {
            SendDoneISR4();
        }
        DMA_ClearITPendingBit(DMA2_IT_TC5);
    }

//    SYS_ExitInt();
}

以上是一个DMA 串口4收发的初始化及函数调用的方式





正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

109

主题

5562

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10541
金钱
10541
注册时间
2017-2-18
在线时间
1908 小时
发表于 2024-1-10 09:00:25 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

8

帖子

0

精华

新手入门

积分
1
金钱
1
注册时间
2023-12-28
在线时间
8 小时
发表于 2024-1-11 17:13:40 | 显示全部楼层
感谢分享
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2022-3-20
在线时间
4 小时
发表于 2024-4-8 21:38:42 | 显示全部楼层
大佬我有点不懂 如果我想用串口中断读取接收机的信息是不是必须要使用dma,我有点想不通,我的遥控器一连上之后他就会一直在串口中断里面然后不会返回主函数执行主函数里的代码
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2022-3-20
在线时间
4 小时
发表于 2024-4-8 21:41:16 | 显示全部楼层
大佬,是不是如果想要同时用串口中断读取遥控器接收机数据,然后用主函数进行数据处理就必须要使用DMA阿,我连上遥控器之后就一直进行串口中断里的代码,返回不了主函数了
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-23 05:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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