离线
TA的每日心情 | 慵懒 2021-7-23 17:16 |
---|
签到天数: 17 天 [LV.4]
|
有人预言,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文件
- #ifndef __USART_H
- #define __USART_H
- #include "ch32v10x.h"
- void LED_GPIO_Config(void);
- void USARTx_CFG(void);
- void DMA_INIT(void);
- #endif
复制代码
usart.h文件主要进行相关定义和函数声明;
usart.c文件
- #include "usart.h"
- #include "debug.h"
- void DMA1_Channel2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- //定义SRC_BUF数组作为DMA传输数据源,并将数据存储在内部FLASH中
- u8 TxBuffer1[ ]="DMA test: from memory to peripheral";
- #define TxSize1 (sizeof(TxBuffer1))
- //LED灯初始化配置
- void LED_GPIO_Config(void)
- {
- /*定义一个GPIO_InitTypeDef类型的结构体*/
- GPIO_InitTypeDef GPIO_InitStructure;
- /*开启LED对应GPIO引脚的外设时钟*/
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
- /*选择要控制的GPIOA引脚*/
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
- /*设置引脚模式为通用推挽输出*/
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- /*设置引脚速率为50MHz */
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- /*调用库函数,初始化GPIOA*/
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- /*PA0引脚设置低电平 */
- GPIO_SetBits(GPIOA, GPIO_Pin_0|GPIO_Pin_1);
- }
- /*******************************************************************************
- * Function Name : USARTx_CFG
- * Description : Initializes the USART2 & USART3 peripheral.
- * Input : None
- * Return : None
- *******************************************************************************/
- void USARTx_CFG(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- //使能开启GPIOB和USART3时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
- //串口3对应GPIO引脚初始化
- /* USART3 TX-->B.10 RX-->B.11 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- //串口3初始化配置
- 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_Tx | USART_Mode_Rx;
- USART_Init(USART3, &USART_InitStructure);
- USART_Cmd(USART3, ENABLE); //使能串口3
- }
- /*******************************************************************************
- * Function Name : DMA_INIT
- * Description : Configures the DMA for USART3.
- * Input : None
- * Return : None
- *******************************************************************************/
- void DMA_INIT(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能开启DMA时钟
- DMA_DeInit(DMA1_Channel2);
- DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART3->DATAR); /*设置DMA源:串口3数据寄存器地址*/
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32)TxBuffer1; /*内存地址(要传输的变量的指针)*/
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; /*方向:从内存到外设*/
- DMA_InitStructure.DMA_BufferSize = TxSize1; /*传输大小DMA_BufferSize=TxSize1*/
- 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模式:正常模式,只传输一次。注意:在AD采集之类时要配置成循环模式*/
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; /*优先级:非常高*/
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /*禁止内存到内存的传输*/
- DMA_Init(DMA1_Channel2, &DMA_InitStructure); /*配置DMA1的2通道*/
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); //使能DMA传输完成中断
- DMA_Cmd (DMA1_Channel2,ENABLE); //使能DMA
- }
- void DMA1_Channel2_IRQHandler(void)
- {
- if(DMA_GetITStatus(DMA1_IT_TC2))
- {
- printf("USART DMA complete\r\n");
- //Delay_Ms(500);
- GPIO_ResetBits(GPIOA, GPIO_Pin_0);
- DMA_ClearITPendingBit(DMA1_IT_TC2); //清除全部中断标志
- }
- }
复制代码
usart.c文件主要对相关外设进行初始化配置和中断服务函数配置。
main.c文件
- /********************************** (C) COPYRIGHT *******************************
- * File Name : main.c
- * Author : WCH
- * Version : V1.0.0
- * Date : 2019/10/15
- * Description : Main program body.
- *******************************************************************************/
- #include "debug.h"
- #include "usart.h"
- /*******************************************************************************
- * Function Name : main
- * Description : Main program.
- * Input : None
- * Return : None
- *******************************************************************************/
- int main(void)
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%d\r\n",SystemCoreClock);
- printf("USART DMA TEST\r\n");
- LED_GPIO_Config();
- USARTx_CFG();
- DMA_INIT();
- /*串口3向DMA发出TX请求,此时CPU是空闲的,可以干其他的事情,例如同时控制LED */
- USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
- Delay_Ms(10);
- while(1)
- {
- //Delay_Ms(500);
- GPIO_ResetBits(GPIOA, GPIO_Pin_1);
- Delay_Ms(500);
- GPIO_SetBits(GPIOA, GPIO_Pin_1);
- Delay_Ms(500);
- }
- }
复制代码 main.c文件主要函数初始化以及使能串口3向DMA发出TX请求。
4、下载验证
将编译好的程序下载到开发板并复位,通过串口3与串口调试助手接好之后串口打印如下:
同时可以看到测试板LED1常亮说明进入DMA发送完成中断,同时主函数while(1)循环中LED2闪烁。
101、USART-DMA-TC中断.rar
(392.91 KB, 下载次数: 15)
完
|
上一篇: 第一百零一章:CH32V103应用教程——旋转编码器下一篇: 第一百零三章:CH32V103应用教程——RCC—HSE/HSI时钟配置
|