单片机DMA实验

单片机 :STM32F407

开发板:DMF407电机开发板

平台:keil V5.31

HSE 为8MHZ

HSI为16MHZ

主函数:

复制代码
#define SEND_BUF_SIZE       (sizeof(TEXT_TO_SEND) + 2) * 200    /* 发送数据长度, 等于sizeof(TEXT_TO_SEND) + 2的200倍. */

const uint8_t TEXT_TO_SEND[] = {"正点原子 STM32 DMA 串口实验的顾客那两个男生的国产漫画防火密封 胶 吗 踢 踢 踢i 提 提!"}; /* 要循环发送的字符串 */

uint8_t g_sendbuf[SEND_BUF_SIZE];           /* 发送数据缓冲区 */

int main(void)
{
    uint8_t  key = 0;
    uint16_t i, k;
    uint16_t len;
    uint8_t  mask = 0;
    float pro = 0;                          /* 进度 */
    
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);     /* 设置时钟,168Mhz */
    delay_init(168);                        /* 延时初始化 */
//    usart_init(115200);                     /* 串口初始化为115200 */
		usart_init(9600);                     /* 串口初始化为115200 */
    led_init();                             /* 初始化LED */
    lcd_init();                             /* 初始化LCD */
    key_init();                             /* 初始化按键 */
    
    dma_init(DMA2_Stream7, DMA_CHANNEL_4);  /* 初始化DMA */
    
    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "DMA TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "KEY0:Start", RED);

    len = sizeof(TEXT_TO_SEND);
    k = 0;
    
    for (i = 0; i < SEND_BUF_SIZE; i++)     /* 填充ASCII字符集数据 */
    {
        if (k >= len)   /* 入换行符 */
        {
            if (mask)
            {
                g_sendbuf[i] = 0x0a;
                k = 0;
            }
            else
            {
                g_sendbuf[i] = 0x0d;
                mask++;
            }
        }
        else    /* 复制TEXT_TO_SEND语句 */
        {
            mask = 0;
            g_sendbuf[i] = TEXT_TO_SEND[k];
            k++;
        }
    }
 
    i = 0;

    while (1)
    {
        key = key_scan(0);

        if (key == KEY0_PRES)   /* KEY0按下 */
        {
            printf("\r\nDMA DATA:\r\n");
            lcd_show_string(30, 130, 200, 16, 16, "Start Transimit....", BLUE);
            lcd_show_string(30, 150, 200, 16, 16, "   %", BLUE);                /* 显示百分号 */

            HAL_UART_Transmit_DMA(&g_uart1_handle, g_sendbuf, SEND_BUF_SIZE);   /* 开始一次DMA传输! */

            /* 等待DMA传输完成,此时我们来做另外一些事情,比如点灯  
             * 实际应用中,传输数据期间,可以执行另外的任务 
             */
            while (1)
            {
                if (__HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TCIF3_7))        /* 等待DMA2_Stream7传输完成 */
                {
                    __HAL_DMA_CLEAR_FLAG(&g_dma_handle, DMA_FLAG_TCIF3_7);      /* 清除DMA2_Stream7传输完成标志 */
                    HAL_UART_DMAStop(&g_uart1_handle);      /* 传输完成以后关闭串口DMA */
                    break;
                }

                pro = __HAL_DMA_GET_COUNTER(&g_dma_handle); /* 获取当前还剩余多少个数据 */
                len = SEND_BUF_SIZE;                        /* 总长度 */
                pro = 1 - (pro / len);                      /* 得到百分比 */
                pro *= 100;                                 /* 扩大100倍 */
                lcd_show_num(30, 150, pro, 3, 16, BLUE);
            }
            lcd_show_num(30, 150, 100, 3, 16, BLUE);        /* 显示100% */
            lcd_show_string(30, 130, 200, 16, 16, "Transimit Finished!", BLUE);     /* 提示传送完成 */
        }

        i++;
        delay_ms(10);

        if (i == 20)
        {
            LED0_TOGGLE();  /* LED0闪烁,提示系统正在运行 */
            i = 0;
        }
    }
}

配置:

复制代码
void dma_init(DMA_Stream_TypeDef *dma_stream_handle, uint32_t ch)
{ 
    if ((uint32_t)dma_stream_handle > (uint32_t)DMA2)               /* 得到当前stream是属于DMA2还是DMA1 */
    {
        __HAL_RCC_DMA2_CLK_ENABLE();                                /* DMA2时钟使能 */
    }
    else
    {
        __HAL_RCC_DMA1_CLK_ENABLE();                                /* DMA1时钟使能 */
    }

    __HAL_LINKDMA(&g_uart1_handle, hdmatx, g_dma_handle);           /* 将DMA与USART1联系起来(发送DMA) */

    /* Tx DMA配置 */
    g_dma_handle.Instance = dma_stream_handle;                      /* 数据流选择 */
    g_dma_handle.Init.Channel = ch;                                 /* DMA通道选择 */
    g_dma_handle.Init.Direction = DMA_MEMORY_TO_PERIPH;             /* 存储器到外设 */
    g_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;                 /* 外设非增量模式 */
    g_dma_handle.Init.MemInc = DMA_MINC_ENABLE;                     /* 存储器增量模式 */
    g_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;    /* 外设数据长度:8位 */
    g_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;       /* 存储器数据长度:8位 */
    g_dma_handle.Init.Mode = DMA_NORMAL;                            /* 外设流控模式 */
    g_dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;               /* 中等优先级 */
    g_dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;              /* 关闭FIFO模式 */
    g_dma_handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;      /* FIFO阈值配置 */
    g_dma_handle.Init.MemBurst = DMA_MBURST_SINGLE;                 /* 存储器突发单次传输 */
    g_dma_handle.Init.PeriphBurst = DMA_PBURST_SINGLE;              /* 外设突发单次传输 */

    HAL_DMA_DeInit(&g_dma_handle);   
    HAL_DMA_Init(&g_dma_handle);
}

波特率越低,传输越慢,效果越明显。

相关推荐
XMAIPC_Robot2 小时前
基于RK3588 ARM+FPGA电火花数控机床控制系统设计,兼顾ethercat软硬件实时
linux·arm开发·人工智能·嵌入式硬件·fpga开发
QiLinkOS2 小时前
QiLink 技术委员会选举实施细则
c语言·数据结构·c++·单片机·嵌入式硬件·算法·开源
QiLinkOS2 小时前
发明人与专利价值共生逻辑
c语言·数据结构·c++·人工智能·单片机·嵌入式硬件·算法
Sakuyu434682 小时前
STM32中断
stm32·单片机·嵌入式硬件
嵌入式小站3 小时前
STM32 零基础可移植教程 13:输入捕获入门,怎么测一个方波频率
stm32·单片机·嵌入式硬件
Rocktech_ruixun3 小时前
智慧餐饮新机遇:全场景无人化升级,破解餐饮业降本增效难题
人工智能·嵌入式硬件·ai·机器人
Dillon Dong6 小时前
【风电控制】TI TMS320F28379D 双CPU架构解析与任务分布设计
嵌入式硬件·算法·变流器·风电控制
三易串口屏14 小时前
实验20 自动灭火场景实验
嵌入式硬件·串口屏·三易串口屏·uart 通信
蒸蛋一级爱好者14 小时前
TFTP协议
单片机·嵌入式硬件