查看: 1869|回复: 0
收起左侧

第一百零二章:CH32V103应用教程——USART-DMA-TC中断

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-7-31 19:04:25 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本章主要实现以下功能:在DMA中处理串口通信,通过DMA实现数据从内存(数组)到外设(串口)的转移,并在DMA数据发送完成之后进入中断并执行中断函数相关程序。

    1、DMA简介

    每个DMA通道都可以在DMA传输过半、传输完成和传输错误时产生中断。为应用的灵活性考虑,可通过设置寄存器的不同位来打开这些中断,具体如下:

    (1)传输过半:对应DMA_INTFR寄存器中的HTIFx位硬件置位。当DMA的传输数目减至初始设定值一半以下将会产生DMA传输过半标志,如果在 DMA_CCRx寄存器中置位了HTIE,则将产生中断。硬件通过此标志提醒应用程序,可以为新一轮数据传输做准备。

    (2)传输完成:对应DMA_INTFR寄存器中的TCIFx位硬件置位。当DMA的传输数目减至0将会产生DMA传输完成标志,如果在DMA_CCRx寄存器中置位了TCIE,则将产生中断。

    (3)传输错误:对应DMA_INTFR寄存器中的TEIFx位硬件置位。读写一个保留的地址区域,将会产生DMA传输错误。同时模块硬件会自动清0发生错误的通道所对应的DMA_CCRx寄存器的EN位,该通道被关闭。如果在DMA_CCRx寄存器中置位了TEIE,则将产生中断。
    应用程序在查询DMA通道状态时,可以先访问DMA_INTFR寄存器的GIFx 位,判断出当前哪个通道发生了DMA事件,进而处理该通道的具体DAM事件内容。

    本章主要进行DMA传输完成中断,关于DMA具体介绍,可参考CH32V103应用手册。

    2、硬件设计本章教程主要使用DMA进行串口数据传输,所用资源均为CH32V103开发板内部资源,无需进行其他硬件连接,只需进行程序配置即可。可通过串口3与串口调试助手连接查看发送数据。若要通过LED灯看现象,可将PA0与LED1连接,PA1与LED2连接。

    3、软件设计

    本章教程主要进行DMA传输完成中断实验,具体程序如下:
    usart.h文件
    1. #ifndef __USART_H

    2. #define __USART_H



    3. #include "ch32v10x.h"



    4. void LED_GPIO_Config(void);

    5. void USARTx_CFG(void);

    6. void DMA_INIT(void);



    7. #endif
    复制代码

    usart.h文件主要进行相关定义和函数声明;
    usart.c文件


    1. #include "usart.h"

    2. #include "debug.h"



    3. void DMA1_Channel2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));



    4. //定义SRC_BUF数组作为DMA传输数据源,并将数据存储在内部FLASH中

    5. u8 TxBuffer1[ ]="DMA test: from memory to peripheral";



    6. #define TxSize1   (sizeof(TxBuffer1))



    7. //LED灯初始化配置

    8. void LED_GPIO_Config(void)

    9. {

    10.         /*定义一个GPIO_InitTypeDef类型的结构体*/

    11.         GPIO_InitTypeDef GPIO_InitStructure;

    12.         /*开启LED对应GPIO引脚的外设时钟*/

    13.         RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);

    14.         /*选择要控制的GPIOA引脚*/

    15.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;

    16.         /*设置引脚模式为通用推挽输出*/

    17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    18.         /*设置引脚速率为50MHz */

    19.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    20.         /*调用库函数,初始化GPIOA*/

    21.         GPIO_Init(GPIOA, &GPIO_InitStructure);

    22.         /*PA0引脚设置低电平 */

    23.         GPIO_SetBits(GPIOA, GPIO_Pin_0|GPIO_Pin_1);

    24. }



    25. /*******************************************************************************

    26. * Function Name  : USARTx_CFG

    27. * Description    : Initializes the USART2 & USART3 peripheral.

    28. * Input          : None

    29. * Return         : None

    30. *******************************************************************************/

    31. void USARTx_CFG(void)

    32. {



    33.     GPIO_InitTypeDef  GPIO_InitStructure;

    34.     USART_InitTypeDef USART_InitStructure;



    35.     //使能开启GPIOB和USART3时钟

    36.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);

    37.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);



    38.     //串口3对应GPIO引脚初始化

    39.     /* USART3 TX-->B.10  RX-->B.11 */

    40.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

    41.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    42.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    43.     GPIO_Init(GPIOB, &GPIO_InitStructure);

    44.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;

    45.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    46.     GPIO_Init(GPIOB, &GPIO_InitStructure);



    47.     //串口3初始化配置

    48.     USART_InitStructure.USART_BaudRate = 115200;

    49.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    50.     USART_InitStructure.USART_StopBits = USART_StopBits_1;

    51.     USART_InitStructure.USART_Parity = USART_Parity_No;

    52.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    53.     USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

    54.     USART_Init(USART3, &USART_InitStructure);



    55.     USART_Cmd(USART3, ENABLE);  //使能串口3

    56. }



    57. /*******************************************************************************

    58. * Function Name  : DMA_INIT

    59. * Description    : Configures the DMA for USART3.

    60. * Input          : None

    61. * Return         : None

    62. *******************************************************************************/

    63. void DMA_INIT(void)

    64. {

    65.     DMA_InitTypeDef   DMA_InitStructure;

    66.     NVIC_InitTypeDef  NVIC_InitStructure;



    67.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                       //使能开启DMA时钟



    68.     DMA_DeInit(DMA1_Channel2);

    69.     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART3->DATAR);        /*设置DMA源:串口3数据寄存器地址*/

    70.     DMA_InitStructure.DMA_MemoryBaseAddr = (u32)TxBuffer1;                   /*内存地址(要传输的变量的指针)*/

    71.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                       /*方向:从内存到外设*/

    72.     DMA_InitStructure.DMA_BufferSize = TxSize1;                              /*传输大小DMA_BufferSize=TxSize1*/

    73.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;         /*外设地址不增*/

    74.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                  /*内存地址自增*/

    75.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  /*外设数据单位 字节*/

    76.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;          /*内存数据单位 字节*/

    77.     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                            /*DMA模式:正常模式,只传输一次。注意:在AD采集之类时要配置成循环模式*/

    78.     DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                  /*优先级:非常高*/

    79.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                             /*禁止内存到内存的传输*/

    80.     DMA_Init(DMA1_Channel2, &DMA_InitStructure);                             /*配置DMA1的2通道*/



    81.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    82.     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;

    83.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    84.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    85.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    86.     NVIC_Init(&NVIC_InitStructure);



    87.     DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);  //使能DMA传输完成中断



    88.     DMA_Cmd (DMA1_Channel2,ENABLE);  //使能DMA

    89. }



    90. void DMA1_Channel2_IRQHandler(void)

    91. {

    92.     if(DMA_GetITStatus(DMA1_IT_TC2))

    93.     {

    94.         printf("USART DMA complete\r\n");

    95.         //Delay_Ms(500);

    96.         GPIO_ResetBits(GPIOA, GPIO_Pin_0);

    97.         DMA_ClearITPendingBit(DMA1_IT_TC2); //清除全部中断标志

    98.     }

    99. }
    复制代码

    usart.c文件主要对相关外设进行初始化配置和中断服务函数配置。
    main.c文件
    1. /********************************** (C) COPYRIGHT *******************************

    2. * File Name          : main.c

    3. * Author             : WCH

    4. * Version            : V1.0.0

    5. * Date               : 2019/10/15

    6. * Description        : Main program body.

    7. *******************************************************************************/



    8. #include "debug.h"

    9. #include "usart.h"



    10. /*******************************************************************************

    11. * Function Name  : main

    12. * Description    : Main program.

    13. * Input          : None

    14. * Return         : None

    15. *******************************************************************************/

    16. int main(void)

    17. {



    18.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    19.     Delay_Init();

    20.     USART_Printf_Init(115200);

    21.     printf("SystemClk:%d\r\n",SystemCoreClock);

    22.     printf("USART DMA TEST\r\n");



    23.     LED_GPIO_Config();

    24.     USARTx_CFG();

    25.     DMA_INIT();



    26.     /*串口3向DMA发出TX请求,此时CPU是空闲的,可以干其他的事情,例如同时控制LED */

    27.     USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);



    28.     Delay_Ms(10);



    29.     while(1)

    30.     {

    31.         //Delay_Ms(500);

    32.         GPIO_ResetBits(GPIOA, GPIO_Pin_1);

    33.         Delay_Ms(500);

    34.         GPIO_SetBits(GPIOA, GPIO_Pin_1);

    35.         Delay_Ms(500);

    36.     }

    37. }
    复制代码
    main.c文件主要函数初始化以及使能串口3向DMA发出TX请求。

    4、下载验证

    将编译好的程序下载到开发板并复位,通过串口3与串口调试助手接好之后串口打印如下:
    CH32V CH573单片机芯片-第一百零二章:CH32V103应用教程——USART-DMA-TC中断risc-v单片机中文社区(1)

    同时可以看到测试板LED1常亮说明进入DMA发送完成中断,同时主函数while(1)循环中LED2闪烁。

    CH32V CH573单片机芯片-第一百零二章:CH32V103应用教程——USART-DMA-TC中断risc-v单片机中文社区(2) 101、USART-DMA-TC中断.rar (392.91 KB, 下载次数: 15)








    上一篇:第一百零一章:CH32V103应用教程——旋转编码器
    下一篇:第一百零三章:CH32V103应用教程——RCC—HSE/HSI时钟配置
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-11-26 09:53 , Processed in 0.272839 second(s), 46 queries .

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